mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 17:39:40 +01:00
Compare commits
1131 Commits
jdk-21.0.3
...
lanai
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28a7fb6c8c | ||
|
|
91bf7d554c | ||
|
|
1ef3bdbc2e | ||
|
|
62bc06db05 | ||
|
|
260a213461 | ||
|
|
660abf5054 | ||
|
|
bf4e5e338c | ||
|
|
094ce3e479 | ||
|
|
17bff28e75 | ||
|
|
03900083a4 | ||
|
|
6a5eaf8b18 | ||
|
|
edb7063a03 | ||
|
|
3fdb753e81 | ||
|
|
fe2dc0b470 | ||
|
|
64809bfc31 | ||
|
|
f653e09f37 | ||
|
|
e31170f23c | ||
|
|
3e69e3374e | ||
|
|
64f3aa5532 | ||
|
|
e6b5aedb89 | ||
|
|
d70158857f | ||
|
|
10062c5a37 | ||
|
|
dd22f92e4d | ||
|
|
401014c95e | ||
|
|
d8ff1fdada | ||
|
|
ea4a024993 | ||
|
|
920306eea4 | ||
|
|
3f77ccc46e | ||
|
|
3bce45f535 | ||
|
|
c582a9cc98 | ||
|
|
656404eb0a | ||
|
|
79b2f86596 | ||
|
|
084887dc1a | ||
|
|
4639971ded | ||
|
|
d729f30fdf | ||
|
|
8ba59cf7c5 | ||
|
|
be067d4468 | ||
|
|
42f6a5ff01 | ||
|
|
6d34f21d67 | ||
|
|
d605bfb9a7 | ||
|
|
42387eb464 | ||
|
|
587d6c046c | ||
|
|
21bee5fee0 | ||
|
|
6f128b439d | ||
|
|
41df642df1 | ||
|
|
d3d1daaa98 | ||
|
|
4188413f0d | ||
|
|
478286d547 | ||
|
|
5bb76c338f | ||
|
|
50bf043568 | ||
|
|
15df88a770 | ||
|
|
b1419d2036 | ||
|
|
abe08b13cc | ||
|
|
b10507ac67 | ||
|
|
223e3cba58 | ||
|
|
07ce8091f3 | ||
|
|
e5a27b5ee4 | ||
|
|
85f7c21dc5 | ||
|
|
e800b7b260 | ||
|
|
99874878f7 | ||
|
|
80418ede33 | ||
|
|
2d7ccff5a4 | ||
|
|
d207aca8f0 | ||
|
|
0fc706e9b3 | ||
|
|
c2a26224d9 | ||
|
|
495aeb4ef7 | ||
|
|
4c01dde78c | ||
|
|
1eefa8f3d9 | ||
|
|
d486cd85f6 | ||
|
|
22b1c087dd | ||
|
|
946a51c455 | ||
|
|
fe605e36ad | ||
|
|
e0ea4f0497 | ||
|
|
379b63d115 | ||
|
|
530cbaf32b | ||
|
|
2a30ee5af6 | ||
|
|
7d1d38fb3e | ||
|
|
2b38e11dda | ||
|
|
510a6ebc02 | ||
|
|
7d6464cb03 | ||
|
|
482cb2cd7d | ||
|
|
7653c969c3 | ||
|
|
97ccc3b92a | ||
|
|
234186f8f2 | ||
|
|
52c97e57f1 | ||
|
|
5c73963639 | ||
|
|
addfb6a977 | ||
|
|
67afe90b36 | ||
|
|
8884f9d8a4 | ||
|
|
e36391eff6 | ||
|
|
5db5591c91 | ||
|
|
79bb7559e5 | ||
|
|
64a3f881e6 | ||
|
|
131a603276 | ||
|
|
0ef13100d9 | ||
|
|
e38adfd765 | ||
|
|
25eace05a9 | ||
|
|
2826fc7066 | ||
|
|
986dca23d5 | ||
|
|
7b42e06aef | ||
|
|
fdcc9fddbf | ||
|
|
81729ba051 | ||
|
|
7b6b7be68e | ||
|
|
30b87c955c | ||
|
|
5a3cc03b79 | ||
|
|
7bf226fcbc | ||
|
|
5aca2ac657 | ||
|
|
6a4d69512b | ||
|
|
b64eb4e257 | ||
|
|
6a33829b36 | ||
|
|
b8f99e1fa2 | ||
|
|
162fbcd1de | ||
|
|
99b2ff50f1 | ||
|
|
9890f0844d | ||
|
|
f4666a6a97 | ||
|
|
a6f59f9137 | ||
|
|
1cc80db805 | ||
|
|
88c1ff807d | ||
|
|
2a9fcc5f34 | ||
|
|
24f0d2a213 | ||
|
|
710301d7a5 | ||
|
|
10cabad7fc | ||
|
|
9116da91bf | ||
|
|
fe6142e0e7 | ||
|
|
df45ee2af5 | ||
|
|
50ff3117d8 | ||
|
|
d6260ae2d9 | ||
|
|
b4be448352 | ||
|
|
2bdc2ad599 | ||
|
|
3d1cca4fc1 | ||
|
|
fb9b56b267 | ||
|
|
dd770c0c49 | ||
|
|
a086f21948 | ||
|
|
1aeed78423 | ||
|
|
729546ecec | ||
|
|
ffff4e1315 | ||
|
|
61b650c24f | ||
|
|
ba667323a3 | ||
|
|
b68d1e466e | ||
|
|
0ee76de31e | ||
|
|
f38c45ed85 | ||
|
|
98822bb325 | ||
|
|
aade96699f | ||
|
|
8e3298000d | ||
|
|
66bdd366c9 | ||
|
|
48977119d6 | ||
|
|
b5719f7774 | ||
|
|
ab4b36a540 | ||
|
|
9075f2829a | ||
|
|
cd17eb8622 | ||
|
|
a4f15c1c4b | ||
|
|
5a0ccbd732 | ||
|
|
d1919ac1a8 | ||
|
|
459b91e7a8 | ||
|
|
914ef36948 | ||
|
|
81cdc7b150 | ||
|
|
9a2e3d13f2 | ||
|
|
96d9156bd4 | ||
|
|
d004e2609b | ||
|
|
cf5c1adcd9 | ||
|
|
e0c34c174c | ||
|
|
4cc0ffde54 | ||
|
|
e361b77627 | ||
|
|
10be998a95 | ||
|
|
44f1aa29b0 | ||
|
|
79dfc90d9b | ||
|
|
49c84d0d46 | ||
|
|
62fe8aaaa4 | ||
|
|
44c1b84b6a | ||
|
|
72eaf07598 | ||
|
|
52639745f1 | ||
|
|
5c53e622ef | ||
|
|
bac73bd20f | ||
|
|
a47c1df13d | ||
|
|
b6cb08c7e4 | ||
|
|
d878c5228a | ||
|
|
f8dafc0c1f | ||
|
|
c62d6e9e8d | ||
|
|
155ae3df3b | ||
|
|
b6071d966d | ||
|
|
ee97a0686d | ||
|
|
6ebf5f9607 | ||
|
|
0854159747 | ||
|
|
21d33db037 | ||
|
|
cace27df22 | ||
|
|
e3bfd4e107 | ||
|
|
4bc2b15bf9 | ||
|
|
2ea17a6f06 | ||
|
|
2dbceb92a2 | ||
|
|
33a384e5a7 | ||
|
|
85fcedca4d | ||
|
|
ca1296ffef | ||
|
|
adbb74a935 | ||
|
|
a4f5e37655 | ||
|
|
c6bc2f1241 | ||
|
|
9782047b09 | ||
|
|
aafb51fd34 | ||
|
|
7be48b0e98 | ||
|
|
add594364d | ||
|
|
ec6c1f4621 | ||
|
|
77dca424db | ||
|
|
dcff176cd1 | ||
|
|
205bae2a49 | ||
|
|
3c27630ad7 | ||
|
|
eeadc05079 | ||
|
|
32fd6b345a | ||
|
|
08af64f46b | ||
|
|
155894a070 | ||
|
|
41ebd23426 | ||
|
|
bcb5b1e9c7 | ||
|
|
7979846a80 | ||
|
|
489d303270 | ||
|
|
cf94b38ac5 | ||
|
|
501ace0275 | ||
|
|
3713bafaf7 | ||
|
|
352aa3d09d | ||
|
|
e5da31146b | ||
|
|
bc0f5d20ff | ||
|
|
fc9638cac9 | ||
|
|
a66358d388 | ||
|
|
2f883fe273 | ||
|
|
ced205874d | ||
|
|
fea7abd0b8 | ||
|
|
d9d2c0adcf | ||
|
|
fbc066e0a2 | ||
|
|
e47e233fcf | ||
|
|
9d02701886 | ||
|
|
38e78cdea3 | ||
|
|
febb0275c4 | ||
|
|
afc927b611 | ||
|
|
f4f9e934e7 | ||
|
|
952bef438e | ||
|
|
6fbe9a2850 | ||
|
|
43f1444ef0 | ||
|
|
2a5cf85aaf | ||
|
|
454fe1949d | ||
|
|
dd9a5fbcad | ||
|
|
cdfa562f2b | ||
|
|
f42d024a4f | ||
|
|
adf44f92db | ||
|
|
807c640c14 | ||
|
|
74f7f5f4f8 | ||
|
|
82bc7ce40e | ||
|
|
ef3dbe5a9a | ||
|
|
120fa46b4b | ||
|
|
53d0d6742d | ||
|
|
9f517857a8 | ||
|
|
f90afe7aa1 | ||
|
|
9fc1e40ac8 | ||
|
|
3a8f5fd9fa | ||
|
|
52be8a98ab | ||
|
|
4af6e072ff | ||
|
|
b2d67d1a76 | ||
|
|
a8f779d7fb | ||
|
|
bf3b3c9ab8 | ||
|
|
84058e38e3 | ||
|
|
57c551e09d | ||
|
|
5fab7690f1 | ||
|
|
057fc7c24d | ||
|
|
ee23dcda71 | ||
|
|
1e5a5c9c10 | ||
|
|
c4433bd988 | ||
|
|
a1aa4d9188 | ||
|
|
08527778b5 | ||
|
|
64c145afc4 | ||
|
|
a7c59e75b7 | ||
|
|
7964f7f878 | ||
|
|
b60294f464 | ||
|
|
507a093794 | ||
|
|
ac7f36b767 | ||
|
|
28cdf8acf8 | ||
|
|
cfab014f6c | ||
|
|
f62fdf6836 | ||
|
|
1553e9a1d1 | ||
|
|
1e88cd03ea | ||
|
|
df33968cc6 | ||
|
|
52becacc85 | ||
|
|
12363abf0a | ||
|
|
6461f3754e | ||
|
|
fe76452a6c | ||
|
|
f6e488b273 | ||
|
|
f095de66af | ||
|
|
971434904d | ||
|
|
ddc7693e7c | ||
|
|
0e9118f2ad | ||
|
|
248576ae65 | ||
|
|
de1213f107 | ||
|
|
746ea173ee | ||
|
|
ca6f3cac48 | ||
|
|
243c841996 | ||
|
|
d638a78e91 | ||
|
|
aa75d33288 | ||
|
|
06db9a2811 | ||
|
|
3409cb7dcc | ||
|
|
ce13b0f1e2 | ||
|
|
b776c5abab | ||
|
|
0794d75af7 | ||
|
|
6aacf1d087 | ||
|
|
b369c73961 | ||
|
|
d07e71c880 | ||
|
|
69998b371e | ||
|
|
66518371cf | ||
|
|
30b446ce88 | ||
|
|
34cdd52696 | ||
|
|
4b3046e7b4 | ||
|
|
9bf8b49c7e | ||
|
|
05dba46171 | ||
|
|
6dcee9f01d | ||
|
|
8c3d37f4be | ||
|
|
17047c22a7 | ||
|
|
faaac4bdbb | ||
|
|
aa2e7e7e0d | ||
|
|
b43461e7b5 | ||
|
|
558f5b04cd | ||
|
|
27eab83a03 | ||
|
|
5e7ff8853a | ||
|
|
2b54a293d2 | ||
|
|
2026fc1402 | ||
|
|
3f04475fd1 | ||
|
|
4eb5cb72e3 | ||
|
|
e7823d8202 | ||
|
|
82e504bbd6 | ||
|
|
3f2cc917f7 | ||
|
|
521ad857be | ||
|
|
994240ff9d | ||
|
|
69bc41be53 | ||
|
|
f638c5b050 | ||
|
|
e77f8f17a3 | ||
|
|
389eab6fe8 | ||
|
|
4a8f2d21cc | ||
|
|
23aeda1cba | ||
|
|
c9dcc4d4d0 | ||
|
|
272da50636 | ||
|
|
9be21072a2 | ||
|
|
571e894e2b | ||
|
|
426647994a | ||
|
|
bfcf110242 | ||
|
|
bcb31edf1f | ||
|
|
6cecbedbae | ||
|
|
2c50c0f4fb | ||
|
|
ab213f56af | ||
|
|
db306e2f09 | ||
|
|
d3bbb05e12 | ||
|
|
bcc85aa76e | ||
|
|
a3d5998513 | ||
|
|
b79f4f0301 | ||
|
|
74560722e4 | ||
|
|
57bf93dda2 | ||
|
|
b5a80794cc | ||
|
|
7bc726537f | ||
|
|
898c29ffbe | ||
|
|
197d72e351 | ||
|
|
39dcd31ec0 | ||
|
|
238655b025 | ||
|
|
bc7caad91e | ||
|
|
75f133c004 | ||
|
|
ba7eb53bca | ||
|
|
83e0ecb953 | ||
|
|
208b1206fe | ||
|
|
d4ef7fae99 | ||
|
|
93913adbc9 | ||
|
|
2d93ba3755 | ||
|
|
580efd590e | ||
|
|
058a4aecaf | ||
|
|
af4203a015 | ||
|
|
cbd7b826f5 | ||
|
|
b8d14fc5ba | ||
|
|
e4d4828a3b | ||
|
|
44ad9322e6 | ||
|
|
e95e1381cd | ||
|
|
9ac3073307 | ||
|
|
76b0dc5f6c | ||
|
|
45d8d4ca12 | ||
|
|
ef91729062 | ||
|
|
a7d1a64cb6 | ||
|
|
e590fc9098 | ||
|
|
2289fbb230 | ||
|
|
cc188e6e31 | ||
|
|
4ca27927a5 | ||
|
|
22afbe5649 | ||
|
|
5414b6fabb | ||
|
|
e038528e97 | ||
|
|
fe0c2ad903 | ||
|
|
3746ed3370 | ||
|
|
f042a4e0de | ||
|
|
acc03fe0ec | ||
|
|
ffd78a95b2 | ||
|
|
5eaef6de03 | ||
|
|
a0ddd7a9e6 | ||
|
|
de84793a57 | ||
|
|
d372b52789 | ||
|
|
98f5ae24c7 | ||
|
|
ed8324eaad | ||
|
|
5a56a00605 | ||
|
|
02857c2ba7 | ||
|
|
80d4f49031 | ||
|
|
f9ed6b5681 | ||
|
|
fa036c8f54 | ||
|
|
f443628fb2 | ||
|
|
cb14b33c76 | ||
|
|
0e024b33ef | ||
|
|
b02054be18 | ||
|
|
19216ac7c7 | ||
|
|
85eca9be05 | ||
|
|
6173a38bc6 | ||
|
|
3af532e7df | ||
|
|
47ea44d7bd | ||
|
|
015c0b5aa9 | ||
|
|
1845dd2a4a | ||
|
|
461a4d5e75 | ||
|
|
074cabcb6d | ||
|
|
2665df9304 | ||
|
|
c4bcb12905 | ||
|
|
86e953b5a9 | ||
|
|
a9a6e4f7cd | ||
|
|
1e4c6aff8b | ||
|
|
b20264e377 | ||
|
|
0e80c21f1a | ||
|
|
ca68b1854b | ||
|
|
d5e8f23555 | ||
|
|
80f1b6a031 | ||
|
|
e0763c5907 | ||
|
|
4f978172b4 | ||
|
|
1a24996ca3 | ||
|
|
e3e4d1ac78 | ||
|
|
3282e70c55 | ||
|
|
655b45f2db | ||
|
|
cbeab12fd8 | ||
|
|
e292f04264 | ||
|
|
e6f39e177e | ||
|
|
bfe17acf0b | ||
|
|
84215334c8 | ||
|
|
87e1ab5298 | ||
|
|
64ae0bb2bf | ||
|
|
1e90934b33 | ||
|
|
6842061ad2 | ||
|
|
ba36dbcc3b | ||
|
|
91ff090341 | ||
|
|
ea02307411 | ||
|
|
b2237008cc | ||
|
|
ac4a6c9989 | ||
|
|
59d5f4dcc7 | ||
|
|
8c53a97973 | ||
|
|
81c501e521 | ||
|
|
0261de472a | ||
|
|
3ccb4939b7 | ||
|
|
fefb9c89f1 | ||
|
|
46b5560bd0 | ||
|
|
c24e7ba0b4 | ||
|
|
75a8c715f9 | ||
|
|
a9298a07c5 | ||
|
|
b55df03ed6 | ||
|
|
53e266d8d8 | ||
|
|
ea029715c1 | ||
|
|
319348b4ce | ||
|
|
329cc86959 | ||
|
|
e1a7832e2a | ||
|
|
6fe09318c5 | ||
|
|
21a2bc9188 | ||
|
|
0cfd010246 | ||
|
|
6a50cb6b9c | ||
|
|
cad4272fa2 | ||
|
|
f01c72a255 | ||
|
|
33f1d05b13 | ||
|
|
f7737da205 | ||
|
|
6fbbd9b11b | ||
|
|
080b9eae81 | ||
|
|
8919329cd3 | ||
|
|
19c4f8b158 | ||
|
|
0776cc78a0 | ||
|
|
b3653ac439 | ||
|
|
63a4356325 | ||
|
|
57e72cfbf9 | ||
|
|
24ea96f2b5 | ||
|
|
49e4022c3c | ||
|
|
256cb2b121 | ||
|
|
8a4cf7f868 | ||
|
|
14d6adc003 | ||
|
|
860a529c13 | ||
|
|
7d30450314 | ||
|
|
f85fcbbe8a | ||
|
|
7c8ed857b9 | ||
|
|
f8eca6520e | ||
|
|
ab151c3e99 | ||
|
|
1eb98fc127 | ||
|
|
52a8e0f858 | ||
|
|
f0e5824f35 | ||
|
|
a0cde95b67 | ||
|
|
a9e6747954 | ||
|
|
f8257688c5 | ||
|
|
1da978d352 | ||
|
|
8eed9aad77 | ||
|
|
3fe2535719 | ||
|
|
dd8d78a367 | ||
|
|
562dd2d04c | ||
|
|
3596e7ed84 | ||
|
|
d91817e75b | ||
|
|
f27024b750 | ||
|
|
ddd632e238 | ||
|
|
96616eae2a | ||
|
|
f19d554955 | ||
|
|
3b9aface5d | ||
|
|
951b12a622 | ||
|
|
ecf41658ed | ||
|
|
15cb764bc9 | ||
|
|
20ed11da49 | ||
|
|
306ad64007 | ||
|
|
e361a58a54 | ||
|
|
ac7f8f89c2 | ||
|
|
94fadf1d1c | ||
|
|
b9462e2957 | ||
|
|
f597b5895f | ||
|
|
d2d4a20f64 | ||
|
|
f0897c8a25 | ||
|
|
6f28c2a23a | ||
|
|
e2a95a27de | ||
|
|
9e403d1f88 | ||
|
|
5153ff087f | ||
|
|
bb00b05eee | ||
|
|
0244642b7f | ||
|
|
f243aba573 | ||
|
|
be5517884c | ||
|
|
b324345623 | ||
|
|
f47f30ed09 | ||
|
|
9c5d0fdb8f | ||
|
|
81ffb36296 | ||
|
|
7ead8f46a6 | ||
|
|
9e29d3e251 | ||
|
|
51cc98fdce | ||
|
|
28b409f56d | ||
|
|
00a596f733 | ||
|
|
d0b46ecf4f | ||
|
|
7a2831e5c6 | ||
|
|
373e96dd29 | ||
|
|
4741abbacc | ||
|
|
7f51f48185 | ||
|
|
3f6b473653 | ||
|
|
9cb870f068 | ||
|
|
3c23d2deba | ||
|
|
84c0e7e715 | ||
|
|
c1749c1e3d | ||
|
|
00c89251a5 | ||
|
|
b3d6b110be | ||
|
|
58fa31ef8b | ||
|
|
28725af444 | ||
|
|
02dea52021 | ||
|
|
7bffa1395a | ||
|
|
09105bbefe | ||
|
|
f70b5a38f6 | ||
|
|
89be6f1e48 | ||
|
|
d7b6bc7131 | ||
|
|
1076f6f3be | ||
|
|
3169011aca | ||
|
|
512374628d | ||
|
|
84057fea55 | ||
|
|
4e9881f8fe | ||
|
|
445ac9d18f | ||
|
|
3f8f82876c | ||
|
|
7f0f62bad5 | ||
|
|
1459ec5b3b | ||
|
|
8902fb180d | ||
|
|
a9f94bde3e | ||
|
|
9d8d5097b3 | ||
|
|
4e9ae3219d | ||
|
|
64cf9ce2d7 | ||
|
|
2e7508c2b5 | ||
|
|
754006d60b | ||
|
|
0bf69016b0 | ||
|
|
23edf8dbff | ||
|
|
354dcda373 | ||
|
|
2388590911 | ||
|
|
607b761ff8 | ||
|
|
9ddc381962 | ||
|
|
f44f50f284 | ||
|
|
b95e50aad1 | ||
|
|
d812ec38a5 | ||
|
|
c8a85b41a3 | ||
|
|
e20fe4a07e | ||
|
|
178c45c8db | ||
|
|
69a95c6741 | ||
|
|
1de354a056 | ||
|
|
8d2f237d2f | ||
|
|
444ace6221 | ||
|
|
cfc0f227aa | ||
|
|
0080bb63c5 | ||
|
|
7ff77a54c3 | ||
|
|
203ab1b07c | ||
|
|
397ce2de6a | ||
|
|
65de2224b4 | ||
|
|
0a126f157e | ||
|
|
13c2eac172 | ||
|
|
3ef68753a4 | ||
|
|
eb0aaef256 | ||
|
|
6521b6f6d6 | ||
|
|
93e5c3acf5 | ||
|
|
83dc820d83 | ||
|
|
53f926a063 | ||
|
|
1fc2faadee | ||
|
|
146169b8e3 | ||
|
|
10213a152f | ||
|
|
8efe76838c | ||
|
|
8a37ddf992 | ||
|
|
2ec9c6f236 | ||
|
|
11e1028122 | ||
|
|
919f276985 | ||
|
|
c716ccfa98 | ||
|
|
99aa00b4f9 | ||
|
|
cd26a39135 | ||
|
|
f21835aff6 | ||
|
|
94a969e5d4 | ||
|
|
a13a2aa9fd | ||
|
|
f275a8b63a | ||
|
|
6fa9578e99 | ||
|
|
e61611f084 | ||
|
|
454407b58e | ||
|
|
fb44e873b8 | ||
|
|
5991dbb379 | ||
|
|
d94a7c401a | ||
|
|
69ed4f9804 | ||
|
|
5e053c9458 | ||
|
|
47f6e1bd6b | ||
|
|
2144fcc400 | ||
|
|
f9e00a2600 | ||
|
|
ceb4ae8e07 | ||
|
|
5e9aeb3ae3 | ||
|
|
108d17432c | ||
|
|
e9654634bf | ||
|
|
c3c969d58d | ||
|
|
ac1f04f2cd | ||
|
|
88265996ea | ||
|
|
26d736db49 | ||
|
|
d523e838cd | ||
|
|
fb8ea97df3 | ||
|
|
96fdc0ed0d | ||
|
|
51a9431735 | ||
|
|
16075ea255 | ||
|
|
88297c1316 | ||
|
|
b09b36acac | ||
|
|
18f53dcfe3 | ||
|
|
f0f26043a6 | ||
|
|
da8bffffaf | ||
|
|
6a66ac34e9 | ||
|
|
bdac412f01 | ||
|
|
785aa0f844 | ||
|
|
fc913d485d | ||
|
|
ff76801f48 | ||
|
|
14bc361d40 | ||
|
|
1408a8f868 | ||
|
|
bfbfd928c7 | ||
|
|
a80a39eb9d | ||
|
|
a98c638ae7 | ||
|
|
b4c17693a5 | ||
|
|
3dc1bed616 | ||
|
|
4a21d0da38 | ||
|
|
dcb4a8d1d9 | ||
|
|
67f5341ffe | ||
|
|
1159a67509 | ||
|
|
9ec75c9079 | ||
|
|
d95ea12a06 | ||
|
|
913a12b7be | ||
|
|
c935976db5 | ||
|
|
41a8bfdc49 | ||
|
|
4de9999ecc | ||
|
|
37fb43c89e | ||
|
|
52ac1c355e | ||
|
|
06d0c923f1 | ||
|
|
512946734d | ||
|
|
8f1bc47a89 | ||
|
|
a9268c7cc0 | ||
|
|
92b4f568f6 | ||
|
|
fb600ad773 | ||
|
|
18c3a1eaae | ||
|
|
3b5c80a702 | ||
|
|
a9647c5185 | ||
|
|
a406428fe8 | ||
|
|
5382177581 | ||
|
|
9cf06e4092 | ||
|
|
0a4ddac117 | ||
|
|
bd424852bd | ||
|
|
889b463d2b | ||
|
|
5a8c995a37 | ||
|
|
995c35c81c | ||
|
|
f951fa8b3a | ||
|
|
5880ed7c11 | ||
|
|
694387943c | ||
|
|
eaade7b5f7 | ||
|
|
9effb06c24 | ||
|
|
9e2a80fe9d | ||
|
|
866c67c3bc | ||
|
|
b9e0d7cdb1 | ||
|
|
b01b4ed2d9 | ||
|
|
7954d97230 | ||
|
|
044a3c519b | ||
|
|
911e038572 | ||
|
|
309917ce65 | ||
|
|
e2294c1ced | ||
|
|
2622e560b2 | ||
|
|
314ce0bba0 | ||
|
|
eaf32de573 | ||
|
|
07dbd94b3c | ||
|
|
dd8931d54d | ||
|
|
285a279a8c | ||
|
|
21b06954b7 | ||
|
|
954e32d27b | ||
|
|
cc53f8a628 | ||
|
|
19df711dc9 | ||
|
|
9f421d031b | ||
|
|
2815830965 | ||
|
|
2c3738563e | ||
|
|
5b186304ba | ||
|
|
5bdf05590f | ||
|
|
bb354b9dd1 | ||
|
|
c3296c4698 | ||
|
|
7d0afd2b26 | ||
|
|
8bb092be76 | ||
|
|
77f82b3298 | ||
|
|
83a7a649a2 | ||
|
|
1d65cbd155 | ||
|
|
3a78fa5adb | ||
|
|
e4cc944428 | ||
|
|
cb7bd4b0fb | ||
|
|
61db079ef1 | ||
|
|
d2a9c11d6b | ||
|
|
31795ff972 | ||
|
|
fe28c1d4b1 | ||
|
|
5f10fe3baa | ||
|
|
5709133f80 | ||
|
|
73bcb5c2c1 | ||
|
|
03663eb45d | ||
|
|
733dde1645 | ||
|
|
acc99a4a94 | ||
|
|
17d32adccf | ||
|
|
380dbb2c22 | ||
|
|
973a3dc5d0 | ||
|
|
74112916e6 | ||
|
|
19abdabf1a | ||
|
|
429914b3b6 | ||
|
|
b92ab434bc | ||
|
|
778a985cb8 | ||
|
|
bb52380f07 | ||
|
|
57f9c6180d | ||
|
|
d5a602f8d0 | ||
|
|
7b3dbfd920 | ||
|
|
6fb7cfc182 | ||
|
|
e27e41c899 | ||
|
|
a057120da3 | ||
|
|
a5c3460875 | ||
|
|
74618f7a28 | ||
|
|
f38fb70374 | ||
|
|
0fa3c6a1a7 | ||
|
|
7a904f3451 | ||
|
|
b74b49287b | ||
|
|
08469dbd44 | ||
|
|
9c05f763db | ||
|
|
68c479d257 | ||
|
|
61108f2409 | ||
|
|
e05a51a009 | ||
|
|
ea873c5ea2 | ||
|
|
6f3d6865e8 | ||
|
|
18fdf05076 | ||
|
|
1b6f67134b | ||
|
|
21b99411de | ||
|
|
b6d88a9023 | ||
|
|
853ad083f3 | ||
|
|
8703ff443a | ||
|
|
642343eb67 | ||
|
|
68c08afede | ||
|
|
2ddf1a1e35 | ||
|
|
8835dcb3ac | ||
|
|
19d757e310 | ||
|
|
813322264f | ||
|
|
9d4ccfbe5d | ||
|
|
ff87ee097e | ||
|
|
e7bad41a32 | ||
|
|
d38172c84d | ||
|
|
c3464101c8 | ||
|
|
d70a42a510 | ||
|
|
a6d931b27f | ||
|
|
8c4b228755 | ||
|
|
087dd7dfd0 | ||
|
|
1e5d70b3d5 | ||
|
|
e635c5f1cf | ||
|
|
6d6fd5faf0 | ||
|
|
cde65ccc84 | ||
|
|
1969c3448d | ||
|
|
83e8d6a494 | ||
|
|
0d8db7a7af | ||
|
|
c8292d3f15 | ||
|
|
49591370e1 | ||
|
|
9a822e7e6c | ||
|
|
95a0895f61 | ||
|
|
7addad25b6 | ||
|
|
086c3bdd3d | ||
|
|
850faa827b | ||
|
|
c6817d9881 | ||
|
|
01d9d3aaf1 | ||
|
|
7d98c22d37 | ||
|
|
6dc6400a38 | ||
|
|
60bc0e1582 | ||
|
|
7a4efdf1ec | ||
|
|
f9e530de24 | ||
|
|
73f3a6b948 | ||
|
|
f5520acde1 | ||
|
|
925e9ac4d6 | ||
|
|
69eff78a8d | ||
|
|
4f32b8d075 | ||
|
|
36eaf0011d | ||
|
|
d1cc002d96 | ||
|
|
c45b7bf5e4 | ||
|
|
2122e5be4f | ||
|
|
2ac547fa25 | ||
|
|
88d110b4a8 | ||
|
|
40c1013ca6 | ||
|
|
eb448c2cf9 | ||
|
|
edea0cf63f | ||
|
|
64e30cf6b9 | ||
|
|
974a943bc6 | ||
|
|
4217fd195e | ||
|
|
2ee839a77b | ||
|
|
9875dddddd | ||
|
|
21d0b3f048 | ||
|
|
ea28491041 | ||
|
|
6dc4ef7af1 | ||
|
|
f12f0bf59c | ||
|
|
8b13aa24e8 | ||
|
|
f9327b3708 | ||
|
|
28f3f21fd6 | ||
|
|
78cac844c8 | ||
|
|
3629cd2661 | ||
|
|
1a163bce48 | ||
|
|
c8c4efa7cf | ||
|
|
b7b6c80016 | ||
|
|
3682655fa0 | ||
|
|
88d59e59f5 | ||
|
|
eaf4be06ba | ||
|
|
2aea8cfda2 | ||
|
|
c21dc22dfd | ||
|
|
45904370a8 | ||
|
|
369d0527da | ||
|
|
2af788b883 | ||
|
|
9afc2f65c1 | ||
|
|
0ab11c2409 | ||
|
|
fd2ca0b9b8 | ||
|
|
1a1367b701 | ||
|
|
15c059f0aa | ||
|
|
436cd605a6 | ||
|
|
bbef2df66d | ||
|
|
7891649b57 | ||
|
|
3bca569234 | ||
|
|
d80efd8ad9 | ||
|
|
a361daf0b1 | ||
|
|
214aef51ee | ||
|
|
e5edd0c32e | ||
|
|
597016b5ad | ||
|
|
091d6a5f8f | ||
|
|
a2fcc2aba9 | ||
|
|
0485b4e34b | ||
|
|
7c5db51dcd | ||
|
|
a0d86b77e6 | ||
|
|
01159e7339 | ||
|
|
ea9ce2f7d7 | ||
|
|
42535d03f3 | ||
|
|
1314319b00 | ||
|
|
33bf12529e | ||
|
|
683da66f10 | ||
|
|
3088310c88 | ||
|
|
60f307fd1d | ||
|
|
8f9de8ff7f | ||
|
|
314f2fd5f4 | ||
|
|
5bb93deef2 | ||
|
|
51172c40fe | ||
|
|
ebaa2c3c14 | ||
|
|
948a7ff99c | ||
|
|
2431174483 | ||
|
|
fc34f9094f | ||
|
|
6605af4cfc | ||
|
|
a812cd299c | ||
|
|
6eebdca862 | ||
|
|
fa26bb0d9d | ||
|
|
e3272713c7 | ||
|
|
3ca8fb7188 | ||
|
|
a294e092f0 | ||
|
|
d376f608c4 | ||
|
|
a808295619 | ||
|
|
5bc5c86f26 | ||
|
|
53032c587f | ||
|
|
8885a83d73 | ||
|
|
c4d0058b19 | ||
|
|
f59ac21a98 | ||
|
|
d742a467b1 | ||
|
|
6aafff1513 | ||
|
|
f747f1c95a | ||
|
|
5a6f74152e | ||
|
|
430cc5c84f | ||
|
|
43f3262467 | ||
|
|
8dc8b55602 | ||
|
|
b519a2cdd8 | ||
|
|
788edb6960 | ||
|
|
fe3b44abfb | ||
|
|
ba56f01e26 | ||
|
|
90cfe209ff | ||
|
|
51ccb1965d | ||
|
|
94ab177a51 | ||
|
|
59322f865d | ||
|
|
75cb54ec9f | ||
|
|
34cf684fe6 | ||
|
|
d129fd67ec | ||
|
|
e6e5096e36 | ||
|
|
695a7852f1 | ||
|
|
c993ee4b9c | ||
|
|
790c6cc195 | ||
|
|
212a39be42 | ||
|
|
74bd95bcc1 | ||
|
|
e2b632ebaf | ||
|
|
047949d2a1 | ||
|
|
1256e2bcc3 | ||
|
|
cf0f63f151 | ||
|
|
d7e99e607f | ||
|
|
1d93ce2b05 | ||
|
|
3749a30c50 | ||
|
|
bd00604ea1 | ||
|
|
6a91c5161a | ||
|
|
c567877ecb | ||
|
|
d178203283 | ||
|
|
ef313f7710 | ||
|
|
858e37a0cf | ||
|
|
2947a7c344 | ||
|
|
e16e7f0b61 | ||
|
|
955a58a59b | ||
|
|
12b63f53e8 | ||
|
|
5645835acd | ||
|
|
4116ed6213 | ||
|
|
676af46996 | ||
|
|
a876ec7d5b | ||
|
|
8fae5e00b5 | ||
|
|
4ac8803c5d | ||
|
|
961a913a5a | ||
|
|
c9e8f24ae1 | ||
|
|
c723f0966a | ||
|
|
a403550ceb | ||
|
|
0c519db955 | ||
|
|
413525fb9d | ||
|
|
ccf8d55371 | ||
|
|
a7d93863a1 | ||
|
|
168dd4fd9c | ||
|
|
40d3b75fc6 | ||
|
|
258fc0be9d | ||
|
|
6f7f9a0c84 | ||
|
|
f2d5dcf256 | ||
|
|
fbd6b2b6b9 | ||
|
|
e3088fedfc | ||
|
|
8b8b0b1953 | ||
|
|
37cfa9f0fd | ||
|
|
5a69bfbe9b | ||
|
|
ddbe37caec | ||
|
|
009ccc3828 | ||
|
|
d3b8b8b6f1 | ||
|
|
929c1ba66c | ||
|
|
830f96afe2 | ||
|
|
30d07796d6 | ||
|
|
cdc54cbc15 | ||
|
|
fa761007e0 | ||
|
|
b9452e95cf | ||
|
|
bec6212151 | ||
|
|
1ab93cb993 | ||
|
|
5c212fc881 | ||
|
|
1773b20de2 | ||
|
|
bd03d4d220 | ||
|
|
88a1f69fb5 | ||
|
|
de6cd3a80b | ||
|
|
8927d5c2f7 | ||
|
|
7b6d7af13f | ||
|
|
03b75851a3 | ||
|
|
167a33c011 | ||
|
|
c76eeefa8e | ||
|
|
161711cb2f | ||
|
|
de2abf17d6 | ||
|
|
b8f0b5fc66 | ||
|
|
5a37b5225a | ||
|
|
a3691b07ef | ||
|
|
38811d3a0e | ||
|
|
04523d9d80 | ||
|
|
0002a91517 | ||
|
|
5f36a43220 | ||
|
|
6698ac4ded | ||
|
|
ef98db1d0d | ||
|
|
f643afdb22 | ||
|
|
be4bea9585 | ||
|
|
20f6e79c6d | ||
|
|
d22b543058 | ||
|
|
341cf3716a | ||
|
|
7c59839250 | ||
|
|
923bd0bb87 | ||
|
|
9d847b543a | ||
|
|
e54446332d | ||
|
|
ac569a56a0 | ||
|
|
89705e4cd8 | ||
|
|
07e9fbf764 | ||
|
|
e9d7168fc7 | ||
|
|
7cc7448622 | ||
|
|
b6f2fd6c44 | ||
|
|
bc4283413d | ||
|
|
92f27e94d7 | ||
|
|
4ffc9752bc | ||
|
|
b5c1be0c30 | ||
|
|
fd4cf1d519 | ||
|
|
130560f769 | ||
|
|
fd85e5fbd1 | ||
|
|
d991baed46 | ||
|
|
79f176b4a1 | ||
|
|
61fdc8a95a | ||
|
|
ec0ca2bc72 | ||
|
|
137168f694 | ||
|
|
ce891e9756 | ||
|
|
3eb5cfb91a | ||
|
|
ee7fee1d07 | ||
|
|
616100a6c4 | ||
|
|
63f81c9587 | ||
|
|
1c0fe72535 | ||
|
|
45534e2389 | ||
|
|
469c179c9a | ||
|
|
5cae755f21 | ||
|
|
8d90ece185 | ||
|
|
35aa6e1810 | ||
|
|
aeb0b443d1 | ||
|
|
e945ccef4b | ||
|
|
c7ab913154 | ||
|
|
639f384353 | ||
|
|
e00df2c2d3 | ||
|
|
4ae50c4519 | ||
|
|
0772c1933b | ||
|
|
15d9b35741 | ||
|
|
5574cca908 | ||
|
|
3fcc3f71d9 | ||
|
|
76e7b41c53 | ||
|
|
7d657e8c94 | ||
|
|
0de241433d | ||
|
|
fd95090fa2 | ||
|
|
9cb40a9bc7 | ||
|
|
97c7a63ab6 | ||
|
|
623aa48c4f | ||
|
|
83bbb3941e | ||
|
|
cae4b9cc37 | ||
|
|
9226e84501 | ||
|
|
3da068b282 | ||
|
|
45fea40dbd | ||
|
|
e5d516d182 | ||
|
|
db88ce172a | ||
|
|
4a9a1708b3 | ||
|
|
43bbd51b72 | ||
|
|
c02799eede | ||
|
|
6ff6db02e7 | ||
|
|
032aeb34e6 | ||
|
|
8b636c6a87 | ||
|
|
26d9a0794c | ||
|
|
7744fb099e | ||
|
|
f66a1f1263 | ||
|
|
bc73e009cc | ||
|
|
ff5966de7f | ||
|
|
6ab1ed5817 | ||
|
|
075e1321e3 | ||
|
|
6a57e1fd9c | ||
|
|
2e6bdc171a | ||
|
|
72cac62f89 | ||
|
|
98743762dd | ||
|
|
f0445c24e8 | ||
|
|
d0b2ad3e82 | ||
|
|
32a1a537f0 | ||
|
|
5199fb702d | ||
|
|
3bd02981db | ||
|
|
8a1132d3a2 | ||
|
|
3174bd2c75 | ||
|
|
6e24ac5e09 | ||
|
|
6d8ae023f2 | ||
|
|
c8002d297a | ||
|
|
3b48643a82 | ||
|
|
07ac868b77 | ||
|
|
a2d1099854 | ||
|
|
96a52e96de | ||
|
|
57e1ab737d | ||
|
|
7bc2660967 | ||
|
|
c4ef423d8e | ||
|
|
269e7e98e6 | ||
|
|
136f957e05 | ||
|
|
364be79d47 | ||
|
|
2ad73d2e67 | ||
|
|
a941e59035 | ||
|
|
c4baadb3c9 | ||
|
|
e2d1e4c804 | ||
|
|
dee4009a97 | ||
|
|
e682c5129a | ||
|
|
cdcb094b65 | ||
|
|
537653bd49 | ||
|
|
4fd7c3c449 | ||
|
|
2ec02181fa | ||
|
|
14e6b1244c | ||
|
|
24bff4e701 | ||
|
|
18b550e872 | ||
|
|
fab846163c | ||
|
|
03aa3101a1 | ||
|
|
c8b91c2d3f | ||
|
|
5b3c412357 | ||
|
|
95b69fe529 | ||
|
|
535fff0dac | ||
|
|
bbfac12c68 | ||
|
|
1768149951 | ||
|
|
49ca894f15 | ||
|
|
0f76adc28d | ||
|
|
cfc96d96f7 | ||
|
|
4921d927e0 | ||
|
|
61aeca21c1 | ||
|
|
fda678bef9 | ||
|
|
aba2c30d1e | ||
|
|
3ecd356574 | ||
|
|
762853fe8f | ||
|
|
f879fa4e34 | ||
|
|
6c8022b1ee | ||
|
|
d691007acc | ||
|
|
9f250e53c8 | ||
|
|
7cba2b956a | ||
|
|
c4ee724176 | ||
|
|
393e924d2d | ||
|
|
fcba1675a7 | ||
|
|
493e7d102a | ||
|
|
54f1e4ec23 | ||
|
|
a59e9ab2ac | ||
|
|
6bd87cb96f | ||
|
|
7a448bc74d | ||
|
|
b5cc29da48 | ||
|
|
d98d18b297 | ||
|
|
1441538b23 |
47
.jcheck/conf
47
.jcheck/conf
@@ -1,13 +1,32 @@
|
||||
;
|
||||
; Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
;
|
||||
; This code is free software; you can redistribute it and/or modify it
|
||||
; under the terms of the GNU General Public License version 2 only, as
|
||||
; published by the Free Software Foundation.
|
||||
;
|
||||
; This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
; version 2 for more details (a copy is included in the LICENSE file that
|
||||
; accompanied this code).
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License version
|
||||
; 2 along with this work; if not, write to the Free Software Foundation,
|
||||
; Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
;
|
||||
; Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
; or visit www.oracle.com if you need additional information or have any
|
||||
; questions.
|
||||
;
|
||||
|
||||
[general]
|
||||
project=jdk
|
||||
project=lanai
|
||||
jbs=JDK
|
||||
|
||||
[checks]
|
||||
error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists
|
||||
|
||||
[repository]
|
||||
tags=(?:jdk-(?:[1-9]([0-9]*)(?:\.(?:0|[1-9][0-9]*)){0,4})(?:\+(?:(?:[0-9]+))|(?:-ga)))|(?:jdk[4-9](?:u\d{1,3})?-(?:(?:b\d{2,3})|(?:ga)))|(?:hs\d\d(?:\.\d{1,2})?-b\d\d)
|
||||
branches=
|
||||
error=author,whitespace,executable
|
||||
|
||||
[census]
|
||||
version=0
|
||||
@@ -16,19 +35,3 @@ domain=openjdk.org
|
||||
[checks "whitespace"]
|
||||
files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm|.*\.gmk|.*\.m4|.*\.ac|Makefile
|
||||
ignore-tabs=.*\.gmk|Makefile
|
||||
|
||||
[checks "merge"]
|
||||
message=Merge
|
||||
|
||||
[checks "reviewers"]
|
||||
reviewers=1
|
||||
ignore=duke
|
||||
|
||||
[checks "committer"]
|
||||
role=committer
|
||||
|
||||
[checks "issues"]
|
||||
pattern=^([124-8][0-9]{6}): (\S.*)$
|
||||
|
||||
[checks "problemlists"]
|
||||
dirs=test/jdk|test/langtools|test/lib-test|test/hotspot/jtreg|test/jaxp
|
||||
|
||||
10
jb/project/docker/Dockerfile
Normal file
10
jb/project/docker/Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
||||
# jetbrains/runtime:jbr15env
|
||||
FROM centos:7
|
||||
RUN yum -y install centos-release-scl
|
||||
RUN yum -y install devtoolset-8
|
||||
RUN yum -y install zip bzip2 unzip tar wget make autoconf automake libtool alsa-devel cups-devel xorg-x11-devel libjpeg62-devel giflib-devel freetype-devel file which libXtst-devel libXt-devel libXrender-devel alsa-lib-devel fontconfig-devel libXrandr-devel libXi-devel git
|
||||
# Install Java 11
|
||||
RUN wget https://download.java.net/java/GA/jdk13.0.1/cec27d702aa74d5a8630c65ae61e4305/9/GPL/openjdk-13.0.1_linux-x64_bin.tar.gz \
|
||||
-O - | tar xz -C /
|
||||
ENV JAVA_HOME /jbrsdk
|
||||
ENV PATH $JAVA_HOME/bin:/opt/rh/devtoolset-8/root/usr/bin:$PATH
|
||||
135
jb/project/java-gradle/build.gradle
Normal file
135
jb/project/java-gradle/build.gradle
Normal file
@@ -0,0 +1,135 @@
|
||||
apply plugin: 'java'
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
def test_jvm = {
|
||||
if (project.hasProperty('jbsdkhome')) {
|
||||
file(jbsdkhome + (OperatingSystem.current().isWindows()?"/bin/java.exe" : "/bin/java")).absolutePath
|
||||
} else {
|
||||
if (OperatingSystem.current().isMacOsX()) {
|
||||
file('../../../build/macosx-x86_64-normal-server-release/images/jdk-bundle/jdk-11.0.4.jdk/Contents/Home/bin/java').absolutePath
|
||||
} else if (OperatingSystem.current().isLinux()) {
|
||||
file('../../../build/linux-x86_64-normal-server-release/images/jdk/bin/java').absolutePath
|
||||
} else {
|
||||
file('../../../build/windows-x86_64-normal-server-release/images/jdk/bin/java.exe').absolutePath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile('junit:junit:4.12'){
|
||||
exclude group: 'org.hamcrest'
|
||||
}
|
||||
testCompile 'org.hamcrest:hamcrest-library:1.3'
|
||||
testCompile 'net.java.dev.jna:jna:4.4.0'
|
||||
testCompile 'com.twelvemonkeys.imageio:imageio-tiff:3.3.2'
|
||||
testCompile 'org.apache.commons:commons-lang3:3.0'
|
||||
}
|
||||
|
||||
def jdk_modules = ["java.base", "java.logging", "java.prefs",
|
||||
"java.se.ee", "java.sql", "java.datatransfer",
|
||||
"java.management", "java.rmi", "java.security.jgss",
|
||||
"java.sql.rowset", "java.desktop", "java.management.rmi",
|
||||
"java.scripting", "java.security.sasl", "java.transaction",
|
||||
"java.instrument", "java.naming", "java.se",
|
||||
"java.smartcardio", "java.xml.crypto"]
|
||||
|
||||
def jdk_class_dirs = []
|
||||
|
||||
jdk_modules.collect(jdk_class_dirs) {
|
||||
new File("../../../src/" + it + "/share/classes")
|
||||
}
|
||||
|
||||
if (OperatingSystem.current().isMacOsX())
|
||||
jdk_modules.collect(jdk_class_dirs) {
|
||||
"../../../src/" + it + "/macosx/classes"
|
||||
}
|
||||
else if (OperatingSystem.current().isLinux()) {
|
||||
jdk_modules.collect(jdk_class_dirs) {
|
||||
"../../../src/" + it + "/solaris/classes"
|
||||
}
|
||||
jdk_modules.collect(jdk_class_dirs) {
|
||||
"../../../src/" + it + "/unix/classes"
|
||||
}
|
||||
} else
|
||||
jdk_modules.collect(jdk_class_dirs) {
|
||||
"../../../src/" + it + "/windows/classes"
|
||||
}
|
||||
|
||||
sourceSets.main.java.srcDirs = jdk_class_dirs
|
||||
|
||||
sourceSets {
|
||||
test {
|
||||
java {
|
||||
srcDir "../../../test/jdk/jbu"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test.dependsOn.clear()
|
||||
|
||||
test.dependsOn tasks.compileTestJava
|
||||
|
||||
test {
|
||||
systemProperty "jb.java2d.metal", "true"
|
||||
systemProperty "testdata", file('../../../test/jdk/jbu/testdata').absolutePath
|
||||
|
||||
// Generate golden images for DroidFontTest and MixedTextTest
|
||||
// systemProperty "gentestdata", ""
|
||||
|
||||
// Enable Java2D logging (https://confluence.jetbrains.com/display/JRE/Java2D+Rendering+Logging)
|
||||
// systemProperty "sun.java2d.trace", "log"
|
||||
// systemProperty "sun.java2d.trace", "log,pimpl"
|
||||
|
||||
outputs.upToDateWhen { false }
|
||||
executable = test_jvm()
|
||||
|
||||
// Enable async/dtrace profiler
|
||||
jvmArgs "-XX:+PreserveFramePointer"
|
||||
// Enable native J2D logging (only in debug build)
|
||||
// Can be turned on for J2D by adding "#define DEBUG 1" into jdk/src/share/native/sun/java2d/Trace.h
|
||||
|
||||
// environment 'J2D_TRACE_LEVEL', '4'
|
||||
}
|
||||
|
||||
def buildDir = project.buildscript.sourceFile.parentFile.parentFile.parentFile.parentFile
|
||||
|
||||
def make_cmd = "make"
|
||||
if (OperatingSystem.current().isWindows()) {
|
||||
def cyg_make_cmd = new File("c:/cygwin64/bin/make.exe")
|
||||
if (cyg_make_cmd.exists()) make_cmd = cyg_make_cmd.absolutePath
|
||||
}
|
||||
def test_run = false
|
||||
task make_images {
|
||||
doLast {
|
||||
if (!test_run) {
|
||||
def pb = new ProcessBuilder().command(make_cmd.toString(), "-C", buildDir.absolutePath, "images")
|
||||
def proc = pb.redirectErrorStream(true).start()
|
||||
proc.inputStream.eachLine { println it }
|
||||
assert proc.waitFor() == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task make_clean {
|
||||
doLast {
|
||||
def pb = new ProcessBuilder().command(make_cmd.toString(), "-C", buildDir.absolutePath, "clean")
|
||||
def proc = pb.redirectErrorStream(true).start()
|
||||
proc.inputStream.eachLine { println it }
|
||||
assert proc.waitFor() == 0
|
||||
}
|
||||
}
|
||||
|
||||
task run_test {
|
||||
doLast {
|
||||
test_run = true
|
||||
}
|
||||
}
|
||||
|
||||
tasks.cleanTest.dependsOn tasks.run_test
|
||||
classes.dependsOn.clear()
|
||||
classes.dependsOn tasks.make_images
|
||||
tasks.cleanClasses.dependsOn tasks.make_clean
|
||||
BIN
jb/project/java-gradle/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
jb/project/java-gradle/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
jb/project/java-gradle/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
jb/project/java-gradle/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Thu Dec 06 20:31:44 MSK 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
|
||||
172
jb/project/java-gradle/gradlew
vendored
Executable file
172
jb/project/java-gradle/gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
9
jb/project/tools/linux/scripts/mkbundles_x64.sh
Executable file
9
jb/project/tools/linux/scripts/mkbundles_x64.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
script_dir=jb/project/tools/linux/scripts
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $?
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $?
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $?
|
||||
77
jb/project/tools/linux/scripts/mkimages_aarch64.sh
Executable file
77
jb/project/tools/linux/scripts/mkimages_aarch64.sh
Executable file
@@ -0,0 +1,77 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-build=$JDK_BUILD_NUMBER \
|
||||
--with-version-pre= \
|
||||
--with-version-opt=b$build_number \
|
||||
--with-boot-jdk=amazon-corretto-11.0.5.10.1-linux-aarch64 \
|
||||
--with-import-modules=./modular-sdk \
|
||||
--enable-cds=yes || exit $?
|
||||
make clean CONF=linux-aarch64-normal-server-release || exit $?
|
||||
make images CONF=linux-aarch64-normal-server-release test-image || exit $?
|
||||
|
||||
JBSDK=${JBRSDK_BASE_NAME}-linux-aarch64-b${build_number}
|
||||
BASE_DIR=build/linux-aarch64-normal-server-release/images
|
||||
JSDK=${BASE_DIR}/jdk
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
echo Fixing permissions
|
||||
chmod -R a+r $JSDK
|
||||
|
||||
rm -rf $BASE_DIR/$JBRSDK_BUNDLE
|
||||
cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
tar -pcf $JBSDK.tar \
|
||||
--exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \
|
||||
-C $BASE_DIR ${JBRSDK_BUNDLE} || exit $?
|
||||
gzip $JBSDK.tar || exit $?
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
rm -rf $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-aarch64-b$build_number
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.aarch64
|
||||
echo Running jlink....
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list.aarch64 | sed s/" "//g | sed s/,$//g) \
|
||||
--output ${BASE_DIR}/${JBR_BUNDLE} || exit $?
|
||||
|
||||
echo Modifying release info ...
|
||||
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release
|
||||
|
||||
echo Creating $JBR.tar.gz ...
|
||||
tar -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $?
|
||||
gzip $JBR.tar || exit $?
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-aarch64-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
139
jb/project/tools/linux/scripts/mkimages_x64.sh
Executable file
139
jb/project/tools/linux/scripts/mkimages_x64.sh
Executable file
@@ -0,0 +1,139 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
|
||||
function create_jbr {
|
||||
|
||||
case "$1" in
|
||||
"${bundle_type}_lw")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION}
|
||||
grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list
|
||||
;;
|
||||
"jfx" | "jcef")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
"jfx_jcef")
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
*)
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
esac
|
||||
rm -rf ${BASE_DIR}/${JBR_BUNDLE}
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-x64-b$build_number
|
||||
|
||||
echo Running jlink....
|
||||
$JSDK/bin/jlink \
|
||||
--module-path $JSDK/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
if [[ "$bundle_type" == *jcef* ]]; then
|
||||
cp -R $BASE_DIR/$JBR_BUNDLE $BASE_DIR/jbr
|
||||
cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $?
|
||||
fi
|
||||
grep -v "^JAVA_VERSION" $JSDK/release | grep -v "^MODULES" >> $BASE_DIR/$JBR_BUNDLE/release
|
||||
|
||||
echo Creating $JBR.tar.gz ...
|
||||
if [ ! -z "$bundle_type" ]; then
|
||||
rm -rf ${BASE_DIR}/jbr
|
||||
cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr
|
||||
fi
|
||||
tar -pcf $JBR.tar -C $BASE_DIR jbr || exit $?
|
||||
gzip $JBR.tar || exit $?
|
||||
rm -rf ${BASE_DIR}/${JBR_BUNDLE}
|
||||
}
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION
|
||||
|
||||
#git checkout -- modules.list src
|
||||
case "$bundle_type" in
|
||||
"jfx")
|
||||
git apply -p0 < jb/project/tools/exclude_jcef_module.patch
|
||||
;;
|
||||
"jcef")
|
||||
git apply -p0 < jb/project/tools/exclude_jfx_module.patch
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBR_BUNDLE=jbr
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-boot-jdk=$BOOT_JDK \
|
||||
--enable-cds=yes || exit $?
|
||||
else
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-import-modules=./modular-sdk \
|
||||
--with-boot-jdk=$BOOT_JDK \
|
||||
--enable-cds=yes || exit $?
|
||||
fi
|
||||
|
||||
make images CONF=linux-x86_64-server-release || exit $?
|
||||
|
||||
JSDK=build/linux-x86_64-server-release/images/jdk
|
||||
JBSDK=$JBRSDK_BASE_NAME-linux-x64-b$build_number
|
||||
|
||||
echo Fixing permissions
|
||||
chmod -R a+r $JSDK
|
||||
|
||||
BASE_DIR=build/linux-x86_64-server-release/images
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
rm -rf $BASE_DIR/$JBRSDK_BUNDLE
|
||||
cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
|
||||
if [[ "$bundle_type" == *jcef* ]]; then
|
||||
cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $?
|
||||
fi
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \
|
||||
-C $BASE_DIR $JBRSDK_BUNDLE || exit $?
|
||||
gzip $JBSDK.tar || exit $?
|
||||
fi
|
||||
|
||||
create_jbr ${bundle_type}
|
||||
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
make test-image || exit $?
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x64-b$build_number
|
||||
|
||||
echo Creating $JBSDK_TEST.tar.gz ...
|
||||
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
fi
|
||||
72
jb/project/tools/linux/scripts/mkimages_x64_fd.sh
Executable file
72
jb/project/tools/linux/scripts/mkimages_x64_fd.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=fastdebug \
|
||||
--with-version-build=$JDK_BUILD_NUMBER \
|
||||
--with-version-pre= \
|
||||
--with-version-opt=b$build_number \
|
||||
--with-import-modules=./modular-sdk \
|
||||
--enable-cds=yes || exit $?
|
||||
make clean CONF=linux-x86_64-normal-server-fastdebug || exit $?
|
||||
make images CONF=linux-x86_64-normal-server-fastdebug || exit $?
|
||||
|
||||
JBSDK=${JBRSDK_BASE_NAME}-linux-x64-fastdebug-b${build_number}
|
||||
BASE_DIR=build/linux-x86_64-normal-server-fastdebug/images
|
||||
JSDK=${BASE_DIR}/jdk
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
echo Fixing permissions
|
||||
chmod -R a+r $JSDK
|
||||
|
||||
rm -rf $BASE_DIR/$JBRSDK_BUNDLE
|
||||
cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
cp -R jcef_linux_x64/* $BASE_DIR/$JBRSDK_BUNDLE/lib || exit $?
|
||||
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
tar -pcf $JBSDK.tar \
|
||||
--exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \
|
||||
-C $BASE_DIR ${JBRSDK_BUNDLE} || exit $?
|
||||
gzip $JBSDK.tar || exit $?
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
rm -rf $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-x64-fastdebug-b$build_number
|
||||
echo Running jlink....
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list | sed s/" "//g | sed s/,$//g) \
|
||||
--output ${BASE_DIR}/${JBR_BUNDLE} || exit $?
|
||||
cp -R jcef_linux_x64/* $BASE_DIR/$JBR_BUNDLE/lib || exit $?
|
||||
|
||||
echo Modifying release info ...
|
||||
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release
|
||||
|
||||
echo Creating $JBR.tar.gz ...
|
||||
tar -czf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $?
|
||||
gzip $JBR.tar || exit $?
|
||||
73
jb/project/tools/linux/scripts/mkimages_x86.sh
Executable file
73
jb/project/tools/linux/scripts/mkimages_x86.sh
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
linux32 bash configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-build=$JDK_BUILD_NUMBER \
|
||||
--with-version-pre= \
|
||||
--with-version-opt=b$build_number \
|
||||
--with-boot-jdk=/jbrsdk-11.0.5-b1 \
|
||||
--enable-cds=yes || exit $?
|
||||
make clean CONF=linux-x86-normal-server-release || exit $?
|
||||
make images CONF=linux-x86-normal-server-release test-image || exit $?
|
||||
|
||||
JBSDK=${JBRSDK_BASE_NAME}-linux-x86-b${build_number}
|
||||
BASE_DIR=build/linux-x86-normal-server-release/images
|
||||
JSDK=${BASE_DIR}/jdk
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
echo Fixing permissions
|
||||
chmod -R a+r $JSDK
|
||||
|
||||
rm -rf $BASE_DIR/$JBRSDK_BUNDLE
|
||||
cp -r $JSDK $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
tar -pcf $JBSDK.tar --exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man -C $BASE_DIR ${JBRSDK_BUNDLE} || exit $?
|
||||
gzip $JBSDK.tar || exit $?
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
rm -rf $BASE_DIR/$JBR_BUNDLE
|
||||
|
||||
JBR=$JBR_BASE_NAME-linux-x86-b$build_number
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
echo Running jlink....
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list.x86 | sed s/" "//g | sed s/,$//g) --output ${BASE_DIR}/${JBR_BUNDLE} || exit $?
|
||||
|
||||
echo Modifying release info ...
|
||||
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release
|
||||
|
||||
echo Creating $JBR.tar.gz ...
|
||||
tar -pcf $JBR.tar -C $BASE_DIR $JBR_BUNDLE || exit $?
|
||||
gzip $JBR.tar || exit $?
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-x86-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' --exclude='test/hotspot/gtest' test || exit $?
|
||||
gzip $JBRSDK_TEST.tar || exit $?
|
||||
16
jb/project/tools/mac/scripts/entitlements.xml
Normal file
16
jb/project/tools/mac/scripts/entitlements.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-executable-page-protection</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
9
jb/project/tools/mac/scripts/mkbundles.sh
Executable file
9
jb/project/tools/mac/scripts/mkbundles.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
script_dir=jb/project/tools/mac/scripts
|
||||
${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $?
|
||||
${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $?
|
||||
${script_dir}/mkimages.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $?
|
||||
148
jb/project/tools/mac/scripts/mkimages.sh
Executable file
148
jb/project/tools/mac/scripts/mkimages.sh
Executable file
@@ -0,0 +1,148 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
|
||||
function create_jbr {
|
||||
|
||||
case "$1" in
|
||||
"${bundle_type}_lw")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION}
|
||||
grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list
|
||||
;;
|
||||
"jfx" | "jcef")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
"jfx_jcef")
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
*)
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
esac
|
||||
rm -rf ${BASE_DIR}/${JBR_BUNDLE}
|
||||
|
||||
JRE_CONTENTS=${BASE_DIR}/${JBR_BUNDLE}/Contents
|
||||
JRE_HOME=${JRE_CONTENTS}/Home
|
||||
if [ -d "${JRE_CONTENTS}" ]; then
|
||||
rm -rf ${JRE_CONTENTS}
|
||||
fi
|
||||
mkdir -p ${JRE_CONTENTS}
|
||||
|
||||
JBR=${JBR_BASE_NAME}-osx-x64-b${build_number}
|
||||
|
||||
${BASE_DIR}/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \
|
||||
--module-path ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JRE_HOME} || exit $?
|
||||
grep -v "^JAVA_VERSION" ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Home/release | grep -v "^MODULES" >> ${JRE_HOME}/release
|
||||
cp -R ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/MacOS ${JRE_CONTENTS}
|
||||
cp ${BASE_DIR}/${JBRSDK_BUNDLE}/Contents/Info.plist ${JRE_CONTENTS}
|
||||
|
||||
if [[ "${bundle_type}" == *jcef* ]]; then
|
||||
rm -rf ${JRE_CONTENTS}/Frameworks || exit $?
|
||||
rm -rf ${JRE_CONTENTS}/Helpers || exit $?
|
||||
cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $?
|
||||
cp -a jcef_mac/Helpers ${JRE_CONTENTS} || exit $?
|
||||
fi
|
||||
|
||||
echo Creating ${JBR}.tar.gz ...
|
||||
if [ ! -z "$bundle_type" ]; then
|
||||
rm -rf ${BASE_DIR}/jbr
|
||||
cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr
|
||||
fi
|
||||
COPYFILE_DISABLE=1 tar -pczf ${JBR}.tar.gz --exclude='*.dSYM' --exclude='man' -C ${BASE_DIR} jbr || exit $?
|
||||
rm -rf ${BASE_DIR}/${JBR_BUNDLE}
|
||||
}
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
#git checkout -- modules.list src
|
||||
case "$bundle_type" in
|
||||
"jfx")
|
||||
git apply -p0 < jb/project/tools/exclude_jcef_module.patch
|
||||
;;
|
||||
"jcef")
|
||||
git apply -p0 < jb/project/tools/exclude_jfx_module.patch
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBR_BUNDLE=jbr
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-boot-jdk=`/usr/libexec/java_home -v $BOOT_JDK` \
|
||||
--enable-cds=yes || exit $?
|
||||
else
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=release \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-import-modules=./modular-sdk \
|
||||
--with-boot-jdk=`/usr/libexec/java_home -v $BOOT_JDK` \
|
||||
--enable-cds=yes || exit $?
|
||||
fi
|
||||
make images CONF=macosx-x86_64-server-release || exit $?
|
||||
|
||||
JSDK=build/macosx-x86_64-server-release/images/jdk-bundle
|
||||
JBSDK=${JBRSDK_BASE_NAME}-osx-x64-b${build_number}
|
||||
|
||||
BASE_DIR=jre
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
rm -rf $BASE_DIR
|
||||
mkdir $BASE_DIR || exit $?
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
|
||||
if [[ "$bundle_type" == *jcef* ]]; then
|
||||
cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/ || exit $?
|
||||
cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents/ || exit $?
|
||||
fi
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
COPYFILE_DISABLE=1 tar -pczf $JBSDK.tar.gz -C $BASE_DIR \
|
||||
--exclude='._*' --exclude='.DS_Store' --exclude='*~' \
|
||||
--exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \
|
||||
$JBRSDK_BUNDLE || exit $?
|
||||
fi
|
||||
|
||||
create_jbr "${bundle_type}" || exit $?
|
||||
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
make test-image || exit $?
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-osx-test-x64-b$build_number
|
||||
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
COPYFILE_DISABLE=1 tar -pczf $JBRSDK_TEST.tar.gz -C build/macosx-x86_64-server-release/images \
|
||||
--exclude='test/jdk/demos' test || exit $?
|
||||
fi
|
||||
83
jb/project/tools/mac/scripts/mkimages_fd.sh
Executable file
83
jb/project/tools/mac/scripts/mkimages_fd.sh
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
|
||||
sh configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-debug-level=fastdebug \
|
||||
--with-version-build=$JDK_BUILD_NUMBER \
|
||||
--with-version-pre= \
|
||||
--with-version-opt=b$build_number \
|
||||
--with-import-modules=./modular-sdk \
|
||||
--with-boot-jdk=`/usr/libexec/java_home -v 11` \
|
||||
--enable-cds=yes || exit $?
|
||||
make clean CONF=macosx-x86_64-normal-server-fastdebug || exit $?
|
||||
make images CONF=macosx-x86_64-normal-server-fastdebug || exit $?
|
||||
|
||||
JSDK=build/macosx-x86_64-normal-server-fastdebug/images/jdk-bundle
|
||||
JBSDK=${JBRSDK_BASE_NAME}-osx-x64-fastdebug-b${build_number}
|
||||
|
||||
BASE_DIR=jre
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
rm -rf $BASE_DIR
|
||||
mkdir $BASE_DIR || exit $?
|
||||
JBSDK_VERSION_WITH_DOTS=$(echo $JBSDK_VERSION | sed 's/_/\./g')
|
||||
cp -a $JSDK/jdk-$JBSDK_VERSION_WITH_DOTS.jdk $BASE_DIR/$JBRSDK_BUNDLE || exit $?
|
||||
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
cp -a jcef_mac/Frameworks $BASE_DIR/$JBRSDK_BUNDLE/Contents/
|
||||
cp -a jcef_mac/Helpers $BASE_DIR/$JBRSDK_BUNDLE/Contents
|
||||
|
||||
COPYFILE_DISABLE=1 \
|
||||
tar -pczf ${JBSDK}.tar.gz -C ${BASE_DIR} \
|
||||
--exclude='._*' --exclude='.DS_Store' --exclude='*~' \
|
||||
--exclude='Home/demo' --exclude='Home/man' --exclude='Home/sample' \
|
||||
${JBRSDK_BUNDLE} || exit $?
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
JRE_CONTENTS=$BASE_DIR/$JBR_BUNDLE/Contents
|
||||
JRE_HOME=$JRE_CONTENTS/Home
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
|
||||
mkdir -p $JRE_CONTENTS
|
||||
|
||||
if [ -d "$JRE_HOME" ]; then
|
||||
rm -rf $JRE_HOME
|
||||
fi
|
||||
|
||||
JBR=${JBR_BASE_NAME}-osx-x64-fastdebug-b${build_number}
|
||||
|
||||
$BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/bin/jlink \
|
||||
--module-path $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list | sed s/" "//g) --output $JRE_HOME || exit $?
|
||||
grep -v "^JAVA_VERSION" $BASE_DIR/$JBRSDK_BUNDLE/Contents/Home/release | grep -v "^MODULES" >> $JRE_HOME/release
|
||||
cp -R $BASE_DIR/$JBRSDK_BUNDLE/Contents/MacOS $JRE_CONTENTS
|
||||
cp $BASE_DIR/$JBRSDK_BUNDLE/Contents/Info.plist $JRE_CONTENTS
|
||||
cp -a jcef_mac/Frameworks ${JRE_CONTENTS} || exit $?
|
||||
cp -a jcef_mac/Helpers ${JRE_CONTENTS} || exit $?
|
||||
|
||||
|
||||
echo Creating $JBR.tar.gz ...
|
||||
COPYFILE_DISABLE=1 tar -pczf $JBR.tar.gz --exclude='*.dSYM' --exclude='man' -C $BASE_DIR $JBR_BUNDLE || exit $?
|
||||
120
jb/project/tools/mac/scripts/notarize.sh
Executable file
120
jb/project/tools/mac/scripts/notarize.sh
Executable file
@@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
|
||||
APP_DIRECTORY=$1
|
||||
APPL_USER=$2
|
||||
APPL_PASSWORD=$3
|
||||
APP_NAME=$4
|
||||
BUNDLE_ID=$5
|
||||
FAKE_ROOT="${6:-fake-root}"
|
||||
|
||||
if [[ -z "$APP_DIRECTORY" ]] || [[ -z "$APPL_USER" ]] || [[ -z "$APPL_PASSWORD" ]]; then
|
||||
echo "Usage: $0 AppDirectory Username Password"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -d "$APP_DIRECTORY" ]]; then
|
||||
echo "AppDirectory '$APP_DIRECTORY' does not exist or not a directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function log() {
|
||||
echo "$(date '+[%H:%M:%S]') $*"
|
||||
}
|
||||
|
||||
function publish-log() {
|
||||
id=$1
|
||||
file=$2
|
||||
curl -T "$file" "$ARTIFACTORY_URL/$id" || true
|
||||
}
|
||||
|
||||
function altool-upload() {
|
||||
# Since altool uses same file for upload token we have to trick it into using different folders for token file location
|
||||
# Also it copies zip into TMPDIR so we override it too, to simplify cleanup
|
||||
OLD_HOME="$HOME"
|
||||
export HOME="$FAKE_ROOT/home"
|
||||
export TMPDIR="$FAKE_ROOT/tmp"
|
||||
mkdir -p "$HOME"
|
||||
mkdir -p "$TMPDIR"
|
||||
export _JAVA_OPTIONS="-Duser.home=$HOME -Djava.io.tmpdir=$TMPDIR"
|
||||
# Reduce amount of downloads, cache transporter libraries
|
||||
shared_itmstransporter="$OLD_HOME/shared-itmstransporter"
|
||||
if [[ -f "$shared_itmstransporter" ]]; then
|
||||
cp -r "$shared_itmstransporter" "$HOME/.itmstransporter"
|
||||
fi
|
||||
# For some reason altool prints everything to stderr, not stdout
|
||||
set +e
|
||||
xcrun altool --notarize-app \
|
||||
--username "$APPL_USER" --password "$APPL_PASSWORD" \
|
||||
--primary-bundle-id "$BUNDLE_ID" \
|
||||
--asc-provider JetBrainssro --file "$1" 2>&1 | tee "altool.init.out"
|
||||
unset TMPDIR
|
||||
export HOME="$OLD_HOME"
|
||||
set -e
|
||||
}
|
||||
|
||||
#immediately exit script with an error if a command fails
|
||||
set -euo pipefail
|
||||
|
||||
file="$APP_NAME.zip"
|
||||
|
||||
log "Zipping $file..."
|
||||
rm -rf "$file"
|
||||
ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY/Contents" "$file"
|
||||
|
||||
log "Notarizing $file..."
|
||||
rm -rf "altool.init.out" "altool.check.out"
|
||||
altool-upload "$file"
|
||||
|
||||
rm -rf "$file"
|
||||
|
||||
notarization_info="$(grep -e "RequestUUID" "altool.init.out" | grep -oE '([0-9a-f-]{36})')"
|
||||
|
||||
if [ -z "$notarization_info" ]; then
|
||||
log "Faile to read RequestUUID from altool.init.out"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
PATH="$PATH:/usr/local/bin/"
|
||||
|
||||
log "Notarization request sent, awaiting response"
|
||||
spent=0
|
||||
|
||||
while true; do
|
||||
# For some reason altool prints everything to stderr, not stdout
|
||||
xcrun altool --username "$APPL_USER" --notarization-info "$notarization_info" --password "$APPL_PASSWORD" >"altool.check.out" 2>&1 || true
|
||||
status="$(grep -oe 'Status: .*' "altool.check.out" | cut -c 9- || true)"
|
||||
log "Current status: $status"
|
||||
if [ "$status" = "invalid" ]; then
|
||||
log "Notarization failed"
|
||||
ec=1
|
||||
elif [ "$status" = "success" ]; then
|
||||
log "Notarization succeeded"
|
||||
ec=0
|
||||
else
|
||||
if [ "$status" != "in progress" ]; then
|
||||
log "Unknown notarization status, waiting more, altool output:"
|
||||
cat "altool.check.out"
|
||||
fi
|
||||
if [[ $spent -gt 60 ]]; then
|
||||
log "Waiting time out (apx 60 minutes)"
|
||||
ec=2
|
||||
break
|
||||
fi
|
||||
sleep 60
|
||||
((spent += 1))
|
||||
continue
|
||||
fi
|
||||
developer_log="developer_log.json"
|
||||
log "Fetching $developer_log"
|
||||
# TODO: Replace cut with trim or something better
|
||||
url="$(grep -oe 'LogFileURL: .*' "altool.check.out" | cut -c 13-)"
|
||||
wget "$url" -O "$developer_log" && cat "$developer_log" || true
|
||||
if [ $ec != 0 ]; then
|
||||
log "Publishing $developer_log"
|
||||
publish-log "$notarization_info" "$developer_log"
|
||||
fi
|
||||
break
|
||||
done
|
||||
cat "altool.check.out"
|
||||
|
||||
rm -rf "altool.init.out" "altool.check.out"
|
||||
exit $ec
|
||||
93
jb/project/tools/mac/scripts/sign.sh
Executable file
93
jb/project/tools/mac/scripts/sign.sh
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
|
||||
APP_DIRECTORY=$1
|
||||
JB_CERT=$2
|
||||
|
||||
if [[ -z "$APP_DIRECTORY" ]] || [[ -z "$JB_CERT" ]]; then
|
||||
echo "Usage: $0 AppDirectory CertificateID"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -d "$APP_DIRECTORY" ]]; then
|
||||
echo "AppDirectory '$APP_DIRECTORY' does not exist or not a directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function log() {
|
||||
echo "$(date '+[%H:%M:%S]') $*"
|
||||
}
|
||||
|
||||
#immediately exit script with an error if a command fails
|
||||
set -euo pipefail
|
||||
|
||||
# Cleanup files left from previous sign attempt (if any)
|
||||
find "$APP_DIRECTORY" -name '*.cstemp' -exec rm '{}' \;
|
||||
|
||||
log "Signing libraries and executables..."
|
||||
# -perm +111 searches for executables
|
||||
for f in \
|
||||
"Contents/Home/bin" \
|
||||
"Contents/Home/lib"; do
|
||||
if [ -d "$APP_DIRECTORY/$f" ]; then
|
||||
find "$APP_DIRECTORY/$f" \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \
|
||||
-exec codesign --timestamp \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
--entitlements entitlements.xml {} \;
|
||||
fi
|
||||
done
|
||||
|
||||
log "Signing libraries in jars in $PWD"
|
||||
|
||||
# todo: add set -euo pipefail; into the inner sh -c
|
||||
# `-e` prevents `grep -q && printf` loginc
|
||||
# with `-o pipefail` there's no input for 'while' loop
|
||||
find "$APP_DIRECTORY" -name '*.jar' \
|
||||
-exec sh -c "set -u; unzip -l \"\$0\" | grep -q -e '\.dylib\$' -e '\.jnilib\$' -e '\.so\$' -e '^jattach\$' && printf \"\$0\0\" " {} \; |
|
||||
while IFS= read -r -d $'\0' file; do
|
||||
log "Processing libraries in $file"
|
||||
|
||||
rm -rf jarfolder jar.jar
|
||||
mkdir jarfolder
|
||||
filename="${file##*/}"
|
||||
log "Filename: $filename"
|
||||
cp "$file" jarfolder && (cd jarfolder && jar xf "$filename" && rm "$filename")
|
||||
|
||||
find jarfolder \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "jattach" \) \
|
||||
-exec codesign --timestamp \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
--entitlements entitlements.xml {} \;
|
||||
|
||||
(cd jarfolder; zip -q -r -o ../jar.jar .)
|
||||
mv jar.jar "$file"
|
||||
done
|
||||
|
||||
rm -rf jarfolder jar.jar
|
||||
|
||||
log "Signing other files..."
|
||||
for f in \
|
||||
"Contents/MacOS"; do
|
||||
if [ -d "$APP_DIRECTORY/$f" ]; then
|
||||
find "$APP_DIRECTORY/$f" \
|
||||
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \
|
||||
-exec codesign --timestamp \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
--entitlements entitlements.xml {} \;
|
||||
fi
|
||||
done
|
||||
|
||||
#log "Signing executable..."
|
||||
#codesign --timestamp \
|
||||
# -v -s "$JB_CERT" --options=runtime \
|
||||
# --force \
|
||||
# --entitlements entitlements.xml "$APP_DIRECTORY/Contents/MacOS/idea"
|
||||
|
||||
log "Signing whole app..."
|
||||
codesign --timestamp \
|
||||
-v -s "$JB_CERT" --options=runtime \
|
||||
--force \
|
||||
--entitlements entitlements.xml "$APP_DIRECTORY"
|
||||
|
||||
log "Verifying java is not broken"
|
||||
find "$APP_DIRECTORY" \
|
||||
-type f -name 'java' -perm +111 -exec {} -version \;
|
||||
145
jb/project/tools/mac/scripts/signapp.sh
Executable file
145
jb/project/tools/mac/scripts/signapp.sh
Executable file
@@ -0,0 +1,145 @@
|
||||
#!/bin/bash
|
||||
|
||||
#immediately exit script with an error if a command fails
|
||||
set -euo pipefail
|
||||
|
||||
export COPY_EXTENDED_ATTRIBUTES_DISABLE=true
|
||||
export COPYFILE_DISABLE=true
|
||||
|
||||
INPUT_FILE=$1
|
||||
EXPLODED=$2.exploded
|
||||
BACKUP_JMODS=$2.backup
|
||||
USERNAME=$3
|
||||
PASSWORD=$4
|
||||
CODESIGN_STRING=$5
|
||||
NOTARIZE=$6
|
||||
BUNDLE_ID=$7
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
function log() {
|
||||
echo "$(date '+[%H:%M:%S]') $*"
|
||||
}
|
||||
|
||||
log "Deleting $EXPLODED ..."
|
||||
if test -d "$EXPLODED"; then
|
||||
find "$EXPLODED" -mindepth 1 -maxdepth 1 -exec chmod -R u+wx '{}' \;
|
||||
fi
|
||||
rm -rf "$EXPLODED"
|
||||
mkdir "$EXPLODED"
|
||||
rm -rf "$BACKUP_JMODS"
|
||||
mkdir "$BACKUP_JMODS"
|
||||
|
||||
log "Unzipping $INPUT_FILE to $EXPLODED ..."
|
||||
tar -xzvf "$INPUT_FILE" --directory $EXPLODED
|
||||
rm "$INPUT_FILE"
|
||||
BUILD_NAME="$(ls "$EXPLODED")"
|
||||
if test -d $EXPLODED/$BUILD_NAME/Contents/Home/jmods; then
|
||||
mv $EXPLODED/$BUILD_NAME/Contents/Home/jmods $BACKUP_JMODS
|
||||
fi
|
||||
if test -d $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks; then
|
||||
mv $EXPLODED/$BUILD_NAME/Contents/Home/Frameworks $BACKUP_JMODS
|
||||
fi
|
||||
if test -f $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib; then
|
||||
mv $EXPLODED/$BUILD_NAME/Contents/MacOS/libjli.dylib $BACKUP_JMODS
|
||||
fi
|
||||
|
||||
#log "$INPUT_FILE unzipped and removed"
|
||||
log "$INPUT_FILE extracted and removed"
|
||||
|
||||
APPLICATION_PATH="$EXPLODED/$BUILD_NAME"
|
||||
|
||||
find "$APPLICATION_PATH/Contents/Home/bin" \
|
||||
-maxdepth 1 -type f -name '*.jnilib' -print0 |
|
||||
while IFS= read -r -d $'\0' file; do
|
||||
if [ -f "$file" ]; then
|
||||
log "Linking $file"
|
||||
b="$(basename "$file" .jnilib)"
|
||||
ln -sf "$b.jnilib" "$(dirname "$file")/$b.dylib"
|
||||
fi
|
||||
done
|
||||
|
||||
find "$APPLICATION_PATH/Contents/" \
|
||||
-maxdepth 1 -type f -name '*.txt' -print0 |
|
||||
while IFS= read -r -d $'\0' file; do
|
||||
if [ -f "$file" ]; then
|
||||
log "Moving $file"
|
||||
mv "$file" "$APPLICATION_PATH/Contents/Resources"
|
||||
fi
|
||||
done
|
||||
|
||||
non_plist=$(find "$APPLICATION_PATH/Contents/" -maxdepth 1 -type f -and -not -name 'Info.plist' | wc -l)
|
||||
if [[ $non_plist -gt 0 ]]; then
|
||||
log "Only Info.plist file is allowed in Contents directory but found $non_plist file(s):"
|
||||
log "$(find "$APPLICATION_PATH/Contents/" -maxdepth 1 -type f -and -not -name 'Info.plist')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Unlocking keychain..."
|
||||
# Make sure *.p12 is imported into local KeyChain
|
||||
security unlock-keychain -p "$PASSWORD" "/Users/$USERNAME/Library/Keychains/login.keychain"
|
||||
|
||||
attempt=1
|
||||
limit=3
|
||||
set +e
|
||||
while [[ $attempt -le $limit ]]; do
|
||||
log "Signing (attempt $attempt) $APPLICATION_PATH ..."
|
||||
./sign.sh "$APPLICATION_PATH" "$CODESIGN_STRING"
|
||||
ec=$?
|
||||
if [[ $ec -ne 0 ]]; then
|
||||
((attempt += 1))
|
||||
if [ $attempt -eq $limit ]; then
|
||||
set -e
|
||||
fi
|
||||
log "Signing failed, wait for 30 sec and try to sign again"
|
||||
sleep 30
|
||||
else
|
||||
log "Signing done"
|
||||
codesign -v "$APPLICATION_PATH" -vvvvv
|
||||
log "Check sign done"
|
||||
((attempt += limit))
|
||||
fi
|
||||
done
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$NOTARIZE" = "yes" ]; then
|
||||
log "Notarizing..."
|
||||
# shellcheck disable=SC1090
|
||||
source "$HOME/.notarize_token"
|
||||
APP_NAME=$(echo ${INPUT_FILE} | awk -F"." '{ print $1 }')
|
||||
# Since notarization tool uses same file for upload token we have to trick it into using different folders, hence fake root
|
||||
# Also it leaves copy of zip file in TMPDIR, so notarize.sh overrides it and uses FAKE_ROOT as location for temp TMPDIR
|
||||
FAKE_ROOT="$(pwd)/fake-root"
|
||||
mkdir -p "$FAKE_ROOT"
|
||||
echo "Notarization will use fake root: $FAKE_ROOT"
|
||||
./notarize.sh "$APPLICATION_PATH" "$APPLE_USERNAME" "$APPLE_PASSWORD" "$APP_NAME" "$BUNDLE_ID" "$FAKE_ROOT"
|
||||
rm -rf "$FAKE_ROOT"
|
||||
|
||||
set +e
|
||||
log "Stapling..."
|
||||
xcrun stapler staple "$APPLICATION_PATH"
|
||||
else
|
||||
log "Notarization disabled"
|
||||
log "Stapling disabled"
|
||||
fi
|
||||
|
||||
log "Zipping $BUILD_NAME to $INPUT_FILE ..."
|
||||
(
|
||||
#cd "$EXPLODED"
|
||||
#ditto -c -k --sequesterRsrc --keepParent "$BUILD_NAME" "../$INPUT_FILE"
|
||||
if test ! -z $(ls $BACKUP_JMODS/libjli.dylib); then
|
||||
mv $BACKUP_JMODS/libjli.dylib $EXPLODED/$BUILD_NAME/Contents/MacOS
|
||||
fi
|
||||
if test -d $BACKUP_JMODS/jmods; then
|
||||
mv $BACKUP_JMODS/jmods $EXPLODED/$BUILD_NAME/Contents/Home
|
||||
fi
|
||||
if test -d $BACKUP_JMODS/Frameworks; then
|
||||
mv $BACKUP_JMODS/Frameworks $EXPLODED/$BUILD_NAME/Contents/Home
|
||||
fi
|
||||
|
||||
COPYFILE_DISABLE=1 tar -pczf $INPUT_FILE --exclude='*.dSYM' --exclude='man' -C $EXPLODED $BUILD_NAME
|
||||
log "Finished zipping"
|
||||
)
|
||||
rm -rf "$EXPLODED"
|
||||
log "Done"
|
||||
9
jb/project/tools/windows/scripts/mkbundles_x64.sh
Executable file
9
jb/project/tools/windows/scripts/mkbundles_x64.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
script_dir=jb/project/tools/windows/scripts
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jcef" || exit $?
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx" || exit $?
|
||||
${script_dir}/mkimages_x64.sh $JBSDK_VERSION $JDK_BUILD_NUMBER $build_number "jfx_jcef" || exit $?
|
||||
119
jb/project/tools/windows/scripts/mkimages_x64.sh
Executable file
119
jb/project/tools/windows/scripts/mkimages_x64.sh
Executable file
@@ -0,0 +1,119 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
|
||||
function create_jbr {
|
||||
|
||||
case "$1" in
|
||||
"${bundle_type}_lw")
|
||||
grep -v "jdk.compiler\|jdk.hotspot.agent" modules.list > modules_tmp.list
|
||||
;;
|
||||
"jfx" | "jcef" | "jfx_jcef")
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
*)
|
||||
cat modules.list > modules_tmp.list
|
||||
;;
|
||||
esac
|
||||
rm -rf ${JBR_BUNDLE}
|
||||
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules_tmp.list | sed s/" "//g) --output ${JBR_BUNDLE} || exit $?
|
||||
if [[ "${bundle_type}" == *jcef* ]]
|
||||
then
|
||||
cp -R jcef_win_x64/* ${JBR_BUNDLE}/bin
|
||||
fi
|
||||
echo Modifying release info ...
|
||||
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release
|
||||
}
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
WORK_DIR=$(pwd)
|
||||
|
||||
#git checkout -- modules.list src
|
||||
case "$bundle_type" in
|
||||
"jfx")
|
||||
echo "Excluding jcef modules"
|
||||
git apply -p0 < jb/project/tools/exclude_jcef_module.patch
|
||||
;;
|
||||
"jcef")
|
||||
echo "Excluding jfx modules"
|
||||
git apply -p0 < jb/project/tools/exclude_jfx_module.patch
|
||||
;;
|
||||
esac
|
||||
|
||||
PATH="/usr/local/bin:/usr/bin:${PATH}"
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
bash ./configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-target-bits=64 \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-toolchain-version=${TOOLCHAIN_VERSION} \
|
||||
--with-boot-jdk=${BOOT_JDK} \
|
||||
--disable-ccache \
|
||||
--enable-cds=yes || exit 1
|
||||
else
|
||||
bash ./configure \
|
||||
--disable-warnings-as-errors \
|
||||
--with-target-bits=64 \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-import-modules=${WORK_DIR}/modular-sdk \
|
||||
--with-toolchain-version=${TOOLCHAIN_VERSION} \
|
||||
--with-boot-jdk=${BOOT_JDK} \
|
||||
--disable-ccache \
|
||||
--enable-cds=yes || exit 1
|
||||
fi
|
||||
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
make LOG=info images CONF=windows-x86_64-server-release test-image || exit 1
|
||||
else
|
||||
make LOG=info images CONF=windows-x86_64-server-release || exit 1
|
||||
fi
|
||||
|
||||
JSDK=build/windows-x86_64-server-release/images/jdk
|
||||
if [[ "$bundle_type" == "*jcef*" || -z "$bundle_type" ]]; then
|
||||
JBSDK=${JBRSDK_BASE_NAME}-windows-x64-b${build_number}
|
||||
fi
|
||||
BASE_DIR=build/windows-x86_64-server-release/images
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1
|
||||
if [[ "$bundle_type" == "*jcef*" ]]; then
|
||||
cp -R jcef_win_x64/* ${JBRSDK_BUNDLE}/bin
|
||||
fi
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBR_BUNDLE=jbr
|
||||
else
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
fi
|
||||
create_jbr ${bundle_type}
|
||||
|
||||
#JBR_BUNDLE=jbr_${bundle_type}_lw
|
||||
#create_jbr ${bundle_type}_lw
|
||||
57
jb/project/tools/windows/scripts/mkimages_x86.sh
Executable file
57
jb/project/tools/windows/scripts/mkimages_x86.sh
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
|
||||
WORK_DIR=$(pwd)
|
||||
|
||||
PATH="/usr/local/bin:/usr/bin:${PATH}"
|
||||
./configure \
|
||||
--disable-warnings-as-errors \
|
||||
--disable-debug-symbols \
|
||||
--with-target-bits=32 \
|
||||
--with-version-pre= \
|
||||
--with-version-build=${JDK_BUILD_NUMBER} \
|
||||
--with-version-opt=b${build_number} \
|
||||
--with-toolchain-version=2015 \
|
||||
--with-boot-jdk=${BOOT_JDK} \
|
||||
--disable-ccache \
|
||||
--enable-cds=yes || exit 1
|
||||
make clean CONF=windows-x86-normal-server-release || exit 1
|
||||
make LOG=info images CONF=windows-x86-normal-server-release test-image || exit 1
|
||||
|
||||
JBSDK=${JBRSDK_BASE_NAME}-windows-x86-b${build_number}
|
||||
BASE_DIR=build/windows-x86-normal-server-release/images
|
||||
JSDK=${BASE_DIR}/jdk
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
|
||||
rm -rf ${BASE_DIR}/${JBRSDK_BUNDLE} && rsync -a --exclude demo --exclude sample ${JSDK}/ ${JBRSDK_BUNDLE} || exit 1
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
rm -rf ${JBR_BUNDLE}
|
||||
grep -v javafx modules.list | grep -v "jdk.internal.vm\|jdk.aot\|jcef" > modules.list.x86
|
||||
${JSDK}/bin/jlink \
|
||||
--module-path ${JSDK}/jmods --no-man-pages --compress=2 \
|
||||
--add-modules $(xargs < modules.list.x86 | sed s/" "//g) --output ${JBR_BUNDLE} || exit $?
|
||||
|
||||
echo Modifying release info ...
|
||||
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${JBR_BUNDLE}/release
|
||||
79
jb/project/tools/windows/scripts/pack_x64.sh
Executable file
79
jb/project/tools/windows/scripts/pack_x64.sh
Executable file
@@ -0,0 +1,79 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
bundle_type=$4
|
||||
|
||||
function pack_jbr {
|
||||
|
||||
case "$1" in
|
||||
"${bundle_type}_lw")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}_lw-${JBSDK_VERSION}
|
||||
;;
|
||||
"jfx" | "jcef")
|
||||
JBR_BASE_NAME=jbr_${bundle_type}-${JBSDK_VERSION}
|
||||
;;
|
||||
"jfx_jcef" | "")
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
;;
|
||||
*)
|
||||
echo "***ERR*** bundle was not specified" && exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
JBR=$JBR_BASE_NAME-windows-x64-b$build_number
|
||||
echo Creating $JBR.tar.gz ...
|
||||
if [ ! -z "$bundle_type" ]; then
|
||||
rm -rf ${BASE_DIR}/jbr
|
||||
cp -R ${BASE_DIR}/${JBR_BUNDLE} ${BASE_DIR}/jbr
|
||||
fi
|
||||
|
||||
/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR jbr || exit 1
|
||||
#rm -rf ${BASE_DIR}/${JBR_BUNDLE}
|
||||
}
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
|
||||
IMAGES_DIR=build/windows-x86_64-server-release/images
|
||||
JSDK=$IMAGES_DIR/jdk
|
||||
JBSDK=$JBRSDK_BASE_NAME-windows-x64-b$build_number
|
||||
BASE_DIR=.
|
||||
|
||||
if [ -z "$bundle_type" ]; then
|
||||
JBR_BUNDLE=jbr
|
||||
else
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
fi
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1
|
||||
fi
|
||||
|
||||
JBR_BUNDLE=jbr_${bundle_type}
|
||||
pack_jbr $bundle_type
|
||||
|
||||
if [[ "$bundle_type" == "jfx_jcef" || -z "$bundle_type" ]]; then
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x64-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1
|
||||
fi
|
||||
45
jb/project/tools/windows/scripts/pack_x86.sh
Executable file
45
jb/project/tools/windows/scripts/pack_x86.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# The following parameters must be specified:
|
||||
# JBSDK_VERSION - specifies the current version of OpenJDK e.g. 11_0_6
|
||||
# JDK_BUILD_NUMBER - specifies the number of OpenJDK build or the value of --with-version-build argument to configure
|
||||
# build_number - specifies the number of JetBrainsRuntime build
|
||||
# bundle_type - specifies bundle to bu built; possible values:
|
||||
# jcef - the bundles 1) jbr with jcef+javafx, 2) jbrsdk and 3) test will be created
|
||||
# jfx - the bundle 1) jbr with javafx only will be created
|
||||
#
|
||||
# jbrsdk-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
# jbr-${JBSDK_VERSION}-osx-x64-b${build_number}.tar.gz
|
||||
#
|
||||
# $ ./java --version
|
||||
# openjdk 11.0.6 2020-01-14
|
||||
# OpenJDK Runtime Environment (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number})
|
||||
# OpenJDK 64-Bit Server VM (build 11.0.6+${JDK_BUILD_NUMBER}-b${build_number}, mixed mode)
|
||||
#
|
||||
|
||||
JBSDK_VERSION=$1
|
||||
JDK_BUILD_NUMBER=$2
|
||||
build_number=$3
|
||||
|
||||
JBRSDK_BASE_NAME=jbrsdk-$JBSDK_VERSION
|
||||
JBR_BASE_NAME=jbr-$JBSDK_VERSION
|
||||
|
||||
IMAGES_DIR=build/windows-x86-normal-server-release/images
|
||||
JSDK=$IMAGES_DIR/jdk
|
||||
JBSDK=$JBRSDK_BASE_NAME-windows-x86-b$build_number
|
||||
BASE_DIR=.
|
||||
|
||||
JBRSDK_BUNDLE=jbrsdk
|
||||
echo Creating $JBSDK.tar.gz ...
|
||||
/usr/bin/tar -czf $JBSDK.tar.gz $JBRSDK_BUNDLE || exit 1
|
||||
|
||||
JBR_BUNDLE=jbr
|
||||
JBR_BASE_NAME=jbr-${JBSDK_VERSION}
|
||||
|
||||
JBR=$JBR_BASE_NAME-windows-x86-b$build_number
|
||||
echo Creating $JBR.tar.gz ...
|
||||
/usr/bin/tar -czf $JBR.tar.gz -C $BASE_DIR ${JBR_BUNDLE} || exit 1
|
||||
|
||||
JBRSDK_TEST=$JBRSDK_BASE_NAME-windows-test-x86-b$build_number
|
||||
echo Creating $JBRSDK_TEST.tar.gz ...
|
||||
/usr/bin/tar -czf $JBRSDK_TEST.tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || exit 1
|
||||
@@ -576,6 +576,8 @@ CXXFILT:=@CXXFILT@
|
||||
|
||||
LIPO:=@LIPO@
|
||||
INSTALL_NAME_TOOL:=@INSTALL_NAME_TOOL@
|
||||
METAL := @METAL@
|
||||
METALLIB := @METALLIB@
|
||||
|
||||
# Options to linker to specify a mapfile.
|
||||
# (Note absence of := assignment, because we do not want to evaluate the macro body here)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -723,6 +723,32 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_EXTRA],
|
||||
UTIL_LOOKUP_PROGS(LIPO, lipo)
|
||||
UTIL_REQUIRE_PROGS(OTOOL, otool)
|
||||
UTIL_REQUIRE_PROGS(INSTALL_NAME_TOOL, install_name_tool)
|
||||
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS(METAL, metal)
|
||||
if test "x$METAL" = x; then
|
||||
AC_MSG_CHECKING([if metal can be run using xcrun])
|
||||
METAL="xcrun -sdk macosx metal"
|
||||
test_metal=`$METAL --version 2>&1`
|
||||
if test $? -ne 0; then
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([XCode tool 'metal' neither found in path nor with xcrun])
|
||||
else
|
||||
AC_MSG_RESULT([yes, will be using '$METAL'])
|
||||
fi
|
||||
fi
|
||||
|
||||
UTIL_LOOKUP_TOOLCHAIN_PROGS(METALLIB, metallib)
|
||||
if test "x$METALLIB" = x; then
|
||||
AC_MSG_CHECKING([if metallib can be run using xcrun])
|
||||
METALLIB="xcrun -sdk macosx metallib"
|
||||
test_metallib=`$METALLIB --version 2>&1`
|
||||
if test $? -ne 0; then
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([XCode tool 'metallib' neither found in path nor with xcrun])
|
||||
else
|
||||
AC_MSG_RESULT([yes, will be using '$METALLIB'])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -24,6 +24,7 @@
|
||||
#
|
||||
|
||||
include LibCommon.gmk
|
||||
include Execute.gmk
|
||||
|
||||
# Hook to include the corresponding custom file, if present.
|
||||
$(eval $(call IncludeCustomExtension, modules/java.desktop/Lib.gmk))
|
||||
|
||||
@@ -160,6 +160,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \
|
||||
LIBS_macosx := -lmlib_image \
|
||||
-framework Cocoa \
|
||||
-framework OpenGL \
|
||||
-framework Metal \
|
||||
-framework JavaRuntimeSupport \
|
||||
-framework ApplicationServices \
|
||||
-framework AudioToolbox, \
|
||||
@@ -766,7 +767,8 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false)
|
||||
-framework ApplicationServices \
|
||||
-framework Foundation \
|
||||
-framework Security \
|
||||
-framework Cocoa
|
||||
-framework Cocoa \
|
||||
-framework Metal
|
||||
else ifeq ($(call isTargetOs, windows), true)
|
||||
LIBSPLASHSCREEN_LIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib $(WIN_JAVA_LIB) jvm.lib
|
||||
else
|
||||
@@ -827,6 +829,7 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
libawt_lwawt/awt \
|
||||
libawt_lwawt/font \
|
||||
libawt_lwawt/java2d/opengl \
|
||||
libawt_lwawt/java2d/metal \
|
||||
include \
|
||||
common/awt/debug \
|
||||
common/java2d/opengl \
|
||||
@@ -862,6 +865,7 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
-framework AudioToolbox \
|
||||
-framework Carbon \
|
||||
-framework Cocoa \
|
||||
-framework Metal \
|
||||
-framework Security \
|
||||
-framework ExceptionHandling \
|
||||
-framework JavaRuntimeSupport \
|
||||
@@ -884,6 +888,28 @@ endif
|
||||
################################################################################
|
||||
|
||||
ifeq ($(call isTargetOs, macosx), true)
|
||||
SHADERS_SRC := $(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders.metal
|
||||
SHADERS_SUPPORT_DIR := $(SUPPORT_OUTPUTDIR)/native/java.desktop/libosxui
|
||||
SHADERS_AIR := $(SHADERS_SUPPORT_DIR)/shaders.air
|
||||
SHADERS_LIB := $(INSTALL_LIBRARIES_HERE)/shaders.metallib
|
||||
|
||||
$(eval $(call SetupExecute, metal_shaders, \
|
||||
INFO := Running metal on $(notdir $(SHADERS_SRC)) (for libosxui.dylib), \
|
||||
DEPS := $(SHADERS_SRC), \
|
||||
OUTPUT_FILE := $(SHADERS_AIR), \
|
||||
SUPPORT_DIR := $(SHADERS_SUPPORT_DIR), \
|
||||
COMMAND := $(METAL) -c -std=osx-metal2.0 -o $(SHADERS_AIR) $(SHADERS_SRC), \
|
||||
))
|
||||
|
||||
$(eval $(call SetupExecute, metallib_shaders, \
|
||||
INFO := Running metallib on $(notdir $(SHADERS_AIR)) (for libosxui.dylib), \
|
||||
DEPS := $(SHADERS_AIR), \
|
||||
OUTPUT_FILE := $(SHADERS_LIB), \
|
||||
SUPPORT_DIR := $(SHADERS_SUPPORT_DIR), \
|
||||
COMMAND := $(METALLIB) -o $(SHADERS_LIB) $(SHADERS_AIR), \
|
||||
))
|
||||
|
||||
TARGETS += $(SHADERS_LIB)
|
||||
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBOSXUI, \
|
||||
NAME := osxui, \
|
||||
@@ -899,6 +925,7 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
-L$(INSTALL_LIBRARIES_HERE), \
|
||||
LIBS := -lawt -losxapp -lawt_lwawt \
|
||||
-framework Cocoa \
|
||||
-framework Metal \
|
||||
-framework Carbon \
|
||||
-framework ApplicationServices \
|
||||
-framework JavaRuntimeSupport \
|
||||
@@ -906,6 +933,7 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_LIBOSXUI)
|
||||
$(BUILD_LIBOSXUI): $(SHADERS_LIB)
|
||||
|
||||
$(BUILD_LIBOSXUI): $(BUILD_LIBAWT)
|
||||
|
||||
|
||||
53
modules.list
Normal file
53
modules.list
Normal file
@@ -0,0 +1,53 @@
|
||||
java.base,
|
||||
java.compiler,
|
||||
java.datatransfer,
|
||||
java.desktop,
|
||||
java.instrument,
|
||||
java.logging,
|
||||
java.management,
|
||||
java.management.rmi,
|
||||
java.naming,
|
||||
java.net.http,
|
||||
java.prefs,
|
||||
java.rmi,
|
||||
java.scripting,
|
||||
java.se,
|
||||
java.security.jgss,
|
||||
java.security.sasl,
|
||||
java.smartcardio,
|
||||
java.sql,
|
||||
java.sql.rowset,
|
||||
java.transaction.xa,
|
||||
java.xml,
|
||||
java.xml.crypto,
|
||||
jdk.accessibility,
|
||||
jdk.aot,
|
||||
jdk.charsets,
|
||||
jdk.compiler,
|
||||
jdk.crypto.cryptoki,
|
||||
jdk.crypto.ec,
|
||||
jdk.dynalink,
|
||||
jdk.httpserver,
|
||||
jdk.internal.ed,
|
||||
jdk.internal.le,
|
||||
jdk.internal.vm.ci,
|
||||
jdk.internal.vm.compiler,
|
||||
jdk.internal.vm.compiler.management,
|
||||
jdk.jdi,
|
||||
jdk.jdwp.agent,
|
||||
jdk.jfr,
|
||||
jdk.jsobject,
|
||||
jdk.localedata,
|
||||
jdk.management,
|
||||
jdk.management.agent,
|
||||
jdk.management.jfr,
|
||||
jdk.naming.dns,
|
||||
jdk.naming.rmi,
|
||||
jdk.net,
|
||||
jdk.sctp,
|
||||
jdk.security.auth,
|
||||
jdk.security.jgss,
|
||||
jdk.unsupported,
|
||||
jdk.xml.dom,
|
||||
jdk.zipfs,
|
||||
jdk.hotspot.agent
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -32,8 +32,8 @@ import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.ColorModel;
|
||||
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.opengl.CGLLayer;
|
||||
import sun.lwawt.LWGraphicsConfig;
|
||||
import sun.lwawt.macosx.CFRetainedResource;
|
||||
|
||||
public abstract class CGraphicsConfig extends GraphicsConfiguration
|
||||
implements LWGraphicsConfig {
|
||||
@@ -80,7 +80,7 @@ public abstract class CGraphicsConfig extends GraphicsConfiguration
|
||||
* Creates a new SurfaceData that will be associated with the given
|
||||
* CGLLayer.
|
||||
*/
|
||||
public abstract SurfaceData createSurfaceData(CGLLayer layer);
|
||||
public abstract SurfaceData createSurfaceData(CFRetainedResource layer);
|
||||
|
||||
@Override
|
||||
public final boolean isTranslucencyCapable() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -37,6 +37,8 @@ import java.awt.peer.WindowPeer;
|
||||
import java.util.Objects;
|
||||
|
||||
import sun.java2d.SunGraphicsEnvironment;
|
||||
import sun.java2d.MacOSFlags;
|
||||
import sun.java2d.metal.MTLGraphicsConfig;
|
||||
import sun.java2d.opengl.CGLGraphicsConfig;
|
||||
|
||||
import static java.awt.peer.ComponentPeer.SET_BOUNDS;
|
||||
@@ -54,7 +56,10 @@ public final class CGraphicsDevice extends GraphicsDevice
|
||||
private volatile Rectangle bounds;
|
||||
private volatile int scale;
|
||||
|
||||
private final GraphicsConfiguration config;
|
||||
private GraphicsConfiguration config;
|
||||
private static boolean metalPipelineEnabled = false;
|
||||
private static boolean oglPipelineEnabled = false;
|
||||
|
||||
|
||||
private static AWTPermission fullScreenExclusivePermission;
|
||||
|
||||
@@ -63,7 +68,64 @@ public final class CGraphicsDevice extends GraphicsDevice
|
||||
|
||||
public CGraphicsDevice(final int displayID) {
|
||||
this.displayID = displayID;
|
||||
config = CGLGraphicsConfig.getConfig(this);
|
||||
|
||||
if (MacOSFlags.isMetalEnabled()) {
|
||||
// Try to create MTLGraphicsConfig, if it fails,
|
||||
// try to create CGLGraphicsConfig as a fallback
|
||||
this.config = MTLGraphicsConfig.getConfig(this, displayID);
|
||||
|
||||
if (this.config != null) {
|
||||
metalPipelineEnabled = true;
|
||||
} else {
|
||||
// Try falling back to OpenGL pipeline
|
||||
if (MacOSFlags.isMetalVerbose()) {
|
||||
System.out.println("Metal rendering pipeline" +
|
||||
" initialization failed,using OpenGL" +
|
||||
" rendering pipeline");
|
||||
}
|
||||
|
||||
this.config = CGLGraphicsConfig.getConfig(this);
|
||||
|
||||
if (this.config != null) {
|
||||
oglPipelineEnabled = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Try to create CGLGraphicsConfig, if it fails,
|
||||
// try to create MTLGraphicsConfig as a fallback
|
||||
this.config = CGLGraphicsConfig.getConfig(this);
|
||||
|
||||
if (this.config != null) {
|
||||
oglPipelineEnabled = true;
|
||||
} else {
|
||||
// Try falling back to Metal pipeline
|
||||
if (MacOSFlags.isOGLVerbose()) {
|
||||
System.out.println("OpenGL rendering pipeline" +
|
||||
" initialization failed,using Metal" +
|
||||
" rendering pipeline");
|
||||
}
|
||||
|
||||
this.config = MTLGraphicsConfig.getConfig(this, displayID);
|
||||
|
||||
if (this.config != null) {
|
||||
metalPipelineEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!metalPipelineEnabled && !oglPipelineEnabled) {
|
||||
// This indicates fallback to other rendering pipeline also failed.
|
||||
// Should never reach here
|
||||
throw new InternalError("Error - unable to initialize any" +
|
||||
" rendering pipeline.");
|
||||
}
|
||||
|
||||
if (metalPipelineEnabled && MacOSFlags.isMetalVerbose()) {
|
||||
System.out.println("Metal pipeline enabled on screen " + displayID);
|
||||
} else if (oglPipelineEnabled && MacOSFlags.isOGLVerbose()) {
|
||||
System.out.println("OpenGL pipeline enabled on screen " + displayID);
|
||||
}
|
||||
|
||||
// initializes default device state, might be redundant step since we
|
||||
// call "displayChanged()" later anyway, but we do not want to leave the
|
||||
// device in an inconsistent state after construction
|
||||
@@ -265,6 +327,10 @@ public final class CGraphicsDevice extends GraphicsDevice
|
||||
return nativeGetDisplayModes(displayID);
|
||||
}
|
||||
|
||||
public static boolean usingMetalPipeline() {
|
||||
return metalPipelineEnabled;
|
||||
}
|
||||
|
||||
private void initScaleFactor() {
|
||||
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
|
||||
double debugScale = SunGraphicsEnvironment.getDebugScale();
|
||||
|
||||
165
src/java.desktop/macosx/classes/sun/java2d/MacOSFlags.java
Normal file
165
src/java.desktop/macosx/classes/sun/java2d/MacOSFlags.java
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d;
|
||||
|
||||
import java.security.PrivilegedAction;
|
||||
import sun.java2d.metal.MTLGraphicsConfig;
|
||||
import sun.java2d.opengl.CGLGraphicsConfig;
|
||||
|
||||
|
||||
public class MacOSFlags {
|
||||
|
||||
/**
|
||||
* Description of command-line flags. All flags with [true|false]
|
||||
* values
|
||||
* metalEnabled: usage: "-Dsun.java2d.metal=[true|false]"
|
||||
*/
|
||||
|
||||
private static boolean oglEnabled;
|
||||
private static boolean oglVerbose;
|
||||
private static boolean metalEnabled;
|
||||
private static boolean metalVerbose;
|
||||
|
||||
private enum PropertyState {ENABLED, DISABLED, UNSPECIFIED};
|
||||
|
||||
static {
|
||||
initJavaFlags();
|
||||
}
|
||||
|
||||
private static PropertyState getBooleanProp(String p, PropertyState defaultVal) {
|
||||
String propString = System.getProperty(p);
|
||||
PropertyState returnVal = defaultVal;
|
||||
if (propString != null) {
|
||||
if (propString.equals("true") ||
|
||||
propString.equals("t") ||
|
||||
propString.equals("True") ||
|
||||
propString.equals("T") ||
|
||||
propString.equals("")) // having the prop name alone
|
||||
{ // is equivalent to true
|
||||
returnVal = PropertyState.ENABLED;
|
||||
} else if (propString.equals("false") ||
|
||||
propString.equals("f") ||
|
||||
propString.equals("False") ||
|
||||
propString.equals("F"))
|
||||
{
|
||||
returnVal = PropertyState.DISABLED;
|
||||
}
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
private static boolean isBooleanPropTrueVerbose(String p) {
|
||||
String propString = System.getProperty(p);
|
||||
if (propString != null) {
|
||||
if (propString.equals("True") ||
|
||||
propString.equals("T"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void initJavaFlags() {
|
||||
java.security.AccessController.doPrivileged(
|
||||
(PrivilegedAction<Object>) () -> {
|
||||
PropertyState oglState = getBooleanProp("sun.java2d.opengl", PropertyState.UNSPECIFIED);
|
||||
PropertyState metalState = getBooleanProp("sun.java2d.metal", PropertyState.UNSPECIFIED);
|
||||
|
||||
// Handle invalid combinations to use the default rendering pipeline
|
||||
// Current default rendering pipeline is OpenGL
|
||||
// (The default can be changed to Metal in future just by toggling two states in this if condition block)
|
||||
if ((oglState == PropertyState.UNSPECIFIED && metalState == PropertyState.UNSPECIFIED) ||
|
||||
(oglState == PropertyState.DISABLED && metalState == PropertyState.DISABLED) ||
|
||||
(oglState == PropertyState.ENABLED && metalState == PropertyState.ENABLED)) {
|
||||
oglState = PropertyState.ENABLED; // Enable default pipeline
|
||||
metalState = PropertyState.DISABLED; // Disable non-default pipeline
|
||||
}
|
||||
|
||||
if (metalState == PropertyState.UNSPECIFIED) {
|
||||
if (oglState == PropertyState.DISABLED) {
|
||||
oglEnabled = false;
|
||||
metalEnabled = true;
|
||||
} else {
|
||||
oglEnabled = true;
|
||||
metalEnabled = false;
|
||||
}
|
||||
} else if (metalState == PropertyState.ENABLED) {
|
||||
oglEnabled = false;
|
||||
metalEnabled = true;
|
||||
} else if (metalState == PropertyState.DISABLED) {
|
||||
oglEnabled = true;
|
||||
metalEnabled = false;
|
||||
}
|
||||
|
||||
oglVerbose = isBooleanPropTrueVerbose("sun.java2d.opengl");
|
||||
metalVerbose = isBooleanPropTrueVerbose("sun.java2d.metal");
|
||||
|
||||
if (oglEnabled && !metalEnabled) {
|
||||
// Check whether OGL is available
|
||||
if (!CGLGraphicsConfig.isCGLAvailable()) {
|
||||
if (oglVerbose) {
|
||||
System.out.println("Could not enable OpenGL pipeline (CGL not available)");
|
||||
}
|
||||
oglEnabled = false;
|
||||
metalEnabled = MTLGraphicsConfig.isMetalAvailable();
|
||||
}
|
||||
} else if (metalEnabled && !oglEnabled) {
|
||||
// Check whether Metal framework is available
|
||||
if (!MTLGraphicsConfig.isMetalAvailable()) {
|
||||
if (metalVerbose) {
|
||||
System.out.println("Could not enable Metal pipeline (Metal framework not available)");
|
||||
}
|
||||
metalEnabled = false;
|
||||
oglEnabled = CGLGraphicsConfig.isCGLAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
// At this point one of the rendering pipeline must be enabled.
|
||||
if (!metalEnabled && !oglEnabled) {
|
||||
throw new InternalError("Error - unable to initialize any rendering pipeline.");
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isMetalEnabled() {
|
||||
return metalEnabled;
|
||||
}
|
||||
|
||||
public static boolean isMetalVerbose() {
|
||||
return metalVerbose;
|
||||
}
|
||||
|
||||
public static boolean isOGLEnabled() {
|
||||
return oglEnabled;
|
||||
}
|
||||
|
||||
public static boolean isOGLVerbose() {
|
||||
return oglVerbose;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -27,6 +27,8 @@ package sun.java2d;
|
||||
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.VolatileSurfaceManager;
|
||||
import sun.awt.CGraphicsDevice;
|
||||
import sun.java2d.metal.MTLVolatileSurfaceManager;
|
||||
import sun.java2d.opengl.CGLVolatileSurfaceManager;
|
||||
|
||||
/**
|
||||
@@ -42,13 +44,14 @@ public class MacosxSurfaceManagerFactory extends SurfaceManagerFactory {
|
||||
* as a way for the caller to pass pipeline-specific context data to
|
||||
* the VolatileSurfaceManager (such as a backbuffer handle, for example).
|
||||
*
|
||||
* For Mac OS X, this method returns either an CGL-specific
|
||||
* For Mac OS X, this method returns either an CGL/MTL-specific
|
||||
* VolatileSurfaceManager based on the GraphicsConfiguration
|
||||
* under which the SunVolatileImage was created.
|
||||
*/
|
||||
public VolatileSurfaceManager createVolatileManager(SunVolatileImage vImg,
|
||||
Object context)
|
||||
{
|
||||
return new CGLVolatileSurfaceManager(vImg, context);
|
||||
return CGraphicsDevice.usingMetalPipeline() ? new MTLVolatileSurfaceManager(vImg, context) :
|
||||
new CGLVolatileSurfaceManager(vImg, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,905 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.Blit;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr;
|
||||
import sun.java2d.loops.ScaledBlit;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.loops.TransformBlit;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.lang.annotation.Native;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import static sun.java2d.pipe.BufferedOpCodes.BLIT;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.SURFACE_TO_SW_BLIT;
|
||||
|
||||
final class MTLBlitLoops {
|
||||
|
||||
static void register() {
|
||||
Blit blitIntArgbPreToSurface =
|
||||
new MTLSwToSurfaceBlit(SurfaceType.IntArgbPre,
|
||||
MTLSurfaceData.PF_INT_ARGB_PRE);
|
||||
Blit blitIntArgbPreToTexture =
|
||||
new MTLSwToTextureBlit(SurfaceType.IntArgbPre,
|
||||
MTLSurfaceData.PF_INT_ARGB_PRE);
|
||||
TransformBlit transformBlitIntArgbPreToSurface =
|
||||
new MTLSwToSurfaceTransform(SurfaceType.IntArgbPre,
|
||||
MTLSurfaceData.PF_INT_ARGB_PRE);
|
||||
MTLSurfaceToSwBlit blitSurfaceToIntArgbPre =
|
||||
new MTLSurfaceToSwBlit(SurfaceType.IntArgbPre,
|
||||
MTLSurfaceData.PF_INT_ARGB_PRE);
|
||||
|
||||
GraphicsPrimitive[] primitives = {
|
||||
// surface->surface ops
|
||||
new MTLSurfaceToSurfaceBlit(),
|
||||
new MTLSurfaceToSurfaceScale(),
|
||||
new MTLSurfaceToSurfaceTransform(),
|
||||
|
||||
// render-to-texture surface->surface ops
|
||||
new MTLRTTSurfaceToSurfaceBlit(),
|
||||
new MTLRTTSurfaceToSurfaceScale(),
|
||||
new MTLRTTSurfaceToSurfaceTransform(),
|
||||
|
||||
// surface->sw ops
|
||||
new MTLSurfaceToSwBlit(SurfaceType.IntArgb,
|
||||
MTLSurfaceData.PF_INT_ARGB),
|
||||
blitSurfaceToIntArgbPre,
|
||||
|
||||
// sw->surface ops
|
||||
blitIntArgbPreToSurface,
|
||||
new MTLSwToSurfaceBlit(SurfaceType.IntRgb,
|
||||
MTLSurfaceData.PF_INT_RGB),
|
||||
new MTLSwToSurfaceBlit(SurfaceType.IntRgbx,
|
||||
MTLSurfaceData.PF_INT_RGBX),
|
||||
new MTLSwToSurfaceBlit(SurfaceType.IntBgr,
|
||||
MTLSurfaceData.PF_INT_BGR),
|
||||
new MTLSwToSurfaceBlit(SurfaceType.IntBgrx,
|
||||
MTLSurfaceData.PF_INT_BGRX),
|
||||
new MTLGeneralBlit(MTLSurfaceData.MTLSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
blitIntArgbPreToSurface),
|
||||
|
||||
new MTLAnyCompositeBlit(MTLSurfaceData.MTLSurface,
|
||||
blitSurfaceToIntArgbPre,
|
||||
blitSurfaceToIntArgbPre,
|
||||
blitIntArgbPreToSurface),
|
||||
new MTLAnyCompositeBlit(SurfaceType.Any,
|
||||
null,
|
||||
blitSurfaceToIntArgbPre,
|
||||
blitIntArgbPreToSurface),
|
||||
|
||||
new MTLSwToSurfaceScale(SurfaceType.IntRgb,
|
||||
MTLSurfaceData.PF_INT_RGB),
|
||||
new MTLSwToSurfaceScale(SurfaceType.IntRgbx,
|
||||
MTLSurfaceData.PF_INT_RGBX),
|
||||
new MTLSwToSurfaceScale(SurfaceType.IntBgr,
|
||||
MTLSurfaceData.PF_INT_BGR),
|
||||
new MTLSwToSurfaceScale(SurfaceType.IntBgrx,
|
||||
MTLSurfaceData.PF_INT_BGRX),
|
||||
new MTLSwToSurfaceScale(SurfaceType.IntArgbPre,
|
||||
MTLSurfaceData.PF_INT_ARGB_PRE),
|
||||
|
||||
new MTLSwToSurfaceTransform(SurfaceType.IntRgb,
|
||||
MTLSurfaceData.PF_INT_RGB),
|
||||
new MTLSwToSurfaceTransform(SurfaceType.IntRgbx,
|
||||
MTLSurfaceData.PF_INT_RGBX),
|
||||
new MTLSwToSurfaceTransform(SurfaceType.IntBgr,
|
||||
MTLSurfaceData.PF_INT_BGR),
|
||||
new MTLSwToSurfaceTransform(SurfaceType.IntBgrx,
|
||||
MTLSurfaceData.PF_INT_BGRX),
|
||||
transformBlitIntArgbPreToSurface,
|
||||
|
||||
new MTLGeneralTransformedBlit(transformBlitIntArgbPreToSurface),
|
||||
|
||||
// texture->surface ops
|
||||
new MTLTextureToSurfaceBlit(),
|
||||
new MTLTextureToSurfaceScale(),
|
||||
new MTLTextureToSurfaceTransform(),
|
||||
|
||||
// sw->texture ops
|
||||
blitIntArgbPreToTexture,
|
||||
new MTLSwToTextureBlit(SurfaceType.IntRgb,
|
||||
MTLSurfaceData.PF_INT_RGB),
|
||||
new MTLSwToTextureBlit(SurfaceType.IntRgbx,
|
||||
MTLSurfaceData.PF_INT_RGBX),
|
||||
new MTLSwToTextureBlit(SurfaceType.IntBgr,
|
||||
MTLSurfaceData.PF_INT_BGR),
|
||||
new MTLSwToTextureBlit(SurfaceType.IntBgrx,
|
||||
MTLSurfaceData.PF_INT_BGRX),
|
||||
new MTLGeneralBlit(MTLSurfaceData.MTLTexture,
|
||||
CompositeType.SrcNoEa,
|
||||
blitIntArgbPreToTexture),
|
||||
};
|
||||
GraphicsPrimitiveMgr.register(primitives);
|
||||
}
|
||||
|
||||
/**
|
||||
* The following offsets are used to pack the parameters in
|
||||
* createPackedParams(). (They are also used at the native level when
|
||||
* unpacking the params.)
|
||||
*/
|
||||
@Native private static final int OFFSET_SRCTYPE = 16;
|
||||
@Native private static final int OFFSET_HINT = 8;
|
||||
@Native private static final int OFFSET_TEXTURE = 3;
|
||||
@Native private static final int OFFSET_RTT = 2;
|
||||
@Native private static final int OFFSET_XFORM = 1;
|
||||
@Native private static final int OFFSET_ISOBLIT = 0;
|
||||
|
||||
/**
|
||||
* Packs the given parameters into a single int value in order to save
|
||||
* space on the rendering queue.
|
||||
*/
|
||||
private static int createPackedParams(boolean isoblit, boolean texture,
|
||||
boolean rtt, boolean xform,
|
||||
int hint, int srctype)
|
||||
{
|
||||
return
|
||||
((srctype << OFFSET_SRCTYPE) |
|
||||
(hint << OFFSET_HINT ) |
|
||||
((texture ? 1 : 0) << OFFSET_TEXTURE) |
|
||||
((rtt ? 1 : 0) << OFFSET_RTT ) |
|
||||
((xform ? 1 : 0) << OFFSET_XFORM ) |
|
||||
((isoblit ? 1 : 0) << OFFSET_ISOBLIT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues a BLIT operation with the given parameters. Note that the
|
||||
* RenderQueue lock must be held before calling this method.
|
||||
*/
|
||||
private static void enqueueBlit(RenderQueue rq,
|
||||
SurfaceData src, SurfaceData dst,
|
||||
int packedParams,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(72, 24);
|
||||
buf.putInt(BLIT);
|
||||
buf.putInt(packedParams);
|
||||
buf.putInt(sx1).putInt(sy1);
|
||||
buf.putInt(sx2).putInt(sy2);
|
||||
buf.putDouble(dx1).putDouble(dy1);
|
||||
buf.putDouble(dx2).putDouble(dy2);
|
||||
buf.putLong(src.getNativeOps());
|
||||
buf.putLong(dst.getNativeOps());
|
||||
}
|
||||
|
||||
static void Blit(SurfaceData srcData, SurfaceData dstData,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform xform, int hint,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
int srctype, boolean texture)
|
||||
{
|
||||
int ctxflags = 0;
|
||||
if (srcData.getTransparency() == Transparency.OPAQUE) {
|
||||
ctxflags |= MTLContext.SRC_IS_OPAQUE;
|
||||
}
|
||||
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// make sure the RenderQueue keeps a hard reference to the
|
||||
// source (sysmem) SurfaceData to prevent it from being
|
||||
// disposed while the operation is processed on the QFT
|
||||
rq.addReference(srcData);
|
||||
|
||||
MTLSurfaceData mtlDst = (MTLSurfaceData)dstData;
|
||||
if (texture) {
|
||||
// make sure we have a current context before uploading
|
||||
// the sysmem data to the texture object
|
||||
MTLGraphicsConfig gc = mtlDst.getMTLGraphicsConfig();
|
||||
MTLContext.setScratchSurface(gc);
|
||||
} else {
|
||||
MTLContext.validateContext(mtlDst, mtlDst,
|
||||
clip, comp, xform, null, null,
|
||||
ctxflags);
|
||||
}
|
||||
|
||||
int packedParams = createPackedParams(false, texture,
|
||||
false /*unused*/, xform != null,
|
||||
hint, srctype);
|
||||
enqueueBlit(rq, srcData, dstData,
|
||||
packedParams,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2);
|
||||
|
||||
// always flush immediately, since we (currently) have no means
|
||||
// of tracking changes to the system memory surface
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: The srcImg and biop parameters are only used when invoked
|
||||
* from the MTLBufImgOps.renderImageWithOp() method; in all other cases,
|
||||
* this method can be called with null values for those two parameters,
|
||||
* and they will be effectively ignored.
|
||||
*/
|
||||
static void IsoBlit(SurfaceData srcData, SurfaceData dstData,
|
||||
BufferedImage srcImg, BufferedImageOp biop,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform xform, int hint,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
boolean texture)
|
||||
{
|
||||
int ctxflags = 0;
|
||||
if (srcData.getTransparency() == Transparency.OPAQUE) {
|
||||
ctxflags |= MTLContext.SRC_IS_OPAQUE;
|
||||
}
|
||||
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
MTLSurfaceData mtlSrc = (MTLSurfaceData)srcData;
|
||||
MTLSurfaceData mtlDst = (MTLSurfaceData)dstData;
|
||||
int srctype = mtlSrc.getType();
|
||||
boolean rtt;
|
||||
MTLSurfaceData srcCtxData;
|
||||
if (srctype == MTLSurfaceData.TEXTURE) {
|
||||
// the source is a regular texture object; we substitute
|
||||
// the destination surface for the purposes of making a
|
||||
// context current
|
||||
rtt = false;
|
||||
srcCtxData = mtlDst;
|
||||
} else {
|
||||
// the source is a pbuffer, backbuffer, or render-to-texture
|
||||
// surface; we set rtt to true to differentiate this kind
|
||||
// of surface from a regular texture object
|
||||
rtt = true;
|
||||
if (srctype == AccelSurface.RT_TEXTURE) {
|
||||
srcCtxData = mtlDst;
|
||||
} else {
|
||||
srcCtxData = mtlSrc;
|
||||
}
|
||||
}
|
||||
|
||||
MTLContext.validateContext(srcCtxData, mtlDst,
|
||||
clip, comp, xform, null, null,
|
||||
ctxflags);
|
||||
|
||||
if (biop != null) {
|
||||
MTLBufImgOps.enableBufImgOp(rq, mtlSrc, srcImg, biop);
|
||||
}
|
||||
|
||||
int packedParams = createPackedParams(true, texture,
|
||||
false /*unused*/, xform != null,
|
||||
hint, 0 /*unused*/);
|
||||
enqueueBlit(rq, srcData, dstData,
|
||||
packedParams,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2);
|
||||
|
||||
if (biop != null) {
|
||||
MTLBufImgOps.disableBufImgOp(rq, biop);
|
||||
}
|
||||
|
||||
if (rtt && mtlDst.isOnScreen()) {
|
||||
// we only have to flush immediately when copying from a
|
||||
// (non-texture) surface to the screen; otherwise Swing apps
|
||||
// might appear unresponsive until the auto-flush completes
|
||||
rq.flushNow();
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MTLSurfaceToSurfaceBlit extends Blit {
|
||||
|
||||
MTLSurfaceToSurfaceBlit() {
|
||||
super(MTLSurfaceData.MTLSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
MTLBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLSurfaceToSurfaceScale extends ScaledBlit {
|
||||
|
||||
MTLSurfaceToSurfaceScale() {
|
||||
super(MTLSurfaceData.MTLSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
MTLBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLSurfaceToSurfaceTransform extends TransformBlit {
|
||||
|
||||
MTLSurfaceToSurfaceTransform() {
|
||||
super(MTLSurfaceData.MTLSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
MTLBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLRTTSurfaceToSurfaceBlit extends Blit {
|
||||
|
||||
MTLRTTSurfaceToSurfaceBlit() {
|
||||
super(MTLSurfaceData.MTLSurfaceRTT,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
MTLBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLRTTSurfaceToSurfaceScale extends ScaledBlit {
|
||||
|
||||
MTLRTTSurfaceToSurfaceScale() {
|
||||
super(MTLSurfaceData.MTLSurfaceRTT,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
MTLBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLRTTSurfaceToSurfaceTransform extends TransformBlit {
|
||||
|
||||
MTLRTTSurfaceToSurfaceTransform() {
|
||||
super(MTLSurfaceData.MTLSurfaceRTT,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
MTLBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
final class MTLSurfaceToSwBlit extends Blit {
|
||||
|
||||
private final int typeval;
|
||||
private WeakReference<SurfaceData> srcTmp;
|
||||
|
||||
// destination will actually be ArgbPre or Argb
|
||||
MTLSurfaceToSwBlit(final SurfaceType dstType, final int typeval) {
|
||||
super(MTLSurfaceData.MTLSurface,
|
||||
CompositeType.SrcNoEa,
|
||||
dstType);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h) {
|
||||
SurfaceData cachedSrc = null;
|
||||
if (srcTmp != null) {
|
||||
// use cached intermediate surface, if available
|
||||
cachedSrc = srcTmp.get();
|
||||
}
|
||||
|
||||
// We can convert argb_pre data from MTL surface in two places:
|
||||
// - During MTL surface -> SW blit
|
||||
// - During SW -> SW blit
|
||||
// The first one is faster when we use opaque MTL surface, because in
|
||||
// this case we simply skip conversion and use color components as is.
|
||||
// Because of this we align intermediate buffer type with type of
|
||||
// destination not source.
|
||||
final int type = typeval == MTLSurfaceData.PF_INT_ARGB_PRE ?
|
||||
BufferedImage.TYPE_INT_ARGB_PRE :
|
||||
BufferedImage.TYPE_INT_ARGB;
|
||||
|
||||
src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type);
|
||||
|
||||
// copy intermediate SW to destination SW using complex clip
|
||||
final Blit performop = Blit.getFromCache(src.getSurfaceType(),
|
||||
CompositeType.SrcNoEa,
|
||||
dst.getSurfaceType());
|
||||
performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h);
|
||||
|
||||
if (src != cachedSrc) {
|
||||
// cache the intermediate surface
|
||||
srcTmp = new WeakReference<>(src);
|
||||
}
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
if (clip != null) {
|
||||
clip = clip.getIntersectionXYWH(dx, dy, w, h);
|
||||
// At the end this method will flush the RenderQueue, we should exit
|
||||
// from it as soon as possible.
|
||||
if (clip.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
sx += clip.getLoX() - dx;
|
||||
sy += clip.getLoY() - dy;
|
||||
dx = clip.getLoX();
|
||||
dy = clip.getLoY();
|
||||
w = clip.getWidth();
|
||||
h = clip.getHeight();
|
||||
|
||||
if (!clip.isRectangular()) {
|
||||
complexClipBlit(src, dst, comp, clip, sx, sy, dx, dy, w, h);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// make sure the RenderQueue keeps a hard reference to the
|
||||
// destination (sysmem) SurfaceData to prevent it from being
|
||||
// disposed while the operation is processed on the QFT
|
||||
rq.addReference(dst);
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
MTLContext.validateContext((MTLSurfaceData)src);
|
||||
|
||||
rq.ensureCapacityAndAlignment(48, 32);
|
||||
buf.putInt(SURFACE_TO_SW_BLIT);
|
||||
buf.putInt(sx).putInt(sy);
|
||||
buf.putInt(dx).putInt(dy);
|
||||
buf.putInt(w).putInt(h);
|
||||
buf.putInt(typeval);
|
||||
buf.putLong(src.getNativeOps());
|
||||
buf.putLong(dst.getNativeOps());
|
||||
|
||||
// always flush immediately
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MTLSwToSurfaceBlit extends Blit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
MTLSwToSurfaceBlit(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
MTLBlitLoops.Blit(src, dst,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
typeval, false);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLSwToSurfaceScale extends ScaledBlit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
MTLSwToSurfaceScale(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
MTLBlitLoops.Blit(src, dst,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
typeval, false);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLSwToSurfaceTransform extends TransformBlit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
MTLSwToSurfaceTransform(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
MTLBlitLoops.Blit(src, dst,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
typeval, false);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLSwToTextureBlit extends Blit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
MTLSwToTextureBlit(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.SrcNoEa,
|
||||
MTLSurfaceData.MTLTexture);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
MTLBlitLoops.Blit(src, dst,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
typeval, true);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLTextureToSurfaceBlit extends Blit {
|
||||
|
||||
MTLTextureToSurfaceBlit() {
|
||||
super(MTLSurfaceData.MTLTexture,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
MTLBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLTextureToSurfaceScale extends ScaledBlit {
|
||||
|
||||
MTLTextureToSurfaceScale() {
|
||||
super(MTLSurfaceData.MTLTexture,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
MTLBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class MTLTextureToSurfaceTransform extends TransformBlit {
|
||||
|
||||
MTLTextureToSurfaceTransform() {
|
||||
super(MTLSurfaceData.MTLTexture,
|
||||
CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
MTLBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This general Blit implementation converts any source surface to an
|
||||
* intermediate IntArgbPre surface, and then uses the more specific
|
||||
* IntArgbPre->MTLSurface/Texture loop to get the intermediate
|
||||
* (premultiplied) surface down to Metal using simple blit.
|
||||
*/
|
||||
class MTLGeneralBlit extends Blit {
|
||||
|
||||
private final Blit performop;
|
||||
private WeakReference<SurfaceData> srcTmp;
|
||||
|
||||
MTLGeneralBlit(SurfaceType dstType,
|
||||
CompositeType compType,
|
||||
Blit performop)
|
||||
{
|
||||
super(SurfaceType.Any, compType, dstType);
|
||||
this.performop = performop;
|
||||
}
|
||||
|
||||
public synchronized void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgbPre);
|
||||
|
||||
SurfaceData cachedSrc = null;
|
||||
if (srcTmp != null) {
|
||||
// use cached intermediate surface, if available
|
||||
cachedSrc = srcTmp.get();
|
||||
}
|
||||
|
||||
// convert source to IntArgbPre
|
||||
src = convertFrom(convertsrc, src, sx, sy, w, h,
|
||||
cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
|
||||
// copy IntArgbPre intermediate surface to Metal surface
|
||||
performop.Blit(src, dst, comp, clip,
|
||||
0, 0, dx, dy, w, h);
|
||||
|
||||
if (src != cachedSrc) {
|
||||
// cache the intermediate surface
|
||||
srcTmp = new WeakReference<>(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This general TransformedBlit implementation converts any source surface to an
|
||||
* intermediate IntArgbPre surface, and then uses the more specific
|
||||
* IntArgbPre->MTLSurface/Texture loop to get the intermediate
|
||||
* (premultiplied) surface down to Metal using simple transformBlit.
|
||||
*/
|
||||
final class MTLGeneralTransformedBlit extends TransformBlit {
|
||||
|
||||
private final TransformBlit performop;
|
||||
private WeakReference<SurfaceData> srcTmp;
|
||||
|
||||
MTLGeneralTransformedBlit(final TransformBlit performop) {
|
||||
super(SurfaceType.Any, CompositeType.AnyAlpha,
|
||||
MTLSurfaceData.MTLSurface);
|
||||
this.performop = performop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint, int srcx,
|
||||
int srcy, int dstx, int dsty, int width,
|
||||
int height){
|
||||
Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgbPre);
|
||||
// use cached intermediate surface, if available
|
||||
final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null;
|
||||
// convert source to IntArgbPre
|
||||
src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc,
|
||||
BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
|
||||
// transform IntArgbPre intermediate surface to Metal surface
|
||||
performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty,
|
||||
width, height);
|
||||
|
||||
if (src != cachedSrc) {
|
||||
// cache the intermediate surface
|
||||
srcTmp = new WeakReference<>(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This general MTLAnyCompositeBlit implementation can convert any source/target
|
||||
* surface to an intermediate surface using convertsrc/convertdst loops, applies
|
||||
* necessary composite operation, and then uses convertresult loop to get the
|
||||
* intermediate surface down to Metal.
|
||||
*/
|
||||
final class MTLAnyCompositeBlit extends Blit {
|
||||
|
||||
private WeakReference<SurfaceData> dstTmp;
|
||||
private WeakReference<SurfaceData> srcTmp;
|
||||
private final Blit convertsrc;
|
||||
private final Blit convertdst;
|
||||
private final Blit convertresult;
|
||||
|
||||
MTLAnyCompositeBlit(SurfaceType srctype, Blit convertsrc, Blit convertdst,
|
||||
Blit convertresult) {
|
||||
super(srctype, CompositeType.Any, MTLSurfaceData.MTLSurface);
|
||||
this.convertsrc = convertsrc;
|
||||
this.convertdst = convertdst;
|
||||
this.convertresult = convertresult;
|
||||
}
|
||||
|
||||
public synchronized void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
if (convertsrc != null) {
|
||||
SurfaceData cachedSrc = null;
|
||||
if (srcTmp != null) {
|
||||
// use cached intermediate surface, if available
|
||||
cachedSrc = srcTmp.get();
|
||||
}
|
||||
// convert source to IntArgbPre
|
||||
src = convertFrom(convertsrc, src, sx, sy, w, h, cachedSrc,
|
||||
BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
if (src != cachedSrc) {
|
||||
// cache the intermediate surface
|
||||
srcTmp = new WeakReference<>(src);
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceData cachedDst = null;
|
||||
|
||||
if (dstTmp != null) {
|
||||
// use cached intermediate surface, if available
|
||||
cachedDst = dstTmp.get();
|
||||
}
|
||||
|
||||
// convert destination to IntArgbPre
|
||||
SurfaceData dstBuffer = convertFrom(convertdst, dst, dx, dy, w, h,
|
||||
cachedDst, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
Region bufferClip =
|
||||
clip == null ? null : clip.getTranslatedRegion(-dx, -dy);
|
||||
|
||||
Blit performop = Blit.getFromCache(src.getSurfaceType(),
|
||||
CompositeType.Any, dstBuffer.getSurfaceType());
|
||||
performop.Blit(src, dstBuffer, comp, bufferClip, sx, sy, 0, 0, w, h);
|
||||
|
||||
if (dstBuffer != cachedDst) {
|
||||
// cache the intermediate surface
|
||||
dstTmp = new WeakReference<>(dstBuffer);
|
||||
}
|
||||
// now blit the buffer back to the destination
|
||||
convertresult.Blit(dstBuffer, dst, AlphaComposite.Src, clip, 0, 0, dx,
|
||||
dy, w, h);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.pipe.BufferedBufImgOps;
|
||||
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ConvolveOp;
|
||||
import java.awt.image.LookupOp;
|
||||
import java.awt.image.RescaleOp;
|
||||
|
||||
import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_BIOP_SHADER;
|
||||
|
||||
class MTLBufImgOps extends BufferedBufImgOps {
|
||||
|
||||
/**
|
||||
* This method is called from MTLDrawImage.transformImage() only. It
|
||||
* validates the provided BufferedImageOp to determine whether the op
|
||||
* is one that can be accelerated by the MTL pipeline. If the operation
|
||||
* cannot be completed for any reason, this method returns false;
|
||||
* otherwise, the given BufferedImage is rendered to the destination
|
||||
* using the provided BufferedImageOp and this method returns true.
|
||||
*/
|
||||
static boolean renderImageWithOp(SunGraphics2D sg, BufferedImage img,
|
||||
BufferedImageOp biop, int x, int y)
|
||||
{
|
||||
// Validate the provided BufferedImage (make sure it is one that
|
||||
// is supported, and that its properties are acceleratable)
|
||||
if (biop instanceof ConvolveOp) {
|
||||
if (!isConvolveOpValid((ConvolveOp)biop)) {
|
||||
return false;
|
||||
}
|
||||
} else if (biop instanceof RescaleOp) {
|
||||
if (!isRescaleOpValid((RescaleOp)biop, img)) {
|
||||
return false;
|
||||
}
|
||||
} else if (biop instanceof LookupOp) {
|
||||
if (!isLookupOpValid((LookupOp)biop, img)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// No acceleration for other BufferedImageOps (yet)
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceData dstData = sg.surfaceData;
|
||||
if (!(dstData instanceof MTLSurfaceData) ||
|
||||
(sg.interpolationType == AffineTransformOp.TYPE_BICUBIC) ||
|
||||
(sg.compositeState > SunGraphics2D.COMP_ALPHA))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof MTLSurfaceData)) {
|
||||
// REMIND: this hack tries to ensure that we have a cached texture
|
||||
srcData =
|
||||
dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof MTLSurfaceData)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the source surface is actually a texture and
|
||||
// that the operation is supported
|
||||
MTLSurfaceData mtlSrc = (MTLSurfaceData)srcData;
|
||||
MTLGraphicsConfig gc = mtlSrc.getMTLGraphicsConfig();
|
||||
if (mtlSrc.getType() != MTLSurfaceData.TEXTURE ||
|
||||
!gc.isCapPresent(CAPS_EXT_BIOP_SHADER))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int sw = img.getWidth();
|
||||
int sh = img.getHeight();
|
||||
MTLBlitLoops.IsoBlit(srcData, dstData,
|
||||
img, biop,
|
||||
sg.composite, sg.getCompClip(),
|
||||
sg.transform, sg.interpolationType,
|
||||
0, 0, sw, sh,
|
||||
x, y, x+sw, y+sh,
|
||||
true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
154
src/java.desktop/macosx/classes/sun/java2d/metal/MTLContext.java
Normal file
154
src/java.desktop/macosx/classes/sun/java2d/metal/MTLContext.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.java2d.pipe.BufferedContext;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
|
||||
import static sun.java2d.pipe.BufferedOpCodes.INVALIDATE_CONTEXT;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.SET_SCRATCH_SURFACE;
|
||||
|
||||
/**
|
||||
* Note that the RenderQueue lock must be acquired before calling any of
|
||||
* the methods in this class.
|
||||
*/
|
||||
final class MTLContext extends BufferedContext {
|
||||
|
||||
public MTLContext(RenderQueue rq) {
|
||||
super(rq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that delegates to setScratchSurface() below.
|
||||
*/
|
||||
static void setScratchSurface(MTLGraphicsConfig gc) {
|
||||
setScratchSurface(gc.getNativeConfigInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the given GraphicsConfig's context current to its associated
|
||||
* "scratch surface". Each GraphicsConfig maintains a native context
|
||||
* (MTLDevice) as well as a native MTLTexture
|
||||
* known as the "scratch surface". By making the context current to the
|
||||
* scratch surface, we are assured that we have a current context for
|
||||
* the relevant GraphicsConfig, and can therefore perform operations
|
||||
* depending on the capabilities of that GraphicsConfig.
|
||||
* This method should be used for operations with an MTL texture
|
||||
* as the destination surface (e.g. a sw->texture blit loop), or in those
|
||||
* situations where we may not otherwise have a current context (e.g.
|
||||
* when disposing a texture-based surface).
|
||||
*/
|
||||
public static void setScratchSurface(long pConfigInfo) {
|
||||
// assert MTLRenderQueue.getInstance().lock.isHeldByCurrentThread();
|
||||
|
||||
// invalidate the current context
|
||||
currentContext = null;
|
||||
|
||||
// set the scratch context
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(SET_SCRATCH_SURFACE);
|
||||
buf.putLong(pConfigInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the currentContext field to ensure that we properly
|
||||
* revalidate the MTLContext (make it current, etc.) next time through
|
||||
* the validate() method. This is typically invoked from methods
|
||||
* that affect the current context state (e.g. disposing a context or
|
||||
* surface).
|
||||
*/
|
||||
public static void invalidateCurrentContext() {
|
||||
// assert MTLRenderQueue.getInstance().lock.isHeldByCurrentThread();
|
||||
|
||||
// invalidate the current Java-level context so that we
|
||||
// revalidate everything the next time around
|
||||
if (currentContext != null) {
|
||||
currentContext.invalidateContext();
|
||||
currentContext = null;
|
||||
}
|
||||
|
||||
// invalidate the context reference at the native level, and
|
||||
// then flush the queue so that we have no pending operations
|
||||
// dependent on the current context
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.ensureCapacity(4);
|
||||
rq.getBuffer().putInt(INVALIDATE_CONTEXT);
|
||||
rq.flushNow();
|
||||
}
|
||||
|
||||
public static class MTLContextCaps extends ContextCapabilities {
|
||||
|
||||
/** Indicates that the context is doublebuffered. */
|
||||
@Native
|
||||
public static final int CAPS_DOUBLEBUFFERED = (FIRST_PRIVATE_CAP << 0);
|
||||
/**
|
||||
* This cap will only be set if the lcdshader system property has been
|
||||
* enabled and the hardware supports the minimum number of texture units
|
||||
*/
|
||||
@Native
|
||||
static final int CAPS_EXT_LCD_SHADER = (FIRST_PRIVATE_CAP << 1);
|
||||
/**
|
||||
* This cap will only be set if the biopshader system property has been
|
||||
* enabled and the hardware meets our minimum requirements.
|
||||
*/
|
||||
@Native
|
||||
public static final int CAPS_EXT_BIOP_SHADER = (FIRST_PRIVATE_CAP << 2);
|
||||
/**
|
||||
* This cap will only be set if the gradshader system property has been
|
||||
* enabled and the hardware meets our minimum requirements.
|
||||
*/
|
||||
@Native
|
||||
static final int CAPS_EXT_GRAD_SHADER = (FIRST_PRIVATE_CAP << 3);
|
||||
|
||||
public MTLContextCaps(int caps, String adapterId) {
|
||||
super(caps, adapterId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(super.toString());
|
||||
if ((caps & CAPS_DOUBLEBUFFERED) != 0) {
|
||||
sb.append("CAPS_DOUBLEBUFFERED|");
|
||||
}
|
||||
if ((caps & CAPS_EXT_LCD_SHADER) != 0) {
|
||||
sb.append("CAPS_EXT_LCD_SHADER|");
|
||||
}
|
||||
if ((caps & CAPS_EXT_BIOP_SHADER) != 0) {
|
||||
sb.append("CAPS_BIOP_SHADER|");
|
||||
}
|
||||
if ((caps & CAPS_EXT_GRAD_SHADER) != 0) {
|
||||
sb.append("CAPS_EXT_GRAD_SHADER|");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.loops.TransformBlit;
|
||||
import sun.java2d.pipe.DrawImage;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Image;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
|
||||
public class MTLDrawImage extends DrawImage {
|
||||
|
||||
@Override
|
||||
protected void renderImageXform(SunGraphics2D sg, Image img,
|
||||
AffineTransform tx, int interpType,
|
||||
int sx1, int sy1, int sx2, int sy2,
|
||||
Color bgColor)
|
||||
{
|
||||
// punt to the MediaLib-based transformImage() in the superclass if:
|
||||
// - bicubic interpolation is specified
|
||||
// - a background color is specified and will be used
|
||||
// - the source surface is neither a texture nor render-to-texture
|
||||
// surface, and a non-default interpolation hint is specified
|
||||
// (we can only control the filtering for texture->surface
|
||||
// copies)
|
||||
// REMIND: we should tweak the sw->texture->surface
|
||||
// transform case to handle filtering appropriately
|
||||
// (see 4841762)...
|
||||
// - an appropriate TransformBlit primitive could not be found
|
||||
if (interpType != AffineTransformOp.TYPE_BICUBIC) {
|
||||
SurfaceData dstData = sg.surfaceData;
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(img,
|
||||
SunGraphics2D.TRANSFORM_GENERIC,
|
||||
sg.imageComp,
|
||||
bgColor);
|
||||
|
||||
if (srcData != null &&
|
||||
!isBgOperation(srcData, bgColor) &&
|
||||
(srcData.getSurfaceType() == MTLSurfaceData.MTLTexture ||
|
||||
srcData.getSurfaceType() == MTLSurfaceData.MTLSurfaceRTT ||
|
||||
interpType == AffineTransformOp.TYPE_NEAREST_NEIGHBOR))
|
||||
{
|
||||
SurfaceType srcType = srcData.getSurfaceType();
|
||||
SurfaceType dstType = dstData.getSurfaceType();
|
||||
TransformBlit blit = TransformBlit.getFromCache(srcType,
|
||||
sg.imageComp,
|
||||
dstType);
|
||||
|
||||
if (blit != null) {
|
||||
blit.Transform(srcData, dstData,
|
||||
sg.composite, sg.getCompClip(),
|
||||
tx, interpType,
|
||||
sx1, sy1, 0, 0, sx2-sx1, sy2-sy1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.renderImageXform(sg, img, tx, interpType,
|
||||
sx1, sy1, sx2, sy2, bgColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformImage(SunGraphics2D sg, BufferedImage img,
|
||||
BufferedImageOp op, int x, int y)
|
||||
{
|
||||
if (op != null) {
|
||||
if (op instanceof AffineTransformOp) {
|
||||
AffineTransformOp atop = (AffineTransformOp) op;
|
||||
transformImage(sg, img, x, y,
|
||||
atop.getTransform(),
|
||||
atop.getInterpolationType());
|
||||
return;
|
||||
} else {
|
||||
if (MTLBufImgOps.renderImageWithOp(sg, img, op, x, y)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
img = op.filter(img, null);
|
||||
}
|
||||
copyImage(sg, img, x, y, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.awt.CGraphicsConfig;
|
||||
import sun.awt.CGraphicsDevice;
|
||||
import sun.awt.image.OffScreenImage;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.java2d.Disposer;
|
||||
import sun.java2d.DisposerRecord;
|
||||
import sun.java2d.Surface;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.hw.AccelGraphicsConfig;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
import sun.java2d.pipe.hw.AccelTypedVolatileImage;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
import sun.lwawt.LWComponentPeer;
|
||||
import sun.lwawt.macosx.CFRetainedResource;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.io.File;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_GRAD_SHADER;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.TEXTURE;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.RT_TEXTURE;
|
||||
import static sun.java2d.pipe.hw.ContextCapabilities.*;
|
||||
|
||||
import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_BIOP_SHADER;
|
||||
|
||||
public final class MTLGraphicsConfig extends CGraphicsConfig
|
||||
implements AccelGraphicsConfig, SurfaceManager.ProxiedGraphicsConfig
|
||||
{
|
||||
private static boolean mtlAvailable;
|
||||
private static ImageCapabilities imageCaps = new MTLImageCaps();
|
||||
|
||||
private static final String mtlShadersLib = AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () ->
|
||||
System.getProperty("java.home", "") + File.separator +
|
||||
"lib" + File.separator + "shaders.metallib");
|
||||
|
||||
|
||||
private BufferCapabilities bufferCaps;
|
||||
private long pConfigInfo;
|
||||
private ContextCapabilities mtlCaps;
|
||||
private final MTLContext context;
|
||||
private final Object disposerReferent = new Object();
|
||||
private final int maxTextureSize;
|
||||
|
||||
private static native boolean isMetalFrameworkAvailable();
|
||||
private static native boolean tryLoadMetalLibrary(int displayID, String shaderLib);
|
||||
private static native long getMTLConfigInfo(int displayID, String mtlShadersLib);
|
||||
|
||||
/**
|
||||
* Returns maximum texture size supported by Metal. Must be
|
||||
* called under MTLRQ lock.
|
||||
*/
|
||||
private static native int nativeGetMaxTextureSize();
|
||||
|
||||
static {
|
||||
mtlAvailable = isMetalFrameworkAvailable();
|
||||
}
|
||||
|
||||
private MTLGraphicsConfig(CGraphicsDevice device,
|
||||
long configInfo, int maxTextureSize,
|
||||
ContextCapabilities mtlCaps) {
|
||||
super(device);
|
||||
|
||||
this.pConfigInfo = configInfo;
|
||||
this.mtlCaps = mtlCaps;
|
||||
this.maxTextureSize = maxTextureSize;
|
||||
context = new MTLContext(MTLRenderQueue.getInstance());
|
||||
// add a record to the Disposer so that we destroy the native
|
||||
// MTLGraphicsConfigInfo data when this object goes away
|
||||
Disposer.addRecord(disposerReferent,
|
||||
new MTLGCDisposerRecord(pConfigInfo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProxyKey() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SurfaceData createManagedSurface(int w, int h, int transparency) {
|
||||
return MTLSurfaceData.createData(this, w, h,
|
||||
getColorModel(transparency),
|
||||
null,
|
||||
MTLSurfaceData.TEXTURE);
|
||||
}
|
||||
|
||||
public static MTLGraphicsConfig getConfig(CGraphicsDevice device,
|
||||
int displayID)
|
||||
{
|
||||
if (!mtlAvailable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!tryLoadMetalLibrary(displayID, mtlShadersLib)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
long cfginfo = 0;
|
||||
int textureSize = 0;
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// getMTLConfigInfo() creates and destroys temporary
|
||||
// surfaces/contexts, so we should first invalidate the current
|
||||
// Java-level context and flush the queue...
|
||||
MTLContext.invalidateCurrentContext();
|
||||
cfginfo = getMTLConfigInfo(displayID, mtlShadersLib);
|
||||
if (cfginfo != 0L) {
|
||||
textureSize = nativeGetMaxTextureSize();
|
||||
// TODO : This clamping code is same as in OpenGL.
|
||||
// Whether we need such clamping or not in case of Metal
|
||||
// will be pursued under 8260644
|
||||
textureSize = textureSize <= 16384 ? textureSize / 2 : 8192;
|
||||
MTLContext.setScratchSurface(cfginfo);
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
if (cfginfo == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ContextCapabilities caps = new MTLContext.MTLContextCaps(
|
||||
CAPS_PS30 | CAPS_PS20 |
|
||||
CAPS_RT_TEXTURE_ALPHA | CAPS_RT_TEXTURE_OPAQUE |
|
||||
CAPS_MULTITEXTURE | CAPS_TEXNONPOW2 | CAPS_TEXNONSQUARE |
|
||||
CAPS_EXT_BIOP_SHADER | CAPS_EXT_GRAD_SHADER,
|
||||
null);
|
||||
return new MTLGraphicsConfig(device, cfginfo, textureSize, caps);
|
||||
}
|
||||
|
||||
public static boolean isMetalAvailable() {
|
||||
return mtlAvailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the provided capability bit is present for this config.
|
||||
* See MTLContext.java for a list of supported capabilities.
|
||||
*/
|
||||
public boolean isCapPresent(int cap) {
|
||||
return ((mtlCaps.getCaps() & cap) != 0);
|
||||
}
|
||||
|
||||
public long getNativeConfigInfo() {
|
||||
return pConfigInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see sun.java2d.pipe.hw.BufferedContextProvider#getContext
|
||||
*/
|
||||
@Override
|
||||
public MTLContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage createCompatibleImage(int width, int height) {
|
||||
ColorModel model = new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
|
||||
WritableRaster
|
||||
raster = model.createCompatibleWritableRaster(width, height);
|
||||
return new BufferedImage(model, raster, model.isAlphaPremultiplied(),
|
||||
null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorModel getColorModel(int transparency) {
|
||||
switch (transparency) {
|
||||
case Transparency.OPAQUE:
|
||||
// REMIND: once the ColorModel spec is changed, this should be
|
||||
// an opaque premultiplied DCM...
|
||||
return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
|
||||
case Transparency.BITMASK:
|
||||
return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
|
||||
case Transparency.TRANSLUCENT:
|
||||
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
|
||||
return new DirectColorModel(cs, 32,
|
||||
0xff0000, 0xff00, 0xff, 0xff000000,
|
||||
true, DataBuffer.TYPE_INT);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDoubleBuffered() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class MTLGCDisposerRecord implements DisposerRecord {
|
||||
private long pCfgInfo;
|
||||
public MTLGCDisposerRecord(long pCfgInfo) {
|
||||
this.pCfgInfo = pCfgInfo;
|
||||
}
|
||||
public void dispose() {
|
||||
if (pCfgInfo != 0) {
|
||||
MTLRenderQueue.disposeGraphicsConfig(pCfgInfo);
|
||||
pCfgInfo = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ("MTLGraphicsConfig[" + getDevice().getIDstring() + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData createSurfaceData(CFRetainedResource layer) {
|
||||
return MTLSurfaceData.createData((MTLLayer) layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image createAcceleratedImage(Component target,
|
||||
int width, int height)
|
||||
{
|
||||
ColorModel model = getColorModel(Transparency.OPAQUE);
|
||||
WritableRaster wr = model.createCompatibleWritableRaster(width, height);
|
||||
return new OffScreenImage(target, model, wr,
|
||||
model.isAlphaPremultiplied());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertOperationSupported(final int numBuffers,
|
||||
final BufferCapabilities caps)
|
||||
throws AWTException {
|
||||
// Assume this method is never called with numBuffers != 2, as 0 is
|
||||
// unsupported, and 1 corresponds to a SingleBufferStrategy which
|
||||
// doesn't depend on the peer. Screen is considered as a separate
|
||||
// "buffer".
|
||||
if (numBuffers != 2) {
|
||||
throw new AWTException("Only double buffering is supported");
|
||||
}
|
||||
final BufferCapabilities configCaps = getBufferCapabilities();
|
||||
if (!configCaps.isPageFlipping()) {
|
||||
throw new AWTException("Page flipping is not supported");
|
||||
}
|
||||
if (caps.getFlipContents() == BufferCapabilities.FlipContents.PRIOR) {
|
||||
throw new AWTException("FlipContents.PRIOR is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image createBackBuffer(final LWComponentPeer<?, ?> peer) {
|
||||
final Rectangle r = peer.getBounds();
|
||||
// It is possible for the component to have size 0x0, adjust it to
|
||||
// be at least 1x1 to avoid IAE
|
||||
final int w = Math.max(1, r.width);
|
||||
final int h = Math.max(1, r.height);
|
||||
final int transparency = peer.isTranslucent() ? Transparency.TRANSLUCENT
|
||||
: Transparency.OPAQUE;
|
||||
return new SunVolatileImage(this, w, h, transparency, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyBackBuffer(final Image backBuffer) {
|
||||
if (backBuffer != null) {
|
||||
backBuffer.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flip(final LWComponentPeer<?, ?> peer, final Image backBuffer,
|
||||
final int x1, final int y1, final int x2, final int y2,
|
||||
final BufferCapabilities.FlipContents flipAction) {
|
||||
final Graphics g = peer.getGraphics();
|
||||
try {
|
||||
g.drawImage(backBuffer, x1, y1, x2, y2, x1, y1, x2, y2, null);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
|
||||
final Graphics2D bg = (Graphics2D) backBuffer.getGraphics();
|
||||
try {
|
||||
bg.setBackground(peer.getBackground());
|
||||
bg.clearRect(0, 0, backBuffer.getWidth(null),
|
||||
backBuffer.getHeight(null));
|
||||
} finally {
|
||||
bg.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MTLBufferCaps extends BufferCapabilities {
|
||||
public MTLBufferCaps(boolean dblBuf) {
|
||||
super(imageCaps, imageCaps,
|
||||
dblBuf ? FlipContents.UNDEFINED : null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferCapabilities getBufferCapabilities() {
|
||||
if (bufferCaps == null) {
|
||||
bufferCaps = new MTLBufferCaps(isDoubleBuffered());
|
||||
}
|
||||
return bufferCaps;
|
||||
}
|
||||
|
||||
private static class MTLImageCaps extends ImageCapabilities {
|
||||
private MTLImageCaps() {
|
||||
super(true);
|
||||
}
|
||||
public boolean isTrueVolatile() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCapabilities getImageCapabilities() {
|
||||
return imageCaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolatileImage createCompatibleVolatileImage(int width, int height,
|
||||
int transparency,
|
||||
int type) {
|
||||
if ((type != RT_TEXTURE && type != TEXTURE) ||
|
||||
transparency == Transparency.BITMASK) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
|
||||
transparency, type);
|
||||
Surface sd = vi.getDestSurface();
|
||||
if (!(sd instanceof AccelSurface) ||
|
||||
((AccelSurface)sd).getType() != type)
|
||||
{
|
||||
vi.flush();
|
||||
vi = null;
|
||||
}
|
||||
|
||||
return vi;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities
|
||||
*/
|
||||
@Override
|
||||
public ContextCapabilities getContextCapabilities() {
|
||||
return mtlCaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxTextureWidth() {
|
||||
return Math.max(maxTextureSize / getDevice().getScaleFactor(),
|
||||
getBounds().width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxTextureHeight() {
|
||||
return Math.max(maxTextureSize / getDevice().getScaleFactor(),
|
||||
getBounds().height);
|
||||
}
|
||||
}
|
||||
154
src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java
Normal file
154
src/java.desktop/macosx/classes/sun/java2d/metal/MTLLayer.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.java2d.NullSurfaceData;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.lwawt.LWWindowPeer;
|
||||
import sun.lwawt.macosx.CFRetainedResource;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
|
||||
public class MTLLayer extends CFRetainedResource {
|
||||
|
||||
private native long nativeCreateLayer();
|
||||
private static native void nativeSetScale(long layerPtr, double scale);
|
||||
|
||||
// Pass the insets to native code to make adjustments in blitTexture
|
||||
private static native void nativeSetInsets(long layerPtr, int top, int left);
|
||||
private static native void validate(long layerPtr, MTLSurfaceData mtlsd);
|
||||
private static native void blitTexture(long layerPtr);
|
||||
|
||||
private LWWindowPeer peer;
|
||||
private int scale = 1;
|
||||
|
||||
private SurfaceData surfaceData; // represents intermediate buffer (texture)
|
||||
|
||||
public MTLLayer(LWWindowPeer peer) {
|
||||
super(0, true);
|
||||
|
||||
setPtr(nativeCreateLayer());
|
||||
this.peer = peer;
|
||||
}
|
||||
|
||||
public long getPointer() {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
public Rectangle getBounds() {
|
||||
return peer.getBounds();
|
||||
}
|
||||
|
||||
public GraphicsConfiguration getGraphicsConfiguration() {
|
||||
return peer.getGraphicsConfiguration();
|
||||
}
|
||||
|
||||
public boolean isOpaque() {
|
||||
return !peer.isTranslucent();
|
||||
}
|
||||
|
||||
public int getTransparency() {
|
||||
return isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT;
|
||||
}
|
||||
|
||||
public Object getDestination() {
|
||||
return peer.getTarget();
|
||||
}
|
||||
|
||||
public SurfaceData replaceSurfaceData() {
|
||||
if (getBounds().isEmpty()) {
|
||||
surfaceData = NullSurfaceData.theInstance;
|
||||
return surfaceData;
|
||||
}
|
||||
|
||||
// the layer redirects all painting to the buffer's graphics
|
||||
// and blits the buffer to the layer surface (in display callback)
|
||||
MTLGraphicsConfig gc = (MTLGraphicsConfig)getGraphicsConfiguration();
|
||||
surfaceData = gc.createSurfaceData(this);
|
||||
setScale(gc.getDevice().getScaleFactor());
|
||||
Insets insets = peer.getInsets();
|
||||
execute(ptr -> nativeSetInsets(ptr, insets.top, insets.left));
|
||||
// the layer holds a reference to the buffer, which in
|
||||
// turn has a reference back to this layer
|
||||
if (surfaceData instanceof MTLSurfaceData) {
|
||||
validate((MTLSurfaceData)surfaceData);
|
||||
}
|
||||
|
||||
return surfaceData;
|
||||
}
|
||||
|
||||
public SurfaceData getSurfaceData() {
|
||||
return surfaceData;
|
||||
}
|
||||
|
||||
public void validate(final MTLSurfaceData mtlsd) {
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
execute(ptr -> validate(ptr, mtlsd));
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
// break the connection between the layer and the buffer
|
||||
validate(null);
|
||||
SurfaceData oldData = surfaceData;
|
||||
surfaceData = NullSurfaceData.theInstance;;
|
||||
if (oldData != null) {
|
||||
oldData.flush();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private void setScale(final int _scale) {
|
||||
if (scale != _scale) {
|
||||
scale = _scale;
|
||||
execute(ptr -> nativeSetScale(ptr, scale));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// NATIVE CALLBACKS
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
private void drawInMTLContext() {
|
||||
// tell the flusher thread not to update the intermediate buffer
|
||||
// until we are done blitting from it
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
execute(ptr -> blitTexture(ptr));
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.pipe.BufferedMaskBlit;
|
||||
import sun.java2d.pipe.Region;
|
||||
|
||||
import java.awt.Composite;
|
||||
|
||||
import static sun.java2d.loops.CompositeType.SrcNoEa;
|
||||
import static sun.java2d.loops.CompositeType.SrcOver;
|
||||
import static sun.java2d.loops.SurfaceType.*;
|
||||
|
||||
class MTLMaskBlit extends BufferedMaskBlit {
|
||||
|
||||
static void register() {
|
||||
GraphicsPrimitive[] primitives = {
|
||||
new MTLMaskBlit(IntArgb, SrcOver),
|
||||
new MTLMaskBlit(IntArgbPre, SrcOver),
|
||||
new MTLMaskBlit(IntRgb, SrcOver),
|
||||
new MTLMaskBlit(IntRgb, SrcNoEa),
|
||||
new MTLMaskBlit(IntBgr, SrcOver),
|
||||
new MTLMaskBlit(IntBgr, SrcNoEa),
|
||||
};
|
||||
GraphicsPrimitiveMgr.register(primitives);
|
||||
}
|
||||
|
||||
private MTLMaskBlit(SurfaceType srcType,
|
||||
CompositeType compType)
|
||||
{
|
||||
super(MTLRenderQueue.getInstance(),
|
||||
srcType, compType, MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateContext(SurfaceData dstData,
|
||||
Composite comp, Region clip)
|
||||
{
|
||||
MTLSurfaceData mtlDst = (MTLSurfaceData)dstData;
|
||||
MTLContext.validateContext(mtlDst, mtlDst,
|
||||
clip, comp, null, null, null,
|
||||
MTLContext.NO_CONTEXT_FLAGS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.pipe.BufferedMaskFill;
|
||||
|
||||
import java.awt.Composite;
|
||||
|
||||
import static sun.java2d.loops.CompositeType.SrcNoEa;
|
||||
import static sun.java2d.loops.CompositeType.SrcOver;
|
||||
import static sun.java2d.loops.SurfaceType.*;
|
||||
|
||||
class MTLMaskFill extends BufferedMaskFill {
|
||||
|
||||
static void register() {
|
||||
GraphicsPrimitive[] primitives = {
|
||||
new MTLMaskFill(AnyColor, SrcOver),
|
||||
new MTLMaskFill(OpaqueColor, SrcNoEa),
|
||||
new MTLMaskFill(GradientPaint, SrcOver),
|
||||
new MTLMaskFill(OpaqueGradientPaint, SrcNoEa),
|
||||
new MTLMaskFill(LinearGradientPaint, SrcOver),
|
||||
new MTLMaskFill(OpaqueLinearGradientPaint, SrcNoEa),
|
||||
new MTLMaskFill(RadialGradientPaint, SrcOver),
|
||||
new MTLMaskFill(OpaqueRadialGradientPaint, SrcNoEa),
|
||||
new MTLMaskFill(TexturePaint, SrcOver),
|
||||
new MTLMaskFill(OpaqueTexturePaint, SrcNoEa),
|
||||
};
|
||||
GraphicsPrimitiveMgr.register(primitives);
|
||||
}
|
||||
|
||||
protected MTLMaskFill(SurfaceType srcType, CompositeType compType) {
|
||||
super(MTLRenderQueue.getInstance(),
|
||||
srcType, compType, MTLSurfaceData.MTLSurface);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected native void maskFill(int x, int y, int w, int h,
|
||||
int maskoff, int maskscan, int masklen,
|
||||
byte[] mask);
|
||||
|
||||
@Override
|
||||
protected void validateContext(SunGraphics2D sg2d,
|
||||
Composite comp, int ctxflags)
|
||||
{
|
||||
MTLSurfaceData dstData;
|
||||
try {
|
||||
dstData = (MTLSurfaceData) sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " +
|
||||
sg2d.surfaceData);
|
||||
}
|
||||
|
||||
MTLContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), comp,
|
||||
null, sg2d.paint, sg2d, ctxflags);
|
||||
}
|
||||
}
|
||||
199
src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java
Normal file
199
src/java.desktop/macosx/classes/sun/java2d/metal/MTLPaints.java
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
|
||||
import java.awt.LinearGradientPaint;
|
||||
import java.awt.MultipleGradientPaint;
|
||||
import java.awt.TexturePaint;
|
||||
|
||||
import java.awt.MultipleGradientPaint.ColorSpaceType;
|
||||
import java.awt.MultipleGradientPaint.CycleMethod;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static sun.java2d.metal.MTLContext.MTLContextCaps.CAPS_EXT_GRAD_SHADER;
|
||||
import static sun.java2d.pipe.BufferedPaints.MULTI_MAX_FRACTIONS;
|
||||
|
||||
abstract class MTLPaints {
|
||||
|
||||
/**
|
||||
* Holds all registered implementations, using the corresponding
|
||||
* SunGraphics2D.PAINT_* constant as the hash key.
|
||||
*/
|
||||
private static Map<Integer, MTLPaints> impls =
|
||||
new HashMap<Integer, MTLPaints>(4, 1.0f);
|
||||
|
||||
static {
|
||||
impls.put(SunGraphics2D.PAINT_GRADIENT, new Gradient());
|
||||
impls.put(SunGraphics2D.PAINT_LIN_GRADIENT, new LinearGradient());
|
||||
impls.put(SunGraphics2D.PAINT_RAD_GRADIENT, new RadialGradient());
|
||||
impls.put(SunGraphics2D.PAINT_TEXTURE, new Texture());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to locate an implementation corresponding to the paint state
|
||||
* of the provided SunGraphics2D object. If no implementation can be
|
||||
* found, or if the paint cannot be accelerated under the conditions
|
||||
* of the SunGraphics2D, this method returns false; otherwise, returns
|
||||
* true.
|
||||
*/
|
||||
static boolean isValid(SunGraphics2D sg2d) {
|
||||
MTLPaints impl = impls.get(sg2d.paintState);
|
||||
return (impl != null && impl.isPaintValid(sg2d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this implementation is able to accelerate the
|
||||
* Paint object associated with, and under the conditions of, the
|
||||
* provided SunGraphics2D instance; otherwise returns false.
|
||||
*/
|
||||
abstract boolean isPaintValid(SunGraphics2D sg2d);
|
||||
|
||||
/************************* GradientPaint support ****************************/
|
||||
|
||||
private static class Gradient extends MTLPaints {
|
||||
private Gradient() {}
|
||||
|
||||
/**
|
||||
* There are no restrictions for accelerating GradientPaint, so
|
||||
* this method always returns true.
|
||||
*/
|
||||
@Override
|
||||
boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/************************** TexturePaint support ****************************/
|
||||
|
||||
private static class Texture extends MTLPaints {
|
||||
private Texture() {}
|
||||
|
||||
/**
|
||||
* Returns true if the given TexturePaint instance can be used by the
|
||||
* accelerated MTLPaints.Texture implementation. A TexturePaint is
|
||||
* considered valid if the following conditions are met:
|
||||
* - the texture image dimensions are power-of-two
|
||||
* - the texture image can be (or is already) cached in an Metal
|
||||
* texture object
|
||||
*/
|
||||
@Override
|
||||
boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
TexturePaint paint = (TexturePaint)sg2d.paint;
|
||||
MTLSurfaceData dstData = (MTLSurfaceData)sg2d.surfaceData;
|
||||
BufferedImage bi = paint.getImage();
|
||||
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(bi,
|
||||
SunGraphics2D.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof MTLSurfaceData)) {
|
||||
// REMIND: this is a hack that attempts to cache the system
|
||||
// memory image from the TexturePaint instance into an
|
||||
// Metal texture...
|
||||
srcData =
|
||||
dstData.getSourceSurfaceData(bi,
|
||||
SunGraphics2D.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof MTLSurfaceData)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// verify that the source surface is actually a texture
|
||||
MTLSurfaceData mtlData = (MTLSurfaceData)srcData;
|
||||
if (mtlData.getType() != MTLSurfaceData.TEXTURE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/****************** Shared MultipleGradientPaint support ********************/
|
||||
|
||||
private abstract static class MultiGradient extends MTLPaints {
|
||||
protected MultiGradient() {}
|
||||
|
||||
/**
|
||||
* Returns true if the given MultipleGradientPaint instance can be
|
||||
* used by the accelerated MTLPaints.MultiGradient implementation.
|
||||
* A MultipleGradientPaint is considered valid if the following
|
||||
* conditions are met:
|
||||
* - the number of gradient "stops" is <= MAX_FRACTIONS
|
||||
* - the destination has support for fragment shaders
|
||||
*/
|
||||
@Override
|
||||
boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
MultipleGradientPaint paint = (MultipleGradientPaint)sg2d.paint;
|
||||
// REMIND: ugh, this creates garbage; would be nicer if
|
||||
// we had a MultipleGradientPaint.getNumStops() method...
|
||||
if (paint.getFractions().length > MULTI_MAX_FRACTIONS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MTLSurfaceData dstData = (MTLSurfaceData)sg2d.surfaceData;
|
||||
MTLGraphicsConfig gc = dstData.getMTLGraphicsConfig();
|
||||
if (!gc.isCapPresent(CAPS_EXT_GRAD_SHADER)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/********************** LinearGradientPaint support *************************/
|
||||
|
||||
private static class LinearGradient extends MultiGradient {
|
||||
private LinearGradient() {}
|
||||
|
||||
@Override
|
||||
boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;
|
||||
|
||||
if (paint.getFractions().length == 2 &&
|
||||
paint.getCycleMethod() != CycleMethod.REPEAT &&
|
||||
paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
|
||||
{
|
||||
// we can delegate to the optimized two-color gradient
|
||||
// codepath, which does not require fragment shader support
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.isPaintValid(sg2d);
|
||||
}
|
||||
}
|
||||
|
||||
/********************** RadialGradientPaint support *************************/
|
||||
|
||||
private static class RadialGradient extends MultiGradient {
|
||||
private RadialGradient() {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.awt.util.ThreadGroupUtils;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import static sun.java2d.pipe.BufferedOpCodes.DISPOSE_CONFIG;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.SYNC;
|
||||
|
||||
/**
|
||||
* MTL-specific implementation of RenderQueue. This class provides a
|
||||
* single (daemon) thread that is responsible for periodically flushing
|
||||
* the queue, thus ensuring that only one thread communicates with the native
|
||||
* OpenGL libraries for the entire process.
|
||||
*/
|
||||
public class MTLRenderQueue extends RenderQueue {
|
||||
|
||||
private static MTLRenderQueue theInstance;
|
||||
private final QueueFlusher flusher;
|
||||
|
||||
private MTLRenderQueue() {
|
||||
/*
|
||||
* The thread must be a member of a thread group
|
||||
* which will not get GCed before VM exit.
|
||||
*/
|
||||
flusher = AccessController.doPrivileged((PrivilegedAction<QueueFlusher>) QueueFlusher::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the single MTLRenderQueue instance. If it has not yet been
|
||||
* initialized, this method will first construct the single instance
|
||||
* before returning it.
|
||||
*/
|
||||
public static synchronized MTLRenderQueue getInstance() {
|
||||
if (theInstance == null) {
|
||||
theInstance = new MTLRenderQueue();
|
||||
}
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the single MTLRenderQueue instance synchronously. If an
|
||||
* MTLRenderQueue has not yet been instantiated, this method is a no-op.
|
||||
* This method is useful in the case of Toolkit.sync(), in which we want
|
||||
* to flush the MTL pipeline, but only if the MTL pipeline is currently
|
||||
* enabled. Since this class has few external dependencies, callers need
|
||||
* not be concerned that calling this method will trigger initialization
|
||||
* of the MTL pipeline and related classes.
|
||||
*/
|
||||
public static void sync() {
|
||||
if (theInstance != null) {
|
||||
theInstance.lock();
|
||||
try {
|
||||
theInstance.ensureCapacity(4);
|
||||
theInstance.getBuffer().putInt(SYNC);
|
||||
theInstance.flushNow();
|
||||
} finally {
|
||||
theInstance.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the native memory associated with the given native
|
||||
* graphics config info pointer on the single queue flushing thread.
|
||||
*/
|
||||
public static void disposeGraphicsConfig(long pConfigInfo) {
|
||||
MTLRenderQueue rq = getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// make sure we make the context associated with the given
|
||||
// GraphicsConfig current before disposing the native resources
|
||||
MTLContext.setScratchSurface(pConfigInfo);
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(DISPOSE_CONFIG);
|
||||
buf.putLong(pConfigInfo);
|
||||
|
||||
// this call is expected to complete synchronously, so flush now
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current thread is the MTL QueueFlusher thread.
|
||||
*/
|
||||
public static boolean isQueueFlusherThread() {
|
||||
return (Thread.currentThread() == getInstance().flusher.thread);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void flushNow() {
|
||||
// assert lock.isHeldByCurrentThread();
|
||||
try {
|
||||
flusher.flushNow();
|
||||
} catch (Exception e) {
|
||||
System.err.println("exception in flushNow:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void flushAndInvokeNow(Runnable r) {
|
||||
// assert lock.isHeldByCurrentThread();
|
||||
try {
|
||||
flusher.flushAndInvokeNow(r);
|
||||
} catch (Exception e) {
|
||||
System.err.println("exception in flushAndInvokeNow:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private native void flushBuffer(long buf, int limit);
|
||||
|
||||
private void flushBuffer() {
|
||||
// assert lock.isHeldByCurrentThread();
|
||||
int limit = buf.position();
|
||||
if (limit > 0) {
|
||||
// process the queue
|
||||
flushBuffer(buf.getAddress(), limit);
|
||||
}
|
||||
// reset the buffer position
|
||||
buf.clear();
|
||||
// clear the set of references, since we no longer need them
|
||||
refSet.clear();
|
||||
}
|
||||
|
||||
private class QueueFlusher implements Runnable {
|
||||
private boolean needsFlush;
|
||||
private Runnable task;
|
||||
private Error error;
|
||||
private final Thread thread;
|
||||
|
||||
public QueueFlusher() {
|
||||
String name = "Java2D Queue Flusher";
|
||||
thread = new Thread(ThreadGroupUtils.getRootThreadGroup(),
|
||||
this, name, 0, false);
|
||||
thread.setDaemon(true);
|
||||
thread.setPriority(Thread.MAX_PRIORITY);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public synchronized void flushNow() {
|
||||
// wake up the flusher
|
||||
needsFlush = true;
|
||||
notify();
|
||||
|
||||
// wait for flush to complete
|
||||
while (needsFlush) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
// re-throw any error that may have occurred during the flush
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void flushAndInvokeNow(Runnable task) {
|
||||
this.task = task;
|
||||
flushNow();
|
||||
}
|
||||
|
||||
public synchronized void run() {
|
||||
boolean timedOut = false;
|
||||
while (true) {
|
||||
while (!needsFlush) {
|
||||
try {
|
||||
timedOut = false;
|
||||
/*
|
||||
* Wait until we're woken up with a flushNow() call,
|
||||
* or the timeout period elapses (so that we can
|
||||
* flush the queue periodically).
|
||||
*/
|
||||
wait(100);
|
||||
/*
|
||||
* We will automatically flush the queue if the
|
||||
* following conditions apply:
|
||||
* - the wait() timed out
|
||||
* - we can lock the queue (without blocking)
|
||||
* - there is something in the queue to flush
|
||||
* Otherwise, just continue (we'll flush eventually).
|
||||
*/
|
||||
if (!needsFlush && (timedOut = tryLock())) {
|
||||
if (buf.position() > 0) {
|
||||
needsFlush = true;
|
||||
} else {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
// reset the throwable state
|
||||
error = null;
|
||||
// flush the buffer now
|
||||
flushBuffer();
|
||||
// if there's a task, invoke that now as well
|
||||
if (task != null) {
|
||||
task.run();
|
||||
}
|
||||
} catch (Error e) {
|
||||
error = e;
|
||||
} catch (Exception x) {
|
||||
System.err.println("exception in QueueFlusher:");
|
||||
x.printStackTrace();
|
||||
} finally {
|
||||
if (timedOut) {
|
||||
unlock();
|
||||
}
|
||||
task = null;
|
||||
// allow the waiting thread to continue
|
||||
needsFlush = false;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.BufferedRenderPipe;
|
||||
import sun.java2d.pipe.ParallelogramPipe;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import sun.java2d.pipe.SpanIterator;
|
||||
|
||||
import java.awt.Transparency;
|
||||
import java.awt.geom.Path2D;
|
||||
|
||||
import static sun.java2d.pipe.BufferedOpCodes.COPY_AREA;
|
||||
|
||||
class MTLRenderer extends BufferedRenderPipe {
|
||||
|
||||
MTLRenderer(RenderQueue rq) {
|
||||
super(rq);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateContext(SunGraphics2D sg2d) {
|
||||
int ctxflags =
|
||||
sg2d.paint.getTransparency() == Transparency.OPAQUE ?
|
||||
MTLContext.SRC_IS_OPAQUE : MTLContext.NO_CONTEXT_FLAGS;
|
||||
MTLSurfaceData dstData;
|
||||
try {
|
||||
dstData = (MTLSurfaceData)sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
|
||||
}
|
||||
MTLContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), sg2d.composite,
|
||||
null, sg2d.paint, sg2d, ctxflags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateContextAA(SunGraphics2D sg2d) {
|
||||
int ctxflags = MTLContext.NO_CONTEXT_FLAGS;
|
||||
MTLSurfaceData dstData;
|
||||
try {
|
||||
dstData = (MTLSurfaceData)sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
|
||||
}
|
||||
MTLContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), sg2d.composite,
|
||||
null, sg2d.paint, sg2d, ctxflags);
|
||||
}
|
||||
|
||||
void copyArea(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h, int dx, int dy)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
int ctxflags =
|
||||
sg2d.surfaceData.getTransparency() == Transparency.OPAQUE ?
|
||||
MTLContext.SRC_IS_OPAQUE : MTLContext.NO_CONTEXT_FLAGS;
|
||||
MTLSurfaceData dstData;
|
||||
try {
|
||||
dstData = (MTLSurfaceData)sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
|
||||
}
|
||||
MTLContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), sg2d.composite,
|
||||
null, null, null, ctxflags);
|
||||
|
||||
rq.ensureCapacity(28);
|
||||
buf.putInt(COPY_AREA);
|
||||
buf.putInt(x).putInt(y).putInt(w).putInt(h);
|
||||
buf.putInt(dx).putInt(dy);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected native void drawPoly(int[] xPoints, int[] yPoints,
|
||||
int nPoints, boolean isClosed,
|
||||
int transX, int transY);
|
||||
|
||||
MTLRenderer traceWrap() {
|
||||
return new Tracer(this);
|
||||
}
|
||||
|
||||
private class Tracer extends MTLRenderer {
|
||||
private MTLRenderer mtlr;
|
||||
Tracer(MTLRenderer mtlr) {
|
||||
super(mtlr.rq);
|
||||
this.mtlr = mtlr;
|
||||
}
|
||||
public ParallelogramPipe getAAParallelogramPipe() {
|
||||
final ParallelogramPipe realpipe = mtlr.getAAParallelogramPipe();
|
||||
return new ParallelogramPipe() {
|
||||
public void fillParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("MTLFillAAParallelogram");
|
||||
realpipe.fillParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
public void drawParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("MTLDrawAAParallelogram");
|
||||
realpipe.drawParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2,
|
||||
lw1, lw2);
|
||||
}
|
||||
};
|
||||
}
|
||||
protected void validateContext(SunGraphics2D sg2d) {
|
||||
mtlr.validateContext(sg2d);
|
||||
}
|
||||
public void drawLine(SunGraphics2D sg2d,
|
||||
int x1, int y1, int x2, int y2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("MTLDrawLine");
|
||||
mtlr.drawLine(sg2d, x1, y1, x2, y2);
|
||||
}
|
||||
public void drawRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
|
||||
GraphicsPrimitive.tracePrimitive("MTLDrawRect");
|
||||
mtlr.drawRect(sg2d, x, y, w, h);
|
||||
}
|
||||
protected void drawPoly(SunGraphics2D sg2d,
|
||||
int[] xPoints, int[] yPoints,
|
||||
int nPoints, boolean isClosed)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("MTLDrawPoly");
|
||||
mtlr.drawPoly(sg2d, xPoints, yPoints, nPoints, isClosed);
|
||||
}
|
||||
public void fillRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
|
||||
GraphicsPrimitive.tracePrimitive("MTLFillRect");
|
||||
mtlr.fillRect(sg2d, x, y, w, h);
|
||||
}
|
||||
protected void drawPath(SunGraphics2D sg2d,
|
||||
Path2D.Float p2df, int transx, int transy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("MTLDrawPath");
|
||||
mtlr.drawPath(sg2d, p2df, transx, transy);
|
||||
}
|
||||
protected void fillPath(SunGraphics2D sg2d,
|
||||
Path2D.Float p2df, int transx, int transy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("MTLFillPath");
|
||||
mtlr.fillPath(sg2d, p2df, transx, transy);
|
||||
}
|
||||
protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,
|
||||
int transx, int transy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("MTLFillSpans");
|
||||
mtlr.fillSpans(sg2d, si, transx, transy);
|
||||
}
|
||||
public void fillParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("MTLFillParallelogram");
|
||||
mtlr.fillParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
public void drawParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("MTLDrawParallelogram");
|
||||
mtlr.drawParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2, lw1, lw2);
|
||||
}
|
||||
public void copyArea(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h, int dx, int dy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("MTLCopyArea");
|
||||
mtlr.copyArea(sg2d, x, y, w, h, dx, dy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,642 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.awt.SunHints;
|
||||
import sun.awt.image.PixelConverter;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.SurfaceDataProxy;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.MaskFill;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.pipe.ParallelogramPipe;
|
||||
import sun.java2d.pipe.PixelToParallelogramConverter;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.TextPipe;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Composite;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
|
||||
import static sun.java2d.pipe.BufferedOpCodes.DISPOSE_SURFACE;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.FLUSH_SURFACE;
|
||||
import static sun.java2d.pipe.hw.ContextCapabilities.CAPS_MULTITEXTURE;
|
||||
import static sun.java2d.pipe.hw.ContextCapabilities.CAPS_PS30;
|
||||
|
||||
|
||||
public abstract class MTLSurfaceData extends SurfaceData
|
||||
implements AccelSurface {
|
||||
|
||||
/**
|
||||
* Pixel formats
|
||||
*/
|
||||
public static final int PF_INT_ARGB = 0;
|
||||
public static final int PF_INT_ARGB_PRE = 1;
|
||||
public static final int PF_INT_RGB = 2;
|
||||
public static final int PF_INT_RGBX = 3;
|
||||
public static final int PF_INT_BGR = 4;
|
||||
public static final int PF_INT_BGRX = 5;
|
||||
public static final int PF_USHORT_565_RGB = 6;
|
||||
public static final int PF_USHORT_555_RGB = 7;
|
||||
public static final int PF_USHORT_555_RGBX = 8;
|
||||
public static final int PF_BYTE_GRAY = 9;
|
||||
public static final int PF_USHORT_GRAY = 10;
|
||||
public static final int PF_3BYTE_BGR = 11;
|
||||
/**
|
||||
* SurfaceTypes
|
||||
*/
|
||||
|
||||
private static final String DESC_MTL_SURFACE = "MTL Surface";
|
||||
private static final String DESC_MTL_SURFACE_RTT =
|
||||
"MTL Surface (render-to-texture)";
|
||||
private static final String DESC_MTL_TEXTURE = "MTL Texture";
|
||||
|
||||
|
||||
static final SurfaceType MTLSurface =
|
||||
SurfaceType.Any.deriveSubType(DESC_MTL_SURFACE,
|
||||
PixelConverter.ArgbPre.instance);
|
||||
static final SurfaceType MTLSurfaceRTT =
|
||||
MTLSurface.deriveSubType(DESC_MTL_SURFACE_RTT);
|
||||
static final SurfaceType MTLTexture =
|
||||
SurfaceType.Any.deriveSubType(DESC_MTL_TEXTURE);
|
||||
|
||||
protected static MTLRenderer mtlRenderPipe;
|
||||
protected static PixelToParallelogramConverter mtlTxRenderPipe;
|
||||
protected static ParallelogramPipe mtlAAPgramPipe;
|
||||
protected static MTLTextRenderer mtlTextPipe;
|
||||
protected static MTLDrawImage mtlImagePipe;
|
||||
|
||||
static {
|
||||
if (!GraphicsEnvironment.isHeadless()) {
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
mtlImagePipe = new MTLDrawImage();
|
||||
mtlTextPipe = new MTLTextRenderer(rq);
|
||||
mtlRenderPipe = new MTLRenderer(rq);
|
||||
if (GraphicsPrimitive.tracingEnabled()) {
|
||||
mtlTextPipe = mtlTextPipe.traceWrap();
|
||||
//The wrapped mtlRenderPipe will wrap the AA pipe as well...
|
||||
//mtlAAPgramPipe = mtlRenderPipe.traceWrap();
|
||||
}
|
||||
mtlAAPgramPipe = mtlRenderPipe.getAAParallelogramPipe();
|
||||
mtlTxRenderPipe =
|
||||
new PixelToParallelogramConverter(mtlRenderPipe,
|
||||
mtlRenderPipe,
|
||||
1.0, 0.25, true);
|
||||
|
||||
MTLBlitLoops.register();
|
||||
MTLMaskFill.register();
|
||||
MTLMaskBlit.register();
|
||||
}
|
||||
}
|
||||
|
||||
protected final int scale;
|
||||
protected final int width;
|
||||
protected final int height;
|
||||
protected int type;
|
||||
private MTLGraphicsConfig graphicsConfig;
|
||||
// these fields are set from the native code when the surface is
|
||||
// initialized
|
||||
private int nativeWidth;
|
||||
private int nativeHeight;
|
||||
|
||||
/**
|
||||
* Returns the appropriate SurfaceType corresponding to the given Metal
|
||||
* surface type constant (e.g. TEXTURE -> MTLTexture).
|
||||
*/
|
||||
private static SurfaceType getCustomSurfaceType(int mtlType) {
|
||||
switch (mtlType) {
|
||||
case TEXTURE:
|
||||
return MTLTexture;
|
||||
case RT_TEXTURE:
|
||||
return MTLSurfaceRTT;
|
||||
default:
|
||||
return MTLSurface;
|
||||
}
|
||||
}
|
||||
|
||||
private native void initOps(MTLGraphicsConfig gc, long pConfigInfo, long pPeerData, long layerPtr,
|
||||
int xoff, int yoff, boolean isOpaque);
|
||||
|
||||
private MTLSurfaceData(MTLLayer layer, MTLGraphicsConfig gc,
|
||||
ColorModel cm, int type, int width, int height)
|
||||
{
|
||||
super(getCustomSurfaceType(type), cm);
|
||||
this.graphicsConfig = gc;
|
||||
this.type = type;
|
||||
setBlitProxyKey(gc.getProxyKey());
|
||||
|
||||
// TEXTURE shouldn't be scaled, it is used for managed BufferedImages.
|
||||
scale = type == TEXTURE ? 1 : gc.getDevice().getScaleFactor();
|
||||
this.width = width * scale;
|
||||
this.height = height * scale;
|
||||
|
||||
long pConfigInfo = gc.getNativeConfigInfo();
|
||||
long layerPtr = 0L;
|
||||
boolean isOpaque = true;
|
||||
if (layer != null) {
|
||||
layerPtr = layer.getPointer();
|
||||
isOpaque = layer.isOpaque();
|
||||
}
|
||||
initOps(gc, pConfigInfo, 0, layerPtr, 0, 0, isOpaque);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return graphicsConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SurfaceData object representing the intermediate buffer
|
||||
* between the Java2D flusher thread and the AppKit thread.
|
||||
*/
|
||||
public static MTLLayerSurfaceData createData(MTLLayer layer) {
|
||||
MTLGraphicsConfig gc = (MTLGraphicsConfig)layer.getGraphicsConfiguration();
|
||||
Rectangle r = layer.getBounds();
|
||||
return new MTLLayerSurfaceData(layer, gc, r.width, r.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SurfaceData object representing an off-screen buffer
|
||||
*/
|
||||
public static MTLOffScreenSurfaceData createData(MTLGraphicsConfig gc,
|
||||
int width, int height,
|
||||
ColorModel cm, Image image,
|
||||
int type) {
|
||||
return new MTLOffScreenSurfaceData(gc, width, height, image, cm,
|
||||
type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDefaultScaleX() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDefaultScaleY() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
return new Rectangle(width, height);
|
||||
}
|
||||
|
||||
protected native void clearWindow();
|
||||
|
||||
protected native boolean initTexture(long pData, boolean isOpaque, int width, int height);
|
||||
|
||||
protected native boolean initRTexture(long pData, boolean isOpaque, int width, int height);
|
||||
|
||||
protected native boolean initFlipBackbuffer(long pData);
|
||||
|
||||
@Override
|
||||
public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
|
||||
return MTLSurfaceDataProxy.createProxy(srcData, graphicsConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: This should only be called from the QFT under the AWT lock.
|
||||
* This method is kept separate from the initSurface() method below just
|
||||
* to keep the code a bit cleaner.
|
||||
*/
|
||||
private void initSurfaceNow(int width, int height) {
|
||||
boolean isOpaque = (getTransparency() == Transparency.OPAQUE);
|
||||
boolean success = false;
|
||||
|
||||
switch (type) {
|
||||
case TEXTURE:
|
||||
success = initTexture(getNativeOps(), isOpaque, width, height);
|
||||
break;
|
||||
|
||||
case RT_TEXTURE:
|
||||
success = initRTexture(getNativeOps(), isOpaque, width, height);
|
||||
break;
|
||||
|
||||
case FLIP_BACKBUFFER:
|
||||
success = initFlipBackbuffer(getNativeOps());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
throw new OutOfMemoryError("can't create offscreen surface");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the appropriate Metal offscreen surface based on the value
|
||||
* of the type parameter. If the surface creation fails for any reason,
|
||||
* an OutOfMemoryError will be thrown.
|
||||
*/
|
||||
protected void initSurface(final int width, final int height) {
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
switch (type) {
|
||||
case TEXTURE:
|
||||
case RT_TEXTURE:
|
||||
// need to make sure the context is current before
|
||||
// creating the texture
|
||||
MTLContext.setScratchSurface(graphicsConfig);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
initSurfaceNow(width, height);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MTLContext for the GraphicsConfig associated with this
|
||||
* surface.
|
||||
*/
|
||||
public final MTLContext getContext() {
|
||||
return graphicsConfig.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MTLGraphicsConfig associated with this surface.
|
||||
*/
|
||||
final MTLGraphicsConfig getMTLGraphicsConfig() {
|
||||
return graphicsConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one of the surface type constants defined above.
|
||||
*/
|
||||
public final int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, we can only render LCD text if:
|
||||
* - the fragment shader extension is available, and
|
||||
* - the source color is opaque, and
|
||||
* - blending is SrcOverNoEa or disabled
|
||||
* - and the destination is opaque
|
||||
*
|
||||
* Eventually, we could enhance the native MTL text rendering code
|
||||
* and remove the above restrictions, but that would require significantly
|
||||
* more code just to support a few uncommon cases.
|
||||
*/
|
||||
public boolean canRenderLCDText(SunGraphics2D sg2d) {
|
||||
return
|
||||
sg2d.surfaceData.getTransparency() == Transparency.OPAQUE &&
|
||||
sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR &&
|
||||
(sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY ||
|
||||
(sg2d.compositeState <= SunGraphics2D.COMP_ALPHA && canHandleComposite(sg2d.composite)));
|
||||
}
|
||||
|
||||
private boolean canHandleComposite(Composite c) {
|
||||
if (c instanceof AlphaComposite) {
|
||||
AlphaComposite ac = (AlphaComposite)c;
|
||||
|
||||
return ac.getRule() == AlphaComposite.SRC_OVER && ac.getAlpha() >= 1f;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void validatePipe(SunGraphics2D sg2d) {
|
||||
TextPipe textpipe;
|
||||
boolean validated = false;
|
||||
|
||||
// MTLTextRenderer handles both AA and non-AA text, but
|
||||
// only works with the following modes:
|
||||
// (Note: For LCD text we only enter this code path if
|
||||
// canRenderLCDText() has already validated that the mode is
|
||||
// CompositeType.SrcNoEa (opaque color), which will be subsumed
|
||||
// by the CompositeType.SrcNoEa (any color) test below.)
|
||||
|
||||
if (/* CompositeType.SrcNoEa (any color) */
|
||||
(sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
|
||||
sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) ||
|
||||
|
||||
/* CompositeType.SrcOver (any color) */
|
||||
(sg2d.compositeState == SunGraphics2D.COMP_ALPHA &&
|
||||
sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
|
||||
(((AlphaComposite)sg2d.composite).getRule() ==
|
||||
AlphaComposite.SRC_OVER)) ||
|
||||
|
||||
/* CompositeType.Xor (any color) */
|
||||
(sg2d.compositeState == SunGraphics2D.COMP_XOR &&
|
||||
sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR))
|
||||
{
|
||||
textpipe = mtlTextPipe;
|
||||
} else {
|
||||
// do this to initialize textpipe correctly; we will attempt
|
||||
// to override the non-text pipes below
|
||||
super.validatePipe(sg2d);
|
||||
textpipe = sg2d.textpipe;
|
||||
validated = true;
|
||||
}
|
||||
|
||||
PixelToParallelogramConverter txPipe = null;
|
||||
MTLRenderer nonTxPipe = null;
|
||||
|
||||
if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
|
||||
if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
|
||||
if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) {
|
||||
txPipe = mtlTxRenderPipe;
|
||||
nonTxPipe = mtlRenderPipe;
|
||||
}
|
||||
} else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {
|
||||
if (MTLPaints.isValid(sg2d)) {
|
||||
txPipe = mtlTxRenderPipe;
|
||||
nonTxPipe = mtlRenderPipe;
|
||||
}
|
||||
// custom paints handled by super.validatePipe() below
|
||||
}
|
||||
} else {
|
||||
if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
|
||||
if (graphicsConfig.isCapPresent(CAPS_PS30) &&
|
||||
(sg2d.imageComp == CompositeType.SrcOverNoEa ||
|
||||
sg2d.imageComp == CompositeType.SrcOver))
|
||||
{
|
||||
if (!validated) {
|
||||
super.validatePipe(sg2d);
|
||||
validated = true;
|
||||
}
|
||||
PixelToParallelogramConverter aaConverter =
|
||||
new PixelToParallelogramConverter(sg2d.shapepipe,
|
||||
mtlAAPgramPipe,
|
||||
1.0/8.0, 0.499,
|
||||
false);
|
||||
sg2d.drawpipe = aaConverter;
|
||||
sg2d.fillpipe = aaConverter;
|
||||
sg2d.shapepipe = aaConverter;
|
||||
} else if (sg2d.compositeState == SunGraphics2D.COMP_XOR) {
|
||||
// install the solid pipes when AA and XOR are both enabled
|
||||
txPipe = mtlTxRenderPipe;
|
||||
nonTxPipe = mtlRenderPipe;
|
||||
}
|
||||
}
|
||||
// other cases handled by super.validatePipe() below
|
||||
}
|
||||
|
||||
if (txPipe != null) {
|
||||
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
|
||||
sg2d.drawpipe = txPipe;
|
||||
sg2d.fillpipe = txPipe;
|
||||
} else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {
|
||||
sg2d.drawpipe = txPipe;
|
||||
sg2d.fillpipe = nonTxPipe;
|
||||
} else {
|
||||
sg2d.drawpipe = nonTxPipe;
|
||||
sg2d.fillpipe = nonTxPipe;
|
||||
}
|
||||
// Note that we use the transforming pipe here because it
|
||||
// will examine the shape and possibly perform an optimized
|
||||
// operation if it can be simplified. The simplifications
|
||||
// will be valid for all STROKE and TRANSFORM types.
|
||||
sg2d.shapepipe = txPipe;
|
||||
} else {
|
||||
if (!validated) {
|
||||
super.validatePipe(sg2d);
|
||||
}
|
||||
}
|
||||
|
||||
// install the text pipe based on our earlier decision
|
||||
sg2d.textpipe = textpipe;
|
||||
|
||||
// always override the image pipe with the specialized MTL pipe
|
||||
sg2d.imagepipe = mtlImagePipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MaskFill getMaskFill(SunGraphics2D sg2d) {
|
||||
if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR) {
|
||||
/*
|
||||
* We can only accelerate non-Color MaskFill operations if
|
||||
* all of the following conditions hold true:
|
||||
* - there is an implementation for the given paintState
|
||||
* - the current Paint can be accelerated for this destination
|
||||
* - multitexturing is available (since we need to modulate
|
||||
* the alpha mask texture with the paint texture)
|
||||
*
|
||||
* In all other cases, we return null, in which case the
|
||||
* validation code will choose a more general software-based loop.
|
||||
*/
|
||||
if (!MTLPaints.isValid(sg2d) ||
|
||||
!graphicsConfig.isCapPresent(CAPS_MULTITEXTURE))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return super.getMaskFill(sg2d);
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
invalidate();
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// make sure we have a current context before
|
||||
// disposing the native resources (e.g. texture object)
|
||||
MTLContext.setScratchSurface(graphicsConfig);
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(FLUSH_SURFACE);
|
||||
buf.putLong(getNativeOps());
|
||||
|
||||
// this call is expected to complete synchronously, so flush now
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOnScreen() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private native long getMTLTexturePointer(long pData);
|
||||
|
||||
/**
|
||||
* Returns native resource of specified {@code resType} associated with
|
||||
* this surface.
|
||||
*
|
||||
* Specifically, for {@code MTLSurfaceData} this method returns the
|
||||
* the following:
|
||||
* <pre>
|
||||
* TEXTURE - texture id
|
||||
* </pre>
|
||||
*
|
||||
* Note: the resource returned by this method is only valid on the rendering
|
||||
* thread.
|
||||
*
|
||||
* @return native resource of specified type or 0L if
|
||||
* such resource doesn't exist or can not be retrieved.
|
||||
* @see AccelSurface#getNativeResource
|
||||
*/
|
||||
public long getNativeResource(int resType) {
|
||||
if (resType == TEXTURE) {
|
||||
return getMTLTexturePointer(getNativeOps());
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
public Raster getRaster(int x, int y, int w, int h) {
|
||||
throw new InternalError("not implemented yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h,
|
||||
int dx, int dy) {
|
||||
if (sg2d.compositeState >= SunGraphics2D.COMP_XOR) {
|
||||
return false;
|
||||
}
|
||||
mtlRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy);
|
||||
return true;
|
||||
}
|
||||
|
||||
public Rectangle getNativeBounds() {
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
return new Rectangle(nativeWidth, nativeHeight);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A surface which implements an intermediate buffer between
|
||||
* the Java2D flusher thread and the AppKit thread.
|
||||
*
|
||||
* This surface serves as a buffer attached to a MTLLayer and
|
||||
* the layer redirects all painting to the buffer's graphics.
|
||||
*/
|
||||
public static class MTLLayerSurfaceData extends MTLSurfaceData {
|
||||
|
||||
private final MTLLayer layer;
|
||||
|
||||
private MTLLayerSurfaceData(MTLLayer layer, MTLGraphicsConfig gc,
|
||||
int width, int height) {
|
||||
super(layer, gc, gc.getColorModel(), RT_TEXTURE, width, height);
|
||||
this.layer = layer;
|
||||
initSurface(this.width, this.height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData getReplacement() {
|
||||
return layer.getSurfaceData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnScreen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDestination() {
|
||||
return layer.getDestination();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransparency() {
|
||||
return layer.getTransparency();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
super.invalidate();
|
||||
clearWindow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SurfaceData object representing an off-screen buffer
|
||||
*/
|
||||
public static class MTLOffScreenSurfaceData extends MTLSurfaceData {
|
||||
private final Image offscreenImage;
|
||||
|
||||
public MTLOffScreenSurfaceData(MTLGraphicsConfig gc, int width,
|
||||
int height, Image image,
|
||||
ColorModel cm, int type) {
|
||||
super(null, gc, cm, type, width, height);
|
||||
offscreenImage = image;
|
||||
initSurface(this.width, this.height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData getReplacement() {
|
||||
return restoreContents(offscreenImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns destination Image associated with this SurfaceData.
|
||||
*/
|
||||
@Override
|
||||
public Object getDestination() {
|
||||
return offscreenImage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disposes the native resources associated with the given MTLSurfaceData
|
||||
* (referenced by the pData parameter). This method is invoked from
|
||||
* the native Dispose() method from the Disposer thread when the
|
||||
* Java-level MTLSurfaceData object is about to go away.
|
||||
*/
|
||||
public static void dispose(long pData, MTLGraphicsConfig gc) {
|
||||
MTLRenderQueue rq = MTLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// make sure we have a current context before
|
||||
// disposing the native resources (e.g. texture object)
|
||||
MTLContext.setScratchSurface(gc);
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(DISPOSE_SURFACE);
|
||||
buf.putLong(pData);
|
||||
|
||||
// this call is expected to complete synchronously, so flush now
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.SurfaceDataProxy;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Transparency;
|
||||
|
||||
/**
|
||||
* The proxy class contains the logic for when to replace a
|
||||
* SurfaceData with a cached MTL Texture and the code to create
|
||||
* the accelerated surfaces.
|
||||
*/
|
||||
public class MTLSurfaceDataProxy extends SurfaceDataProxy {
|
||||
public static SurfaceDataProxy createProxy(SurfaceData srcData,
|
||||
MTLGraphicsConfig dstConfig)
|
||||
{
|
||||
if (srcData instanceof MTLSurfaceData) {
|
||||
// srcData must be a VolatileImage which either matches
|
||||
// our pixel format or not - either way we do not cache it...
|
||||
return UNCACHED;
|
||||
}
|
||||
|
||||
return new MTLSurfaceDataProxy(dstConfig, srcData.getTransparency());
|
||||
}
|
||||
|
||||
MTLGraphicsConfig mtlgc;
|
||||
int transparency;
|
||||
|
||||
public MTLSurfaceDataProxy(MTLGraphicsConfig mtlgc, int transparency) {
|
||||
this.mtlgc = mtlgc;
|
||||
this.transparency = transparency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData validateSurfaceData(SurfaceData srcData,
|
||||
SurfaceData cachedData,
|
||||
int w, int h)
|
||||
{
|
||||
if (cachedData == null) {
|
||||
try {
|
||||
cachedData = mtlgc.createManagedSurface(w, h, transparency);
|
||||
} catch (OutOfMemoryError er) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedOperation(SurfaceData srcData,
|
||||
int txtype,
|
||||
CompositeType comp,
|
||||
Color bgColor)
|
||||
{
|
||||
return comp.isDerivedFrom(CompositeType.AnyAlpha) &&
|
||||
(bgColor == null || transparency == Transparency.OPAQUE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.font.GlyphList;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.BufferedTextPipe;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
|
||||
import java.awt.Composite;
|
||||
|
||||
class MTLTextRenderer extends BufferedTextPipe {
|
||||
|
||||
MTLTextRenderer(RenderQueue rq) {
|
||||
super(rq);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected native void drawGlyphList(int numGlyphs, boolean usePositions,
|
||||
boolean subPixPos, boolean rgbOrder,
|
||||
int lcdContrast,
|
||||
float glOrigX, float glOrigY,
|
||||
long[] images, float[] positions);
|
||||
|
||||
@Override
|
||||
protected void validateContext(SunGraphics2D sg2d, Composite comp) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
MTLSurfaceData mtlDst = (MTLSurfaceData)sg2d.surfaceData;
|
||||
MTLContext.validateContext(mtlDst, mtlDst,
|
||||
sg2d.getCompClip(), comp,
|
||||
null, sg2d.paint, sg2d,
|
||||
MTLContext.NO_CONTEXT_FLAGS);
|
||||
}
|
||||
|
||||
MTLTextRenderer traceWrap() {
|
||||
return new Tracer(this);
|
||||
}
|
||||
|
||||
private static class Tracer extends MTLTextRenderer {
|
||||
Tracer(MTLTextRenderer mtltr) {
|
||||
super(mtltr.rq);
|
||||
}
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
|
||||
GraphicsPrimitive.tracePrimitive("MTLDrawGlyphs");
|
||||
super.drawGlyphList(sg2d, gl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.metal;
|
||||
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.VolatileSurfaceManager;
|
||||
import sun.java2d.SurfaceData;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.ColorModel;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
|
||||
public class MTLVolatileSurfaceManager extends VolatileSurfaceManager {
|
||||
|
||||
private final boolean accelerationEnabled;
|
||||
|
||||
public MTLVolatileSurfaceManager(SunVolatileImage vImg, Object context) {
|
||||
super(vImg, context);
|
||||
|
||||
/*
|
||||
* We will attempt to accelerate this image only
|
||||
* if the image is not bitmask
|
||||
*/
|
||||
int transparency = vImg.getTransparency();
|
||||
accelerationEnabled = transparency != Transparency.BITMASK;
|
||||
}
|
||||
|
||||
protected boolean isAccelerationEnabled() {
|
||||
return accelerationEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SurfaceData object (or init the backbuffer
|
||||
* of an existing window if this is a double buffered GraphicsConfig)
|
||||
*/
|
||||
protected SurfaceData initAcceleratedSurface() {
|
||||
try {
|
||||
MTLGraphicsConfig gc =
|
||||
(MTLGraphicsConfig)vImg.getGraphicsConfig();
|
||||
ColorModel cm = gc.getColorModel(vImg.getTransparency());
|
||||
int type = vImg.getForcedAccelSurfaceType();
|
||||
// if acceleration type is forced (type != UNDEFINED) then
|
||||
// use the forced type, otherwise choose RT_TEXTURE
|
||||
if (type == AccelSurface.UNDEFINED) {
|
||||
type = AccelSurface.RT_TEXTURE;
|
||||
}
|
||||
return MTLSurfaceData.createData(gc,
|
||||
vImg.getWidth(),
|
||||
vImg.getHeight(),
|
||||
cm, vImg, type);
|
||||
} catch (NullPointerException | OutOfMemoryError ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isConfigValid(GraphicsConfiguration gc) {
|
||||
return ((gc == null) || (gc == vImg.getGraphicsConfig()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initContents() {
|
||||
if (vImg.getForcedAccelSurfaceType() != AccelSurface.TEXTURE) {
|
||||
super.initContents();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -55,6 +55,7 @@ import sun.java2d.pipe.hw.AccelSurface;
|
||||
import sun.java2d.pipe.hw.AccelTypedVolatileImage;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
import sun.lwawt.LWComponentPeer;
|
||||
import sun.lwawt.macosx.CFRetainedResource;
|
||||
|
||||
import static sun.java2d.opengl.OGLContext.OGLContextCaps.CAPS_DOUBLEBUFFERED;
|
||||
import static sun.java2d.opengl.OGLContext.OGLContextCaps.CAPS_EXT_FBOBJECT;
|
||||
@@ -248,8 +249,8 @@ public final class CGLGraphicsConfig extends CGraphicsConfig
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData createSurfaceData(CGLLayer layer) {
|
||||
return CGLSurfaceData.createData(layer);
|
||||
public SurfaceData createSurfaceData(CFRetainedResource layer) {
|
||||
return CGLSurfaceData.createData((CGLLayer) layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -68,14 +68,17 @@ import javax.swing.SwingUtilities;
|
||||
|
||||
import com.sun.java.swing.SwingUtilities3;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.CGraphicsDevice;
|
||||
import sun.awt.PaintEventDispatcher;
|
||||
import sun.awt.RepaintArea;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.event.IgnorePaintEvent;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.metal.MTLRenderQueue;
|
||||
import sun.java2d.opengl.OGLRenderQueue;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
public abstract class LWComponentPeer<T extends Component, D extends JComponent>
|
||||
@@ -1414,7 +1417,8 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
|
||||
}
|
||||
|
||||
protected static final void flushOnscreenGraphics(){
|
||||
final OGLRenderQueue rq = OGLRenderQueue.getInstance();
|
||||
RenderQueue rq = CGraphicsDevice.usingMetalPipeline() ?
|
||||
MTLRenderQueue.getInstance() : OGLRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushNow();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -28,12 +28,16 @@ package sun.lwawt.macosx;
|
||||
import java.awt.*;
|
||||
import java.awt.event.FocusEvent;
|
||||
|
||||
import sun.awt.CGraphicsDevice;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.metal.MTLLayer;
|
||||
import sun.java2d.opengl.CGLLayer;
|
||||
import sun.lwawt.LWWindowPeer;
|
||||
import sun.lwawt.PlatformWindow;
|
||||
import sun.lwawt.macosx.CFRetainedResource;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
|
||||
/*
|
||||
* Provides a lightweight implementation of the EmbeddedFrame.
|
||||
*/
|
||||
@@ -42,7 +46,7 @@ public class CPlatformEmbeddedFrame implements PlatformWindow {
|
||||
private static final PlatformLogger focusLogger = PlatformLogger.getLogger(
|
||||
"sun.lwawt.macosx.focus.CPlatformEmbeddedFrame");
|
||||
|
||||
private CGLLayer windowLayer;
|
||||
private CFRetainedResource windowLayer;
|
||||
private LWWindowPeer peer;
|
||||
private CEmbeddedFrame target;
|
||||
|
||||
@@ -52,7 +56,11 @@ public class CPlatformEmbeddedFrame implements PlatformWindow {
|
||||
@Override // PlatformWindow
|
||||
public void initialize(Window target, final LWWindowPeer peer, PlatformWindow owner) {
|
||||
this.peer = peer;
|
||||
this.windowLayer = new CGLLayer(peer);
|
||||
if (CGraphicsDevice.usingMetalPipeline()) {
|
||||
this.windowLayer = new MTLLayer(peer);
|
||||
} else {
|
||||
this.windowLayer = new CGLLayer(peer);
|
||||
}
|
||||
this.target = (CEmbeddedFrame)target;
|
||||
}
|
||||
|
||||
@@ -63,12 +71,20 @@ public class CPlatformEmbeddedFrame implements PlatformWindow {
|
||||
|
||||
@Override
|
||||
public long getLayerPtr() {
|
||||
return windowLayer.getPointer();
|
||||
if (CGraphicsDevice.usingMetalPipeline()) {
|
||||
return ((MTLLayer)windowLayer).getPointer();
|
||||
} else {
|
||||
return ((CGLLayer)windowLayer).getPointer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
windowLayer.dispose();
|
||||
if (CGraphicsDevice.usingMetalPipeline()) {
|
||||
((MTLLayer)windowLayer).dispose();
|
||||
} else {
|
||||
((CGLLayer)windowLayer).dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,12 +115,20 @@ public class CPlatformEmbeddedFrame implements PlatformWindow {
|
||||
|
||||
@Override
|
||||
public SurfaceData getScreenSurface() {
|
||||
return windowLayer.getSurfaceData();
|
||||
if ( CGraphicsDevice.usingMetalPipeline()) {
|
||||
return ((MTLLayer)windowLayer).getSurfaceData();
|
||||
} else {
|
||||
return ((CGLLayer)windowLayer).getSurfaceData();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData replaceSurfaceData() {
|
||||
return windowLayer.replaceSurfaceData();
|
||||
if (CGraphicsDevice.usingMetalPipeline()) {
|
||||
return ((MTLLayer)windowLayer).replaceSurfaceData();
|
||||
} else {
|
||||
return ((CGLLayer)windowLayer).replaceSurfaceData();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -35,9 +35,12 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import sun.awt.CGraphicsEnvironment;
|
||||
import sun.awt.CGraphicsDevice;
|
||||
import sun.java2d.metal.MTLLayer;
|
||||
import sun.lwawt.LWWindowPeer;
|
||||
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.opengl.CGLLayer;
|
||||
import sun.lwawt.LWWindowPeer;
|
||||
|
||||
public class CPlatformView extends CFRetainedResource {
|
||||
private native long nativeCreateView(int x, int y, int width, int height, long windowLayerPtr);
|
||||
@@ -48,7 +51,7 @@ public class CPlatformView extends CFRetainedResource {
|
||||
|
||||
private LWWindowPeer peer;
|
||||
private SurfaceData surfaceData;
|
||||
private CGLLayer windowLayer;
|
||||
private CFRetainedResource windowLayer;
|
||||
private CPlatformResponder responder;
|
||||
|
||||
public CPlatformView() {
|
||||
@@ -58,7 +61,7 @@ public class CPlatformView extends CFRetainedResource {
|
||||
public void initialize(LWWindowPeer peer, CPlatformResponder responder) {
|
||||
initializeBase(peer, responder);
|
||||
|
||||
this.windowLayer = createCGLayer();
|
||||
this.windowLayer = CGraphicsDevice.usingMetalPipeline()? createMTLLayer() : createCGLayer();
|
||||
setPtr(nativeCreateView(0, 0, 0, 0, getWindowLayerPtr()));
|
||||
}
|
||||
|
||||
@@ -66,6 +69,11 @@ public class CPlatformView extends CFRetainedResource {
|
||||
return new CGLLayer(peer);
|
||||
}
|
||||
|
||||
public MTLLayer createMTLLayer() {
|
||||
return new MTLLayer(peer);
|
||||
}
|
||||
|
||||
|
||||
protected void initializeBase(LWWindowPeer peer, CPlatformResponder responder) {
|
||||
this.peer = peer;
|
||||
this.responder = responder;
|
||||
@@ -96,7 +104,10 @@ public class CPlatformView extends CFRetainedResource {
|
||||
// PAINTING METHODS
|
||||
// ----------------------------------------------------------------------
|
||||
public SurfaceData replaceSurfaceData() {
|
||||
surfaceData = windowLayer.replaceSurfaceData();
|
||||
surfaceData = (CGraphicsDevice.usingMetalPipeline()) ?
|
||||
((MTLLayer)windowLayer).replaceSurfaceData() :
|
||||
((CGLLayer)windowLayer).replaceSurfaceData()
|
||||
;
|
||||
return surfaceData;
|
||||
}
|
||||
|
||||
@@ -111,7 +122,9 @@ public class CPlatformView extends CFRetainedResource {
|
||||
}
|
||||
|
||||
public long getWindowLayerPtr() {
|
||||
return windowLayer.getPointer();
|
||||
return CGraphicsDevice.usingMetalPipeline() ?
|
||||
((MTLLayer)windowLayer).getPointer() :
|
||||
((CGLLayer)windowLayer).getPointer();
|
||||
}
|
||||
|
||||
public void setAutoResizable(boolean toResize) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -29,6 +29,7 @@ import sun.awt.AWTAccessor;
|
||||
import sun.awt.IconInfo;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.metal.MTLLayer;
|
||||
import sun.java2d.opengl.CGLLayer;
|
||||
import sun.lwawt.LWWindowPeer;
|
||||
import sun.lwawt.PlatformEventNotifier;
|
||||
@@ -300,6 +301,23 @@ public final class CWarningWindow extends CPlatformWindow
|
||||
}
|
||||
};
|
||||
}
|
||||
public MTLLayer createMTLLayer() {
|
||||
return new MTLLayer(null) {
|
||||
public Rectangle getBounds() {
|
||||
return CWarningWindow.this.getBounds();
|
||||
}
|
||||
|
||||
public GraphicsConfiguration getGraphicsConfiguration() {
|
||||
LWWindowPeer peer = ownerPeer.get();
|
||||
return peer.getGraphicsConfiguration();
|
||||
}
|
||||
|
||||
public boolean isOpaque() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -109,6 +109,7 @@ import sun.awt.SunToolkit;
|
||||
import sun.awt.datatransfer.DataTransferer;
|
||||
import sun.awt.dnd.SunDragSourceContextPeer;
|
||||
import sun.awt.util.ThreadGroupUtils;
|
||||
import sun.java2d.metal.MTLRenderQueue;
|
||||
import sun.java2d.opengl.OGLRenderQueue;
|
||||
import sun.lwawt.LWComponentPeer;
|
||||
import sun.lwawt.LWCursorManager;
|
||||
@@ -500,8 +501,12 @@ public final class LWCToolkit extends LWToolkit {
|
||||
|
||||
@Override
|
||||
public void sync() {
|
||||
// flush the OGL pipeline (this is a no-op if OGL is not enabled)
|
||||
OGLRenderQueue.sync();
|
||||
// flush the rendering pipeline
|
||||
if (CGraphicsDevice.usingMetalPipeline()) {
|
||||
MTLRenderQueue.sync();
|
||||
} else {
|
||||
OGLRenderQueue.sync();
|
||||
}
|
||||
// setNeedsDisplay() selector was sent to the appropriate CALayer so now
|
||||
// we have to flush the native selectors queue.
|
||||
flushNativeSelectors();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -29,6 +29,7 @@
|
||||
#import "JNIUtilities.h"
|
||||
|
||||
#import <QuartzCore/CATransaction.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
@implementation AWTSurfaceLayers
|
||||
|
||||
@@ -67,10 +68,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Updates back buffer size of the layer if it's an OpenGL layer
|
||||
// including all OpenGL sublayers
|
||||
// Updates back buffer size of the layer if it's an OpenGL/Metal layer
|
||||
// including all OpenGL/Metal sublayers
|
||||
+ (void) repaintLayersRecursively:(CALayer*)aLayer {
|
||||
if ([aLayer isKindOfClass:[CAOpenGLLayer class]]) {
|
||||
if ([aLayer isKindOfClass:[CAOpenGLLayer class]] ||
|
||||
[aLayer isKindOfClass:[CAMetalLayer class]]) {
|
||||
[aLayer setNeedsDisplay];
|
||||
}
|
||||
for(CALayer *child in aLayer.sublayers) {
|
||||
@@ -92,7 +94,7 @@
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CPlatformComponent
|
||||
* Method: nativeCreateLayer
|
||||
* Method: nativeCreateComponent
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef EncoderManager_h_Included
|
||||
#define EncoderManager_h_Included
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
#include "RenderOptions.h"
|
||||
|
||||
@class MTLContex;
|
||||
|
||||
/**
|
||||
* The EncoderManager class used to obtain MTLRenderCommandEncoder (or MTLBlitCommandEncoder) corresponding
|
||||
* to the current state of MTLContext.
|
||||
*
|
||||
* Due to performance issues (creation of MTLRenderCommandEncoder isn't cheap), each getXXXEncoder invocation
|
||||
* updates properties of common (cached) encoder and returns this encoder.
|
||||
*
|
||||
* Base method getEncoder does the following:
|
||||
* 1. Checks whether common encoder must be closed and recreated (some of encoder properties is 'persistent',
|
||||
* for example destination, stencil, or any other property of MTLRenderPassDescriptor)
|
||||
* 2. Updates 'mutable' properties encoder: pipelineState (with corresponding buffers), clip, transform, e.t.c. To avoid
|
||||
* unnecessary calls of [encoder setXXX] this manager compares requested state with cached one.
|
||||
*/
|
||||
@interface EncoderManager : NSObject
|
||||
- (id _Nonnull)init;
|
||||
- (void)dealloc;
|
||||
|
||||
- (void)setContext:(MTLContex * _Nonnull)mtlc;
|
||||
|
||||
// returns encoder that renders/fills geometry with current paint and composite
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getRenderEncoder:(const BMTLSDOps * _Nonnull)dstOps;
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getAARenderEncoder:(const BMTLSDOps * _Nonnull)dstOps;
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getRenderEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isDstOpaque:(bool)isOpaque;
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getAAShaderRenderEncoder:(const BMTLSDOps * _Nonnull)dstOps;
|
||||
|
||||
// returns encoder that renders/fills geometry with current composite and with given texture
|
||||
// (user must call [encoder setFragmentTexture] before any rendering)
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getTextureEncoder:(const BMTLSDOps * _Nonnull)dstOps
|
||||
isSrcOpaque:(bool)isSrcOpaque;
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getTextureEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
isDstOpaque:(bool)isDstOpaque;
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getLCDEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
isDstOpaque:(bool)isDstOpaque;
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getTextureEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
isDstOpaque:(bool)isDstOpaque
|
||||
interpolation:(int)interpolation;
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getTextureEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
isDstOpaque:(bool)isDstOpaque
|
||||
interpolation:(int)interpolation
|
||||
isAA:(jboolean)isAA;
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getTextEncoder:(const BMTLSDOps * _Nonnull)dstOps
|
||||
isSrcOpaque:(bool)isSrcOpaque;
|
||||
|
||||
// Base method to obtain any MTLRenderCommandEncoder
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isDestOpaque:(jboolean)isDestOpaque
|
||||
renderOptions:(const RenderOptions * _Nonnull)renderOptions;
|
||||
|
||||
- (id<MTLBlitCommandEncoder> _Nonnull)createBlitEncoder;
|
||||
|
||||
- (void)endEncoder;
|
||||
@end
|
||||
|
||||
#endif // EncoderManager_h_Included
|
||||
@@ -0,0 +1,465 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "EncoderManager.h"
|
||||
#include "MTLContext.h"
|
||||
#include "sun_java2d_SunGraphics2D.h"
|
||||
#import "common.h"
|
||||
|
||||
// NOTE: uncomment to disable comparing cached encoder states with requested (for debugging)
|
||||
// #define ALWAYS_UPDATE_ENCODER_STATES
|
||||
|
||||
const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE };
|
||||
|
||||
// Internal utility class that represents the set of 'mutable' encoder properties
|
||||
@interface EncoderStates : NSObject
|
||||
@property (readonly) MTLClip * clip;
|
||||
|
||||
- (id)init;
|
||||
- (void)dealloc;
|
||||
|
||||
- (void)reset:(id<MTLTexture>)destination
|
||||
isDstOpaque:(jboolean)isDstOpaque
|
||||
isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
isAA:(jboolean)isAA
|
||||
isText:(jboolean)isText
|
||||
isLCD:(jboolean)isLCD;
|
||||
|
||||
- (void)updateEncoder:(id<MTLRenderCommandEncoder>)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
forceUpdate:(jboolean)forceUpdate;
|
||||
@property (assign) jboolean aa;
|
||||
@property (assign) jboolean text;
|
||||
@property (assign) jboolean lcd;
|
||||
@property (assign) jboolean aaShader;
|
||||
@property (retain) MTLPaint* paint;
|
||||
@end
|
||||
|
||||
@implementation EncoderStates {
|
||||
MTLPipelineStatesStorage * _pipelineStateStorage;
|
||||
id<MTLDevice> _device;
|
||||
|
||||
// Persistent encoder properties
|
||||
id<MTLTexture> _destination;
|
||||
SurfaceRasterFlags _dstFlags;
|
||||
|
||||
jboolean _isAA;
|
||||
jboolean _isText;
|
||||
jboolean _isLCD;
|
||||
jboolean _isAAShader;
|
||||
|
||||
//
|
||||
// Cached 'mutable' states of encoder
|
||||
//
|
||||
|
||||
// Composite rule and source raster flags (it affects the CAD-multipliers (of pipelineState))
|
||||
MTLComposite * _composite;
|
||||
SurfaceRasterFlags _srcFlags;
|
||||
|
||||
// Paint mode (it affects shaders (of pipelineState) and corresponding buffers)
|
||||
MTLPaint * _paint;
|
||||
|
||||
// If true, indicates that encoder is used for texture drawing (user must do [encoder setFragmentTexture:] before drawing)
|
||||
jboolean _isTexture;
|
||||
int _interpolationMode;
|
||||
|
||||
// Clip rect or stencil
|
||||
MTLClip * _clip;
|
||||
|
||||
// Transform (affects transformation inside vertex shader)
|
||||
MTLTransform * _transform;
|
||||
}
|
||||
@synthesize aa = _isAA;
|
||||
@synthesize text = _isText;
|
||||
@synthesize lcd = _isLCD;
|
||||
@synthesize aaShader = _isAAShader;
|
||||
@synthesize paint = _paint;
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_destination = nil;
|
||||
_composite = [[MTLComposite alloc] init];
|
||||
_paint = [[MTLPaint alloc] init];
|
||||
_transform = [[MTLTransform alloc] init];
|
||||
_clip = [[MTLClip alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_composite release];
|
||||
[_paint release];
|
||||
[_transform release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)setContext:(MTLContext * _Nonnull)mtlc {
|
||||
self->_pipelineStateStorage = mtlc.pipelineStateStorage;
|
||||
self->_device = mtlc.device;
|
||||
}
|
||||
|
||||
- (void)reset:(id<MTLTexture>)destination
|
||||
isDstOpaque:(jboolean)isDstOpaque
|
||||
isDstPremultiplied:(jboolean)isDstPremultiplied
|
||||
isAA:(jboolean)isAA
|
||||
isText:(jboolean)isText
|
||||
isLCD:(jboolean)isLCD {
|
||||
_destination = destination;
|
||||
_dstFlags.isOpaque = isDstOpaque;
|
||||
_dstFlags.isPremultiplied = isDstPremultiplied;
|
||||
_isAA = isAA;
|
||||
_isText = isText;
|
||||
_isLCD = isLCD;
|
||||
// NOTE: probably it's better to invalidate/reset all cached states now
|
||||
}
|
||||
|
||||
- (void)updateEncoder:(id<MTLRenderCommandEncoder>)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
forceUpdate:(jboolean)forceUpdate
|
||||
{
|
||||
// 1. Process special case for stencil mask generation
|
||||
if (mtlc.clip.stencilMaskGenerationInProgress == JNI_TRUE) {
|
||||
// use separate pipeline state for stencil generation
|
||||
if (forceUpdate || (_clip.stencilMaskGenerationInProgress != JNI_TRUE)) {
|
||||
[_clip copyFrom:mtlc.clip];
|
||||
[_clip setMaskGenerationPipelineState:encoder
|
||||
destWidth:_destination.width
|
||||
destHeight:_destination.height
|
||||
pipelineStateStorage:_pipelineStateStorage];
|
||||
}
|
||||
|
||||
[self updateTransform:encoder transform:mtlc.transform forceUpdate:forceUpdate];
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Otherwise update all 'mutable' properties of encoder
|
||||
[self updatePipelineState:encoder
|
||||
context:mtlc
|
||||
renderOptions:renderOptions
|
||||
forceUpdate:forceUpdate];
|
||||
[self updateTransform:encoder transform:mtlc.transform forceUpdate:forceUpdate];
|
||||
[self updateClip:encoder clip:mtlc.clip forceUpdate:forceUpdate];
|
||||
}
|
||||
|
||||
//
|
||||
// Internal methods that update states when necessary (compare with cached states)
|
||||
//
|
||||
|
||||
// Updates pipelineState (and corresponding buffers) with use of paint+composite+flags
|
||||
- (void)updatePipelineState:(id<MTLRenderCommandEncoder>)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
forceUpdate:(jboolean)forceUpdate
|
||||
{
|
||||
if (!forceUpdate
|
||||
&& [_paint isEqual:mtlc.paint]
|
||||
&& [_composite isEqual:mtlc.composite]
|
||||
&& (_isTexture == renderOptions->isTexture && (!renderOptions->isTexture || _interpolationMode == renderOptions->interpolation)) // interpolation is used only in texture mode
|
||||
&& _isAA == renderOptions->isAA
|
||||
&& _isAAShader == renderOptions->isAAShader
|
||||
&& _isText == renderOptions->isText
|
||||
&& _isLCD == renderOptions->isLCD
|
||||
&& _srcFlags.isOpaque == renderOptions->srcFlags.isOpaque && _srcFlags.isPremultiplied == renderOptions->srcFlags.isPremultiplied)
|
||||
return;
|
||||
|
||||
self.paint = mtlc.paint;
|
||||
[_composite copyFrom:mtlc.composite];
|
||||
_isTexture = renderOptions->isTexture;
|
||||
_interpolationMode = renderOptions->interpolation;
|
||||
_isAA = renderOptions->isAA;
|
||||
_isAAShader = renderOptions->isAAShader;
|
||||
_isText = renderOptions->isText;
|
||||
_isLCD = renderOptions->isLCD;
|
||||
_srcFlags = renderOptions->srcFlags;
|
||||
|
||||
if ((jint)[mtlc.composite getCompositeState] == sun_java2d_SunGraphics2D_COMP_XOR) {
|
||||
|
||||
[mtlc.paint setXorModePipelineState:encoder
|
||||
context:mtlc
|
||||
renderOptions:renderOptions
|
||||
pipelineStateStorage:_pipelineStateStorage];
|
||||
} else {
|
||||
[mtlc.paint setPipelineState:encoder
|
||||
context:mtlc
|
||||
renderOptions:renderOptions
|
||||
pipelineStateStorage:_pipelineStateStorage];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) updateClip:(id<MTLRenderCommandEncoder>)encoder clip:(MTLClip *)clip forceUpdate:(jboolean)forceUpdate
|
||||
{
|
||||
if (clip.stencilMaskGenerationInProgress == JNI_TRUE) {
|
||||
// don't set setScissorOrStencil when generation in progress
|
||||
return;
|
||||
}
|
||||
|
||||
if (!forceUpdate && [_clip isEqual:clip])
|
||||
return;
|
||||
|
||||
[_clip copyFrom:clip];
|
||||
[_clip setScissorOrStencil:encoder
|
||||
destWidth:_destination.width
|
||||
destHeight:_destination.height
|
||||
device:_device];
|
||||
}
|
||||
|
||||
- (void)updateTransform:(id <MTLRenderCommandEncoder>)encoder
|
||||
transform:(MTLTransform *)transform
|
||||
forceUpdate:(jboolean)forceUpdate
|
||||
{
|
||||
if (!forceUpdate
|
||||
&& [_transform isEqual:transform])
|
||||
return;
|
||||
|
||||
[_transform copyFrom:transform];
|
||||
[_transform setVertexMatrix:encoder
|
||||
destWidth:_destination.width
|
||||
destHeight:_destination.height];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation EncoderManager {
|
||||
MTLContext * _mtlc; // used to obtain CommandBufferWrapper and Composite/Paint/Transform
|
||||
|
||||
id<MTLRenderCommandEncoder> _encoder;
|
||||
|
||||
// 'Persistent' properties of encoder
|
||||
id<MTLTexture> _destination;
|
||||
id<MTLTexture> _aaDestination;
|
||||
BOOL _useStencil;
|
||||
|
||||
// 'Mutable' states of encoder
|
||||
EncoderStates * _encoderStates;
|
||||
}
|
||||
|
||||
- (id _Nonnull)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_encoder = nil;
|
||||
_destination = nil;
|
||||
_aaDestination = nil;
|
||||
_useStencil = NO;
|
||||
_encoderStates = [[EncoderStates alloc] init];
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_encoderStates release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)setContext:(MTLContex * _Nonnull)mtlc {
|
||||
self->_mtlc = mtlc;
|
||||
[self->_encoderStates setContext:mtlc];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getRenderEncoder:(const BMTLSDOps * _Nonnull)dstOps
|
||||
{
|
||||
return [self getRenderEncoder:dstOps->pTexture isDstOpaque:dstOps->isOpaque];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getAARenderEncoder:(const BMTLSDOps * _Nonnull)dstOps {
|
||||
id<MTLTexture> dstTxt = dstOps->pTexture;
|
||||
RenderOptions roptions = {JNI_FALSE, JNI_TRUE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {dstOps->isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getEncoder:dstTxt renderOptions:&roptions];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getAAShaderRenderEncoder:(const BMTLSDOps * _Nonnull)dstOps
|
||||
{
|
||||
RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {dstOps->isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_TRUE};
|
||||
return [self getEncoder:dstOps->pTexture renderOptions:&roptions];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull)getRenderEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isDstOpaque:(bool)isOpaque
|
||||
{
|
||||
RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getEncoder:dest renderOptions:&roptions];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getTextureEncoder:(const BMTLSDOps * _Nonnull)dstOps
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
{
|
||||
return [self getTextureEncoder:dstOps->pTexture
|
||||
isSrcOpaque:isSrcOpaque
|
||||
isDstOpaque:dstOps->isOpaque
|
||||
interpolation:INTERPOLATION_NEAREST_NEIGHBOR];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getTextureEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
isDstOpaque:(bool)isDstOpaque
|
||||
{
|
||||
return [self getTextureEncoder:dest
|
||||
isSrcOpaque:isSrcOpaque
|
||||
isDstOpaque:isDstOpaque
|
||||
interpolation:INTERPOLATION_NEAREST_NEIGHBOR
|
||||
isAA:JNI_FALSE];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getLCDEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
isDstOpaque:(bool)isDstOpaque
|
||||
{
|
||||
RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, {isSrcOpaque, JNI_TRUE }, {isDstOpaque, JNI_TRUE}, JNI_FALSE, JNI_TRUE, JNI_FALSE};
|
||||
return [self getEncoder:dest renderOptions:&roptions];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getTextureEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
isDstOpaque:(bool)isDstOpaque
|
||||
interpolation:(int)interpolation
|
||||
isAA:(jboolean)isAA
|
||||
{
|
||||
RenderOptions roptions = {JNI_TRUE, isAA, interpolation, { isSrcOpaque, JNI_TRUE }, {isDstOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getEncoder:dest renderOptions:&roptions];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getTextureEncoder:(id<MTLTexture> _Nonnull)dest
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
isDstOpaque:(bool)isDstOpaque
|
||||
interpolation:(int)interpolation
|
||||
{
|
||||
return [self getTextureEncoder:dest isSrcOpaque:isSrcOpaque isDstOpaque:isDstOpaque interpolation:interpolation isAA:JNI_FALSE];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getTextEncoder:(const BMTLSDOps * _Nonnull)dstOps
|
||||
isSrcOpaque:(bool)isSrcOpaque
|
||||
{
|
||||
RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, { isSrcOpaque, JNI_TRUE }, {dstOps->isOpaque, JNI_TRUE}, JNI_TRUE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getEncoder:dstOps->pTexture renderOptions:&roptions];
|
||||
}
|
||||
|
||||
- (id<MTLRenderCommandEncoder> _Nonnull) getEncoder:(id <MTLTexture> _Nonnull)dest
|
||||
renderOptions:(const RenderOptions * _Nonnull)renderOptions
|
||||
{
|
||||
//
|
||||
// 1. check whether it's necessary to call endEncoder
|
||||
//
|
||||
jboolean needEnd = JNI_FALSE;
|
||||
if (_encoder != nil) {
|
||||
if (_destination != dest || renderOptions->isAA != _encoderStates.aa) {
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE,
|
||||
"end common encoder because of dest change: %p -> %p",
|
||||
_destination, dest);
|
||||
needEnd = JNI_TRUE;
|
||||
} else if ((_useStencil == NO) != ([_mtlc.clip isShape] == NO)) {
|
||||
// 1. When mode changes RECT -> SHAPE we must recreate encoder with
|
||||
// stencilAttachment (todo: consider the case when current encoder already
|
||||
// has stencil)
|
||||
//
|
||||
// 2. When mode changes SHAPE -> RECT it seems that we can use the same
|
||||
// encoder with disabled stencil test, but [encoder
|
||||
// setDepthStencilState:nil] causes crash, so we have to recreate encoder
|
||||
// in such case
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE,
|
||||
"end common encoder because toggle stencil: %d -> %d",
|
||||
(int)_useStencil, (int)[_mtlc.clip isShape]);
|
||||
needEnd = JNI_TRUE;
|
||||
}
|
||||
}
|
||||
if (needEnd)
|
||||
[self endEncoder];
|
||||
|
||||
//
|
||||
// 2. recreate encoder if necessary
|
||||
//
|
||||
jboolean forceUpdate = JNI_FALSE;
|
||||
#ifdef ALWAYS_UPDATE_ENCODER_STATES
|
||||
forceUpdate = JNI_TRUE;
|
||||
#endif // ALWAYS_UPDATE_ENCODER_STATES
|
||||
|
||||
if (_encoder == nil) {
|
||||
_destination = dest;
|
||||
_useStencil = [_mtlc.clip isShape] && !_mtlc.clip.stencilMaskGenerationInProgress;
|
||||
forceUpdate = JNI_TRUE;
|
||||
|
||||
MTLCommandBufferWrapper *cbw = [_mtlc getCommandBufferWrapper];
|
||||
MTLRenderPassDescriptor *rpd =
|
||||
[MTLRenderPassDescriptor renderPassDescriptor];
|
||||
MTLRenderPassColorAttachmentDescriptor *ca = rpd.colorAttachments[0];
|
||||
ca.texture = dest;
|
||||
|
||||
// TODO: Find out why we cannot use
|
||||
// if (_mtlc.clip.stencilMaskGenerationInProgress == YES) {
|
||||
// ca.loadAction = MTLLoadActionClear;
|
||||
// ca.clearColor = MTLClearColorMake(0.0f, 0.0f,0.0f, 0.0f);
|
||||
// }
|
||||
// here to avoid creation of clearEncoder in beginShapeClip
|
||||
|
||||
ca.loadAction = MTLLoadActionLoad;
|
||||
ca.storeAction = MTLStoreActionStore;
|
||||
|
||||
if (_useStencil && !renderOptions->isAA) {
|
||||
// If you enable stencil testing or stencil writing, the
|
||||
// MTLRenderPassDescriptor must include a stencil attachment.
|
||||
rpd.stencilAttachment.loadAction = MTLLoadActionLoad;
|
||||
rpd.stencilAttachment.storeAction = MTLStoreActionStore;
|
||||
rpd.stencilAttachment.texture = _mtlc.clip.stencilTextureRef;
|
||||
}
|
||||
|
||||
// J2dTraceLn1(J2D_TRACE_VERBOSE, "created render encoder to draw on
|
||||
// tex=%p", dest);
|
||||
_encoder = [[cbw getCommandBuffer] renderCommandEncoderWithDescriptor:rpd];
|
||||
|
||||
[_encoderStates reset:dest
|
||||
isDstOpaque:renderOptions->dstFlags.isOpaque
|
||||
isDstPremultiplied:YES
|
||||
isAA:renderOptions->isAA
|
||||
isText:renderOptions->isText
|
||||
isLCD:renderOptions->isLCD];
|
||||
}
|
||||
|
||||
//
|
||||
// 3. update encoder states
|
||||
//
|
||||
[_encoderStates updateEncoder:_encoder
|
||||
context:_mtlc
|
||||
renderOptions:renderOptions
|
||||
forceUpdate:forceUpdate];
|
||||
|
||||
return _encoder;
|
||||
}
|
||||
|
||||
- (id<MTLBlitCommandEncoder> _Nonnull) createBlitEncoder {
|
||||
[self endEncoder];
|
||||
return [[[_mtlc getCommandBufferWrapper] getCommandBuffer] blitCommandEncoder];
|
||||
}
|
||||
|
||||
- (void) endEncoder {
|
||||
if (_encoder != nil) {
|
||||
[_encoder endEncoding];
|
||||
_encoder = nil;
|
||||
_destination = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLBlitLoops_h_Included
|
||||
#define MTLBlitLoops_h_Included
|
||||
|
||||
#include "sun_java2d_metal_MTLBlitLoops.h"
|
||||
#include "MTLSurfaceDataBase.h"
|
||||
#include "MTLContext.h"
|
||||
|
||||
#define OFFSET_SRCTYPE sun_java2d_metal_MTLBlitLoops_OFFSET_SRCTYPE
|
||||
#define OFFSET_HINT sun_java2d_metal_MTLBlitLoops_OFFSET_HINT
|
||||
#define OFFSET_TEXTURE sun_java2d_metal_MTLBlitLoops_OFFSET_TEXTURE
|
||||
#define OFFSET_RTT sun_java2d_metal_MTLBlitLoops_OFFSET_RTT
|
||||
#define OFFSET_XFORM sun_java2d_metal_MTLBlitLoops_OFFSET_XFORM
|
||||
#define OFFSET_ISOBLIT sun_java2d_metal_MTLBlitLoops_OFFSET_ISOBLIT
|
||||
|
||||
void MTLBlitLoops_IsoBlit(JNIEnv *env,
|
||||
MTLContext *mtlc, jlong pSrcOps, jlong pDstOps,
|
||||
jboolean xform, jint hint,
|
||||
jboolean texture,
|
||||
jint sx1, jint sy1,
|
||||
jint sx2, jint sy2,
|
||||
jdouble dx1, jdouble dy1,
|
||||
jdouble dx2, jdouble dy2);
|
||||
|
||||
void MTLBlitLoops_Blit(JNIEnv *env,
|
||||
MTLContext *mtlc, jlong pSrcOps, jlong pDstOps,
|
||||
jboolean xform, jint hint,
|
||||
jint srctype, jboolean texture,
|
||||
jint sx1, jint sy1,
|
||||
jint sx2, jint sy2,
|
||||
jdouble dx1, jdouble dy1,
|
||||
jdouble dx2, jdouble dy2);
|
||||
|
||||
void MTLBlitLoops_SurfaceToSwBlit(JNIEnv *env, MTLContext *mtlc,
|
||||
jlong pSrcOps, jlong pDstOps, jint dsttype,
|
||||
jint srcx, jint srcy,
|
||||
jint dstx, jint dsty,
|
||||
jint width, jint height);
|
||||
|
||||
void MTLBlitLoops_CopyArea(JNIEnv *env,
|
||||
MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
jint x, jint y,
|
||||
jint width, jint height,
|
||||
jint dx, jint dy);
|
||||
|
||||
void MTLBlitTex2Tex(MTLContext *mtlc, id<MTLTexture> src, id<MTLTexture> dest);
|
||||
|
||||
void drawTex2Tex(MTLContext *mtlc,
|
||||
id<MTLTexture> src, id<MTLTexture> dst,
|
||||
jboolean isSrcOpaque, jboolean isDstOpaque, jint hint,
|
||||
jint sx1, jint sy1, jint sx2, jint sy2,
|
||||
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2);
|
||||
|
||||
#endif /* MTLBlitLoops_h_Included */
|
||||
@@ -0,0 +1,822 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <jlong.h>
|
||||
|
||||
#include "SurfaceData.h"
|
||||
#include "MTLBlitLoops.h"
|
||||
#include "MTLRenderQueue.h"
|
||||
#include "MTLSurfaceData.h"
|
||||
#include "MTLUtils.h"
|
||||
#include "GraphicsPrimitiveMgr.h"
|
||||
|
||||
#include <string.h> // memcpy
|
||||
#include "IntArgbPre.h"
|
||||
|
||||
#import <Accelerate/Accelerate.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define TRACE_ISOBLIT
|
||||
#define TRACE_BLIT
|
||||
#endif //DEBUG
|
||||
//#define DEBUG_ISOBLIT
|
||||
//#define DEBUG_BLIT
|
||||
|
||||
typedef struct {
|
||||
// Consider deleting this field, since it's always MTLPixelFormatBGRA8Unorm
|
||||
jboolean hasAlpha;
|
||||
jboolean isPremult;
|
||||
NSString* swizzleKernel;
|
||||
} MTLRasterFormatInfo;
|
||||
|
||||
/**
|
||||
* This table contains the "pixel formats" for all system memory surfaces
|
||||
* that Metal is capable of handling, indexed by the "PF_" constants defined
|
||||
* in MTLLSurfaceData.java. These pixel formats contain information that is
|
||||
* passed to Metal when copying from a system memory ("Sw") surface to
|
||||
* an Metal surface
|
||||
*/
|
||||
MTLRasterFormatInfo RasterFormatInfos[] = {
|
||||
{ 1, 0, nil }, /* 0 - IntArgb */ // Argb (in java notation)
|
||||
{ 1, 1, nil }, /* 1 - IntArgbPre */
|
||||
{ 0, 1, @"rgb_to_rgba" }, /* 2 - IntRgb */
|
||||
{ 0, 1, @"xrgb_to_rgba" }, /* 3 - IntRgbx */
|
||||
{ 0, 1, @"bgr_to_rgba" }, /* 4 - IntBgr */
|
||||
{ 0, 1, @"xbgr_to_rgba" }, /* 5 - IntBgrx */
|
||||
|
||||
// TODO: support 2-byte formats
|
||||
// { GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV,
|
||||
// 2, 0, 1, }, /* 7 - Ushort555Rgb */
|
||||
// { GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,
|
||||
// 2, 0, 1, }, /* 8 - Ushort555Rgbx*/
|
||||
// { GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
||||
// 1, 0, 1, }, /* 9 - ByteGray */
|
||||
// { GL_LUMINANCE, GL_UNSIGNED_SHORT,
|
||||
// 2, 0, 1, }, /*10 - UshortGray */
|
||||
// { GL_BGR, GL_UNSIGNED_BYTE,
|
||||
// 1, 0, 1, }, /*11 - ThreeByteBgr */
|
||||
};
|
||||
|
||||
extern void J2dTraceImpl(int level, jboolean cr, const char *string, ...);
|
||||
|
||||
void fillTxQuad(
|
||||
struct TxtVertex * txQuadVerts,
|
||||
jint sx1, jint sy1, jint sx2, jint sy2, jint sw, jint sh,
|
||||
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2, jdouble dw, jdouble dh
|
||||
) {
|
||||
const float nsx1 = sx1/(float)sw;
|
||||
const float nsy1 = sy1/(float)sh;
|
||||
const float nsx2 = sx2/(float)sw;
|
||||
const float nsy2 = sy2/(float)sh;
|
||||
|
||||
txQuadVerts[0].position[0] = dx1;
|
||||
txQuadVerts[0].position[1] = dy1;
|
||||
txQuadVerts[0].txtpos[0] = nsx1;
|
||||
txQuadVerts[0].txtpos[1] = nsy1;
|
||||
|
||||
txQuadVerts[1].position[0] = dx2;
|
||||
txQuadVerts[1].position[1] = dy1;
|
||||
txQuadVerts[1].txtpos[0] = nsx2;
|
||||
txQuadVerts[1].txtpos[1] = nsy1;
|
||||
|
||||
txQuadVerts[2].position[0] = dx2;
|
||||
txQuadVerts[2].position[1] = dy2;
|
||||
txQuadVerts[2].txtpos[0] = nsx2;
|
||||
txQuadVerts[2].txtpos[1] = nsy2;
|
||||
|
||||
txQuadVerts[3].position[0] = dx2;
|
||||
txQuadVerts[3].position[1] = dy2;
|
||||
txQuadVerts[3].txtpos[0] = nsx2;
|
||||
txQuadVerts[3].txtpos[1] = nsy2;
|
||||
|
||||
txQuadVerts[4].position[0] = dx1;
|
||||
txQuadVerts[4].position[1] = dy2;
|
||||
txQuadVerts[4].txtpos[0] = nsx1;
|
||||
txQuadVerts[4].txtpos[1] = nsy2;
|
||||
|
||||
txQuadVerts[5].position[0] = dx1;
|
||||
txQuadVerts[5].position[1] = dy1;
|
||||
txQuadVerts[5].txtpos[0] = nsx1;
|
||||
txQuadVerts[5].txtpos[1] = nsy1;
|
||||
}
|
||||
|
||||
//#define TRACE_drawTex2Tex
|
||||
|
||||
void drawTex2Tex(MTLContext *mtlc,
|
||||
id<MTLTexture> src, id<MTLTexture> dst,
|
||||
jboolean isSrcOpaque, jboolean isDstOpaque, jint hint,
|
||||
jint sx1, jint sy1, jint sx2, jint sy2,
|
||||
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
|
||||
{
|
||||
#ifdef TRACE_drawTex2Tex
|
||||
J2dRlsTraceLn2(J2D_TRACE_VERBOSE, "drawTex2Tex: src tex=%p, dst tex=%p", src, dst);
|
||||
J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " sw=%d sh=%d dw=%d dh=%d", src.width, src.height, dst.width, dst.height);
|
||||
J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", sx1, sy1, sx2, sy2);
|
||||
J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", dx1, dy1, dx2, dy2);
|
||||
#endif //TRACE_drawTex2Tex
|
||||
|
||||
id<MTLRenderCommandEncoder> encoder = [mtlc.encoderManager getTextureEncoder:dst
|
||||
isSrcOpaque:isSrcOpaque
|
||||
isDstOpaque:isDstOpaque
|
||||
interpolation:hint
|
||||
];
|
||||
|
||||
struct TxtVertex quadTxVerticesBuffer[6];
|
||||
fillTxQuad(quadTxVerticesBuffer, sx1, sy1, sx2, sy2, src.width, src.height, dx1, dy1, dx2, dy2, dst.width, dst.height);
|
||||
|
||||
[encoder setVertexBytes:quadTxVerticesBuffer length:sizeof(quadTxVerticesBuffer) atIndex:MeshVertexBuffer];
|
||||
[encoder setFragmentTexture:src atIndex: 0];
|
||||
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
|
||||
}
|
||||
|
||||
static void
|
||||
replaceTextureRegion(MTLContext *mtlc, id<MTLTexture> dest, const SurfaceDataRasInfo *srcInfo,
|
||||
const MTLRasterFormatInfo *rfi,
|
||||
int dx1, int dy1, int dx2, int dy2) {
|
||||
const int sw = srcInfo->bounds.x2 - srcInfo->bounds.x1;
|
||||
const int sh = srcInfo->bounds.y2 - srcInfo->bounds.y1;
|
||||
const int dw = dx2 - dx1;
|
||||
const int dh = dy2 - dy1;
|
||||
if (dw < sw || dh < sh) {
|
||||
J2dTraceLn4(J2D_TRACE_ERROR, "replaceTextureRegion: dest size: (%d, %d) less than source size: (%d, %d)", dw, dh, sw, sh);
|
||||
return;
|
||||
}
|
||||
|
||||
const void *raster = srcInfo->rasBase;
|
||||
raster += (NSUInteger)srcInfo->bounds.y1 * (NSUInteger)srcInfo->scanStride + (NSUInteger)srcInfo->bounds.x1 * (NSUInteger)srcInfo->pixelStride;
|
||||
|
||||
@autoreleasepool {
|
||||
J2dTraceLn4(J2D_TRACE_VERBOSE, "replaceTextureRegion src (dw, dh) : [%d, %d] dest (dx1, dy1) =[%d, %d]",
|
||||
dw, dh, dx1, dy1);
|
||||
id<MTLBuffer> buff = [[mtlc.device newBufferWithLength:(sw * sh * srcInfo->pixelStride) options:MTLResourceStorageModeManaged] autorelease];
|
||||
|
||||
// copy src pixels inside src bounds to buff
|
||||
for (int row = 0; row < sh; row++) {
|
||||
memcpy(buff.contents + (row * sw * srcInfo->pixelStride), raster, sw * srcInfo->pixelStride);
|
||||
raster += (NSUInteger)srcInfo->scanStride;
|
||||
}
|
||||
[buff didModifyRange:NSMakeRange(0, buff.length)];
|
||||
|
||||
if (rfi->swizzleKernel != nil) {
|
||||
id <MTLBuffer> swizzled = [[mtlc.device newBufferWithLength:(sw * sh * srcInfo->pixelStride) options:MTLResourceStorageModeManaged] autorelease];
|
||||
|
||||
// this should be cheap, since data is already on GPU
|
||||
id<MTLCommandBuffer> cb = [mtlc createCommandBuffer];
|
||||
id<MTLComputeCommandEncoder> computeEncoder = [cb computeCommandEncoder];
|
||||
id<MTLComputePipelineState> computePipelineState = [mtlc.pipelineStateStorage
|
||||
getComputePipelineState:rfi->swizzleKernel];
|
||||
[computeEncoder setComputePipelineState:computePipelineState];
|
||||
|
||||
[computeEncoder setBuffer:buff offset:0 atIndex:0];
|
||||
[computeEncoder setBuffer:swizzled offset:0 atIndex:1];
|
||||
|
||||
NSUInteger threadGroupSize = computePipelineState.maxTotalThreadsPerThreadgroup;
|
||||
if (threadGroupSize == 0) {
|
||||
threadGroupSize = 1;
|
||||
}
|
||||
NSUInteger pixelCount = buff.length / srcInfo->pixelStride;
|
||||
MTLSize threadsPerGroup = MTLSizeMake(threadGroupSize, 1, 1);
|
||||
MTLSize threadGroups = MTLSizeMake((pixelCount + threadGroupSize - 1) / threadGroupSize,
|
||||
1, 1);
|
||||
[computeEncoder dispatchThreadgroups:threadGroups
|
||||
threadsPerThreadgroup:threadsPerGroup];
|
||||
[computeEncoder endEncoding];
|
||||
[cb commit];
|
||||
|
||||
buff = swizzled;
|
||||
}
|
||||
|
||||
id<MTLBlitCommandEncoder> blitEncoder = [mtlc.encoderManager createBlitEncoder];
|
||||
[blitEncoder copyFromBuffer:buff
|
||||
sourceOffset:0 sourceBytesPerRow:(sw * srcInfo->pixelStride)
|
||||
sourceBytesPerImage:(sw * sh * srcInfo->pixelStride) sourceSize:MTLSizeMake(sw, sh, 1)
|
||||
toTexture:dest
|
||||
destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(dx1, dy1, 0)];
|
||||
[blitEncoder endEncoding];
|
||||
[mtlc.encoderManager endEncoder];
|
||||
|
||||
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
[commandbuf commit];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner loop used for copying a source system memory ("Sw") surface to a
|
||||
* destination MTL "Surface". This method is invoked from
|
||||
* MTLBlitLoops_Blit().
|
||||
*/
|
||||
|
||||
static void
|
||||
MTLBlitSwToTextureViaPooledTexture(
|
||||
MTLContext *mtlc, SurfaceDataRasInfo *srcInfo, BMTLSDOps * bmtlsdOps,
|
||||
MTLRasterFormatInfo *rfi, jint hint,
|
||||
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
|
||||
{
|
||||
int sw = srcInfo->bounds.x2 - srcInfo->bounds.x1;
|
||||
int sh = srcInfo->bounds.y2 - srcInfo->bounds.y1;
|
||||
|
||||
sw = MIN(sw, MTL_GPU_FAMILY_MAC_TXT_SIZE);
|
||||
sh = MIN(sh, MTL_GPU_FAMILY_MAC_TXT_SIZE);
|
||||
|
||||
id<MTLTexture> dest = bmtlsdOps->pTexture;
|
||||
|
||||
MTLPooledTextureHandle * texHandle = [mtlc.texturePool getTexture:sw height:sh format:MTLPixelFormatBGRA8Unorm];
|
||||
if (texHandle == nil) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitSwToTextureViaPooledTexture: can't obtain temporary texture object from pool");
|
||||
return;
|
||||
}
|
||||
[[mtlc getCommandBufferWrapper] registerPooledTexture:texHandle];
|
||||
|
||||
id<MTLTexture> texBuff = texHandle.texture;
|
||||
replaceTextureRegion(mtlc, texBuff, srcInfo, rfi, 0, 0, sw, sh);
|
||||
|
||||
drawTex2Tex(mtlc, texBuff, dest, !rfi->hasAlpha, bmtlsdOps->isOpaque, hint,
|
||||
0, 0, sw, sh, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
|
||||
static
|
||||
jboolean isIntegerAndUnscaled(
|
||||
jint sx1, jint sy1, jint sx2, jint sy2,
|
||||
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2
|
||||
) {
|
||||
const jdouble epsilon = 0.0001f;
|
||||
|
||||
// check that dx1,dy1 is integer
|
||||
if (fabs(dx1 - (int)dx1) > epsilon || fabs(dy1 - (int)dy1) > epsilon) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
// check that destSize equals srcSize
|
||||
if (fabs(dx2 - dx1 - sx2 + sx1) > epsilon || fabs(dy2 - dy1 - sy2 + sy1) > epsilon) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
jboolean clipDestCoords(
|
||||
jdouble *dx1, jdouble *dy1, jdouble *dx2, jdouble *dy2,
|
||||
jint *sx1, jint *sy1, jint *sx2, jint *sy2,
|
||||
jint destW, jint destH, const MTLScissorRect * clipRect
|
||||
) {
|
||||
// Trim destination rect by clip-rect (or dest.bounds)
|
||||
const jint sw = *sx2 - *sx1;
|
||||
const jint sh = *sy2 - *sy1;
|
||||
const jdouble dw = *dx2 - *dx1;
|
||||
const jdouble dh = *dy2 - *dy1;
|
||||
|
||||
jdouble dcx1 = 0;
|
||||
jdouble dcx2 = destW;
|
||||
jdouble dcy1 = 0;
|
||||
jdouble dcy2 = destH;
|
||||
if (clipRect != NULL) {
|
||||
if (clipRect->x > dcx1)
|
||||
dcx1 = clipRect->x;
|
||||
const int maxX = clipRect->x + clipRect->width;
|
||||
if (dcx2 > maxX)
|
||||
dcx2 = maxX;
|
||||
if (clipRect->y > dcy1)
|
||||
dcy1 = clipRect->y;
|
||||
const int maxY = clipRect->y + clipRect->height;
|
||||
if (dcy2 > maxY)
|
||||
dcy2 = maxY;
|
||||
|
||||
if (dcx1 >= dcx2) {
|
||||
J2dTraceLn2(J2D_TRACE_ERROR, "\tclipDestCoords: dcx1=%1.2f, dcx2=%1.2f", dcx1, dcx2);
|
||||
dcx1 = dcx2;
|
||||
}
|
||||
if (dcy1 >= dcy2) {
|
||||
J2dTraceLn2(J2D_TRACE_ERROR, "\tclipDestCoords: dcy1=%1.2f, dcy2=%1.2f", dcy1, dcy2);
|
||||
dcy1 = dcy2;
|
||||
}
|
||||
}
|
||||
if (*dx2 <= dcx1 || *dx1 >= dcx2 || *dy2 <= dcy1 || *dy1 >= dcy2) {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "\tclipDestCoords: dest rect doesn't intersect clip area");
|
||||
J2dTraceLn4(J2D_TRACE_INFO, "\tdx2=%1.4f <= dcx1=%1.4f || *dx1=%1.4f >= dcx2=%1.4f", *dx2, dcx1, *dx1, dcx2);
|
||||
J2dTraceLn4(J2D_TRACE_INFO, "\t*dy2=%1.4f <= dcy1=%1.4f || *dy1=%1.4f >= dcy2=%1.4f", *dy2, dcy1, *dy1, dcy2);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
if (*dx1 < dcx1) {
|
||||
J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdx1=%1.2f, will be clipped to %1.2f | sx1+=%d", *dx1, dcx1, (jint)((dcx1 - *dx1) * (sw/dw)));
|
||||
*sx1 += (jint)((dcx1 - *dx1) * (sw/dw));
|
||||
*dx1 = dcx1;
|
||||
}
|
||||
if (*dx2 > dcx2) {
|
||||
J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdx2=%1.2f, will be clipped to %1.2f | sx2-=%d", *dx2, dcx2, (jint)((*dx2 - dcx2) * (sw/dw)));
|
||||
*sx2 -= (jint)((*dx2 - dcx2) * (sw/dw));
|
||||
*dx2 = dcx2;
|
||||
}
|
||||
if (*dy1 < dcy1) {
|
||||
J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdy1=%1.2f, will be clipped to %1.2f | sy1+=%d", *dy1, dcy1, (jint)((dcy1 - *dy1) * (sh/dh)));
|
||||
*sy1 += (jint)((dcy1 - *dy1) * (sh/dh));
|
||||
*dy1 = dcy1;
|
||||
}
|
||||
if (*dy2 > dcy2) {
|
||||
J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdy2=%1.2f, will be clipped to %1.2f | sy2-=%d", *dy2, dcy2, (jint)((*dy2 - dcy2) * (sh/dh)));
|
||||
*sy2 -= (jint)((*dy2 - dcy2) * (sh/dh));
|
||||
*dy2 = dcy2;
|
||||
}
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* General blit method for copying a native MTL surface to another MTL "Surface".
|
||||
* Parameter texture == true forces to use 'texture' codepath (dest coordinates will always be integers).
|
||||
* Parameter xform == true only when AffineTransform is used (invoked only from TransformBlit, dest coordinates will always be integers).
|
||||
*/
|
||||
void
|
||||
MTLBlitLoops_IsoBlit(JNIEnv *env,
|
||||
MTLContext *mtlc, jlong pSrcOps, jlong pDstOps,
|
||||
jboolean xform, jint hint, jboolean texture,
|
||||
jint sx1, jint sy1, jint sx2, jint sy2,
|
||||
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
|
||||
{
|
||||
BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrcOps);
|
||||
BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDstOps);
|
||||
|
||||
RETURN_IF_NULL(mtlc);
|
||||
RETURN_IF_NULL(srcOps);
|
||||
RETURN_IF_NULL(dstOps);
|
||||
// Verify if we use a valid MTLContext
|
||||
MTLSDOps *dstMTLOps = (MTLSDOps *)dstOps->privOps;
|
||||
RETURN_IF_TRUE(dstMTLOps->configInfo != NULL && mtlc != dstMTLOps->configInfo->context);
|
||||
|
||||
MTLSDOps *srcMTLOps = (MTLSDOps *)srcOps->privOps;
|
||||
RETURN_IF_TRUE(srcMTLOps->configInfo != NULL && mtlc != srcMTLOps->configInfo->context);
|
||||
|
||||
id<MTLTexture> srcTex = srcOps->pTexture;
|
||||
id<MTLTexture> dstTex = dstOps->pTexture;
|
||||
if (srcTex == nil || srcTex == nil) {
|
||||
J2dTraceLn2(J2D_TRACE_ERROR, "MTLBlitLoops_IsoBlit: surface is null (stex=%p, dtex=%p)", srcTex, dstTex);
|
||||
return;
|
||||
}
|
||||
|
||||
const jint sw = sx2 - sx1;
|
||||
const jint sh = sy2 - sy1;
|
||||
const jdouble dw = dx2 - dx1;
|
||||
const jdouble dh = dy2 - dy1;
|
||||
|
||||
if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0) {
|
||||
J2dTraceLn4(J2D_TRACE_WARNING, "MTLBlitLoops_IsoBlit: invalid dimensions: sw=%d, sh%d, dw=%d, dh=%d", sw, sh, dw, dh);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_ISOBLIT
|
||||
if ((xform == JNI_TRUE) != (mtlc.useTransform == JNI_TRUE)) {
|
||||
J2dTraceImpl(J2D_TRACE_ERROR, JNI_TRUE,
|
||||
"MTLBlitLoops_IsoBlit state error: xform=%d, mtlc.useTransform=%d, texture=%d",
|
||||
xform, mtlc.useTransform, texture);
|
||||
}
|
||||
#endif // DEBUG_ISOBLIT
|
||||
|
||||
if (!xform) {
|
||||
clipDestCoords(
|
||||
&dx1, &dy1, &dx2, &dy2,
|
||||
&sx1, &sy1, &sx2, &sy2,
|
||||
dstTex.width, dstTex.height, texture ? NULL : [mtlc.clip getRect]
|
||||
);
|
||||
}
|
||||
|
||||
SurfaceDataBounds bounds;
|
||||
bounds.x1 = sx1;
|
||||
bounds.y1 = sy1;
|
||||
bounds.x2 = sx2;
|
||||
bounds.y2 = sy2;
|
||||
SurfaceData_IntersectBoundsXYXY(&bounds, 0, 0, srcOps->width, srcOps->height);
|
||||
|
||||
if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLBlitLoops_IsoBlit: source rectangle doesn't intersect with source surface bounds");
|
||||
J2dTraceLn6(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d sw=%d sh=%d", sx1, sy1, sx2, sy2, srcOps->width, srcOps->height);
|
||||
J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", dx1, dy1, dx2, dy2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bounds.x1 != sx1) {
|
||||
dx1 += (bounds.x1 - sx1) * (dw / sw);
|
||||
sx1 = bounds.x1;
|
||||
}
|
||||
if (bounds.y1 != sy1) {
|
||||
dy1 += (bounds.y1 - sy1) * (dh / sh);
|
||||
sy1 = bounds.y1;
|
||||
}
|
||||
if (bounds.x2 != sx2) {
|
||||
dx2 += (bounds.x2 - sx2) * (dw / sw);
|
||||
sx2 = bounds.x2;
|
||||
}
|
||||
if (bounds.y2 != sy2) {
|
||||
dy2 += (bounds.y2 - sy2) * (dh / sh);
|
||||
sy2 = bounds.y2;
|
||||
}
|
||||
|
||||
#ifdef TRACE_ISOBLIT
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE,
|
||||
"MTLBlitLoops_IsoBlit [tx=%d, xf=%d, AC=%s]: src=%s, dst=%s | (%d, %d, %d, %d)->(%1.2f, %1.2f, %1.2f, %1.2f)",
|
||||
texture, xform, [mtlc getCompositeDescription].cString,
|
||||
getSurfaceDescription(srcOps).cString, getSurfaceDescription(dstOps).cString,
|
||||
sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
|
||||
#endif //TRACE_ISOBLIT
|
||||
|
||||
if (!texture && !xform
|
||||
&& srcOps->isOpaque
|
||||
&& isIntegerAndUnscaled(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2)
|
||||
&& (dstOps->isOpaque || !srcOps->isOpaque)
|
||||
) {
|
||||
#ifdef TRACE_ISOBLIT
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via blitEncoder]");
|
||||
#endif //TRACE_ISOBLIT
|
||||
|
||||
id <MTLBlitCommandEncoder> blitEncoder = [mtlc.encoderManager createBlitEncoder];
|
||||
[blitEncoder copyFromTexture:srcTex
|
||||
sourceSlice:0
|
||||
sourceLevel:0
|
||||
sourceOrigin:MTLOriginMake(sx1, sy1, 0)
|
||||
sourceSize:MTLSizeMake(sx2 - sx1, sy2 - sy1, 1)
|
||||
toTexture:dstTex
|
||||
destinationSlice:0
|
||||
destinationLevel:0
|
||||
destinationOrigin:MTLOriginMake(dx1, dy1, 0)];
|
||||
[blitEncoder endEncoding];
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TRACE_ISOBLIT
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via sampling]");
|
||||
#endif //TRACE_ISOBLIT
|
||||
drawTex2Tex(mtlc, srcTex, dstTex,
|
||||
srcOps->isOpaque, dstOps->isOpaque,
|
||||
hint, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
|
||||
/**
|
||||
* General blit method for copying a system memory ("Sw") surface to a native MTL surface.
|
||||
* Parameter texture == true only in SwToTextureBlit (straight copy from sw to texture), dest coordinates will always be integers.
|
||||
* Parameter xform == true only when AffineTransform is used (invoked only from TransformBlit, dest coordinates will always be integers).
|
||||
*/
|
||||
void
|
||||
MTLBlitLoops_Blit(JNIEnv *env,
|
||||
MTLContext *mtlc, jlong pSrcOps, jlong pDstOps,
|
||||
jboolean xform, jint hint,
|
||||
jint srctype, jboolean texture,
|
||||
jint sx1, jint sy1, jint sx2, jint sy2,
|
||||
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
|
||||
{
|
||||
SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps);
|
||||
BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDstOps);
|
||||
|
||||
RETURN_IF_NULL(mtlc);
|
||||
RETURN_IF_NULL(srcOps);
|
||||
RETURN_IF_NULL(dstOps);
|
||||
// Verify if we use a valid MTLContext
|
||||
MTLSDOps *dstMTLOps = (MTLSDOps *)dstOps->privOps;
|
||||
RETURN_IF_TRUE(dstMTLOps->configInfo != NULL && mtlc != dstMTLOps->configInfo->context);
|
||||
|
||||
id<MTLTexture> dest = dstOps->pTexture;
|
||||
if (dest == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitLoops_Blit: dest is null");
|
||||
return;
|
||||
}
|
||||
if (srctype < 0 || srctype >= sizeof(RasterFormatInfos)/ sizeof(MTLRasterFormatInfo)) {
|
||||
J2dTraceLn1(J2D_TRACE_ERROR, "MTLBlitLoops_Blit: source pixel format %d isn't supported", srctype);
|
||||
return;
|
||||
}
|
||||
const jint sw = sx2 - sx1;
|
||||
const jint sh = sy2 - sy1;
|
||||
const jdouble dw = dx2 - dx1;
|
||||
const jdouble dh = dy2 - dy1;
|
||||
|
||||
if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitLoops_Blit: invalid dimensions");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_BLIT
|
||||
if (
|
||||
(xform == JNI_TRUE) != (mtlc.useTransform == JNI_TRUE)
|
||||
|| (xform && texture)
|
||||
) {
|
||||
J2dTraceImpl(J2D_TRACE_ERROR, JNI_TRUE,
|
||||
"MTLBlitLoops_Blit state error: xform=%d, mtlc.useTransform=%d, texture=%d",
|
||||
xform, mtlc.useTransform, texture);
|
||||
}
|
||||
if (texture) {
|
||||
if (!isIntegerAndUnscaled(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2)) {
|
||||
J2dTraceImpl(J2D_TRACE_ERROR, JNI_TRUE,
|
||||
"MTLBlitLoops_Blit state error: texture=true, but src and dst dimensions aren't equal or dest coords aren't integers");
|
||||
}
|
||||
if (!dstOps->isOpaque && !RasterFormatInfos[srctype].hasAlpha) {
|
||||
J2dTraceImpl(J2D_TRACE_ERROR, JNI_TRUE,
|
||||
"MTLBlitLoops_Blit state error: texture=true, but dest has alpha and source hasn't alpha, can't use texture-codepath");
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_BLIT
|
||||
if (!xform) {
|
||||
clipDestCoords(
|
||||
&dx1, &dy1, &dx2, &dy2,
|
||||
&sx1, &sy1, &sx2, &sy2,
|
||||
dest.width, dest.height, texture ? NULL : [mtlc.clip getRect]
|
||||
);
|
||||
}
|
||||
|
||||
SurfaceDataRasInfo srcInfo;
|
||||
srcInfo.bounds.x1 = sx1;
|
||||
srcInfo.bounds.y1 = sy1;
|
||||
srcInfo.bounds.x2 = sx2;
|
||||
srcInfo.bounds.y2 = sy2;
|
||||
|
||||
// NOTE: This function will modify the contents of the bounds field to represent the maximum available raster data.
|
||||
if (srcOps->Lock(env, srcOps, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) {
|
||||
J2dTraceLn(J2D_TRACE_WARNING, "MTLBlitLoops_Blit: could not acquire lock");
|
||||
return;
|
||||
}
|
||||
|
||||
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 && srcInfo.bounds.y2 > srcInfo.bounds.y1) {
|
||||
srcOps->GetRasInfo(env, srcOps, &srcInfo);
|
||||
if (srcInfo.rasBase) {
|
||||
if (srcInfo.bounds.x1 != sx1) {
|
||||
const int dx = srcInfo.bounds.x1 - sx1;
|
||||
dx1 += dx * (dw / sw);
|
||||
}
|
||||
if (srcInfo.bounds.y1 != sy1) {
|
||||
const int dy = srcInfo.bounds.y1 - sy1;
|
||||
dy1 += dy * (dh / sh);
|
||||
}
|
||||
if (srcInfo.bounds.x2 != sx2) {
|
||||
const int dx = srcInfo.bounds.x2 - sx2;
|
||||
dx2 += dx * (dw / sw);
|
||||
}
|
||||
if (srcInfo.bounds.y2 != sy2) {
|
||||
const int dy = srcInfo.bounds.y2 - sy2;
|
||||
dy2 += dy * (dh / sh);
|
||||
}
|
||||
|
||||
#ifdef TRACE_BLIT
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE,
|
||||
"MTLBlitLoops_Blit [tx=%d, xf=%d, AC=%s]: bdst=%s, src=%p (%dx%d) O=%d premul=%d | (%d, %d, %d, %d)->(%1.2f, %1.2f, %1.2f, %1.2f)",
|
||||
texture, xform, [mtlc getCompositeDescription].cString,
|
||||
getSurfaceDescription(dstOps).cString, srcOps,
|
||||
sx2 - sx1, sy2 - sy1,
|
||||
RasterFormatInfos[srctype].hasAlpha ? 0 : 1, RasterFormatInfos[srctype].isPremult ? 1 : 0,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2);
|
||||
#endif //TRACE_BLIT
|
||||
|
||||
MTLRasterFormatInfo rfi = RasterFormatInfos[srctype];
|
||||
|
||||
if (texture) {
|
||||
replaceTextureRegion(mtlc, dest, &srcInfo, &rfi, (int) dx1, (int) dy1, (int) dx2, (int) dy2);
|
||||
} else {
|
||||
MTLBlitSwToTextureViaPooledTexture(mtlc, &srcInfo, dstOps, &rfi, hint, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
}
|
||||
SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
|
||||
}
|
||||
SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
|
||||
}
|
||||
|
||||
void copyFromMTLBuffer(void *pDst, id<MTLBuffer> srcBuf, NSUInteger offset, NSUInteger len, BOOL convertFromArgbPre) {
|
||||
char *pSrc = (char*)srcBuf.contents + offset;
|
||||
if (convertFromArgbPre) {
|
||||
NSUInteger pixelLen = len >> 2;
|
||||
for (NSUInteger i = 0; i < pixelLen; i++) {
|
||||
LoadIntArgbPreTo1IntArgb((jint*)pSrc, 0, i, ((jint*)pDst)[i]);
|
||||
}
|
||||
} else {
|
||||
memcpy(pDst, pSrc, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized blit method for copying a native MTL "Surface" (pbuffer,
|
||||
* window, etc.) to a system memory ("Sw") surface.
|
||||
*/
|
||||
void
|
||||
MTLBlitLoops_SurfaceToSwBlit(JNIEnv *env, MTLContext *mtlc,
|
||||
jlong pSrcOps, jlong pDstOps, jint dsttype,
|
||||
jint srcx, jint srcy, jint dstx, jint dsty,
|
||||
jint width, jint height)
|
||||
{
|
||||
J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLBlitLoops_SurfaceToSwBlit: sx=%d sy=%d w=%d h=%d dx=%d dy=%d", srcx, srcy, width, height, dstx, dsty);
|
||||
|
||||
BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrcOps);
|
||||
SurfaceDataOps *dstOps = (SurfaceDataOps *)jlong_to_ptr(pDstOps);
|
||||
SurfaceDataRasInfo srcInfo, dstInfo;
|
||||
|
||||
if (dsttype < 0 || dsttype >= sizeof(RasterFormatInfos)/ sizeof(MTLRasterFormatInfo)) {
|
||||
J2dTraceLn1(J2D_TRACE_ERROR, "MTLBlitLoops_SurfaceToSwBlit: destination pixel format %d isn't supported", dsttype);
|
||||
return;
|
||||
}
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitLoops_SurfaceToSwBlit: dimensions are non-positive");
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_IF_NULL(srcOps);
|
||||
RETURN_IF_NULL(dstOps);
|
||||
RETURN_IF_NULL(mtlc);
|
||||
RETURN_IF_TRUE(width < 0);
|
||||
RETURN_IF_TRUE(height < 0);
|
||||
NSUInteger w = (NSUInteger)width;
|
||||
NSUInteger h = (NSUInteger)height;
|
||||
|
||||
srcInfo.bounds.x1 = srcx;
|
||||
srcInfo.bounds.y1 = srcy;
|
||||
srcInfo.bounds.x2 = srcx + width;
|
||||
srcInfo.bounds.y2 = srcy + height;
|
||||
dstInfo.bounds.x1 = dstx;
|
||||
dstInfo.bounds.y1 = dsty;
|
||||
dstInfo.bounds.x2 = dstx + width;
|
||||
dstInfo.bounds.y2 = dsty + height;
|
||||
|
||||
if (dstOps->Lock(env, dstOps, &dstInfo, SD_LOCK_WRITE) != SD_SUCCESS) {
|
||||
J2dTraceLn(J2D_TRACE_WARNING,"MTLBlitLoops_SurfaceToSwBlit: could not acquire dst lock");
|
||||
return;
|
||||
}
|
||||
|
||||
SurfaceData_IntersectBoundsXYXY(&srcInfo.bounds,
|
||||
0, 0, srcOps->width, srcOps->height);
|
||||
|
||||
SurfaceData_IntersectBlitBounds(&dstInfo.bounds, &srcInfo.bounds,
|
||||
srcx - dstx, srcy - dsty);
|
||||
|
||||
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 &&
|
||||
srcInfo.bounds.y2 > srcInfo.bounds.y1)
|
||||
{
|
||||
dstOps->GetRasInfo(env, dstOps, &dstInfo);
|
||||
if (dstInfo.rasBase) {
|
||||
void *pDst = dstInfo.rasBase;
|
||||
|
||||
srcx = srcInfo.bounds.x1;
|
||||
srcy = srcInfo.bounds.y1;
|
||||
dstx = dstInfo.bounds.x1;
|
||||
dsty = dstInfo.bounds.y1;
|
||||
width = srcInfo.bounds.x2 - srcInfo.bounds.x1;
|
||||
height = srcInfo.bounds.y2 - srcInfo.bounds.y1;
|
||||
|
||||
pDst = PtrPixelsRow(pDst, dstx, dstInfo.pixelStride);
|
||||
pDst = PtrPixelsRow(pDst, dsty, dstInfo.scanStride);
|
||||
|
||||
// Metal texture is (0,0) at left-top
|
||||
srcx = srcOps->xOffset + srcx;
|
||||
srcy = srcOps->yOffset + srcy;
|
||||
NSUInteger byteLength = w * h * 4; // NOTE: assume that src format is MTLPixelFormatBGRA8Unorm
|
||||
|
||||
// Create MTLBuffer (or use static)
|
||||
id<MTLBuffer> mtlbuf;
|
||||
#ifdef USE_STATIC_BUFFER
|
||||
// NOTE: theoretically we can use newBufferWithBytesNoCopy, but pDst must be allocated with special API
|
||||
// mtlbuf = [mtlc.device
|
||||
// newBufferWithBytesNoCopy:pDst
|
||||
// length:(NSUInteger) srcLength
|
||||
// options:MTLResourceCPUCacheModeDefaultCache
|
||||
// deallocator:nil];
|
||||
//
|
||||
// see https://developer.apple.com/documentation/metal/mtldevice/1433382-newbufferwithbytesnocopy?language=objc
|
||||
//
|
||||
// The storage allocation of the returned new MTLBuffer object is the same as the pointer input value.
|
||||
// The existing memory allocation must be covered by a single VM region, typically allocated with vm_allocate or mmap.
|
||||
// Memory allocated by malloc is specifically disallowed.
|
||||
|
||||
static id<MTLBuffer> mtlIntermediateBuffer = nil; // need to reimplement with MTLBufferManager
|
||||
if (mtlIntermediateBuffer == nil || mtlIntermediateBuffer.length < srcLength) {
|
||||
if (mtlIntermediateBuffer != nil) {
|
||||
[mtlIntermediateBuffer release];
|
||||
}
|
||||
mtlIntermediateBuffer = [mtlc.device newBufferWithLength:srcLength options:MTLResourceCPUCacheModeDefaultCache];
|
||||
}
|
||||
mtlbuf = mtlIntermediateBuffer;
|
||||
#else // USE_STATIC_BUFFER
|
||||
mtlbuf = [mtlc.device newBufferWithLength:byteLength options:MTLResourceStorageModeShared];
|
||||
#endif // USE_STATIC_BUFFER
|
||||
|
||||
// Read from surface into MTLBuffer
|
||||
// NOTE: using of separate blitCommandBuffer can produce errors (draw into surface (with general cmd-buf)
|
||||
// can be unfinished when reading raster from blit cmd-buf).
|
||||
// Consider to use [mtlc.encoderManager createBlitEncoder] and [mtlc commitCommandBuffer:JNI_TRUE];
|
||||
J2dTraceLn1(J2D_TRACE_VERBOSE, "MTLBlitLoops_SurfaceToSwBlit: source texture %p", srcOps->pTexture);
|
||||
|
||||
id<MTLCommandBuffer> cb = [mtlc createCommandBuffer];
|
||||
id<MTLBlitCommandEncoder> blitEncoder = [cb blitCommandEncoder];
|
||||
[blitEncoder copyFromTexture:srcOps->pTexture
|
||||
sourceSlice:0
|
||||
sourceLevel:0
|
||||
sourceOrigin:MTLOriginMake(srcx, srcy, 0)
|
||||
sourceSize:MTLSizeMake(w, h, 1)
|
||||
toBuffer:mtlbuf
|
||||
destinationOffset:0 /*offset already taken in: pDst = PtrPixelsRow(pDst, dstx, dstInfo.pixelStride)*/
|
||||
destinationBytesPerRow:w*4
|
||||
destinationBytesPerImage:byteLength];
|
||||
[blitEncoder endEncoding];
|
||||
|
||||
// Commit and wait for reading complete
|
||||
[cb commit];
|
||||
[cb waitUntilCompleted];
|
||||
|
||||
// Perform conversion if necessary
|
||||
BOOL convertFromPre = !RasterFormatInfos[dsttype].isPremult && !srcOps->isOpaque;
|
||||
|
||||
if ((dstInfo.scanStride == w * dstInfo.pixelStride) &&
|
||||
(height == (dstInfo.bounds.y2 - dstInfo.bounds.y1))) {
|
||||
// mtlbuf.contents have same dimensions as of pDst
|
||||
copyFromMTLBuffer(pDst, mtlbuf, 0, byteLength, convertFromPre);
|
||||
} else {
|
||||
// mtlbuf.contents have smaller dimensions than pDst
|
||||
// copy each row from mtlbuf.contents at appropriate position in pDst
|
||||
// Note : pDst is already addjusted for offsets using PtrAddBytes above
|
||||
|
||||
NSUInteger rowSize = w * dstInfo.pixelStride;
|
||||
for (int y = 0; y < height; y++) {
|
||||
copyFromMTLBuffer(pDst, mtlbuf, y * rowSize, rowSize, convertFromPre);
|
||||
pDst = PtrAddBytes(pDst, dstInfo.scanStride);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef USE_STATIC_BUFFER
|
||||
[mtlbuf release];
|
||||
#endif // USE_STATIC_BUFFER
|
||||
}
|
||||
SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
|
||||
}
|
||||
SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
|
||||
}
|
||||
|
||||
void
|
||||
MTLBlitLoops_CopyArea(JNIEnv *env,
|
||||
MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
jint x, jint y, jint width, jint height,
|
||||
jint dx, jint dy)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE, "MTLBlitLoops_CopyArea: bdst=%p [tex=%p] %dx%d | src (%d, %d), %dx%d -> dst (%d, %d)",
|
||||
dstOps, dstOps->pTexture, ((id<MTLTexture>)dstOps->pTexture).width, ((id<MTLTexture>)dstOps->pTexture).height, x, y, width, height, dx, dy);
|
||||
#endif //DEBUG
|
||||
jint texWidth = ((id<MTLTexture>)dstOps->pTexture).width;
|
||||
jint texHeight = ((id<MTLTexture>)dstOps->pTexture).height;
|
||||
|
||||
SurfaceDataBounds srcBounds, dstBounds;
|
||||
srcBounds.x1 = x;
|
||||
srcBounds.y1 = y;
|
||||
srcBounds.x2 = srcBounds.x1 + width;
|
||||
srcBounds.y2 = srcBounds.y1 + height;
|
||||
dstBounds.x1 = x + dx;
|
||||
dstBounds.y1 = y + dy;
|
||||
dstBounds.x2 = dstBounds.x1 + width;
|
||||
dstBounds.y2 = dstBounds.y1 + height;
|
||||
|
||||
SurfaceData_IntersectBoundsXYXY(&srcBounds, 0, 0, texWidth, texHeight);
|
||||
SurfaceData_IntersectBoundsXYXY(&dstBounds, 0, 0, texWidth, texHeight);
|
||||
SurfaceData_IntersectBlitBounds(&dstBounds, &srcBounds, -dx, -dy);
|
||||
|
||||
int srcWidth = (srcBounds.x2 - srcBounds.x1);
|
||||
int srcHeight = (srcBounds.y2 - srcBounds.y1);
|
||||
|
||||
if ((srcBounds.x1 < srcBounds.x2 && srcBounds.y1 < srcBounds.y2) &&
|
||||
(dstBounds.x1 < dstBounds.x2 && dstBounds.y1 < dstBounds.y2))
|
||||
{
|
||||
@autoreleasepool {
|
||||
id<MTLCommandBuffer> cb = [mtlc createCommandBuffer];
|
||||
id<MTLBlitCommandEncoder> blitEncoder = [cb blitCommandEncoder];
|
||||
|
||||
// Create an intrermediate buffer
|
||||
int totalBuffsize = srcWidth * srcHeight * 4;
|
||||
id <MTLBuffer> buff = [[mtlc.device newBufferWithLength:totalBuffsize options:MTLResourceStorageModePrivate] autorelease];
|
||||
|
||||
[blitEncoder copyFromTexture:dstOps->pTexture
|
||||
sourceSlice:0 sourceLevel:0 sourceOrigin:MTLOriginMake(srcBounds.x1, srcBounds.y1, 0) sourceSize:MTLSizeMake(srcWidth, srcHeight, 1)
|
||||
toBuffer:buff destinationOffset:0 destinationBytesPerRow:(srcWidth * 4) destinationBytesPerImage:totalBuffsize];
|
||||
|
||||
[blitEncoder copyFromBuffer:buff
|
||||
sourceOffset:0 sourceBytesPerRow:srcWidth*4 sourceBytesPerImage:totalBuffsize sourceSize:MTLSizeMake(srcWidth, srcHeight, 1)
|
||||
toTexture:dstOps->pTexture destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(dstBounds.x1, dstBounds.y1, 0)];
|
||||
[blitEncoder endEncoding];
|
||||
|
||||
[cb commit];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLBufImgOps_h_Included
|
||||
#define MTLBufImgOps_h_Included
|
||||
|
||||
#include "MTLContext.h"
|
||||
|
||||
@interface MTLRescaleOp : NSObject
|
||||
- (id)init:(jboolean)isNonPremult factors:(unsigned char *)factors offsets:(unsigned char *)offsets;
|
||||
- (jfloat *)getScaleFactors;
|
||||
- (jfloat *)getOffsets;
|
||||
- (NSString *)getDescription; // creates autorelease string
|
||||
|
||||
@property (readonly) jboolean isNonPremult;
|
||||
@end
|
||||
|
||||
@interface MTLConvolveOp : NSObject
|
||||
- (id)init:(jboolean)edgeZeroFill kernelWidth:(jint)kernelWidth
|
||||
kernelHeight:(jint)kernelHeight
|
||||
srcWidth:(jint)srcWidth
|
||||
srcHeight:(jint)srcHeight
|
||||
kernel:(unsigned char *)kernel
|
||||
device:(id<MTLDevice>)device;
|
||||
- (void) dealloc;
|
||||
|
||||
- (id<MTLBuffer>) getBuffer;
|
||||
- (const float *) getImgEdge;
|
||||
- (NSString *)getDescription; // creates autorelease string
|
||||
|
||||
@property (readonly) jboolean isEdgeZeroFill;
|
||||
@property (readonly) int kernelSize;
|
||||
@end
|
||||
|
||||
@interface MTLLookupOp : NSObject
|
||||
- (id)init:(jboolean)nonPremult shortData:(jboolean)shortData
|
||||
numBands:(jint)numBands
|
||||
bandLength:(jint)bandLength
|
||||
offset:(jint)offset
|
||||
tableValues:(void *)tableValues
|
||||
device:(id<MTLDevice>)device;
|
||||
- (void) dealloc;
|
||||
|
||||
- (jfloat *)getOffset;
|
||||
- (id<MTLTexture>) getLookupTexture;
|
||||
- (NSString *)getDescription; // creates autorelease string
|
||||
|
||||
@property (readonly) jboolean isUseSrcAlpha;
|
||||
@property (readonly) jboolean isNonPremult;
|
||||
@end
|
||||
|
||||
#endif /* MTLBufImgOps_h_Included */
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <jlong.h>
|
||||
|
||||
#include "MTLBufImgOps.h"
|
||||
#include "MTLContext.h"
|
||||
#include "MTLRenderQueue.h"
|
||||
#include "MTLSurfaceDataBase.h"
|
||||
#include "GraphicsPrimitiveMgr.h"
|
||||
|
||||
@implementation MTLRescaleOp {
|
||||
jboolean _isNonPremult;
|
||||
jfloat _normScaleFactors[4];
|
||||
jfloat _normOffsets[4];
|
||||
}
|
||||
|
||||
-(jfloat *) getScaleFactors {
|
||||
return _normScaleFactors;
|
||||
}
|
||||
-(jfloat *) getOffsets {
|
||||
return _normOffsets;
|
||||
}
|
||||
|
||||
- (id)init:(jboolean)isNonPremult factors:(unsigned char *)factors offsets:(unsigned char *)offsets {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
J2dTraceLn1(J2D_TRACE_INFO,"Created MTLRescaleOp: isNonPremult=%d", isNonPremult);
|
||||
|
||||
_isNonPremult = isNonPremult;
|
||||
_normScaleFactors[0] = NEXT_FLOAT(factors);
|
||||
_normScaleFactors[1] = NEXT_FLOAT(factors);
|
||||
_normScaleFactors[2] = NEXT_FLOAT(factors);
|
||||
_normScaleFactors[3] = NEXT_FLOAT(factors);
|
||||
_normOffsets[0] = NEXT_FLOAT(offsets);
|
||||
_normOffsets[1] = NEXT_FLOAT(offsets);
|
||||
_normOffsets[2] = NEXT_FLOAT(offsets);
|
||||
_normOffsets[3] = NEXT_FLOAT(offsets);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)getDescription {
|
||||
return [NSString stringWithFormat:@"rescale: nonPremult=%d", _isNonPremult];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MTLConvolveOp {
|
||||
id<MTLBuffer> _buffer;
|
||||
float _imgEdge[4];
|
||||
int _kernelSize;
|
||||
jboolean _isEdgeZeroFill;
|
||||
}
|
||||
|
||||
- (id)init:(jboolean)edgeZeroFill kernelWidth:(jint)kernelWidth
|
||||
kernelHeight:(jint)kernelHeight
|
||||
srcWidth:(jint)srcWidth
|
||||
srcHeight:(jint)srcHeight
|
||||
kernel:(unsigned char *)kernel
|
||||
device:(id<MTLDevice>)device {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
J2dTraceLn2(J2D_TRACE_INFO,"Created MTLConvolveOp: kernelW=%d kernelH=%d", kernelWidth, kernelHeight);
|
||||
_isEdgeZeroFill = edgeZeroFill;
|
||||
|
||||
_kernelSize = kernelWidth * kernelHeight;
|
||||
_buffer = [device newBufferWithLength:_kernelSize*sizeof(vector_float3) options:MTLResourceStorageModeShared];
|
||||
|
||||
float * kernelVals = [_buffer contents];
|
||||
int kIndex = 0;
|
||||
for (int i = -kernelHeight/2; i < kernelHeight/2+1; i++) {
|
||||
for (int j = -kernelWidth/2; j < kernelWidth/2+1; j++) {
|
||||
kernelVals[kIndex+0] = j/(float)srcWidth;
|
||||
kernelVals[kIndex+1] = i/(float)srcHeight;
|
||||
kernelVals[kIndex+2] = NEXT_FLOAT(kernel);
|
||||
kIndex += 3;
|
||||
}
|
||||
}
|
||||
|
||||
_imgEdge[0] = (kernelWidth/2)/(float)srcWidth;
|
||||
_imgEdge[1] = (kernelHeight/2)/(float)srcHeight;
|
||||
_imgEdge[2] = 1 - _imgEdge[0];
|
||||
_imgEdge[3] = 1 - _imgEdge[1];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
[_buffer release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id<MTLBuffer>) getBuffer {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
- (const float *) getImgEdge {
|
||||
return _imgEdge;
|
||||
}
|
||||
|
||||
- (NSString *)getDescription {
|
||||
return [NSString stringWithFormat:@"convolve: isEdgeZeroFill=%d", _isEdgeZeroFill];
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@implementation MTLLookupOp {
|
||||
float _offset[4];
|
||||
jboolean _isUseSrcAlpha;
|
||||
jboolean _isNonPremult;
|
||||
|
||||
id<MTLTexture> _lookupTex;
|
||||
}
|
||||
|
||||
- (id)init:(jboolean)nonPremult shortData:(jboolean)shortData
|
||||
numBands:(jint)numBands
|
||||
bandLength:(jint)bandLength
|
||||
offset:(jint)offset
|
||||
tableValues:(void *)tableValues
|
||||
device:(id<MTLDevice>)device {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
J2dTraceLn4(J2D_TRACE_INFO,"Created MTLLookupOp: short=%d num=%d len=%d off=%d",
|
||||
shortData, numBands, bandLength, offset);
|
||||
|
||||
_isUseSrcAlpha = numBands != 4;
|
||||
_isNonPremult = nonPremult;
|
||||
|
||||
_offset[0] = offset / 255.0f;
|
||||
_offset[1] = _offset[0];
|
||||
_offset[2] = _offset[0];
|
||||
_offset[3] = _offset[0];
|
||||
|
||||
MTLTextureDescriptor *textureDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatA8Unorm
|
||||
width:(NSUInteger)256
|
||||
height:(NSUInteger)4
|
||||
mipmapped:NO];
|
||||
|
||||
_lookupTex = [device newTextureWithDescriptor:textureDescriptor];
|
||||
|
||||
void *bands[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
bands[i] = NULL;
|
||||
}
|
||||
int bytesPerElem = (shortData ? 2 : 1);
|
||||
if (numBands == 1) {
|
||||
// replicate the single band for R/G/B; alpha band is unused
|
||||
for (int i = 0; i < 3; i++) {
|
||||
bands[i] = tableValues;
|
||||
}
|
||||
bands[3] = NULL;
|
||||
} else if (numBands == 3) {
|
||||
// user supplied band for each of R/G/B; alpha band is unused
|
||||
for (int i = 0; i < 3; i++) {
|
||||
bands[i] = PtrPixelsBand(tableValues, i, bandLength, bytesPerElem);
|
||||
}
|
||||
bands[3] = NULL;
|
||||
} else if (numBands == 4) {
|
||||
// user supplied band for each of R/G/B/A
|
||||
for (int i = 0; i < 4; i++) {
|
||||
bands[i] = PtrPixelsBand(tableValues, i, bandLength, bytesPerElem);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (bands[i] == NULL)
|
||||
continue;
|
||||
|
||||
MTLRegion region = {
|
||||
{0, i, 0},
|
||||
{bandLength, 1,1}
|
||||
};
|
||||
|
||||
[_lookupTex replaceRegion:region
|
||||
mipmapLevel:0
|
||||
withBytes:bands[i]
|
||||
bytesPerRow:bandLength*bytesPerElem];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
[_lookupTex release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (jfloat *) getOffset {
|
||||
return _offset;
|
||||
}
|
||||
|
||||
- (id<MTLTexture>) getLookupTexture {
|
||||
return _lookupTex;
|
||||
}
|
||||
|
||||
- (NSString *)getDescription {
|
||||
return [NSString stringWithFormat:@"lookup: offset=%f", _offset[0]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#import <limits.h>
|
||||
#ifndef MTLClip_h_Included
|
||||
#define MTLClip_h_Included
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "MTLSurfaceDataBase.h"
|
||||
|
||||
enum Clip {
|
||||
NO_CLIP,
|
||||
RECT_CLIP,
|
||||
SHAPE_CLIP
|
||||
};
|
||||
|
||||
@class MTLContext;
|
||||
@class MTLPipelineStatesStorage;
|
||||
|
||||
/**
|
||||
* The MTLClip class represents clip mode (rect or stencil)
|
||||
* */
|
||||
|
||||
@interface MTLClip : NSObject
|
||||
@property (readonly) id<MTLTexture> stencilTextureRef;
|
||||
@property (readonly) BOOL stencilMaskGenerationInProgress;
|
||||
@property NSUInteger shapeX;
|
||||
@property NSUInteger shapeY;
|
||||
@property NSUInteger shapeWidth;
|
||||
@property NSUInteger shapeHeight;
|
||||
|
||||
- (id)init;
|
||||
- (BOOL)isEqual:(MTLClip *)other; // used to compare requested with cached
|
||||
- (void)copyFrom:(MTLClip *)other; // used to save cached
|
||||
|
||||
- (BOOL)isShape;
|
||||
- (BOOL)isRect;
|
||||
|
||||
// returns null when clipType != RECT_CLIP
|
||||
- (const MTLScissorRect *) getRect;
|
||||
|
||||
- (void)reset;
|
||||
- (void)resetStencilState;
|
||||
- (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2;
|
||||
- (void)beginShapeClip:(BMTLSDOps *)dstOps context:(MTLContext *)mtlc;
|
||||
- (void)endShapeClip:(BMTLSDOps *)dstOps context:(MTLContext *)mtlc;
|
||||
|
||||
- (void)setScissorOrStencil:(id<MTLRenderCommandEncoder>)encoder
|
||||
destWidth:(NSUInteger)dw
|
||||
destHeight:(NSUInteger)dh
|
||||
device:(id<MTLDevice>)device;
|
||||
|
||||
- (void)setMaskGenerationPipelineState:(id<MTLRenderCommandEncoder>)encoder
|
||||
destWidth:(NSUInteger)dw
|
||||
destHeight:(NSUInteger)dh
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage;
|
||||
|
||||
- (NSString *)getDescription __unused; // creates autorelease string
|
||||
@end
|
||||
|
||||
#endif // MTLClip_h_Included
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "MTLClip.h"
|
||||
|
||||
#include "MTLContext.h"
|
||||
#include "MTLStencilManager.h"
|
||||
#include "common.h"
|
||||
|
||||
static MTLRenderPipelineDescriptor * templateStencilPipelineDesc = nil;
|
||||
|
||||
static void initTemplatePipelineDescriptors() {
|
||||
if (templateStencilPipelineDesc != nil)
|
||||
return;
|
||||
|
||||
MTLVertexDescriptor *vertDesc = [[MTLVertexDescriptor new] autorelease];
|
||||
vertDesc.attributes[VertexAttributePosition].format = MTLVertexFormatFloat2;
|
||||
vertDesc.attributes[VertexAttributePosition].offset = 0;
|
||||
vertDesc.attributes[VertexAttributePosition].bufferIndex = MeshVertexBuffer;
|
||||
vertDesc.layouts[MeshVertexBuffer].stride = sizeof(struct Vertex);
|
||||
vertDesc.layouts[MeshVertexBuffer].stepRate = 1;
|
||||
vertDesc.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||
|
||||
templateStencilPipelineDesc = [MTLRenderPipelineDescriptor new];
|
||||
templateStencilPipelineDesc.sampleCount = 1;
|
||||
templateStencilPipelineDesc.vertexDescriptor = vertDesc;
|
||||
templateStencilPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatR8Uint; // A byte buffer format
|
||||
templateStencilPipelineDesc.label = @"template_stencil";
|
||||
}
|
||||
|
||||
@implementation MTLClip {
|
||||
jint _clipType;
|
||||
MTLScissorRect _clipRect;
|
||||
MTLContext* _mtlc;
|
||||
BMTLSDOps* _dstOps;
|
||||
BOOL _stencilMaskGenerationInProgress;
|
||||
BOOL _clipReady;
|
||||
MTLOrigin _clipShapeOrigin;
|
||||
MTLSize _clipShapeSize;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_clipType = NO_CLIP;
|
||||
_mtlc = nil;
|
||||
_dstOps = NULL;
|
||||
_stencilMaskGenerationInProgress = NO;
|
||||
_clipReady = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLClip *)other {
|
||||
if (self == other)
|
||||
return YES;
|
||||
if (_stencilMaskGenerationInProgress == JNI_TRUE)
|
||||
return other->_stencilMaskGenerationInProgress == JNI_TRUE;
|
||||
if (_clipType != other->_clipType)
|
||||
return NO;
|
||||
if (_clipType == NO_CLIP)
|
||||
return YES;
|
||||
if (_clipType == RECT_CLIP) {
|
||||
return _clipRect.x == other->_clipRect.x && _clipRect.y == other->_clipRect.y
|
||||
&& _clipRect.width == other->_clipRect.width && _clipRect.height == other->_clipRect.height;
|
||||
}
|
||||
|
||||
// NOTE: can compare stencil-data pointers here
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)isShape {
|
||||
return _clipType == SHAPE_CLIP;
|
||||
}
|
||||
|
||||
- (BOOL)isRect __unused {
|
||||
return _clipType == RECT_CLIP;
|
||||
}
|
||||
|
||||
- (const MTLScissorRect * _Nullable) getRect {
|
||||
return _clipType == RECT_CLIP ? &_clipRect : NULL;
|
||||
}
|
||||
|
||||
- (void)copyFrom:(MTLClip *)other {
|
||||
_clipType = other->_clipType;
|
||||
_stencilMaskGenerationInProgress = other->_stencilMaskGenerationInProgress;
|
||||
_dstOps = other->_dstOps;
|
||||
_mtlc = other->_mtlc;
|
||||
if (other->_clipType == RECT_CLIP) {
|
||||
_clipRect = other->_clipRect;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reset {
|
||||
_clipType = NO_CLIP;
|
||||
_stencilMaskGenerationInProgress = JNI_FALSE;
|
||||
}
|
||||
|
||||
|
||||
- (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2 {
|
||||
if (_clipType == SHAPE_CLIP) {
|
||||
_dstOps = NULL;
|
||||
}
|
||||
|
||||
if (x1 >= x2 || y1 >= y2) {
|
||||
J2dTraceLn4(J2D_TRACE_ERROR, "MTLClip.setClipRect: invalid rect: x1=%d y1=%d x2=%d y2=%d", x1, y1, x2, y2);
|
||||
_clipType = NO_CLIP;
|
||||
}
|
||||
|
||||
const jint width = x2 - x1;
|
||||
const jint height = y2 - y1;
|
||||
|
||||
J2dTraceLn4(J2D_TRACE_INFO, "MTLClip.setClipRect: x=%d y=%d w=%d h=%d", x1, y1, width, height);
|
||||
|
||||
_clipRect.x = (NSUInteger)((x1 >= 0) ? x1 : 0);
|
||||
_clipRect.y = (NSUInteger)((y1 >= 0) ? y1 : 0);
|
||||
_clipRect.width = (NSUInteger)((width >= 0) ? width : 0);
|
||||
_clipRect.height = (NSUInteger)((height >= 0) ? height : 0);
|
||||
_clipType = RECT_CLIP;
|
||||
}
|
||||
|
||||
- (void)beginShapeClip:(BMTLSDOps *)dstOps context:(MTLContext *)mtlc {
|
||||
_stencilMaskGenerationInProgress = YES;
|
||||
|
||||
if ((dstOps == NULL) || (dstOps->pStencilData == NULL) || (dstOps->pStencilTexture == NULL)) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_beginShapeClip: stencil render target or stencil texture is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the stencil render buffer & stencil texture
|
||||
@autoreleasepool {
|
||||
if (dstOps->width <= 0 || dstOps->height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
_clipShapeSize = MTLSizeMake(0, 0, 1);
|
||||
_clipShapeOrigin = MTLOriginMake(0, 0, 0);
|
||||
|
||||
MTLRenderPassDescriptor* clearPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
// set color buffer properties
|
||||
clearPassDescriptor.colorAttachments[0].texture = dstOps->pStencilData;
|
||||
clearPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||
clearPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0f, 0.0f,0.0f, 0.0f);
|
||||
|
||||
id<MTLCommandBuffer> commandBuf = [mtlc createCommandBuffer];
|
||||
id <MTLRenderCommandEncoder> clearEncoder = [commandBuf renderCommandEncoderWithDescriptor:clearPassDescriptor];
|
||||
[clearEncoder endEncoding];
|
||||
[commandBuf commit];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)endShapeClip:(BMTLSDOps *)dstOps context:(MTLContext *)mtlc {
|
||||
|
||||
if ((dstOps == NULL) || (dstOps->pStencilData == NULL) || (dstOps->pStencilTexture == NULL)) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_endShapeClip: stencil render target or stencil texture is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
// Complete the rendering to the stencil buffer ------------
|
||||
[mtlc.encoderManager endEncoder];
|
||||
|
||||
MTLCommandBufferWrapper* cbWrapper = [mtlc pullCommandBufferWrapper];
|
||||
|
||||
id<MTLCommandBuffer> commandBuffer = [cbWrapper getCommandBuffer];
|
||||
[commandBuffer addCompletedHandler:^(id <MTLCommandBuffer> c) {
|
||||
[cbWrapper release];
|
||||
}];
|
||||
|
||||
[commandBuffer commit];
|
||||
|
||||
// Now the stencil data is ready, this needs to be used while rendering further
|
||||
@autoreleasepool {
|
||||
if (_clipShapeSize.width > 0 && _clipShapeSize.height > 0) {
|
||||
id<MTLCommandBuffer> cb = [mtlc createCommandBuffer];
|
||||
id<MTLBlitCommandEncoder> blitEncoder = [cb blitCommandEncoder];
|
||||
[blitEncoder copyFromTexture:dstOps->pStencilData
|
||||
sourceSlice:0
|
||||
sourceLevel:0
|
||||
sourceOrigin:_clipShapeOrigin
|
||||
sourceSize:_clipShapeSize
|
||||
toBuffer:dstOps->pStencilDataBuf
|
||||
destinationOffset:0
|
||||
destinationBytesPerRow:_clipShapeSize.width
|
||||
destinationBytesPerImage:_clipShapeSize.width*_clipShapeSize.height];
|
||||
[blitEncoder endEncoding];
|
||||
[cb commit];
|
||||
}
|
||||
}
|
||||
|
||||
_stencilMaskGenerationInProgress = JNI_FALSE;
|
||||
_mtlc = mtlc;
|
||||
_dstOps = dstOps;
|
||||
_clipType = SHAPE_CLIP;
|
||||
_clipReady = NO;
|
||||
}
|
||||
|
||||
- (void)setMaskGenerationPipelineState:(id<MTLRenderCommandEncoder>)encoder
|
||||
destWidth:(NSUInteger)dw
|
||||
destHeight:(NSUInteger)dh
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
{
|
||||
initTemplatePipelineDescriptors();
|
||||
|
||||
// A PipelineState for rendering to a byte-buffered texture that will be used as a stencil
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:templateStencilPipelineDesc
|
||||
vertexShaderId:@"vert_stencil"
|
||||
fragmentShaderId:@"frag_stencil"];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
|
||||
struct FrameUniforms uf; // color is ignored while writing to stencil buffer
|
||||
memset(&uf, 0, sizeof(uf));
|
||||
[encoder setVertexBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
|
||||
|
||||
_clipRect.x = 0;
|
||||
_clipRect.y = 0;
|
||||
_clipRect.width = dw;
|
||||
_clipRect.height = dh;
|
||||
|
||||
[encoder setScissorRect:_clipRect]; // just for insurance (to reset possible clip from previous drawing)
|
||||
}
|
||||
|
||||
- (void)setScissorOrStencil:(id<MTLRenderCommandEncoder>)encoder
|
||||
destWidth:(NSUInteger)dw
|
||||
destHeight:(NSUInteger)dh
|
||||
device:(id<MTLDevice>)device
|
||||
{
|
||||
if (_clipType == NO_CLIP || _clipType == SHAPE_CLIP) {
|
||||
_clipRect.x = 0;
|
||||
_clipRect.y = 0;
|
||||
_clipRect.width = dw;
|
||||
_clipRect.height = dh;
|
||||
}
|
||||
|
||||
// Clamping clip rect to the destination area
|
||||
MTLScissorRect rect = _clipRect;
|
||||
|
||||
if (rect.x > dw) {
|
||||
rect.x = dw;
|
||||
}
|
||||
|
||||
if (rect.y > dh) {
|
||||
rect.y = dh;
|
||||
}
|
||||
|
||||
if (rect.x + rect.width > dw) {
|
||||
rect.width = dw - rect.x;
|
||||
}
|
||||
|
||||
if (rect.y + rect.height > dh) {
|
||||
rect.height = dh - rect.y;
|
||||
}
|
||||
|
||||
[encoder setScissorRect:rect];
|
||||
if (_clipType == NO_CLIP || _clipType == RECT_CLIP) {
|
||||
// NOTE: It seems that we can use the same encoder (with disabled stencil test) when mode changes from SHAPE to RECT.
|
||||
// But [encoder setDepthStencilState:nil] causes crash, so we have to recreate encoder in such case.
|
||||
// So we can omit [encoder setDepthStencilState:nil] here.
|
||||
return;
|
||||
}
|
||||
|
||||
if (_clipType == SHAPE_CLIP) {
|
||||
// Enable stencil test
|
||||
[encoder setDepthStencilState:_mtlc.stencilManager.stencilState];
|
||||
[encoder setStencilReferenceValue:0xFF];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)getDescription __unused {
|
||||
if (_clipType == NO_CLIP) {
|
||||
return @"NO_CLIP";
|
||||
}
|
||||
if (_clipType == RECT_CLIP) {
|
||||
return [NSString stringWithFormat:@"RECT_CLIP [%lu,%lu - %lux%lu]", _clipRect.x, _clipRect.y, _clipRect.width, _clipRect.height];
|
||||
}
|
||||
return [NSString stringWithFormat:@"SHAPE_CLIP"];
|
||||
}
|
||||
|
||||
- (id<MTLTexture>) stencilTextureRef {
|
||||
if (_dstOps == NULL) return nil;
|
||||
|
||||
id <MTLTexture> _stencilTextureRef = _dstOps->pStencilTexture;
|
||||
|
||||
if (!_clipReady) {
|
||||
@autoreleasepool {
|
||||
|
||||
MTLRenderPassDescriptor* clearPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
// set color buffer properties
|
||||
clearPassDescriptor.stencilAttachment.texture = _stencilTextureRef;
|
||||
clearPassDescriptor.stencilAttachment.clearStencil = 0;
|
||||
clearPassDescriptor.stencilAttachment.loadAction = MTLLoadActionClear;
|
||||
|
||||
id<MTLCommandBuffer> commandBuf = [_mtlc createCommandBuffer];
|
||||
id <MTLRenderCommandEncoder> clearEncoder = [commandBuf renderCommandEncoderWithDescriptor:clearPassDescriptor];
|
||||
[clearEncoder endEncoding];
|
||||
[commandBuf commit];
|
||||
|
||||
id <MTLCommandBuffer> cb = [_mtlc createCommandBuffer];
|
||||
id <MTLBlitCommandEncoder> blitEncoder = [cb blitCommandEncoder];
|
||||
id <MTLBuffer> _stencilDataBufRef = _dstOps->pStencilDataBuf;
|
||||
[blitEncoder copyFromBuffer:_stencilDataBufRef
|
||||
sourceOffset:0
|
||||
sourceBytesPerRow:_clipShapeSize.width
|
||||
sourceBytesPerImage:_clipShapeSize.width * _clipShapeSize.height
|
||||
sourceSize:_clipShapeSize
|
||||
toTexture:_stencilTextureRef
|
||||
destinationSlice:0
|
||||
destinationLevel:0
|
||||
destinationOrigin:_clipShapeOrigin];
|
||||
[blitEncoder endEncoding];
|
||||
[cb commit];
|
||||
_clipReady = YES;
|
||||
}
|
||||
}
|
||||
return _stencilTextureRef;
|
||||
}
|
||||
|
||||
- (NSUInteger)shapeX {
|
||||
return _clipShapeOrigin.x;
|
||||
}
|
||||
|
||||
- (void)setShapeX:(NSUInteger)shapeX {
|
||||
_clipShapeOrigin.x = shapeX;
|
||||
}
|
||||
|
||||
- (NSUInteger)shapeY {
|
||||
return _clipShapeOrigin.y;
|
||||
}
|
||||
|
||||
- (void)setShapeY:(NSUInteger)shapeY {
|
||||
_clipShapeOrigin.y = shapeY;
|
||||
}
|
||||
|
||||
- (NSUInteger)shapeWidth {
|
||||
return _clipShapeSize.width;
|
||||
}
|
||||
|
||||
- (void)setShapeWidth:(NSUInteger)shapeWidth {
|
||||
_clipShapeSize.width = shapeWidth;
|
||||
}
|
||||
|
||||
- (NSUInteger)shapeHeight {
|
||||
return _clipShapeSize.height;
|
||||
}
|
||||
|
||||
- (void)setShapeHeight:(NSUInteger)shapeHeight {
|
||||
_clipShapeSize.height = shapeHeight;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLComposite_h_Included
|
||||
#define MTLComposite_h_Included
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#define FLT_EPS (0.001f)
|
||||
#define FLT_LT(x,y) ((x) < (y) - FLT_EPS)
|
||||
#define FLT_GE(x,y) ((x) >= (y) - FLT_EPS)
|
||||
#define FLT_LE(x,y) ((x) <= (y) + FLT_EPS)
|
||||
#define FLT_GT(x,y) ((x) > (y) + FLT_EPS)
|
||||
|
||||
/**
|
||||
* The MTLComposite class represents composite mode
|
||||
* */
|
||||
|
||||
@interface MTLComposite : NSObject
|
||||
- (id)init;
|
||||
- (BOOL)isEqual:(MTLComposite *)other; // used to compare requested with cached
|
||||
- (void)copyFrom:(MTLComposite *)other; // used to save cached
|
||||
|
||||
- (void)setRule:(jint)rule; // sets extraAlpha=1
|
||||
- (void)setRule:(jint)rule extraAlpha:(jfloat)extraAlpha;
|
||||
- (void)reset;
|
||||
|
||||
- (void)setXORComposite:(jint)color;
|
||||
- (void)setAlphaComposite:(jint)rule;
|
||||
|
||||
|
||||
- (jint)getCompositeState;
|
||||
- (jint)getRule;
|
||||
- (jint)getXorColor;
|
||||
- (jfloat)getExtraAlpha;
|
||||
|
||||
- (NSString *)getDescription; // creates autorelease string
|
||||
@end
|
||||
|
||||
#endif // MTLComposite_h_Included
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "MTLComposite.h"
|
||||
#include "sun_java2d_SunGraphics2D.h"
|
||||
#include "java_awt_AlphaComposite.h"
|
||||
|
||||
@implementation MTLComposite {
|
||||
jint _compState;
|
||||
jint _compositeRule;
|
||||
jint _xorPixel;
|
||||
jfloat _extraAlpha;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_compositeRule = -1;
|
||||
_compState = -1;
|
||||
_xorPixel = 0;
|
||||
_extraAlpha = 1;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLComposite *)other {
|
||||
if (self == other)
|
||||
return YES;
|
||||
|
||||
if (_compState == other->_compState) {
|
||||
if (_compState == sun_java2d_SunGraphics2D_COMP_XOR) {
|
||||
return _xorPixel == other->_xorPixel;
|
||||
}
|
||||
|
||||
if (_compState == sun_java2d_SunGraphics2D_COMP_ALPHA) {
|
||||
return _extraAlpha == other->_extraAlpha
|
||||
&& _compositeRule == other->_compositeRule;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)copyFrom:(MTLComposite *)other {
|
||||
_extraAlpha = other->_extraAlpha;
|
||||
_compositeRule = other->_compositeRule;
|
||||
_compState = other->_compState;
|
||||
_xorPixel = other->_xorPixel;
|
||||
}
|
||||
|
||||
- (void)setRule:(jint)rule {
|
||||
_extraAlpha = 1.f;
|
||||
_compositeRule = rule;
|
||||
}
|
||||
|
||||
- (void)setRule:(jint)rule extraAlpha:(jfloat)extraAlpha {
|
||||
_compState = sun_java2d_SunGraphics2D_COMP_ALPHA;
|
||||
_extraAlpha = extraAlpha;
|
||||
_compositeRule = rule;
|
||||
}
|
||||
|
||||
- (void)reset {
|
||||
_compState = sun_java2d_SunGraphics2D_COMP_ISCOPY;
|
||||
_compositeRule = java_awt_AlphaComposite_SRC;
|
||||
_extraAlpha = 1.f;
|
||||
}
|
||||
|
||||
- (jint)getRule {
|
||||
return _compositeRule;
|
||||
}
|
||||
|
||||
- (NSString *)getDescription {
|
||||
const char * result = "";
|
||||
switch (_compositeRule) {
|
||||
case java_awt_AlphaComposite_CLEAR:
|
||||
{
|
||||
result = "CLEAR";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_SRC:
|
||||
{
|
||||
result = "SRC";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_DST:
|
||||
{
|
||||
result = "DST";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_SRC_OVER:
|
||||
{
|
||||
result = "SRC_OVER";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_DST_OVER:
|
||||
{
|
||||
result = "DST_OVER";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_SRC_IN:
|
||||
{
|
||||
result = "SRC_IN";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_DST_IN:
|
||||
{
|
||||
result = "DST_IN";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_SRC_OUT:
|
||||
{
|
||||
result = "SRC_OUT";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_DST_OUT:
|
||||
{
|
||||
result = "DST_OUT";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_SRC_ATOP:
|
||||
{
|
||||
result = "SRC_ATOP";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_DST_ATOP:
|
||||
{
|
||||
result = "DST_ATOP";
|
||||
}
|
||||
break;
|
||||
case java_awt_AlphaComposite_XOR:
|
||||
{
|
||||
result = "XOR";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
const double epsilon = 0.001f;
|
||||
if (fabs(_extraAlpha - 1.f) > epsilon) {
|
||||
return [NSString stringWithFormat:@"%s [%1.2f]", result, _extraAlpha];
|
||||
}
|
||||
return [NSString stringWithFormat:@"%s", result];
|
||||
}
|
||||
|
||||
- (void)setAlphaComposite:(jint)rule {
|
||||
_compState = sun_java2d_SunGraphics2D_COMP_ALPHA;
|
||||
[self setRule:rule];
|
||||
}
|
||||
|
||||
|
||||
- (jint)getCompositeState {
|
||||
return _compState;
|
||||
}
|
||||
|
||||
|
||||
-(void)setXORComposite:(jint)color {
|
||||
_compState = sun_java2d_SunGraphics2D_COMP_XOR;
|
||||
_xorPixel = color;
|
||||
}
|
||||
|
||||
-(jint)getXorColor {
|
||||
return _xorPixel;
|
||||
}
|
||||
|
||||
- (jfloat)getExtraAlpha {
|
||||
return _extraAlpha;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLContext_h_Included
|
||||
#define MTLContext_h_Included
|
||||
|
||||
#include "sun_java2d_pipe_BufferedContext.h"
|
||||
#include "sun_java2d_metal_MTLContext_MTLContextCaps.h"
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
#include "MTLTexturePool.h"
|
||||
#include "MTLPipelineStatesStorage.h"
|
||||
#include "MTLTransform.h"
|
||||
#include "MTLComposite.h"
|
||||
#include "MTLPaints.h"
|
||||
#include "MTLClip.h"
|
||||
#include "EncoderManager.h"
|
||||
#include "MTLSamplerManager.h"
|
||||
|
||||
@class MTLStencilManager;
|
||||
|
||||
// Constant from
|
||||
// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
|
||||
#define MTL_GPU_FAMILY_MAC_TXT_SIZE 16384
|
||||
|
||||
/**
|
||||
* The MTLCommandBufferWrapper class contains command buffer and
|
||||
* associated resources that will be released in completion handler
|
||||
* */
|
||||
@interface MTLCommandBufferWrapper : NSObject
|
||||
- (id<MTLCommandBuffer>) getCommandBuffer;
|
||||
- (void) onComplete; // invoked from completion handler in some pooled thread
|
||||
- (void) registerPooledTexture:(MTLPooledTextureHandle *)handle;
|
||||
@end
|
||||
|
||||
/**
|
||||
* The MTLContext class contains cached state relevant to the native
|
||||
* MTL context stored within the native ctxInfo field. Each Java-level
|
||||
* MTLContext object is associated with a native-level MTLContext class.
|
||||
* */
|
||||
@interface MTLContext : NSObject
|
||||
@property (readonly) MTLComposite * composite;
|
||||
@property (readwrite, retain) MTLPaint * paint;
|
||||
@property (readonly) MTLTransform * transform;
|
||||
@property (readonly) MTLClip * clip;
|
||||
|
||||
@property jint textureFunction;
|
||||
@property jboolean vertexCacheEnabled;
|
||||
@property jboolean aaEnabled;
|
||||
|
||||
@property (readonly, strong) id<MTLDevice> device;
|
||||
@property (strong) id<MTLCommandQueue> commandQueue;
|
||||
@property (strong) id<MTLCommandQueue> blitCommandQueue;
|
||||
@property (strong) id<MTLBuffer> vertexBuffer;
|
||||
|
||||
@property (readonly) EncoderManager * encoderManager;
|
||||
@property (readonly) MTLSamplerManager * samplerManager;
|
||||
@property (readonly) MTLStencilManager * stencilManager;
|
||||
|
||||
@property (strong)MTLPipelineStatesStorage* pipelineStateStorage;
|
||||
@property (strong)MTLTexturePool* texturePool;
|
||||
|
||||
- (MTLCommandBufferWrapper *) getCommandBufferWrapper; // creates command buffer wrapper (when doesn't exist)
|
||||
- (MTLCommandBufferWrapper *) pullCommandBufferWrapper; // returns current buffer wrapper with loosing object ownership
|
||||
|
||||
/**
|
||||
* Fetches the MTLContext associated with the given destination surface,
|
||||
* makes the context current for those surfaces, updates the destination
|
||||
* viewport, and then returns a pointer to the MTLContext.
|
||||
*/
|
||||
+ (MTLContext*) setSurfacesEnv:(JNIEnv*)env src:(jlong)pSrc dst:(jlong)pDst;
|
||||
|
||||
- (id)initWithDevice:(id<MTLDevice>)d shadersLib:(NSString*)shadersLib;
|
||||
- (void)dealloc;
|
||||
|
||||
/**
|
||||
* Resets the current clip state (disables both scissor and depth tests).
|
||||
*/
|
||||
- (void)resetClip;
|
||||
|
||||
/**
|
||||
* Sets the Metal scissor bounds to the provided rectangular clip bounds.
|
||||
*/
|
||||
- (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2;
|
||||
|
||||
- (const MTLScissorRect *)clipRect;
|
||||
|
||||
/**
|
||||
* Sets up a complex (shape) clip using the Metal stencil buffer. This
|
||||
* method prepares the stencil buffer so that the clip Region spans can
|
||||
* be "rendered" into it. The stencil buffer is first cleared, then the
|
||||
* stencil func is setup so that when we render the clip spans,
|
||||
* nothing is rendered into the color buffer, but for each pixel that would
|
||||
* be rendered, a 0xFF value is placed into that location in the stencil
|
||||
* buffer. With stencil test enabled, pixels will only be rendered into the
|
||||
* color buffer if the corresponding value at that (x,y) location in the
|
||||
* stencil buffer is equal to 0xFF.
|
||||
*/
|
||||
- (void)beginShapeClip:(BMTLSDOps *)dstOps;
|
||||
|
||||
/**
|
||||
* Finishes setting up the shape clip by resetting the stencil func
|
||||
* so that future rendering operations will once again be encoded for the
|
||||
* color buffer (while respecting the clip set up in the stencil buffer).
|
||||
*/
|
||||
- (void)endShapeClip:(BMTLSDOps *)dstOps;
|
||||
|
||||
/**
|
||||
* Resets all Metal compositing state (disables blending and logic
|
||||
* operations).
|
||||
*/
|
||||
- (void)resetComposite;
|
||||
|
||||
/**
|
||||
* Initializes the Metal blending state. XOR mode is disabled and the
|
||||
* appropriate blend functions are setup based on the AlphaComposite rule
|
||||
* constant.
|
||||
*/
|
||||
- (void)setAlphaCompositeRule:(jint)rule extraAlpha:(jfloat)extraAlpha
|
||||
flags:(jint)flags;
|
||||
|
||||
/**
|
||||
* Returns autorelease string with composite description (for debugging only)
|
||||
*/
|
||||
- (NSString*)getCompositeDescription;
|
||||
|
||||
/**
|
||||
* Returns autorelease string with paint description (for debugging only)
|
||||
*/
|
||||
- (NSString*)getPaintDescription;
|
||||
|
||||
/**
|
||||
* Initializes the Metal logic op state to XOR mode. Blending is disabled
|
||||
* before enabling logic op mode. The XOR pixel value will be applied
|
||||
* later in the MTLContext_SetColor() method.
|
||||
*/
|
||||
- (void)setXorComposite:(jint)xorPixel;
|
||||
- (jboolean)useXORComposite;
|
||||
|
||||
/**
|
||||
* Resets the Metal transform state back to the identity matrix.
|
||||
*/
|
||||
- (void)resetTransform;
|
||||
|
||||
/**
|
||||
* Initializes the Metal transform state by setting the modelview transform
|
||||
* using the given matrix parameters.
|
||||
*
|
||||
* REMIND: it may be worthwhile to add serial id to AffineTransform, so we
|
||||
* could do a quick check to see if the xform has changed since
|
||||
* last time... a simple object compare won't suffice...
|
||||
*/
|
||||
- (void)setTransformM00:(jdouble) m00 M10:(jdouble) m10
|
||||
M01:(jdouble) m01 M11:(jdouble) m11
|
||||
M02:(jdouble) m02 M12:(jdouble) m12;
|
||||
|
||||
- (void)reset;
|
||||
- (void)resetPaint;
|
||||
- (void)setColorPaint:(int)pixel;
|
||||
- (void)setGradientPaintUseMask:(jboolean)useMask
|
||||
cyclic:(jboolean)cyclic
|
||||
p0:(jdouble)p0
|
||||
p1:(jdouble)p1
|
||||
p3:(jdouble)p3
|
||||
pixel1:(jint)pixel1
|
||||
pixel2:(jint) pixel2;
|
||||
- (void)setLinearGradientPaint:(jboolean)useMask
|
||||
linear:(jboolean)linear
|
||||
cycleMethod:(jint)cycleMethod
|
||||
numStops:(jint)numStops
|
||||
p0:(jfloat)p0
|
||||
p1:(jfloat)p1
|
||||
p3:(jfloat)p3
|
||||
fractions:(jfloat *)fractions
|
||||
pixels:(jint *)pixels;
|
||||
- (void)setRadialGradientPaint:(jboolean)useMask
|
||||
linear:(jboolean)linear
|
||||
cycleMethod:(jboolean)cycleMethod
|
||||
numStops:(jint)numStops
|
||||
m00:(jfloat)m00
|
||||
m01:(jfloat)m01
|
||||
m02:(jfloat)m02
|
||||
m10:(jfloat)m10
|
||||
m11:(jfloat)m11
|
||||
m12:(jfloat)m12
|
||||
focusX:(jfloat)focusX
|
||||
fractions:(void *)fractions
|
||||
pixels:(void *)pixels;
|
||||
- (void)setTexturePaint:(jboolean)useMask
|
||||
pSrcOps:(jlong)pSrcOps
|
||||
filter:(jboolean)filter
|
||||
xp0:(jdouble)xp0
|
||||
xp1:(jdouble)xp1
|
||||
xp3:(jdouble)xp3
|
||||
yp0:(jdouble)yp0
|
||||
yp1:(jdouble)yp1
|
||||
yp3:(jdouble)yp3;
|
||||
|
||||
// Sets current image conversion operation (instance of MTLConvolveOp, MTLRescaleOp, MTLLookupOp).
|
||||
// Used only in MTLIsoBlit (to blit image with some conversion). Pattern of usage: enableOp -> IsoBlit -> disableOp.
|
||||
// TODO: Need to remove it from MTLContext and pass it as an argument for IsoBlit (because it's more
|
||||
// simple and clear)
|
||||
-(void)setBufImgOp:(NSObject*)bufImgOp;
|
||||
|
||||
-(NSObject*)getBufImgOp;
|
||||
|
||||
- (id<MTLCommandBuffer>)createCommandBuffer;
|
||||
- (id<MTLCommandBuffer>)createBlitCommandBuffer;
|
||||
@end
|
||||
|
||||
/**
|
||||
* See BufferedContext.java for more on these flags...
|
||||
*/
|
||||
#define MTLC_NO_CONTEXT_FLAGS \
|
||||
sun_java2d_pipe_BufferedContext_NO_CONTEXT_FLAGS
|
||||
#define MTLC_SRC_IS_OPAQUE \
|
||||
sun_java2d_pipe_BufferedContext_SRC_IS_OPAQUE
|
||||
#define MTLC_USE_MASK \
|
||||
sun_java2d_pipe_BufferedContext_USE_MASK
|
||||
|
||||
#endif /* MTLContext_h_Included */
|
||||
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sun_java2d_SunGraphics2D.h"
|
||||
|
||||
#include "jlong.h"
|
||||
#import "MTLContext.h"
|
||||
#include "MTLRenderQueue.h"
|
||||
#import "MTLSamplerManager.h"
|
||||
#import "MTLStencilManager.h"
|
||||
|
||||
|
||||
extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *mtlsdo);
|
||||
|
||||
static struct TxtVertex verts[PGRAM_VERTEX_COUNT] = {
|
||||
{{-1.0, 1.0}, {0.0, 0.0}},
|
||||
{{1.0, 1.0}, {1.0, 0.0}},
|
||||
{{1.0, -1.0}, {1.0, 1.0}},
|
||||
{{1.0, -1.0}, {1.0, 1.0}},
|
||||
{{-1.0, -1.0}, {0.0, 1.0}},
|
||||
{{-1.0, 1.0}, {0.0, 0.0}}
|
||||
};
|
||||
|
||||
MTLTransform* tempTransform = nil;
|
||||
|
||||
@implementation MTLCommandBufferWrapper {
|
||||
id<MTLCommandBuffer> _commandBuffer;
|
||||
NSMutableArray * _pooledTextures;
|
||||
NSLock* _lock;
|
||||
}
|
||||
|
||||
- (id) initWithCommandBuffer:(id<MTLCommandBuffer>)cmdBuf {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_commandBuffer = [cmdBuf retain];
|
||||
_pooledTextures = [[NSMutableArray alloc] init];
|
||||
_lock = [[NSLock alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id<MTLCommandBuffer>) getCommandBuffer {
|
||||
return _commandBuffer;
|
||||
}
|
||||
|
||||
- (void) onComplete { // invoked from completion handler in some pooled thread
|
||||
[_lock lock];
|
||||
@try {
|
||||
for (int c = 0; c < [_pooledTextures count]; ++c)
|
||||
[[_pooledTextures objectAtIndex:c] releaseTexture];
|
||||
[_pooledTextures removeAllObjects];
|
||||
} @finally {
|
||||
[_lock unlock];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void) registerPooledTexture:(MTLPooledTextureHandle *)handle {
|
||||
[_lock lock];
|
||||
@try {
|
||||
[_pooledTextures addObject:handle];
|
||||
} @finally {
|
||||
[_lock unlock];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
[self onComplete];
|
||||
|
||||
[_pooledTextures release];
|
||||
_pooledTextures = nil;
|
||||
|
||||
[_commandBuffer release];
|
||||
_commandBuffer = nil;
|
||||
|
||||
[_lock release];
|
||||
_lock = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTLContext {
|
||||
MTLCommandBufferWrapper * _commandBufferWrapper;
|
||||
|
||||
MTLComposite * _composite;
|
||||
MTLPaint * _paint;
|
||||
MTLTransform * _transform;
|
||||
MTLTransform * _tempTransform;
|
||||
MTLClip * _clip;
|
||||
NSObject* _bufImgOp; // TODO: pass as parameter of IsoBlit
|
||||
|
||||
EncoderManager * _encoderManager;
|
||||
MTLSamplerManager * _samplerManager;
|
||||
MTLStencilManager * _stencilManager;
|
||||
}
|
||||
|
||||
@synthesize textureFunction,
|
||||
vertexCacheEnabled, aaEnabled, device, pipelineStateStorage,
|
||||
commandQueue, blitCommandQueue, vertexBuffer,
|
||||
texturePool, paint=_paint, encoderManager=_encoderManager,
|
||||
samplerManager=_samplerManager, stencilManager=_stencilManager;
|
||||
|
||||
extern void initSamplers(id<MTLDevice> device);
|
||||
|
||||
- (id)initWithDevice:(id<MTLDevice>)d shadersLib:(NSString*)shadersLib {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
// Initialization code here.
|
||||
device = d;
|
||||
|
||||
pipelineStateStorage = [[MTLPipelineStatesStorage alloc] initWithDevice:device shaderLibPath:shadersLib];
|
||||
if (pipelineStateStorage == nil) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext.initWithDevice(): Failed to initialize MTLPipelineStatesStorage.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
texturePool = [[MTLTexturePool alloc] initWithDevice:device];
|
||||
|
||||
vertexBuffer = [device newBufferWithBytes:verts
|
||||
length:sizeof(verts)
|
||||
options:MTLResourceCPUCacheModeDefaultCache];
|
||||
|
||||
_encoderManager = [[EncoderManager alloc] init];
|
||||
[_encoderManager setContext:self];
|
||||
_samplerManager = [[MTLSamplerManager alloc] initWithDevice:device];
|
||||
_stencilManager = [[MTLStencilManager alloc] initWithDevice:device];
|
||||
_composite = [[MTLComposite alloc] init];
|
||||
_paint = [[MTLPaint alloc] init];
|
||||
_transform = [[MTLTransform alloc] init];
|
||||
_clip = [[MTLClip alloc] init];
|
||||
_bufImgOp = nil;
|
||||
|
||||
_commandBufferWrapper = nil;
|
||||
|
||||
// Create command queue
|
||||
commandQueue = [device newCommandQueue];
|
||||
blitCommandQueue = [device newCommandQueue];
|
||||
|
||||
_tempTransform = [[MTLTransform alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLContext.dealloc");
|
||||
|
||||
// TODO : Check that texturePool is completely released.
|
||||
// texturePool content is released in MTLCommandBufferWrapper.onComplete()
|
||||
//self.texturePool = nil;
|
||||
self.vertexBuffer = nil;
|
||||
self.commandQueue = nil;
|
||||
self.blitCommandQueue = nil;
|
||||
self.pipelineStateStorage = nil;
|
||||
|
||||
if (_encoderManager != nil) {
|
||||
[_encoderManager release];
|
||||
_encoderManager = nil;
|
||||
}
|
||||
|
||||
if (_samplerManager != nil) {
|
||||
[_samplerManager release];
|
||||
_samplerManager = nil;
|
||||
}
|
||||
|
||||
if (_stencilManager != nil) {
|
||||
[_stencilManager release];
|
||||
_stencilManager = nil;
|
||||
}
|
||||
|
||||
if (_composite != nil) {
|
||||
[_composite release];
|
||||
_composite = nil;
|
||||
}
|
||||
|
||||
if (_paint != nil) {
|
||||
[_paint release];
|
||||
_paint = nil;
|
||||
}
|
||||
|
||||
if (_transform != nil) {
|
||||
[_transform release];
|
||||
_transform = nil;
|
||||
}
|
||||
|
||||
if (_tempTransform != nil) {
|
||||
[_tempTransform release];
|
||||
_tempTransform = nil;
|
||||
}
|
||||
|
||||
if (_clip != nil) {
|
||||
[_clip release];
|
||||
_clip = nil;
|
||||
}
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) reset {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLContext : reset");
|
||||
|
||||
// Add code for context state reset here
|
||||
}
|
||||
|
||||
- (MTLCommandBufferWrapper *) getCommandBufferWrapper {
|
||||
if (_commandBufferWrapper == nil) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLContext : commandBuffer is NULL");
|
||||
// NOTE: Command queues are thread-safe and allow multiple outstanding command buffers to be encoded simultaneously.
|
||||
_commandBufferWrapper = [[MTLCommandBufferWrapper alloc] initWithCommandBuffer:[self.commandQueue commandBuffer]];// released in [layer blitTexture]
|
||||
}
|
||||
return _commandBufferWrapper;
|
||||
}
|
||||
|
||||
- (MTLCommandBufferWrapper *) pullCommandBufferWrapper {
|
||||
MTLCommandBufferWrapper * result = _commandBufferWrapper;
|
||||
_commandBufferWrapper = nil;
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (MTLContext*) setSurfacesEnv:(JNIEnv*)env src:(jlong)pSrc dst:(jlong)pDst {
|
||||
BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrc);
|
||||
BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDst);
|
||||
MTLContext *mtlc = NULL;
|
||||
|
||||
if (srcOps == NULL || dstOps == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_SetSurfaces: ops are null");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLContext_SetSurfaces: bsrc=%p (tex=%p type=%d), bdst=%p (tex=%p type=%d)", srcOps, srcOps->pTexture, srcOps->drawableType, dstOps, dstOps->pTexture, dstOps->drawableType);
|
||||
|
||||
if (dstOps->drawableType == MTLSD_TEXTURE) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLContext_SetSurfaces: texture cannot be used as destination");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dstOps->drawableType == MTLSD_UNDEFINED) {
|
||||
// initialize the surface as an MTLSD_WINDOW
|
||||
if (!MTLSD_InitMTLWindow(env, dstOps)) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLContext_SetSurfaces: could not init MTL window");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// make the context current
|
||||
MTLSDOps *dstMTLOps = (MTLSDOps *)dstOps->privOps;
|
||||
mtlc = dstMTLOps->configInfo->context;
|
||||
|
||||
if (mtlc == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLContext_SetSurfaces: could not make context current");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mtlc;
|
||||
}
|
||||
|
||||
- (void)resetClip {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLContext.resetClip");
|
||||
[_clip reset];
|
||||
}
|
||||
|
||||
- (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2 {
|
||||
J2dTraceLn4(J2D_TRACE_INFO, "MTLContext.setClipRect: %d,%d - %d,%d", x1, y1, x2, y2);
|
||||
[_clip setClipRectX1:x1 Y1:y1 X2:x2 Y2:y2];
|
||||
}
|
||||
|
||||
- (void)beginShapeClip:(BMTLSDOps *)dstOps {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLContext.beginShapeClip");
|
||||
[_clip beginShapeClip:dstOps context:self];
|
||||
|
||||
// Store the current transform as we need to use identity transform
|
||||
// for clip spans rendering
|
||||
[_tempTransform copyFrom:_transform];
|
||||
[self resetTransform];
|
||||
}
|
||||
|
||||
- (void)endShapeClip:(BMTLSDOps *)dstOps {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLContext.endShapeClip");
|
||||
[_clip endShapeClip:dstOps context:self];
|
||||
|
||||
// Reset transform for further rendering
|
||||
[_transform copyFrom:_tempTransform];
|
||||
}
|
||||
|
||||
- (void)resetComposite {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLContext_ResetComposite");
|
||||
[_composite reset];
|
||||
}
|
||||
|
||||
- (void)setAlphaCompositeRule:(jint)rule extraAlpha:(jfloat)extraAlpha
|
||||
flags:(jint)flags {
|
||||
J2dTraceLn3(J2D_TRACE_INFO, "MTLContext_SetAlphaComposite: rule=%d, extraAlpha=%1.2f, flags=%d", rule, extraAlpha, flags);
|
||||
|
||||
[_composite setRule:rule extraAlpha:extraAlpha];
|
||||
}
|
||||
|
||||
- (NSString*)getCompositeDescription {
|
||||
return [_composite getDescription];
|
||||
}
|
||||
|
||||
- (NSString*)getPaintDescription {
|
||||
return [_paint getDescription];
|
||||
}
|
||||
|
||||
- (void)setXorComposite:(jint)xp {
|
||||
J2dTraceLn1(J2D_TRACE_INFO, "MTLContext.setXorComposite: xorPixel=%08x", xp);
|
||||
|
||||
[_composite setXORComposite:xp];
|
||||
}
|
||||
|
||||
- (jboolean) useXORComposite {
|
||||
return ([_composite getCompositeState] == sun_java2d_SunGraphics2D_COMP_XOR);
|
||||
}
|
||||
|
||||
- (void)resetTransform {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLContext_ResetTransform");
|
||||
[_transform resetTransform];
|
||||
}
|
||||
|
||||
- (void)setTransformM00:(jdouble) m00 M10:(jdouble) m10
|
||||
M01:(jdouble) m01 M11:(jdouble) m11
|
||||
M02:(jdouble) m02 M12:(jdouble) m12 {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLContext_SetTransform");
|
||||
[_transform setTransformM00:m00 M10:m10 M01:m01 M11:m11 M02:m02 M12:m12];
|
||||
}
|
||||
|
||||
- (void)resetPaint {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLContext.resetPaint");
|
||||
self.paint = [[[MTLPaint alloc] init] autorelease];
|
||||
}
|
||||
|
||||
- (void)setColorPaint:(int)pixel {
|
||||
J2dTraceLn5(J2D_TRACE_INFO, "MTLContext.setColorPaint: pixel=%08x [r=%d g=%d b=%d a=%d]", pixel, (pixel >> 16) & (0xFF), (pixel >> 8) & 0xFF, (pixel) & 0xFF, (pixel >> 24) & 0xFF);
|
||||
self.paint = [[[MTLColorPaint alloc] initWithColor:pixel] autorelease];
|
||||
}
|
||||
|
||||
- (void)setGradientPaintUseMask:(jboolean)useMask
|
||||
cyclic:(jboolean)cyclic
|
||||
p0:(jdouble)p0
|
||||
p1:(jdouble)p1
|
||||
p3:(jdouble)p3
|
||||
pixel1:(jint)pixel1
|
||||
pixel2:(jint) pixel2
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setGradientPaintUseMask");
|
||||
self.paint = [[[MTLGradPaint alloc] initWithUseMask:useMask
|
||||
cyclic:cyclic
|
||||
p0:p0
|
||||
p1:p1
|
||||
p3:p3
|
||||
pixel1:pixel1
|
||||
pixel2:pixel2] autorelease];
|
||||
}
|
||||
|
||||
- (void)setLinearGradientPaint:(jboolean)useMask
|
||||
linear:(jboolean)linear
|
||||
cycleMethod:(jint)cycleMethod
|
||||
// 0 - NO_CYCLE
|
||||
// 1 - REFLECT
|
||||
// 2 - REPEAT
|
||||
|
||||
numStops:(jint)numStops
|
||||
p0:(jfloat)p0
|
||||
p1:(jfloat)p1
|
||||
p3:(jfloat)p3
|
||||
fractions:(jfloat*)fractions
|
||||
pixels:(jint*)pixels
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setLinearGradientPaint");
|
||||
self.paint = [[[MTLLinearGradPaint alloc] initWithUseMask:useMask
|
||||
linear:linear
|
||||
cycleMethod:cycleMethod
|
||||
numStops:numStops
|
||||
p0:p0
|
||||
p1:p1
|
||||
p3:p3
|
||||
fractions:fractions
|
||||
pixels:pixels] autorelease];
|
||||
}
|
||||
|
||||
- (void)setRadialGradientPaint:(jboolean)useMask
|
||||
linear:(jboolean)linear
|
||||
cycleMethod:(jboolean)cycleMethod
|
||||
numStops:(jint)numStops
|
||||
m00:(jfloat)m00
|
||||
m01:(jfloat)m01
|
||||
m02:(jfloat)m02
|
||||
m10:(jfloat)m10
|
||||
m11:(jfloat)m11
|
||||
m12:(jfloat)m12
|
||||
focusX:(jfloat)focusX
|
||||
fractions:(void *)fractions
|
||||
pixels:(void *)pixels
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setRadialGradientPaint");
|
||||
self.paint = [[[MTLRadialGradPaint alloc] initWithUseMask:useMask
|
||||
linear:linear
|
||||
cycleMethod:cycleMethod
|
||||
numStops:numStops
|
||||
m00:m00
|
||||
m01:m01
|
||||
m02:m02
|
||||
m10:m10
|
||||
m11:m11
|
||||
m12:m12
|
||||
focusX:focusX
|
||||
fractions:fractions
|
||||
pixels:pixels] autorelease];
|
||||
}
|
||||
|
||||
- (void)setTexturePaint:(jboolean)useMask
|
||||
pSrcOps:(jlong)pSrcOps
|
||||
filter:(jboolean)filter
|
||||
xp0:(jdouble)xp0
|
||||
xp1:(jdouble)xp1
|
||||
xp3:(jdouble)xp3
|
||||
yp0:(jdouble)yp0
|
||||
yp1:(jdouble)yp1
|
||||
yp3:(jdouble)yp3
|
||||
{
|
||||
BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrcOps);
|
||||
|
||||
if (srcOps == NULL || srcOps->pTexture == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_setTexturePaint: texture paint - texture is null");
|
||||
return;
|
||||
}
|
||||
|
||||
J2dTraceLn1(J2D_TRACE_INFO, "MTLContext.setTexturePaint [tex=%p]", srcOps->pTexture);
|
||||
|
||||
self.paint = [[[MTLTexturePaint alloc] initWithUseMask:useMask
|
||||
textureID:srcOps->pTexture
|
||||
isOpaque:srcOps->isOpaque
|
||||
filter:filter
|
||||
xp0:xp0
|
||||
xp1:xp1
|
||||
xp3:xp3
|
||||
yp0:yp0
|
||||
yp1:yp1
|
||||
yp3:yp3] autorelease];
|
||||
}
|
||||
|
||||
- (id<MTLCommandBuffer>)createCommandBuffer {
|
||||
return [self.commandQueue commandBuffer];
|
||||
}
|
||||
|
||||
/*
|
||||
* This should be exclusively used only for final blit
|
||||
* and present of CAMetalDrawable in MTLLayer
|
||||
*/
|
||||
- (id<MTLCommandBuffer>)createBlitCommandBuffer {
|
||||
return [self.blitCommandQueue commandBuffer];
|
||||
}
|
||||
|
||||
-(void)setBufImgOp:(NSObject*)bufImgOp {
|
||||
if (_bufImgOp != nil) {
|
||||
[_bufImgOp release]; // context owns bufImgOp object
|
||||
}
|
||||
_bufImgOp = bufImgOp;
|
||||
}
|
||||
|
||||
-(NSObject*)getBufImgOp {
|
||||
return _bufImgOp;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLGlyphCache_h_Included
|
||||
#define MTLGlyphCache_h_Included
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "jni.h"
|
||||
#include "fontscalerdefs.h"
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
typedef void (MTLFlushFunc)();
|
||||
|
||||
typedef struct _MTLCacheCellInfo MTLCacheCellInfo;
|
||||
|
||||
typedef struct {
|
||||
CacheCellInfo *head;
|
||||
CacheCellInfo *tail;
|
||||
id<MTLTexture> texture;
|
||||
jint width;
|
||||
jint height;
|
||||
jint cellWidth;
|
||||
jint cellHeight;
|
||||
MTLFlushFunc *Flush;
|
||||
} MTLGlyphCacheInfo;
|
||||
|
||||
struct _MTLCacheCellInfo {
|
||||
MTLGlyphCacheInfo *cacheInfo;
|
||||
struct GlyphInfo *glyphInfo;
|
||||
// next cell info in the cache's list
|
||||
MTLCacheCellInfo *next;
|
||||
// REMIND: find better name?
|
||||
// next cell info in the glyph's cell list (next Glyph Cache Info)
|
||||
MTLCacheCellInfo *nextGCI;
|
||||
jint timesRendered;
|
||||
jint x;
|
||||
jint y;
|
||||
// number of pixels from the left or right edge not considered touched
|
||||
// by the glyph
|
||||
jint leftOff;
|
||||
jint rightOff;
|
||||
jfloat tx1;
|
||||
jfloat ty1;
|
||||
jfloat tx2;
|
||||
jfloat ty2;
|
||||
};
|
||||
|
||||
MTLGlyphCacheInfo *
|
||||
MTLGlyphCache_Init(jint width, jint height,
|
||||
jint cellWidth, jint cellHeight,
|
||||
MTLFlushFunc *func);
|
||||
MTLCacheCellInfo *
|
||||
MTLGlyphCache_AddGlyph(MTLGlyphCacheInfo *cache, struct GlyphInfo *glyph);
|
||||
bool
|
||||
MTLGlyphCache_IsCacheFull(MTLGlyphCacheInfo *cache, GlyphInfo *glyph);
|
||||
void
|
||||
MTLGlyphCache_Invalidate(MTLGlyphCacheInfo *cache);
|
||||
void
|
||||
MTLGlyphCache_AddCellInfo(struct GlyphInfo *glyph, MTLCacheCellInfo *cellInfo);
|
||||
void
|
||||
MTLGlyphCache_RemoveCellInfo(struct GlyphInfo *glyph, MTLCacheCellInfo *cellInfo);
|
||||
MTLCacheCellInfo *
|
||||
MTLGlyphCache_GetCellInfoForCache(struct GlyphInfo *glyph,
|
||||
MTLGlyphCacheInfo *cache);
|
||||
JNIEXPORT void
|
||||
MTLGlyphCache_RemoveAllCellInfos(struct GlyphInfo *glyph);
|
||||
void
|
||||
MTLGlyphCache_Free(MTLGlyphCacheInfo *cache);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* MTLGlyphCache_h_Included */
|
||||
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "jni.h"
|
||||
#include "MTLGlyphCache.h"
|
||||
#include "Trace.h"
|
||||
|
||||
/**
|
||||
* When the cache is full, we will try to reuse the cache cells that have
|
||||
* been used relatively less than the others (and we will save the cells that
|
||||
* have been rendered more than the threshold defined here).
|
||||
*/
|
||||
#define TIMES_RENDERED_THRESHOLD 5
|
||||
|
||||
/**
|
||||
* Creates a new GlyphCacheInfo structure, fills in the initial values, and
|
||||
* then returns a pointer to the GlyphCacheInfo record.
|
||||
*
|
||||
* Note that this method only sets up a data structure describing a
|
||||
* rectangular region of accelerated memory, containing "virtual" cells of
|
||||
* the requested size. The cell information is added lazily to the linked
|
||||
* list describing the cache as new glyphs are added. Platform specific
|
||||
* glyph caching code is responsible for actually creating the accelerated
|
||||
* memory surface that will contain the individual glyph images.
|
||||
*
|
||||
* Each glyph contains a reference to a list of cell infos - one per glyph
|
||||
* cache. There may be multiple glyph caches (for example, one per graphics
|
||||
* adapter), so if the glyph is cached on two devices its cell list will
|
||||
* consists of two elements corresponding to different glyph caches.
|
||||
*
|
||||
* The platform-specific glyph caching code is supposed to use
|
||||
* GetCellInfoForCache method for retrieving cache infos from the glyph's list.
|
||||
*
|
||||
* Note that if it is guaranteed that there will be only one global glyph
|
||||
* cache then it one does not have to use AccelGlyphCache_GetCellInfoForCache
|
||||
* for retrieving cell info for the glyph, but instead just use the struct's
|
||||
* field directly.
|
||||
*/
|
||||
MTLGlyphCacheInfo *
|
||||
MTLGlyphCache_Init(jint width, jint height,
|
||||
jint cellWidth, jint cellHeight,
|
||||
MTLFlushFunc *func)
|
||||
{
|
||||
MTLGlyphCacheInfo *gcinfo;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_Init");
|
||||
|
||||
gcinfo = (MTLGlyphCacheInfo *)malloc(sizeof(MTLGlyphCacheInfo));
|
||||
if (gcinfo == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLGlyphCache_Init: could not allocate MTLGlyphCacheInfo");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gcinfo->head = NULL;
|
||||
gcinfo->tail = NULL;
|
||||
gcinfo->width = width;
|
||||
gcinfo->height = height;
|
||||
gcinfo->cellWidth = cellWidth;
|
||||
gcinfo->cellHeight = cellHeight;
|
||||
gcinfo->Flush = func;
|
||||
|
||||
return gcinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to add the provided glyph to the specified cache. If the
|
||||
* operation is successful, a pointer to the newly occupied cache cell is
|
||||
* stored in the glyph's cellInfo field; otherwise, its cellInfo field is
|
||||
* set to NULL, indicating that the glyph's original bits should be rendered
|
||||
* instead. If the cache is full, the least-recently-used glyph is
|
||||
* invalidated and its cache cell is reassigned to the new glyph being added.
|
||||
*
|
||||
* Note that this method only ensures that a rectangular region in the
|
||||
* "virtual" glyph cache is available for the glyph image. Platform specific
|
||||
* glyph caching code is responsible for actually caching the glyph image
|
||||
* in the associated accelerated memory surface.
|
||||
*
|
||||
* Returns created cell info if it was successfully created and added to the
|
||||
* cache and glyph's cell lists, NULL otherwise.
|
||||
*/
|
||||
MTLCacheCellInfo *
|
||||
MTLGlyphCache_AddGlyph(MTLGlyphCacheInfo *cache, GlyphInfo *glyph)
|
||||
{
|
||||
MTLCacheCellInfo *cellinfo = NULL;
|
||||
jint w = glyph->width;
|
||||
jint h = glyph->height;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_AddGlyph");
|
||||
|
||||
if ((glyph->width > cache->cellWidth) ||
|
||||
(glyph->height > cache->cellHeight))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jint x, y;
|
||||
|
||||
if (cache->head == NULL) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
} else {
|
||||
x = cache->tail->x + cache->cellWidth;
|
||||
y = cache->tail->y;
|
||||
if ((x + cache->cellWidth) > cache->width) {
|
||||
x = 0;
|
||||
y += cache->cellHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// create new CacheCellInfo
|
||||
cellinfo = (MTLCacheCellInfo *)malloc(sizeof(MTLCacheCellInfo));
|
||||
if (cellinfo == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "could not allocate CellInfo");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cellinfo->cacheInfo = cache;
|
||||
cellinfo->glyphInfo = glyph;
|
||||
cellinfo->timesRendered = 0;
|
||||
cellinfo->x = x;
|
||||
cellinfo->y = y;
|
||||
cellinfo->leftOff = 0;
|
||||
cellinfo->rightOff = 0;
|
||||
cellinfo->tx1 = (jfloat)cellinfo->x / cache->width;
|
||||
cellinfo->ty1 = (jfloat)cellinfo->y / cache->height;
|
||||
cellinfo->tx2 = cellinfo->tx1 + ((jfloat)w / cache->width);
|
||||
cellinfo->ty2 = cellinfo->ty1 + ((jfloat)h / cache->height);
|
||||
|
||||
if (cache->head == NULL) {
|
||||
// initialize the head cell
|
||||
cache->head = cellinfo;
|
||||
} else {
|
||||
// update existing tail cell
|
||||
cache->tail->next = cellinfo;
|
||||
}
|
||||
|
||||
// add the new cell to the end of the list
|
||||
cache->tail = cellinfo;
|
||||
cellinfo->next = NULL;
|
||||
cellinfo->nextGCI = NULL;
|
||||
|
||||
// add cache cell to the glyph's cells list
|
||||
MTLGlyphCache_AddCellInfo(glyph, cellinfo);
|
||||
return cellinfo;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
MTLGlyphCache_IsCacheFull(MTLGlyphCacheInfo *cache, GlyphInfo *glyph)
|
||||
{
|
||||
jint w = glyph->width;
|
||||
jint h = glyph->height;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_IsCacheFull");
|
||||
|
||||
jint x, y;
|
||||
|
||||
if (cache->head == NULL) {
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
x = cache->tail->x + cache->cellWidth;
|
||||
y = cache->tail->y;
|
||||
if ((x + cache->cellWidth) > cache->width) {
|
||||
x = 0;
|
||||
y += cache->cellHeight;
|
||||
if ((y + cache->cellHeight) > cache->height) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
/**
|
||||
* Invalidates all cells in the cache. Note that this method does not
|
||||
* attempt to compact the cache in any way; it just invalidates any cells
|
||||
* that already exist.
|
||||
*/
|
||||
void
|
||||
MTLGlyphCache_Invalidate(MTLGlyphCacheInfo *cache)
|
||||
{
|
||||
MTLCacheCellInfo *cellinfo;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_Invalidate");
|
||||
|
||||
if (cache == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// flush any pending vertices that may be depending on the current
|
||||
// glyph cache layout
|
||||
if (cache->Flush != NULL) {
|
||||
cache->Flush();
|
||||
}
|
||||
|
||||
cellinfo = cache->head;
|
||||
while (cellinfo != NULL) {
|
||||
if (cellinfo->glyphInfo != NULL) {
|
||||
// if the cell is occupied, notify the base glyph that its
|
||||
// cached version for this cache is about to be invalidated
|
||||
MTLGlyphCache_RemoveCellInfo(cellinfo->glyphInfo, cellinfo);
|
||||
}
|
||||
cellinfo = cellinfo->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates and frees all cells and the cache itself. The "cache" pointer
|
||||
* becomes invalid after this function returns.
|
||||
*/
|
||||
void
|
||||
MTLGlyphCache_Free(MTLGlyphCacheInfo *cache)
|
||||
{
|
||||
MTLCacheCellInfo *cellinfo;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_Free");
|
||||
|
||||
if (cache == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// flush any pending vertices that may be depending on the current
|
||||
// glyph cache
|
||||
if (cache->Flush != NULL) {
|
||||
cache->Flush();
|
||||
}
|
||||
|
||||
while (cache->head != NULL) {
|
||||
cellinfo = cache->head;
|
||||
if (cellinfo->glyphInfo != NULL) {
|
||||
// if the cell is occupied, notify the base glyph that its
|
||||
// cached version for this cache is about to be invalidated
|
||||
MTLGlyphCache_RemoveCellInfo(cellinfo->glyphInfo, cellinfo);
|
||||
}
|
||||
cache->head = cellinfo->next;
|
||||
free(cellinfo);
|
||||
}
|
||||
free(cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add cell info to the head of the glyph's list of cached cells.
|
||||
*/
|
||||
void
|
||||
MTLGlyphCache_AddCellInfo(GlyphInfo *glyph, MTLCacheCellInfo *cellInfo)
|
||||
{
|
||||
// assert (glyph != NULL && cellInfo != NULL)
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_AddCellInfo");
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE, " glyph 0x%x: adding cell 0x%x to the list",
|
||||
glyph, cellInfo);
|
||||
|
||||
cellInfo->glyphInfo = glyph;
|
||||
cellInfo->nextGCI = glyph->cellInfo;
|
||||
glyph->cellInfo = cellInfo;
|
||||
glyph->managed = MANAGED_GLYPH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes cell info from the glyph's list of cached cells.
|
||||
*/
|
||||
void
|
||||
MTLGlyphCache_RemoveCellInfo(GlyphInfo *glyph, MTLCacheCellInfo *cellInfo)
|
||||
{
|
||||
MTLCacheCellInfo *currCellInfo = glyph->cellInfo;
|
||||
MTLCacheCellInfo *prevInfo = NULL;
|
||||
// assert (glyph!= NULL && glyph->cellInfo != NULL && cellInfo != NULL)
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_RemoveCellInfo");
|
||||
do {
|
||||
if (currCellInfo == cellInfo) {
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE,
|
||||
" glyph 0x%x: removing cell 0x%x from glyph's list",
|
||||
glyph, currCellInfo);
|
||||
if (prevInfo == NULL) { // it's the head, chop-chop
|
||||
glyph->cellInfo = currCellInfo->nextGCI;
|
||||
} else {
|
||||
prevInfo->nextGCI = currCellInfo->nextGCI;
|
||||
}
|
||||
currCellInfo->glyphInfo = NULL;
|
||||
currCellInfo->nextGCI = NULL;
|
||||
return;
|
||||
}
|
||||
prevInfo = currCellInfo;
|
||||
currCellInfo = currCellInfo->nextGCI;
|
||||
} while (currCellInfo != NULL);
|
||||
J2dTraceLn2(J2D_TRACE_WARNING, "MTLGlyphCache_RemoveCellInfo: "\
|
||||
"no cell 0x%x in glyph 0x%x's cell list",
|
||||
cellInfo, glyph);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes cell info from the glyph's list of cached cells.
|
||||
*/
|
||||
JNIEXPORT void
|
||||
MTLGlyphCache_RemoveAllCellInfos(GlyphInfo *glyph)
|
||||
{
|
||||
MTLCacheCellInfo *currCell, *prevCell;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_RemoveAllCellInfos");
|
||||
|
||||
if (glyph == NULL || glyph->cellInfo == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// invalidate all of this glyph's accelerated cache cells
|
||||
currCell = glyph->cellInfo;
|
||||
do {
|
||||
currCell->glyphInfo = NULL;
|
||||
prevCell = currCell;
|
||||
currCell = currCell->nextGCI;
|
||||
prevCell->nextGCI = NULL;
|
||||
} while (currCell != NULL);
|
||||
|
||||
glyph->cellInfo = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cell info associated with particular cache from the glyph's list of
|
||||
* cached cells.
|
||||
*/
|
||||
MTLCacheCellInfo *
|
||||
MTLGlyphCache_GetCellInfoForCache(GlyphInfo *glyph, MTLGlyphCacheInfo *cache)
|
||||
{
|
||||
// assert (glyph != NULL && cache != NULL)
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE2, "MTLGlyphCache_GetCellInfoForCache");
|
||||
|
||||
if (glyph->cellInfo != NULL) {
|
||||
MTLCacheCellInfo *cellInfo = glyph->cellInfo;
|
||||
do {
|
||||
if (cellInfo->cacheInfo == cache) {
|
||||
J2dTraceLn3(J2D_TRACE_VERBOSE2,
|
||||
" glyph 0x%x: found cell 0x%x for cache 0x%x",
|
||||
glyph, cellInfo, cache);
|
||||
return cellInfo;
|
||||
}
|
||||
cellInfo = cellInfo->nextGCI;
|
||||
} while (cellInfo != NULL);
|
||||
}
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE2, " glyph 0x%x: no cell for cache 0x%x",
|
||||
glyph, cache);
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLGraphicsConfig_h_Included
|
||||
#define MTLGraphicsConfig_h_Included
|
||||
|
||||
#import "JNIUtilities.h"
|
||||
#import "MTLSurfaceDataBase.h"
|
||||
#import "MTLContext.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
|
||||
@interface MTLGraphicsConfigUtil : NSObject {}
|
||||
+ (void) _getMTLConfigInfo: (NSMutableArray *)argValue;
|
||||
@end
|
||||
|
||||
/**
|
||||
* The MTLGraphicsConfigInfo structure contains information specific to a
|
||||
* given MTLGraphicsConfig (pixel format).
|
||||
* MTLContext *context;
|
||||
* The context associated with this MTLGraphicsConfig.
|
||||
*/
|
||||
typedef struct _MTLGraphicsConfigInfo {
|
||||
MTLContext *context;
|
||||
} MTLGraphicsConfigInfo;
|
||||
|
||||
// From "Metal Feature Set Tables"
|
||||
// There are 2 GPU families for mac - MTLGPUFamilyMac1 and MTLGPUFamilyMac2
|
||||
// Both of them support "Maximum 2D texture width and height" of 16384 pixels
|
||||
// Note : there is no API to get this value, hence hardcoding by reading from the table
|
||||
#define MaxTextureSize 16384
|
||||
|
||||
#endif /* MTLGraphicsConfig_h_Included */
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#import "sun_java2d_metal_MTLGraphicsConfig.h"
|
||||
|
||||
#import "MTLGraphicsConfig.h"
|
||||
#import "MTLSurfaceData.h"
|
||||
#import "ThreadUtilities.h"
|
||||
#import "awt.h"
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark "--- Mac OS X specific methods for Metal pipeline ---"
|
||||
|
||||
/**
|
||||
* Disposes all memory and resources associated with the given
|
||||
* MTLGraphicsConfigInfo (including its native MTLContext data).
|
||||
*/
|
||||
void
|
||||
MTLGC_DestroyMTLGraphicsConfig(jlong pConfigInfo)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGC_DestroyMTLGraphicsConfig");
|
||||
|
||||
MTLGraphicsConfigInfo *mtlinfo =
|
||||
(MTLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
|
||||
if (mtlinfo == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLGC_DestroyMTLGraphicsConfig: info is null");
|
||||
return;
|
||||
}
|
||||
|
||||
MTLContext *mtlc = (MTLContext*)mtlinfo->context;
|
||||
if (mtlc != NULL) {
|
||||
[mtlinfo->context release];
|
||||
mtlinfo->context = nil;
|
||||
}
|
||||
free(mtlinfo);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark "--- MTLGraphicsConfig methods ---"
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_java2d_metal_MTLGraphicsConfig_isMetalFrameworkAvailable
|
||||
(JNIEnv *env, jclass mtlgc)
|
||||
{
|
||||
jboolean metalSupported = JNI_FALSE;
|
||||
|
||||
// It is guranteed that metal supported GPU is available macOS 10.14 onwards
|
||||
if (@available(macOS 10.14, *)) {
|
||||
metalSupported = JNI_TRUE;
|
||||
}
|
||||
|
||||
J2dRlsTraceLn1(J2D_TRACE_INFO, "MTLGraphicsConfig_isMetalFrameworkAvailable : %d", metalSupported);
|
||||
|
||||
return metalSupported;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_java2d_metal_MTLGraphicsConfig_tryLoadMetalLibrary
|
||||
(JNIEnv *env, jclass mtlgc, jint displayID, jstring shadersLibName)
|
||||
{
|
||||
jboolean ret = JNI_FALSE;
|
||||
JNI_COCOA_ENTER(env);
|
||||
NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:3];
|
||||
[retArray addObject: [NSNumber numberWithInt: (int)displayID]];
|
||||
char *str = JNU_GetStringPlatformChars(env, shadersLibName, 0);
|
||||
[retArray addObject: [NSString stringWithUTF8String: str]];
|
||||
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^() {
|
||||
[MTLGraphicsConfigUtil _tryLoadMetalLibrary: retArray];
|
||||
}];
|
||||
|
||||
NSNumber * num = (NSNumber *)[retArray objectAtIndex: 0];
|
||||
ret = (jboolean)[num boolValue];
|
||||
JNU_ReleaseStringPlatformChars(env, shadersLibName, str);
|
||||
JNI_COCOA_EXIT(env);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether the MTL pipeline can be used for a given GraphicsConfig
|
||||
* provided its screen number and visual ID. If the minimum requirements are
|
||||
* met, the native MTLGraphicsConfigInfo structure is initialized for this
|
||||
* GraphicsConfig with the necessary information (pixel format, etc.)
|
||||
* and a pointer to this structure is returned as a jlong. If
|
||||
* initialization fails at any point, zero is returned, indicating that MTL
|
||||
* cannot be used for this GraphicsConfig (we should fallback on an existing
|
||||
* 2D pipeline).
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_java2d_metal_MTLGraphicsConfig_getMTLConfigInfo
|
||||
(JNIEnv *env, jclass mtlgc, jint displayID, jstring mtlShadersLib)
|
||||
{
|
||||
jlong ret = 0L;
|
||||
JNI_COCOA_ENTER(env);
|
||||
NSMutableArray * retArray = [NSMutableArray arrayWithCapacity:3];
|
||||
[retArray addObject: [NSNumber numberWithInt: (int)displayID]];
|
||||
char *str = JNU_GetStringPlatformChars(env, mtlShadersLib, 0);
|
||||
[retArray addObject: [NSString stringWithUTF8String: str]];
|
||||
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^() {
|
||||
[MTLGraphicsConfigUtil _getMTLConfigInfo: retArray];
|
||||
}];
|
||||
|
||||
NSNumber * num = (NSNumber *)[retArray objectAtIndex: 0];
|
||||
ret = (jlong)[num longValue];
|
||||
JNU_ReleaseStringPlatformChars(env, mtlShadersLib, str);
|
||||
JNI_COCOA_EXIT(env);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@implementation MTLGraphicsConfigUtil
|
||||
+ (void) _getMTLConfigInfo: (NSMutableArray *)argValue {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue];
|
||||
NSString *mtlShadersLib = (NSString *)[argValue objectAtIndex: 1];
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
[argValue removeAllObjects];
|
||||
|
||||
J2dRlsTraceLn(J2D_TRACE_INFO, "MTLGraphicsConfig_getMTLConfigInfo");
|
||||
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
||||
NSRect contentRect = NSMakeRect(0, 0, 64, 64);
|
||||
NSWindow *window =
|
||||
[[NSWindow alloc]
|
||||
initWithContentRect: contentRect
|
||||
styleMask: NSBorderlessWindowMask
|
||||
backing: NSBackingStoreBuffered
|
||||
defer: false];
|
||||
if (window == nil) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_getMTLConfigInfo: NSWindow is NULL");
|
||||
[argValue addObject: [NSNumber numberWithLong: 0L]];
|
||||
return;
|
||||
}
|
||||
|
||||
MTLContext *mtlc = [[MTLContext alloc] initWithDevice:CGDirectDisplayCopyCurrentMetalDevice(displayID)
|
||||
shadersLib:mtlShadersLib];
|
||||
if (mtlc == 0L) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGC_InitMTLContext: could not initialze MTLContext.");
|
||||
[argValue addObject: [NSNumber numberWithLong: 0L]];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// create the MTLGraphicsConfigInfo record for this config
|
||||
MTLGraphicsConfigInfo *mtlinfo = (MTLGraphicsConfigInfo *)malloc(sizeof(MTLGraphicsConfigInfo));
|
||||
if (mtlinfo == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_getMTLConfigInfo: could not allocate memory for mtlinfo");
|
||||
free(mtlc);
|
||||
[argValue addObject: [NSNumber numberWithLong: 0L]];
|
||||
return;
|
||||
}
|
||||
memset(mtlinfo, 0, sizeof(MTLGraphicsConfigInfo));
|
||||
mtlinfo->context = mtlc;
|
||||
|
||||
[argValue addObject: [NSNumber numberWithLong:ptr_to_jlong(mtlinfo)]];
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
+ (void) _tryLoadMetalLibrary: (NSMutableArray *)argValue {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
jint displayID = (jint)[(NSNumber *)[argValue objectAtIndex: 0] intValue];
|
||||
NSString *mtlShadersLib = (NSString *)[argValue objectAtIndex: 1];
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
[argValue removeAllObjects];
|
||||
|
||||
J2dRlsTraceLn(J2D_TRACE_INFO, "MTLGraphicsConfigUtil_tryLoadMTLLibrary");
|
||||
|
||||
|
||||
BOOL ret = FALSE;;
|
||||
id<MTLDevice> device = CGDirectDisplayCopyCurrentMetalDevice(displayID);
|
||||
if (device != nil) {
|
||||
NSError *error = nil;
|
||||
id<MTLLibrary> lib = [device newLibraryWithFile:mtlShadersLib error:&error];
|
||||
if (lib != nil) {
|
||||
ret = TRUE;
|
||||
} else {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_tryLoadMetalLibrary - Failed to load Metal shader library.");
|
||||
}
|
||||
} else {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLGraphicsConfig_tryLoadMetalLibrary - Failed to create MTLDevice.");
|
||||
}
|
||||
|
||||
[argValue addObject: [NSNumber numberWithBool: ret]];
|
||||
|
||||
}
|
||||
|
||||
@end //GraphicsConfigUtil
|
||||
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_java2d_metal_MTLGraphicsConfig_nativeGetMaxTextureSize
|
||||
(JNIEnv *env, jclass mtlgc)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGraphicsConfig_nativeGetMaxTextureSize");
|
||||
|
||||
return (jint)MaxTextureSize;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLLayer_h_Included
|
||||
#define MTLLayer_h_Included
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
#include <CoreVideo/CVDisplayLink.h>
|
||||
#import "common.h"
|
||||
|
||||
@interface MTLLayer : CAMetalLayer
|
||||
{
|
||||
@private
|
||||
jobject javaLayer;
|
||||
|
||||
// intermediate buffer, used the RQ lock to synchronize
|
||||
MTLContext* ctx;
|
||||
float bufferWidth;
|
||||
float bufferHeight;
|
||||
id<MTLTexture> buffer;
|
||||
int nextDrawableCount;
|
||||
int topInset;
|
||||
int leftInset;
|
||||
CVDisplayLinkRef displayLink;
|
||||
}
|
||||
|
||||
@property (nonatomic) jobject javaLayer;
|
||||
@property (readwrite, assign) MTLContext* ctx;
|
||||
@property (readwrite, assign) float bufferWidth;
|
||||
@property (readwrite, assign) float bufferHeight;
|
||||
@property (readwrite, assign) id<MTLTexture> buffer;
|
||||
@property (readwrite, assign) int nextDrawableCount;
|
||||
@property (readwrite, assign) int topInset;
|
||||
@property (readwrite, assign) int leftInset;
|
||||
@property (readwrite, assign) CVDisplayLinkRef displayLink;
|
||||
|
||||
- (id) initWithJavaLayer:(jobject)layer;
|
||||
|
||||
- (void) blitTexture;
|
||||
- (void) fillParallelogramCtxX:(jfloat)x
|
||||
Y:(jfloat)y
|
||||
DX1:(jfloat)dx1
|
||||
DY1:(jfloat)dy1
|
||||
DX2:(jfloat)dx2
|
||||
DY2:(jfloat)dy2;
|
||||
- (void) blitCallback;
|
||||
- (void) display;
|
||||
- (void) redraw;
|
||||
- (void) startDisplayLink;
|
||||
- (void) stopDisplayLink;
|
||||
@end
|
||||
|
||||
#endif /* MTLLayer_h_Included */
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#import "MTLGraphicsConfig.h"
|
||||
#import "MTLLayer.h"
|
||||
#import "ThreadUtilities.h"
|
||||
#import "LWCToolkit.h"
|
||||
#import "MTLSurfaceData.h"
|
||||
#import "JNIUtilities.h"
|
||||
|
||||
@implementation MTLLayer
|
||||
|
||||
|
||||
@synthesize javaLayer;
|
||||
@synthesize ctx;
|
||||
@synthesize bufferWidth;
|
||||
@synthesize bufferHeight;
|
||||
@synthesize buffer;
|
||||
@synthesize topInset;
|
||||
@synthesize leftInset;
|
||||
@synthesize nextDrawableCount;
|
||||
@synthesize displayLink;
|
||||
|
||||
- (id) initWithJavaLayer:(jobject)layer
|
||||
{
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
// Initialize ourselves
|
||||
self = [super init];
|
||||
if (self == nil) return self;
|
||||
|
||||
self.javaLayer = layer;
|
||||
|
||||
self.contentsGravity = kCAGravityTopLeft;
|
||||
|
||||
//Disable CALayer's default animation
|
||||
NSMutableDictionary * actions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
|
||||
[NSNull null], @"anchorPoint",
|
||||
[NSNull null], @"bounds",
|
||||
[NSNull null], @"contents",
|
||||
[NSNull null], @"contentsScale",
|
||||
[NSNull null], @"onOrderIn",
|
||||
[NSNull null], @"onOrderOut",
|
||||
[NSNull null], @"position",
|
||||
[NSNull null], @"sublayers",
|
||||
nil];
|
||||
self.actions = actions;
|
||||
[actions release];
|
||||
self.topInset = 0;
|
||||
self.leftInset = 0;
|
||||
self.framebufferOnly = NO;
|
||||
self.nextDrawableCount = 0;
|
||||
self.opaque = FALSE;
|
||||
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
|
||||
CVDisplayLinkSetOutputCallback(displayLink, &displayLinkCallback, (__bridge void*)self);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) blitTexture {
|
||||
if (self.ctx == NULL || self.javaLayer == NULL || self.buffer == nil || self.ctx.device == nil) {
|
||||
J2dTraceLn4(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: uninitialized (mtlc=%p, javaLayer=%p, buffer=%p, devide=%p)", self.ctx, self.javaLayer, self.buffer, ctx.device);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.nextDrawableCount != 0) {
|
||||
return;
|
||||
}
|
||||
@autoreleasepool {
|
||||
if ((self.buffer.width == 0) || (self.buffer.height == 0)) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: cannot create drawable of size 0");
|
||||
return;
|
||||
}
|
||||
|
||||
NSUInteger src_x = self.leftInset * self.contentsScale;
|
||||
NSUInteger src_y = self.topInset * self.contentsScale;
|
||||
NSUInteger src_w = self.buffer.width - src_x;
|
||||
NSUInteger src_h = self.buffer.height - src_y;
|
||||
|
||||
if (src_h <= 0 || src_w <= 0) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: Invalid src width or height.");
|
||||
return;
|
||||
}
|
||||
|
||||
id<MTLCommandBuffer> commandBuf = [self.ctx createBlitCommandBuffer];
|
||||
if (commandBuf == nil) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: commandBuf is null");
|
||||
return;
|
||||
}
|
||||
id<CAMetalDrawable> mtlDrawable = [self nextDrawable];
|
||||
if (mtlDrawable == nil) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: nextDrawable is null)");
|
||||
return;
|
||||
}
|
||||
self.nextDrawableCount++;
|
||||
|
||||
id <MTLBlitCommandEncoder> blitEncoder = [commandBuf blitCommandEncoder];
|
||||
|
||||
[blitEncoder
|
||||
copyFromTexture:self.buffer sourceSlice:0 sourceLevel:0
|
||||
sourceOrigin:MTLOriginMake(src_x, src_y, 0)
|
||||
sourceSize:MTLSizeMake(src_w, src_h, 1)
|
||||
toTexture:mtlDrawable.texture destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(0, 0, 0)];
|
||||
[blitEncoder endEncoding];
|
||||
|
||||
[commandBuf presentDrawable:mtlDrawable];
|
||||
[commandBuf addCompletedHandler:^(id <MTLCommandBuffer> commandBuf) {
|
||||
self.nextDrawableCount--;
|
||||
}];
|
||||
|
||||
[commandBuf commit];
|
||||
[self stopDisplayLink];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
(*env)->DeleteWeakGlobalRef(env, self.javaLayer);
|
||||
self.javaLayer = nil;
|
||||
[self stopDisplayLink];
|
||||
CVDisplayLinkRelease(self.displayLink);
|
||||
self.displayLink = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) blitCallback {
|
||||
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
DECLARE_CLASS(jc_JavaLayer, "sun/java2d/metal/MTLLayer");
|
||||
DECLARE_METHOD(jm_drawInMTLContext, jc_JavaLayer, "drawInMTLContext", "()V");
|
||||
|
||||
jobject javaLayerLocalRef = (*env)->NewLocalRef(env, self.javaLayer);
|
||||
if ((*env)->IsSameObject(env, javaLayerLocalRef, NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
(*env)->CallVoidMethod(env, javaLayerLocalRef, jm_drawInMTLContext);
|
||||
CHECK_EXCEPTION();
|
||||
(*env)->DeleteLocalRef(env, javaLayerLocalRef);
|
||||
}
|
||||
|
||||
- (void) display {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_display() called");
|
||||
[self blitCallback];
|
||||
[super display];
|
||||
}
|
||||
|
||||
- (void) redraw {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void) startDisplayLink {
|
||||
if (!CVDisplayLinkIsRunning(self.displayLink))
|
||||
CVDisplayLinkStart(self.displayLink);
|
||||
}
|
||||
|
||||
- (void) stopDisplayLink {
|
||||
if (CVDisplayLinkIsRunning(self.displayLink))
|
||||
CVDisplayLinkStop(self.displayLink);
|
||||
}
|
||||
|
||||
CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_displayLinkCallback() called");
|
||||
@autoreleasepool {
|
||||
MTLLayer *layer = (__bridge MTLLayer *)displayLinkContext;
|
||||
[layer performSelectorOnMainThread:@selector(redraw) withObject:nil waitUntilDone:NO];
|
||||
}
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
@end
|
||||
|
||||
/*
|
||||
* Class: sun_java2d_metal_MTLLayer
|
||||
* Method: nativeCreateLayer
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_java2d_metal_MTLLayer_nativeCreateLayer
|
||||
(JNIEnv *env, jobject obj)
|
||||
{
|
||||
__block MTLLayer *layer = nil;
|
||||
|
||||
JNI_COCOA_ENTER(env);
|
||||
|
||||
jobject javaLayer = (*env)->NewWeakGlobalRef(env, obj);
|
||||
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
layer = [[MTLLayer alloc] initWithJavaLayer: javaLayer];
|
||||
}];
|
||||
|
||||
JNI_COCOA_EXIT(env);
|
||||
|
||||
return ptr_to_jlong(layer);
|
||||
}
|
||||
|
||||
// Must be called under the RQ lock.
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLLayer_validate
|
||||
(JNIEnv *env, jclass cls, jlong layerPtr, jobject surfaceData)
|
||||
{
|
||||
MTLLayer *layer = OBJC(layerPtr);
|
||||
|
||||
if (surfaceData != NULL) {
|
||||
BMTLSDOps *bmtlsdo = (BMTLSDOps*) SurfaceData_GetOps(env, surfaceData);
|
||||
layer.bufferWidth = bmtlsdo->width;
|
||||
layer.bufferHeight = bmtlsdo->width;
|
||||
layer.buffer = bmtlsdo->pTexture;
|
||||
layer.ctx = ((MTLSDOps *)bmtlsdo->privOps)->configInfo->context;
|
||||
layer.device = layer.ctx.device;
|
||||
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
layer.drawableSize =
|
||||
CGSizeMake(layer.buffer.width,
|
||||
layer.buffer.height);
|
||||
[layer startDisplayLink];
|
||||
} else {
|
||||
layer.ctx = NULL;
|
||||
[layer stopDisplayLink];
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLLayer_nativeSetScale
|
||||
(JNIEnv *env, jclass cls, jlong layerPtr, jdouble scale)
|
||||
{
|
||||
JNI_COCOA_ENTER(env);
|
||||
MTLLayer *layer = jlong_to_ptr(layerPtr);
|
||||
// We always call all setXX methods asynchronously, exception is only in
|
||||
// this method where we need to change native texture size and layer's scale
|
||||
// in one call on appkit, otherwise we'll get window's contents blinking,
|
||||
// during screen-2-screen moving.
|
||||
[ThreadUtilities performOnMainThreadWaiting:[NSThread isMainThread] block:^(){
|
||||
layer.contentsScale = scale;
|
||||
}];
|
||||
JNI_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLLayer_nativeSetInsets
|
||||
(JNIEnv *env, jclass cls, jlong layerPtr, jint top, jint left)
|
||||
{
|
||||
MTLLayer *layer = jlong_to_ptr(layerPtr);
|
||||
layer.topInset = top;
|
||||
layer.leftInset = left;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLLayer_blitTexture
|
||||
(JNIEnv *env, jclass cls, jlong layerPtr)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_blitTexture");
|
||||
MTLLayer *layer = jlong_to_ptr(layerPtr);
|
||||
MTLContext * ctx = layer.ctx;
|
||||
if (layer == NULL || ctx == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer_blit : Layer or Context is null");
|
||||
return;
|
||||
}
|
||||
|
||||
[layer blitTexture];
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLMaskBlit_h_Included
|
||||
#define MTLMaskBlit_h_Included
|
||||
|
||||
#include "MTLContext.h"
|
||||
|
||||
void MTLMaskBlit_MaskBlit(JNIEnv *env, MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint dstx, jint dsty,
|
||||
jint width, jint height,
|
||||
void *pPixels);
|
||||
|
||||
#endif /* MTLMaskBlit_h_Included */
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <jlong.h>
|
||||
|
||||
#include "MTLMaskBlit.h"
|
||||
#include "MTLRenderQueue.h"
|
||||
#include "MTLBlitLoops.h"
|
||||
|
||||
/**
|
||||
* REMIND: This method assumes that the dimensions of the incoming pixel
|
||||
* array are less than or equal to the cached blit texture tile;
|
||||
* these are rather fragile assumptions, and should be cleaned up...
|
||||
*/
|
||||
void
|
||||
MTLMaskBlit_MaskBlit(JNIEnv *env, MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint dstx, jint dsty,
|
||||
jint width, jint height,
|
||||
void *pPixels)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLMaskBlit_MaskBlit");
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
J2dTraceLn(J2D_TRACE_WARNING, "MTLMaskBlit_MaskBlit: invalid dimensions");
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_IF_NULL(pPixels);
|
||||
RETURN_IF_NULL(mtlc);
|
||||
|
||||
MTLPooledTextureHandle * texHandle = [mtlc.texturePool
|
||||
getTexture:width
|
||||
height:height
|
||||
format:MTLPixelFormatBGRA8Unorm];
|
||||
if (texHandle == nil) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLMaskBlit_MaskBlit: can't obtain temporary texture object from pool");
|
||||
return;
|
||||
}
|
||||
[[mtlc getCommandBufferWrapper] registerPooledTexture:texHandle];
|
||||
|
||||
id<MTLTexture> texBuff = texHandle.texture;
|
||||
MTLRegion region = MTLRegionMake2D(0, 0, width, height);
|
||||
[texBuff replaceRegion:region mipmapLevel:0 withBytes:pPixels bytesPerRow:4*width];
|
||||
|
||||
drawTex2Tex(mtlc, texBuff, dstOps->pTexture, JNI_FALSE, dstOps->isOpaque, 0,
|
||||
0, 0, width, height, dstx, dsty, dstx + width, dsty + height);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLMaskFill_h_Included
|
||||
#define MTLMaskFill_h_Included
|
||||
|
||||
#include "MTLContext.h"
|
||||
|
||||
void MTLMaskFill_MaskFill(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint x, jint y, jint w, jint h,
|
||||
jint maskoff, jint maskscan, jint masklen,
|
||||
unsigned char *pMask);
|
||||
|
||||
#endif /* MTLMaskFill_h_Included */
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "sun_java2d_metal_MTLMaskFill.h"
|
||||
|
||||
#include "MTLMaskFill.h"
|
||||
#include "MTLRenderQueue.h"
|
||||
#include "MTLVertexCache.h"
|
||||
|
||||
/**
|
||||
* In case of Metal we use shader for texture mapping.
|
||||
*
|
||||
* Descriptions of the many variables used in this method:
|
||||
* x,y - upper left corner of the tile destination
|
||||
* w,h - width/height of the mask tile
|
||||
* x0 - placekeeper for the original destination x location
|
||||
* tw,th - width/height of the actual texture tile in pixels
|
||||
* sx1,sy1 - upper left corner of the mask tile source region
|
||||
* sx2,sy2 - lower left corner of the mask tile source region
|
||||
* sx,sy - "current" upper left corner of the mask tile region of interest
|
||||
*/
|
||||
void
|
||||
MTLMaskFill_MaskFill(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint x, jint y, jint w, jint h,
|
||||
jint maskoff, jint maskscan, jint masklen,
|
||||
unsigned char *pMask)
|
||||
{
|
||||
J2dTraceLn5(J2D_TRACE_INFO, "MTLMaskFill_MaskFill (x=%d y=%d w=%d h=%d pMask=%p)", x, y, w, h, dstOps->pTexture);
|
||||
jint tw, th, x0;
|
||||
jint sx1, sy1, sx2, sy2;
|
||||
jint sx, sy, sw, sh;
|
||||
|
||||
x0 = x;
|
||||
tw = MTLVC_MASK_CACHE_TILE_WIDTH;
|
||||
th = MTLVC_MASK_CACHE_TILE_HEIGHT;
|
||||
sx1 = maskoff % maskscan;
|
||||
sy1 = maskoff / maskscan;
|
||||
sx2 = sx1 + w;
|
||||
sy2 = sy1 + h;
|
||||
|
||||
|
||||
for (sy = sy1; sy < sy2; sy += th, y += th) {
|
||||
x = x0;
|
||||
sh = ((sy + th) > sy2) ? (sy2 - sy) : th;
|
||||
|
||||
for (sx = sx1; sx < sx2; sx += tw, x += tw) {
|
||||
sw = ((sx + tw) > sx2) ? (sx2 - sx) : tw;
|
||||
MTLVertexCache_AddMaskQuad(mtlc,
|
||||
sx, sy, x, y, sw, sh,
|
||||
maskscan, pMask, dstOps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLMaskFill_maskFill
|
||||
(JNIEnv *env, jobject self,
|
||||
jint x, jint y, jint w, jint h,
|
||||
jint maskoff, jint maskscan, jint masklen,
|
||||
jbyteArray maskArray)
|
||||
{
|
||||
MTLContext *mtlc = MTLRenderQueue_GetCurrentContext();
|
||||
BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();
|
||||
unsigned char *mask;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLMaskFill_maskFill");
|
||||
|
||||
if (maskArray != NULL) {
|
||||
mask = (unsigned char *)
|
||||
(*env)->GetPrimitiveArrayCritical(env, maskArray, NULL);
|
||||
} else {
|
||||
mask = NULL;
|
||||
}
|
||||
|
||||
MTLMaskFill_MaskFill(mtlc, dstOps,
|
||||
x, y, w, h,
|
||||
maskoff, maskscan, masklen, mask);
|
||||
if (mtlc != NULL) {
|
||||
RESET_PREVIOUS_OP();
|
||||
[mtlc.encoderManager endEncoder];
|
||||
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
[commandbuf commit];
|
||||
}
|
||||
|
||||
if (mask != NULL) {
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, maskArray, mask, JNI_ABORT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLPaints_h_Included
|
||||
#define MTLPaints_h_Included
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
#include "RenderOptions.h"
|
||||
|
||||
#define sun_java2d_SunGraphics2D_PAINT_UNDEFINED -1
|
||||
|
||||
@class MTLContext;
|
||||
@class MTLComposite;
|
||||
@class MTLClip;
|
||||
@class MTLPipelineStatesStorage;
|
||||
|
||||
/**
|
||||
* The MTLPaint class represents paint mode (color, gradient etc.)
|
||||
*/
|
||||
|
||||
@interface MTLPaint : NSObject
|
||||
|
||||
- (id)initWithState:(jint)state;
|
||||
- (BOOL)isEqual:(MTLPaint *)other; // used to compare requested with cached
|
||||
- (NSString *)getDescription;
|
||||
|
||||
// For the current paint mode and passed composite (and flags):
|
||||
// 1. Selects vertex+fragment shader (and corresponding pipelineDesc) and set pipelineState
|
||||
// 2. Prepares corresponding buffers of vertex and fragment shaders
|
||||
|
||||
- (void)setPipelineState:(id <MTLRenderCommandEncoder>)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage;
|
||||
|
||||
|
||||
- (void)setXorModePipelineState:(id <MTLRenderCommandEncoder>)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage;
|
||||
@end
|
||||
|
||||
@interface MTLColorPaint : MTLPaint
|
||||
- (id)initWithColor:(jint)color;
|
||||
@property (nonatomic, readonly) jint color;
|
||||
@end
|
||||
|
||||
@interface MTLBaseGradPaint : MTLPaint
|
||||
- (id)initWithState:(jint)state
|
||||
mask:(jboolean)useMask
|
||||
cyclic:(jboolean)cyclic;
|
||||
@end
|
||||
|
||||
@interface MTLGradPaint : MTLBaseGradPaint
|
||||
|
||||
- (id)initWithUseMask:(jboolean)useMask
|
||||
cyclic:(jboolean)cyclic
|
||||
p0:(jdouble)p0
|
||||
p1:(jdouble)p1
|
||||
p3:(jdouble)p3
|
||||
pixel1:(jint)pixel1
|
||||
pixel2:(jint)pixel2;
|
||||
@end
|
||||
|
||||
@interface MTLBaseMultiGradPaint : MTLBaseGradPaint
|
||||
|
||||
- (id)initWithState:(jint)state
|
||||
mask:(jboolean)useMask
|
||||
linear:(jboolean)linear
|
||||
cycleMethod:(jboolean)cycleMethod
|
||||
numStops:(jint)numStops
|
||||
fractions:(jfloat *)fractions
|
||||
pixels:(jint *)pixels;
|
||||
@end
|
||||
|
||||
@interface MTLLinearGradPaint : MTLBaseMultiGradPaint
|
||||
|
||||
- (id)initWithUseMask:(jboolean)useMask
|
||||
linear:(jboolean)linear
|
||||
cycleMethod:(jboolean)cycleMethod
|
||||
numStops:(jint)numStops
|
||||
p0:(jfloat)p0
|
||||
p1:(jfloat)p1
|
||||
p3:(jfloat)p3
|
||||
fractions:(jfloat *)fractions
|
||||
pixels:(jint *)pixels;
|
||||
@end
|
||||
|
||||
@interface MTLRadialGradPaint : MTLBaseMultiGradPaint
|
||||
|
||||
- (id)initWithUseMask:(jboolean)useMask
|
||||
linear:(jboolean)linear
|
||||
cycleMethod:(jint)cycleMethod
|
||||
numStops:(jint)numStops
|
||||
m00:(jfloat)m00
|
||||
m01:(jfloat)m01
|
||||
m02:(jfloat)m02
|
||||
m10:(jfloat)m10
|
||||
m11:(jfloat)m11
|
||||
m12:(jfloat)m12
|
||||
focusX:(jfloat)focusX
|
||||
fractions:(void *)fractions
|
||||
pixels:(void *)pixels;
|
||||
@end
|
||||
|
||||
@interface MTLTexturePaint : MTLPaint
|
||||
|
||||
- (id)initWithUseMask:(jboolean)useMask
|
||||
textureID:(id <MTLTexture>)textureID
|
||||
isOpaque:(jboolean)isOpaque
|
||||
filter:(jboolean)filter
|
||||
xp0:(jdouble)xp0
|
||||
xp1:(jdouble)xp1
|
||||
xp3:(jdouble)xp3
|
||||
yp0:(jdouble)yp0
|
||||
yp1:(jdouble)yp1
|
||||
yp3:(jdouble)yp3;
|
||||
@end
|
||||
|
||||
#endif /* MTLPaints_h_Included */
|
||||
@@ -0,0 +1,993 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "MTLPaints.h"
|
||||
#include "MTLClip.h"
|
||||
#include "common.h"
|
||||
|
||||
#include "sun_java2d_SunGraphics2D.h"
|
||||
#include "sun_java2d_pipe_BufferedPaints.h"
|
||||
#import "MTLComposite.h"
|
||||
#import "MTLBufImgOps.h"
|
||||
#include "MTLRenderQueue.h"
|
||||
|
||||
#define RGBA_TO_V4(c) \
|
||||
{ \
|
||||
(((c) >> 16) & (0xFF))/255.0f, \
|
||||
(((c) >> 8) & 0xFF)/255.0f, \
|
||||
((c) & 0xFF)/255.0f, \
|
||||
(((c) >> 24) & 0xFF)/255.0f \
|
||||
}
|
||||
|
||||
#define FLOAT_ARR_TO_V4(p) \
|
||||
{ \
|
||||
p[0], \
|
||||
p[1], \
|
||||
p[2], \
|
||||
p[3] \
|
||||
}
|
||||
|
||||
static MTLRenderPipelineDescriptor * templateRenderPipelineDesc = nil;
|
||||
static MTLRenderPipelineDescriptor * templateTexturePipelineDesc = nil;
|
||||
static MTLRenderPipelineDescriptor * templateAATexturePipelineDesc = nil;
|
||||
static MTLRenderPipelineDescriptor * templateLCDPipelineDesc = nil;
|
||||
static MTLRenderPipelineDescriptor * templateAAPipelineDesc = nil;
|
||||
static void
|
||||
setTxtUniforms(MTLContext *mtlc, int color, id <MTLRenderCommandEncoder> encoder, int interpolation, bool repeat,
|
||||
jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, const SurfaceRasterFlags *dstFlags, int mode);
|
||||
|
||||
static void initTemplatePipelineDescriptors() {
|
||||
if (templateRenderPipelineDesc != nil && templateTexturePipelineDesc != nil &&
|
||||
templateAATexturePipelineDesc != nil && templateLCDPipelineDesc != nil &&
|
||||
templateAAPipelineDesc != nil)
|
||||
return;
|
||||
|
||||
MTLVertexDescriptor *vertDesc = [[MTLVertexDescriptor new] autorelease];
|
||||
vertDesc.attributes[VertexAttributePosition].format = MTLVertexFormatFloat2;
|
||||
vertDesc.attributes[VertexAttributePosition].offset = 0;
|
||||
vertDesc.attributes[VertexAttributePosition].bufferIndex = MeshVertexBuffer;
|
||||
vertDesc.layouts[MeshVertexBuffer].stride = sizeof(struct Vertex);
|
||||
vertDesc.layouts[MeshVertexBuffer].stepRate = 1;
|
||||
vertDesc.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||
|
||||
templateRenderPipelineDesc = [MTLRenderPipelineDescriptor new];
|
||||
templateRenderPipelineDesc.sampleCount = 1;
|
||||
templateRenderPipelineDesc.vertexDescriptor = vertDesc;
|
||||
templateRenderPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
templateRenderPipelineDesc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
||||
templateRenderPipelineDesc.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
|
||||
templateRenderPipelineDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;
|
||||
templateRenderPipelineDesc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
||||
templateRenderPipelineDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
templateRenderPipelineDesc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
templateRenderPipelineDesc.label = @"template_render";
|
||||
|
||||
templateTexturePipelineDesc = [templateRenderPipelineDesc copy];
|
||||
templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].format = MTLVertexFormatFloat2;
|
||||
templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].offset = 2*sizeof(float);
|
||||
templateTexturePipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].bufferIndex = MeshVertexBuffer;
|
||||
templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stride = sizeof(struct TxtVertex);
|
||||
templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepRate = 1;
|
||||
templateTexturePipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||
templateTexturePipelineDesc.label = @"template_texture";
|
||||
|
||||
templateAATexturePipelineDesc = [templateTexturePipelineDesc copy];
|
||||
templateAATexturePipelineDesc.label = @"template_aa_texture";
|
||||
|
||||
templateLCDPipelineDesc = [MTLRenderPipelineDescriptor new];
|
||||
templateLCDPipelineDesc.sampleCount = 1;
|
||||
templateLCDPipelineDesc.vertexDescriptor = vertDesc;
|
||||
templateLCDPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
templateLCDPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].format = MTLVertexFormatFloat2;
|
||||
templateLCDPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].offset = 2*sizeof(float);
|
||||
templateLCDPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].bufferIndex = MeshVertexBuffer;
|
||||
templateLCDPipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stride = sizeof(struct TxtVertex);
|
||||
templateLCDPipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepRate = 1;
|
||||
templateLCDPipelineDesc.vertexDescriptor.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||
templateLCDPipelineDesc.label = @"template_lcd";
|
||||
|
||||
vertDesc = [[MTLVertexDescriptor new] autorelease];
|
||||
vertDesc.attributes[VertexAttributePosition].format = MTLVertexFormatFloat2;
|
||||
vertDesc.attributes[VertexAttributePosition].offset = 0;
|
||||
vertDesc.attributes[VertexAttributePosition].bufferIndex = MeshVertexBuffer;
|
||||
vertDesc.layouts[MeshVertexBuffer].stride = sizeof(struct AAVertex);
|
||||
vertDesc.layouts[MeshVertexBuffer].stepRate = 1;
|
||||
vertDesc.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||
|
||||
templateAAPipelineDesc = [MTLRenderPipelineDescriptor new];
|
||||
templateAAPipelineDesc.sampleCount = 1;
|
||||
templateAAPipelineDesc.vertexDescriptor = vertDesc;
|
||||
templateAAPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
templateAAPipelineDesc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
||||
templateAAPipelineDesc.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
|
||||
templateAAPipelineDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;
|
||||
templateAAPipelineDesc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
||||
templateAAPipelineDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
templateAAPipelineDesc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
templateAAPipelineDesc.colorAttachments[0].blendingEnabled = YES;
|
||||
templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].format = MTLVertexFormatFloat2;
|
||||
templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].offset = 2*sizeof(float);
|
||||
templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeTexPos].bufferIndex = MeshVertexBuffer;
|
||||
templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeITexPos].format = MTLVertexFormatFloat2;
|
||||
templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeITexPos].offset = 4*sizeof(float);
|
||||
templateAAPipelineDesc.vertexDescriptor.attributes[VertexAttributeITexPos].bufferIndex = MeshVertexBuffer;
|
||||
templateAAPipelineDesc.label = @"template_aa";
|
||||
}
|
||||
|
||||
|
||||
@implementation MTLColorPaint {
|
||||
// color-mode
|
||||
jint _color;
|
||||
}
|
||||
- (id)initWithColor:(jint)color {
|
||||
self = [super initWithState:sun_java2d_SunGraphics2D_PAINT_ALPHACOLOR];
|
||||
|
||||
if (self) {
|
||||
_color = color;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (jint)color {
|
||||
return _color;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLColorPaint *)other {
|
||||
if (other == self)
|
||||
return YES;
|
||||
if (!other || ![[other class] isEqual:[self class]])
|
||||
return NO;
|
||||
|
||||
return _color == other->_color;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger h = [super hash];
|
||||
h = h*31 + _color;
|
||||
return h;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:
|
||||
@"[r=%d g=%d b=%d a=%d]",
|
||||
(_color >> 16) & (0xFF),
|
||||
(_color >> 8) & 0xFF,
|
||||
(_color) & 0xFF,
|
||||
(_color >> 24) & 0xFF];
|
||||
}
|
||||
|
||||
- (void)setPipelineState:(id<MTLRenderCommandEncoder>)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
{
|
||||
initTemplatePipelineDescriptors();
|
||||
|
||||
MTLRenderPipelineDescriptor *rpDesc = nil;
|
||||
|
||||
NSString *vertShader = @"vert_col";
|
||||
NSString *fragShader = @"frag_col";
|
||||
|
||||
if (renderOptions->isTexture) {
|
||||
vertShader = @"vert_txt";
|
||||
fragShader = @"frag_txt";
|
||||
rpDesc = [[templateTexturePipelineDesc copy] autorelease];
|
||||
if (renderOptions->isAA) {
|
||||
fragShader = @"aa_frag_txt";
|
||||
rpDesc = [[templateAATexturePipelineDesc copy] autorelease];
|
||||
}
|
||||
if (renderOptions->isText) {
|
||||
fragShader = @"frag_text";
|
||||
}
|
||||
if (renderOptions->isLCD) {
|
||||
vertShader = @"vert_txt_lcd";
|
||||
fragShader = @"lcd_color";
|
||||
rpDesc = [[templateLCDPipelineDesc copy] autorelease];
|
||||
}
|
||||
setTxtUniforms(mtlc, _color, encoder,
|
||||
renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], &renderOptions->srcFlags,
|
||||
&renderOptions->dstFlags, 1);
|
||||
} else if (renderOptions->isAAShader) {
|
||||
vertShader = @"vert_col_aa";
|
||||
fragShader = @"frag_col_aa";
|
||||
rpDesc = [[templateAAPipelineDesc copy] autorelease];
|
||||
} else {
|
||||
rpDesc = [[templateRenderPipelineDesc copy] autorelease];
|
||||
}
|
||||
|
||||
struct FrameUniforms uf = {RGBA_TO_V4(_color)};
|
||||
[encoder setVertexBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
|
||||
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
fragmentShaderId:fragShader
|
||||
composite:mtlc.composite
|
||||
renderOptions:renderOptions
|
||||
stencilNeeded:[mtlc.clip isShape]];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
}
|
||||
|
||||
- (void)setXorModePipelineState:(id<MTLRenderCommandEncoder>)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
{
|
||||
initTemplatePipelineDescriptors();
|
||||
NSString * vertShader = @"vert_col_xorMode";
|
||||
NSString * fragShader = @"frag_col_xorMode";
|
||||
MTLRenderPipelineDescriptor * rpDesc = nil;
|
||||
jint xorColor = (jint) [mtlc.composite getXorColor];
|
||||
// Calculate _color ^ xorColor for RGB components
|
||||
// This color gets XORed with destination framebuffer pixel color
|
||||
const int col = _color ^ xorColor;
|
||||
BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();
|
||||
|
||||
if (renderOptions->isTexture) {
|
||||
vertShader = @"vert_txt_xorMode";
|
||||
fragShader = @"frag_txt_xorMode";
|
||||
rpDesc = [[templateTexturePipelineDesc copy] autorelease];
|
||||
|
||||
setTxtUniforms(mtlc, col, encoder,
|
||||
renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],
|
||||
&renderOptions->srcFlags, &renderOptions->dstFlags, 1);
|
||||
[encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex:0];
|
||||
|
||||
[encoder setFragmentTexture:dstOps->pTexture atIndex:1];
|
||||
} else {
|
||||
struct FrameUniforms uf = {RGBA_TO_V4(col)};
|
||||
rpDesc = [[templateRenderPipelineDesc copy] autorelease];
|
||||
|
||||
[encoder setVertexBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
|
||||
[encoder setFragmentTexture:dstOps->pTexture atIndex:0];
|
||||
}
|
||||
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
fragmentShaderId:fragShader
|
||||
composite:mtlc.composite
|
||||
renderOptions:renderOptions
|
||||
stencilNeeded:[mtlc.clip isShape]];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MTLBaseGradPaint {
|
||||
jboolean _useMask;
|
||||
@protected
|
||||
jint _cyclic;
|
||||
}
|
||||
|
||||
- (id)initWithState:(jint)state mask:(jboolean)useMask cyclic:(jboolean)cyclic {
|
||||
self = [super initWithState:state];
|
||||
|
||||
if (self) {
|
||||
_useMask = useMask;
|
||||
_cyclic = cyclic;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLBaseGradPaint *)other {
|
||||
if (other == self)
|
||||
return YES;
|
||||
if (!other || ![[other class] isEqual:[self class]])
|
||||
return NO;
|
||||
|
||||
return [super isEqual:self] && _cyclic == other->_cyclic && _useMask == other->_useMask;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger h = [super hash];
|
||||
h = h*31 + _cyclic;
|
||||
h = h*31 + _useMask;
|
||||
return h;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTLGradPaint {
|
||||
jdouble _p0;
|
||||
jdouble _p1;
|
||||
jdouble _p3;
|
||||
jint _pixel1;
|
||||
jint _pixel2;
|
||||
}
|
||||
- (id)initWithUseMask:(jboolean)useMask
|
||||
cyclic:(jboolean)cyclic
|
||||
p0:(jdouble)p0
|
||||
p1:(jdouble)p1
|
||||
p3:(jdouble)p3
|
||||
pixel1:(jint)pixel1
|
||||
pixel2:(jint)pixel2
|
||||
{
|
||||
self = [super initWithState:sun_java2d_SunGraphics2D_PAINT_GRADIENT
|
||||
mask:useMask
|
||||
cyclic:cyclic];
|
||||
|
||||
if (self) {
|
||||
_p0 = p0;
|
||||
_p1 = p1;
|
||||
_p3 = p3;
|
||||
_pixel1 = pixel1;
|
||||
_pixel2 = pixel2;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLGradPaint *)other {
|
||||
if (other == self)
|
||||
return YES;
|
||||
if (!other || ![[other class] isEqual:[self class]])
|
||||
return NO;
|
||||
|
||||
return [super isEqual:self] && _p0 == other->_p0 &&
|
||||
_p1 == other->_p1 && _p3 == other->_p3 &&
|
||||
_pixel1 == other->_pixel1 && _pixel2 == other->_pixel2;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger h = [super hash];
|
||||
h = h*31 + [@(_p0) hash];
|
||||
h = h*31 + [@(_p1) hash];;
|
||||
h = h*31 + [@(_p3) hash];;
|
||||
h = h*31 + _pixel1;
|
||||
h = h*31 + _pixel2;
|
||||
return h;
|
||||
}
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"gradient"];
|
||||
}
|
||||
|
||||
- (void)setPipelineState:(id)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
{
|
||||
initTemplatePipelineDescriptors();
|
||||
MTLRenderPipelineDescriptor *rpDesc = nil;
|
||||
|
||||
NSString *vertShader = @"vert_grad";
|
||||
NSString *fragShader = @"frag_grad";
|
||||
|
||||
struct GradFrameUniforms uf = {
|
||||
{_p0, _p1, _p3},
|
||||
RGBA_TO_V4(_pixel1),
|
||||
RGBA_TO_V4(_pixel2),
|
||||
_cyclic,
|
||||
[mtlc.composite getExtraAlpha]
|
||||
};
|
||||
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0];
|
||||
|
||||
if (renderOptions->isTexture) {
|
||||
vertShader = @"vert_txt_grad";
|
||||
fragShader = @"frag_txt_grad";
|
||||
rpDesc = [[templateTexturePipelineDesc copy] autorelease];
|
||||
} else {
|
||||
rpDesc = [[templateRenderPipelineDesc copy] autorelease];
|
||||
}
|
||||
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
fragmentShaderId:fragShader
|
||||
composite:mtlc.composite
|
||||
renderOptions:renderOptions
|
||||
stencilNeeded:[mtlc.clip isShape]];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
}
|
||||
|
||||
- (void)setXorModePipelineState:(id)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
{
|
||||
// This block is not reached in current implementation.
|
||||
// Gradient paint XOR mode rendering uses a tile based rendering using a SW pipe (similar to OGL)
|
||||
initTemplatePipelineDescriptors();
|
||||
NSString* vertShader = @"vert_grad_xorMode";
|
||||
NSString* fragShader = @"frag_grad_xorMode";
|
||||
MTLRenderPipelineDescriptor *rpDesc = [[templateRenderPipelineDesc copy] autorelease];
|
||||
jint xorColor = (jint) [mtlc.composite getXorColor];
|
||||
|
||||
struct GradFrameUniforms uf = {
|
||||
{_p0, _p1, _p3},
|
||||
RGBA_TO_V4(_pixel1 ^ xorColor),
|
||||
RGBA_TO_V4(_pixel2 ^ xorColor),
|
||||
_cyclic,
|
||||
[mtlc.composite getExtraAlpha]
|
||||
};
|
||||
|
||||
[encoder setFragmentBytes: &uf length:sizeof(uf) atIndex:0];
|
||||
BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();
|
||||
[encoder setFragmentTexture:dstOps->pTexture atIndex:0];
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLPaints - setXorModePipelineState -- PAINT_GRADIENT");
|
||||
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
fragmentShaderId:fragShader
|
||||
composite:mtlc.composite
|
||||
renderOptions:renderOptions
|
||||
stencilNeeded:[mtlc.clip isShape]];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTLBaseMultiGradPaint {
|
||||
@protected
|
||||
jboolean _linear;
|
||||
jint _numFracts;
|
||||
jfloat _fract[GRAD_MAX_FRACTIONS];
|
||||
jint _pixel[GRAD_MAX_FRACTIONS];
|
||||
}
|
||||
|
||||
- (id)initWithState:(jint)state
|
||||
mask:(jboolean)useMask
|
||||
linear:(jboolean)linear
|
||||
cycleMethod:(jboolean)cycleMethod
|
||||
numStops:(jint)numStops
|
||||
fractions:(jfloat *)fractions
|
||||
pixels:(jint *)pixels
|
||||
{
|
||||
self = [super initWithState:state
|
||||
mask:useMask
|
||||
cyclic:cycleMethod];
|
||||
|
||||
if (self) {
|
||||
_linear = linear;
|
||||
memcpy(_fract, fractions,numStops*sizeof(jfloat));
|
||||
memcpy(_pixel, pixels, numStops*sizeof(jint));
|
||||
_numFracts = numStops;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLBaseMultiGradPaint *)other {
|
||||
if (other == self)
|
||||
return YES;
|
||||
if (!other || ![[other class] isEqual:[self class]])
|
||||
return NO;
|
||||
|
||||
if (_numFracts != other->_numFracts || ![super isEqual:self])
|
||||
return NO;
|
||||
for (int i = 0; i < _numFracts; i++) {
|
||||
if (_fract[i] != other->_fract[i]) return NO;
|
||||
if (_pixel[i] != other->_pixel[i]) return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger h = [super hash];
|
||||
h = h*31 + _numFracts;
|
||||
for (int i = 0; i < _numFracts; i++) {
|
||||
h = h*31 + [@(_fract[i]) hash];
|
||||
h = h*31 + _pixel[i];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTLLinearGradPaint {
|
||||
jdouble _p0;
|
||||
jdouble _p1;
|
||||
jdouble _p3;
|
||||
}
|
||||
- (void)setPipelineState:(id)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
|
||||
{
|
||||
initTemplatePipelineDescriptors();
|
||||
MTLRenderPipelineDescriptor *rpDesc = nil;
|
||||
|
||||
NSString *vertShader = @"vert_grad";
|
||||
NSString *fragShader = @"frag_lin_grad";
|
||||
|
||||
if (renderOptions->isTexture) {
|
||||
vertShader = @"vert_txt_grad";
|
||||
fragShader = @"frag_txt_lin_grad";
|
||||
rpDesc = [[templateTexturePipelineDesc copy] autorelease];
|
||||
} else {
|
||||
rpDesc = [[templateRenderPipelineDesc copy] autorelease];
|
||||
}
|
||||
|
||||
struct LinGradFrameUniforms uf = {
|
||||
{_p0, _p1, _p3},
|
||||
{},
|
||||
{},
|
||||
_numFracts,
|
||||
_linear,
|
||||
_cyclic,
|
||||
[mtlc.composite getExtraAlpha]
|
||||
};
|
||||
|
||||
memcpy(uf.fract, _fract, _numFracts*sizeof(jfloat));
|
||||
for (int i = 0; i < _numFracts; i++) {
|
||||
vector_float4 v = RGBA_TO_V4(_pixel[i]);
|
||||
uf.color[i] = v;
|
||||
}
|
||||
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0];
|
||||
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
fragmentShaderId:fragShader
|
||||
composite:mtlc.composite
|
||||
renderOptions:renderOptions
|
||||
stencilNeeded:[mtlc.clip isShape]];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
}
|
||||
|
||||
- (id)initWithUseMask:(jboolean)useMask
|
||||
linear:(jboolean)linear
|
||||
cycleMethod:(jboolean)cycleMethod
|
||||
numStops:(jint)numStops
|
||||
p0:(jfloat)p0
|
||||
p1:(jfloat)p1
|
||||
p3:(jfloat)p3
|
||||
fractions:(jfloat *)fractions
|
||||
pixels:(jint *)pixels
|
||||
{
|
||||
self = [super initWithState:sun_java2d_SunGraphics2D_PAINT_LIN_GRADIENT
|
||||
mask:useMask
|
||||
linear:linear
|
||||
cycleMethod:cycleMethod
|
||||
numStops:numStops
|
||||
fractions:fractions
|
||||
pixels:pixels];
|
||||
|
||||
if (self) {
|
||||
_p0 = p0;
|
||||
_p1 = p1;
|
||||
_p3 = p3;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLLinearGradPaint *)other {
|
||||
if (other == self)
|
||||
return YES;
|
||||
if (!other || ![[other class] isEqual:[self class]] || ![super isEqual:other])
|
||||
return NO;
|
||||
|
||||
return _p0 == other->_p0 && _p1 == other->_p1 && _p3 == other->_p3;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger h = [super hash];
|
||||
h = h*31 + [@(_p0) hash];
|
||||
h = h*31 + [@(_p1) hash];
|
||||
h = h*31 + [@(_p3) hash];
|
||||
return h;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"linear_gradient"];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MTLRadialGradPaint {
|
||||
jfloat _m00;
|
||||
jfloat _m01;
|
||||
jfloat _m02;
|
||||
jfloat _m10;
|
||||
jfloat _m11;
|
||||
jfloat _m12;
|
||||
jfloat _focusX;
|
||||
}
|
||||
|
||||
- (id)initWithUseMask:(jboolean)useMask
|
||||
linear:(jboolean)linear
|
||||
cycleMethod:(jint)cycleMethod
|
||||
numStops:(jint)numStops
|
||||
m00:(jfloat)m00
|
||||
m01:(jfloat)m01
|
||||
m02:(jfloat)m02
|
||||
m10:(jfloat)m10
|
||||
m11:(jfloat)m11
|
||||
m12:(jfloat)m12
|
||||
focusX:(jfloat)focusX
|
||||
fractions:(void *)fractions
|
||||
pixels:(void *)pixels
|
||||
{
|
||||
self = [super initWithState:sun_java2d_SunGraphics2D_PAINT_RAD_GRADIENT
|
||||
mask:useMask
|
||||
linear:linear
|
||||
cycleMethod:cycleMethod
|
||||
numStops:numStops
|
||||
fractions:fractions
|
||||
pixels:pixels];
|
||||
|
||||
if (self) {
|
||||
_m00 = m00;
|
||||
_m01 = m01;
|
||||
_m02 = m02;
|
||||
_m10 = m10;
|
||||
_m11 = m11;
|
||||
_m12 = m12;
|
||||
_focusX = focusX;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLRadialGradPaint *)other {
|
||||
if (other == self)
|
||||
return YES;
|
||||
if (!other || ![[other class] isEqual:[self class]]
|
||||
|| ![super isEqual:self])
|
||||
return NO;
|
||||
|
||||
return _m00 == other->_m00 && _m01 == other->_m01 && _m02 == other->_m02 &&
|
||||
_m10 == other->_m10 && _m11 == other->_m11 && _m12 == other->_m12 &&
|
||||
_focusX == other->_focusX;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
NSUInteger h = [super hash];
|
||||
h = h*31 + [@(_m00) hash];
|
||||
h = h*31 + [@(_m01) hash];
|
||||
h = h*31 + [@(_m02) hash];
|
||||
h = h*31 + [@(_m10) hash];
|
||||
h = h*31 + [@(_m11) hash];
|
||||
h = h*31 + [@(_m12) hash];
|
||||
return h;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"radial_gradient"];
|
||||
}
|
||||
|
||||
- (void)setPipelineState:(id)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
{
|
||||
initTemplatePipelineDescriptors();
|
||||
MTLRenderPipelineDescriptor *rpDesc = nil;
|
||||
|
||||
NSString *vertShader = @"vert_grad";
|
||||
NSString *fragShader = @"frag_rad_grad";
|
||||
|
||||
if (renderOptions->isTexture) {
|
||||
vertShader = @"vert_txt_grad";
|
||||
fragShader = @"frag_txt_rad_grad";
|
||||
rpDesc = [[templateTexturePipelineDesc copy] autorelease];
|
||||
} else {
|
||||
rpDesc = [[templateRenderPipelineDesc copy] autorelease];
|
||||
}
|
||||
|
||||
struct RadGradFrameUniforms uf = {
|
||||
{},
|
||||
{},
|
||||
_numFracts,
|
||||
_linear,
|
||||
_cyclic,
|
||||
{_m00, _m01, _m02},
|
||||
{_m10, _m11, _m12},
|
||||
{},
|
||||
[mtlc.composite getExtraAlpha]
|
||||
};
|
||||
|
||||
uf.precalc[0] = _focusX;
|
||||
uf.precalc[1] = 1.0 - (_focusX * _focusX);
|
||||
uf.precalc[2] = 1.0 / uf.precalc[1];
|
||||
|
||||
memcpy(uf.fract, _fract, _numFracts*sizeof(jfloat));
|
||||
for (int i = 0; i < _numFracts; i++) {
|
||||
vector_float4 v = RGBA_TO_V4(_pixel[i]);
|
||||
uf.color[i] = v;
|
||||
}
|
||||
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:0];
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
fragmentShaderId:fragShader
|
||||
composite:mtlc.composite
|
||||
renderOptions:renderOptions
|
||||
stencilNeeded:[mtlc.clip isShape]];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTLTexturePaint {
|
||||
struct AnchorData _anchor;
|
||||
id <MTLTexture> _paintTexture;
|
||||
jboolean _isOpaque;
|
||||
}
|
||||
|
||||
- (id)initWithUseMask:(jboolean)useMask
|
||||
textureID:(id)textureId
|
||||
isOpaque:(jboolean)isOpaque
|
||||
filter:(jboolean)filter
|
||||
xp0:(jdouble)xp0
|
||||
xp1:(jdouble)xp1
|
||||
xp3:(jdouble)xp3
|
||||
yp0:(jdouble)yp0
|
||||
yp1:(jdouble)yp1
|
||||
yp3:(jdouble)yp3
|
||||
{
|
||||
self = [super initWithState:sun_java2d_SunGraphics2D_PAINT_TEXTURE];
|
||||
|
||||
if (self) {
|
||||
_paintTexture = textureId;
|
||||
_anchor.xParams[0] = xp0;
|
||||
_anchor.xParams[1] = xp1;
|
||||
_anchor.xParams[2] = xp3;
|
||||
|
||||
_anchor.yParams[0] = yp0;
|
||||
_anchor.yParams[1] = yp1;
|
||||
_anchor.yParams[2] = yp3;
|
||||
_isOpaque = isOpaque;
|
||||
}
|
||||
return self;
|
||||
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLTexturePaint *)other {
|
||||
if (other == self)
|
||||
return YES;
|
||||
if (!other || ![[other class] isEqual:[self class]])
|
||||
return NO;
|
||||
|
||||
return [_paintTexture isEqual:other->_paintTexture]
|
||||
&& _anchor.xParams[0] == other->_anchor.xParams[0]
|
||||
&& _anchor.xParams[1] == other->_anchor.xParams[1]
|
||||
&& _anchor.xParams[2] == other->_anchor.xParams[2]
|
||||
&& _anchor.yParams[0] == other->_anchor.yParams[0]
|
||||
&& _anchor.yParams[1] == other->_anchor.yParams[1]
|
||||
&& _anchor.yParams[2] == other->_anchor.yParams[2];
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"texture_paint"];
|
||||
}
|
||||
|
||||
- (void)setPipelineState:(id)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
{
|
||||
initTemplatePipelineDescriptors();
|
||||
MTLRenderPipelineDescriptor *rpDesc = nil;
|
||||
|
||||
NSString* vertShader = @"vert_tp";
|
||||
NSString* fragShader = @"frag_tp";
|
||||
|
||||
[encoder setVertexBytes:&_anchor length:sizeof(_anchor) atIndex:FrameUniformBuffer];
|
||||
|
||||
if (renderOptions->isTexture) {
|
||||
vertShader = @"vert_txt_tp";
|
||||
fragShader = @"frag_txt_tp";
|
||||
rpDesc = [[templateTexturePipelineDesc copy] autorelease];
|
||||
[encoder setFragmentTexture:_paintTexture atIndex:1];
|
||||
} else {
|
||||
rpDesc = [[templateRenderPipelineDesc copy] autorelease];
|
||||
[encoder setFragmentTexture:_paintTexture atIndex:0];
|
||||
}
|
||||
const SurfaceRasterFlags srcFlags = {_isOpaque, renderOptions->srcFlags.isPremultiplied};
|
||||
setTxtUniforms(mtlc, 0, encoder,
|
||||
renderOptions->interpolation, YES, [mtlc.composite getExtraAlpha],
|
||||
&srcFlags, &renderOptions->dstFlags, 0);
|
||||
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
fragmentShaderId:fragShader
|
||||
composite:mtlc.composite
|
||||
renderOptions:renderOptions
|
||||
stencilNeeded:[mtlc.clip isShape]];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
}
|
||||
|
||||
- (void)setXorModePipelineState:(id)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
{
|
||||
initTemplatePipelineDescriptors();
|
||||
// This block is not reached in current implementation.
|
||||
// Texture paint XOR mode rendering uses a tile based rendering using a SW pipe (similar to OGL)
|
||||
NSString* vertShader = @"vert_tp_xorMode";
|
||||
NSString* fragShader = @"frag_tp_xorMode";
|
||||
MTLRenderPipelineDescriptor *rpDesc = [[templateRenderPipelineDesc copy] autorelease];
|
||||
jint xorColor = (jint) [mtlc.composite getXorColor];
|
||||
|
||||
[encoder setVertexBytes:&_anchor length:sizeof(_anchor) atIndex:FrameUniformBuffer];
|
||||
[encoder setFragmentTexture:_paintTexture atIndex: 0];
|
||||
BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();
|
||||
[encoder setFragmentTexture:dstOps->pTexture atIndex:1];
|
||||
[encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex: 0];
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLPaints - setXorModePipelineState -- PAINT_TEXTURE");
|
||||
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
fragmentShaderId:fragShader
|
||||
composite:mtlc.composite
|
||||
renderOptions:renderOptions
|
||||
stencilNeeded:[mtlc.clip isShape]];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTLPaint {
|
||||
jint _paintState;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_paintState = sun_java2d_SunGraphics2D_PAINT_UNDEFINED;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithState:(jint)state {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_paintState = state;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLPaint *)other {
|
||||
if (other == self)
|
||||
return YES;
|
||||
if (!other || ![other isKindOfClass:[self class]])
|
||||
return NO;
|
||||
return _paintState == other->_paintState;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return _paintState;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return @"unknown-paint";
|
||||
}
|
||||
|
||||
static void
|
||||
setTxtUniforms(MTLContext *mtlc, int color, id <MTLRenderCommandEncoder> encoder, int interpolation, bool repeat,
|
||||
jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, const SurfaceRasterFlags *dstFlags, int mode) {
|
||||
struct TxtFrameUniforms uf = {RGBA_TO_V4(color), mode, srcFlags->isOpaque, dstFlags->isOpaque, extraAlpha};
|
||||
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
|
||||
[mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:interpolation repeat:repeat];
|
||||
}
|
||||
|
||||
// For the current paint mode:
|
||||
// 1. Selects vertex+fragment shaders (and corresponding pipelineDesc) and set pipelineState
|
||||
// 2. Set vertex and fragment buffers
|
||||
// Base implementation is used in drawTex2Tex
|
||||
- (void)setPipelineState:(id <MTLRenderCommandEncoder>)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
{
|
||||
initTemplatePipelineDescriptors();
|
||||
// Called from drawTex2Tex used in flushBuffer and for buffered image ops
|
||||
if (renderOptions->isTexture) {
|
||||
NSString * vertShader = @"vert_txt";
|
||||
NSString * fragShader = @"frag_txt";
|
||||
MTLRenderPipelineDescriptor* rpDesc = [[templateTexturePipelineDesc copy] autorelease];
|
||||
|
||||
NSObject *bufImgOp = [mtlc getBufImgOp];
|
||||
if (bufImgOp != nil) {
|
||||
if ([bufImgOp isKindOfClass:[MTLRescaleOp class]]) {
|
||||
MTLRescaleOp *rescaleOp = bufImgOp;
|
||||
fragShader = @"frag_txt_op_rescale";
|
||||
|
||||
struct TxtFrameOpRescaleUniforms uf = {
|
||||
RGBA_TO_V4(0), [mtlc.composite getExtraAlpha], renderOptions->srcFlags.isOpaque,
|
||||
rescaleOp.isNonPremult,
|
||||
FLOAT_ARR_TO_V4([rescaleOp getScaleFactors]), FLOAT_ARR_TO_V4([rescaleOp getOffsets])
|
||||
};
|
||||
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
|
||||
[mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:renderOptions->interpolation repeat:NO];
|
||||
} else if ([bufImgOp isKindOfClass:[MTLConvolveOp class]]) {
|
||||
MTLConvolveOp *convolveOp = bufImgOp;
|
||||
fragShader = @"frag_txt_op_convolve";
|
||||
|
||||
struct TxtFrameOpConvolveUniforms uf = {
|
||||
[mtlc.composite getExtraAlpha], renderOptions->srcFlags.isOpaque,
|
||||
FLOAT_ARR_TO_V4([convolveOp getImgEdge]),
|
||||
convolveOp.kernelSize, convolveOp.isEdgeZeroFill,
|
||||
};
|
||||
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
|
||||
[mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:renderOptions->interpolation repeat:NO];
|
||||
|
||||
[encoder setFragmentBuffer:[convolveOp getBuffer] offset:0 atIndex:2];
|
||||
} else if ([bufImgOp isKindOfClass:[MTLLookupOp class]]) {
|
||||
MTLLookupOp *lookupOp = bufImgOp;
|
||||
fragShader = @"frag_txt_op_lookup";
|
||||
|
||||
struct TxtFrameOpLookupUniforms uf = {
|
||||
[mtlc.composite getExtraAlpha], renderOptions->srcFlags.isOpaque,
|
||||
FLOAT_ARR_TO_V4([lookupOp getOffset]), lookupOp.isUseSrcAlpha, lookupOp.isNonPremult,
|
||||
};
|
||||
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
|
||||
[mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:renderOptions->interpolation repeat:NO];
|
||||
[encoder setFragmentTexture:[lookupOp getLookupTexture] atIndex:1];
|
||||
}
|
||||
} else {
|
||||
setTxtUniforms(mtlc, 0, encoder,
|
||||
renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],
|
||||
&renderOptions->srcFlags,
|
||||
&renderOptions->dstFlags, 0);
|
||||
|
||||
}
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
fragmentShaderId:fragShader
|
||||
composite:mtlc.composite
|
||||
renderOptions:renderOptions
|
||||
stencilNeeded:[mtlc.clip isShape]];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
}
|
||||
}
|
||||
|
||||
// For the current paint mode:
|
||||
// 1. Selects vertex+fragment shaders (and corresponding pipelineDesc) and set pipelineState
|
||||
// 2. Set vertex and fragment buffers
|
||||
- (void)setXorModePipelineState:(id <MTLRenderCommandEncoder>)encoder
|
||||
context:(MTLContext *)mtlc
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
|
||||
{
|
||||
initTemplatePipelineDescriptors();
|
||||
if (renderOptions->isTexture) {
|
||||
jint xorColor = (jint) [mtlc.composite getXorColor];
|
||||
NSString * vertShader = @"vert_txt_xorMode";
|
||||
NSString * fragShader = @"frag_txt_xorMode";
|
||||
MTLRenderPipelineDescriptor * rpDesc = [[templateTexturePipelineDesc copy] autorelease];
|
||||
|
||||
const int col = 0 ^ xorColor;
|
||||
setTxtUniforms(mtlc, col, encoder,
|
||||
renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],
|
||||
&renderOptions->srcFlags, &renderOptions->dstFlags, 0);
|
||||
[encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex: 0];
|
||||
|
||||
BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();
|
||||
[encoder setFragmentTexture:dstOps->pTexture atIndex:1];
|
||||
|
||||
setTxtUniforms(mtlc, 0, encoder,
|
||||
renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha],
|
||||
&renderOptions->srcFlags,
|
||||
&renderOptions->dstFlags, 0);
|
||||
|
||||
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:rpDesc
|
||||
vertexShaderId:vertShader
|
||||
fragmentShaderId:fragShader
|
||||
composite:mtlc.composite
|
||||
renderOptions:renderOptions
|
||||
stencilNeeded:[mtlc.clip isShape]];
|
||||
[encoder setRenderPipelineState:pipelineState];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLPipelineStatesStorage_h_Included
|
||||
#define MTLPipelineStatesStorage_h_Included
|
||||
|
||||
#import "MTLUtils.h"
|
||||
#include "RenderOptions.h"
|
||||
|
||||
@class MTLComposite;
|
||||
|
||||
/**
|
||||
* The MTLPipelineStatesStorage class used to obtain MTLRenderPipelineState
|
||||
* */
|
||||
|
||||
|
||||
@interface MTLPipelineStatesStorage : NSObject {
|
||||
@private
|
||||
|
||||
id<MTLDevice> device;
|
||||
id<MTLLibrary> library;
|
||||
NSMutableDictionary<NSString*, id<MTLFunction>> * shaders;
|
||||
NSMutableDictionary<NSString*, id<MTLComputePipelineState>> * computeStates;
|
||||
}
|
||||
|
||||
@property (readwrite, assign) id<MTLDevice> device;
|
||||
@property (readwrite, retain) id<MTLLibrary> library;
|
||||
@property (readwrite, retain) NSMutableDictionary<NSString*, id<MTLFunction>> * shaders;
|
||||
@property (readwrite, retain) NSMutableDictionary<NSString*, NSMutableDictionary *> * states;
|
||||
|
||||
- (id) initWithDevice:(id<MTLDevice>)device shaderLibPath:(NSString *)shadersLib;
|
||||
|
||||
- (id<MTLRenderPipelineState>) getPipelineState:(MTLRenderPipelineDescriptor *) pipelineDescriptor
|
||||
vertexShaderId:(NSString *)vertexShaderId
|
||||
fragmentShaderId:(NSString *)fragmentShaderId;
|
||||
|
||||
- (id<MTLRenderPipelineState>) getPipelineState:(MTLRenderPipelineDescriptor *) pipelineDescriptor
|
||||
vertexShaderId:(NSString *)vertexShaderId
|
||||
fragmentShaderId:(NSString *)fragmentShaderId
|
||||
stencilNeeded:(bool)stencilNeeded;
|
||||
|
||||
- (id<MTLRenderPipelineState>) getPipelineState:(MTLRenderPipelineDescriptor *) pipelineDescriptor
|
||||
vertexShaderId:(NSString *)vertexShaderId
|
||||
fragmentShaderId:(NSString *)fragmentShaderId
|
||||
composite:(MTLComposite*)composite
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
stencilNeeded:(bool)stencilNeeded;
|
||||
|
||||
- (id<MTLComputePipelineState>) getComputePipelineState:(NSString *)computeShaderId;
|
||||
|
||||
- (id<MTLFunction>) getShader:(NSString *)name;
|
||||
@end
|
||||
|
||||
|
||||
#endif // MTLPipelineStatesStorage_h_Included
|
||||
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#import "MTLPipelineStatesStorage.h"
|
||||
|
||||
#include "GraphicsPrimitiveMgr.h"
|
||||
#import "MTLComposite.h"
|
||||
|
||||
#include "sun_java2d_SunGraphics2D.h"
|
||||
|
||||
extern const SurfaceRasterFlags defaultRasterFlags;
|
||||
|
||||
static void setBlendingFactors(
|
||||
MTLRenderPipelineColorAttachmentDescriptor * cad,
|
||||
MTLComposite* composite,
|
||||
const RenderOptions * renderOptions);
|
||||
|
||||
@implementation MTLPipelineStatesStorage
|
||||
|
||||
@synthesize device;
|
||||
@synthesize library;
|
||||
@synthesize shaders;
|
||||
@synthesize states;
|
||||
|
||||
- (id) initWithDevice:(id<MTLDevice>)dev shaderLibPath:(NSString *)shadersLib {
|
||||
self = [super init];
|
||||
if (self == nil) return self;
|
||||
|
||||
self.device = dev;
|
||||
|
||||
NSError *error = nil;
|
||||
self.library = [dev newLibraryWithFile:shadersLib error:&error];
|
||||
if (!self.library) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLPipelineStatesStorage.initWithDevice() - Failed to load Metal shader library.");
|
||||
return nil;
|
||||
}
|
||||
self.shaders = [NSMutableDictionary dictionaryWithCapacity:10];
|
||||
self.states = [NSMutableDictionary dictionaryWithCapacity:10];
|
||||
computeStates = [[NSMutableDictionary dictionaryWithCapacity:10] retain] ;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSPointerArray * ) getSubStates:(NSString *)vertexShaderId fragmentShader:(NSString *)fragmentShaderId {
|
||||
NSMutableDictionary * vSubStates = states[vertexShaderId];
|
||||
if (vSubStates == nil) {
|
||||
@autoreleasepool {
|
||||
vSubStates = [NSMutableDictionary dictionary];
|
||||
[states setObject:vSubStates forKey:vertexShaderId];
|
||||
}
|
||||
}
|
||||
NSPointerArray * sSubStates = vSubStates[fragmentShaderId];
|
||||
if (sSubStates == nil) {
|
||||
@autoreleasepool {
|
||||
sSubStates = [NSPointerArray strongObjectsPointerArray];
|
||||
[vSubStates setObject:sSubStates forKey:fragmentShaderId];
|
||||
}
|
||||
}
|
||||
return sSubStates;
|
||||
}
|
||||
|
||||
- (id<MTLRenderPipelineState>) getPipelineState:(MTLRenderPipelineDescriptor *) pipelineDescriptor
|
||||
vertexShaderId:(NSString *)vertexShaderId
|
||||
fragmentShaderId:(NSString *)fragmentShaderId
|
||||
{
|
||||
RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getPipelineState:pipelineDescriptor
|
||||
vertexShaderId:vertexShaderId
|
||||
fragmentShaderId:fragmentShaderId
|
||||
composite:nil
|
||||
renderOptions:&defaultOptions
|
||||
stencilNeeded:NO];
|
||||
}
|
||||
|
||||
- (id<MTLRenderPipelineState>) getPipelineState:(MTLRenderPipelineDescriptor *) pipelineDescriptor
|
||||
vertexShaderId:(NSString *)vertexShaderId
|
||||
fragmentShaderId:(NSString *)fragmentShaderId
|
||||
stencilNeeded:(bool)stencilNeeded
|
||||
{
|
||||
RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE};
|
||||
return [self getPipelineState:pipelineDescriptor
|
||||
vertexShaderId:vertexShaderId
|
||||
fragmentShaderId:fragmentShaderId
|
||||
composite:nil
|
||||
renderOptions:&defaultOptions
|
||||
stencilNeeded:stencilNeeded];
|
||||
}
|
||||
|
||||
// Base method to obtain MTLRenderPipelineState.
|
||||
// NOTE: parameters compositeRule, srcFlags, dstFlags are used to set MTLRenderPipelineColorAttachmentDescriptor multipliers
|
||||
- (id<MTLRenderPipelineState>) getPipelineState:(MTLRenderPipelineDescriptor *) pipelineDescriptor
|
||||
vertexShaderId:(NSString *)vertexShaderId
|
||||
fragmentShaderId:(NSString *)fragmentShaderId
|
||||
composite:(MTLComposite*) composite
|
||||
renderOptions:(const RenderOptions *)renderOptions
|
||||
stencilNeeded:(bool)stencilNeeded;
|
||||
{
|
||||
jint compositeRule = composite != nil ? [composite getRule] : RULE_Src;
|
||||
const jboolean useXorComposite = composite != nil && [composite getCompositeState] == sun_java2d_SunGraphics2D_COMP_XOR;
|
||||
const jboolean useComposite = composite != nil && compositeRule >= 0
|
||||
&& compositeRule < java_awt_AlphaComposite_MAX_RULE;
|
||||
|
||||
// Calculate index by flags and compositeRule
|
||||
// TODO: reimplement, use map with convenient key (calculated by all arguments)
|
||||
int subIndex = 0;
|
||||
if (useXorComposite) {
|
||||
// compositeRule value is already XOR_COMPOSITE_RULE
|
||||
}
|
||||
else {
|
||||
if (useComposite) {
|
||||
if (!renderOptions->srcFlags.isPremultiplied)
|
||||
subIndex |= 1;
|
||||
if (renderOptions->srcFlags.isOpaque)
|
||||
subIndex |= 1 << 1;
|
||||
if (!renderOptions->dstFlags.isPremultiplied)
|
||||
subIndex |= 1 << 2;
|
||||
if (renderOptions->dstFlags.isOpaque)
|
||||
subIndex |= 1 << 3;
|
||||
} else
|
||||
compositeRule = RULE_Src;
|
||||
}
|
||||
|
||||
if (stencilNeeded) {
|
||||
subIndex |= 1 << 4;
|
||||
}
|
||||
|
||||
if (renderOptions->isAA) {
|
||||
subIndex |= 1 << 5;
|
||||
}
|
||||
|
||||
if ((composite != nil && FLT_LT([composite getExtraAlpha], 1.0f))) {
|
||||
subIndex |= 1 << 6;
|
||||
}
|
||||
int index = compositeRule*64 + subIndex;
|
||||
|
||||
NSPointerArray * subStates = [self getSubStates:vertexShaderId fragmentShader:fragmentShaderId];
|
||||
|
||||
if (index >= subStates.count) {
|
||||
subStates.count = (NSUInteger) (index + 1);
|
||||
}
|
||||
|
||||
id<MTLRenderPipelineState> result = [subStates pointerAtIndex:index];
|
||||
if (result == nil) {
|
||||
@autoreleasepool {
|
||||
id <MTLFunction> vertexShader = [self getShader:vertexShaderId];
|
||||
id <MTLFunction> fragmentShader = [self getShader:fragmentShaderId];
|
||||
MTLRenderPipelineDescriptor *pipelineDesc = [[pipelineDescriptor copy] autorelease];
|
||||
pipelineDesc.vertexFunction = vertexShader;
|
||||
pipelineDesc.fragmentFunction = fragmentShader;
|
||||
|
||||
if (useXorComposite) {
|
||||
/* The below configuration is the best performant implementation of XOR mode rendering.
|
||||
It was found that it works ONLY for basic Colors and not for all RGB combinations.
|
||||
Hence, a slow performant XOR mode rendering has been implemented by
|
||||
disabling blending & committing after each draw call.
|
||||
In XOR mode rendering, subsequent draw calls are rendered
|
||||
by shader using already rendered framebuffer pixel value XORed
|
||||
with current draw color and XOR color.
|
||||
pipelineDesc.colorAttachments[0].blendingEnabled = YES;
|
||||
pipelineDesc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
||||
pipelineDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOneMinusDestinationColor;
|
||||
pipelineDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceColor;
|
||||
*/
|
||||
|
||||
pipelineDesc.colorAttachments[0].blendingEnabled = NO;
|
||||
} else if (useComposite ||
|
||||
(composite != nil &&
|
||||
FLT_LT([composite getExtraAlpha], 1.0f)))
|
||||
{
|
||||
setBlendingFactors(
|
||||
pipelineDesc.colorAttachments[0],
|
||||
composite,
|
||||
renderOptions
|
||||
);
|
||||
}
|
||||
if (stencilNeeded) {
|
||||
pipelineDesc.stencilAttachmentPixelFormat = MTLPixelFormatStencil8;
|
||||
} else {
|
||||
// We continue to use same encoder when we move from shape clip
|
||||
// to other opcodes. So we need to maintain apprppriate state
|
||||
// for stencilAttachmentPixelFormat until we end the encoder
|
||||
pipelineDesc.stencilAttachmentPixelFormat = MTLPixelFormatInvalid;
|
||||
}
|
||||
|
||||
if (renderOptions->isAA) {
|
||||
pipelineDesc.sampleCount = MTLAASampleCount;
|
||||
pipelineDesc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
||||
pipelineDesc.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
|
||||
pipelineDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;
|
||||
pipelineDesc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
||||
pipelineDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
pipelineDesc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
pipelineDesc.colorAttachments[0].blendingEnabled = YES;
|
||||
}
|
||||
|
||||
NSError *error = nil;
|
||||
result = [[self.device newRenderPipelineStateWithDescriptor:pipelineDesc error:&error] autorelease];
|
||||
if (result == nil) {
|
||||
NSLog(@"Failed to create pipeline state, error %@", error);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
[subStates insertPointer:result atIndex:index];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (id<MTLComputePipelineState>) getComputePipelineState:(NSString *)computeShaderId {
|
||||
id<MTLComputePipelineState> result = computeStates[computeShaderId];
|
||||
if (result == nil) {
|
||||
id <MTLFunction> computeShader = [self getShader:computeShaderId];
|
||||
@autoreleasepool {
|
||||
NSError *error = nil;
|
||||
result = (id <MTLComputePipelineState>) [[self.device newComputePipelineStateWithFunction:computeShader error:&error] autorelease];
|
||||
if (result == nil) {
|
||||
NSLog(@"Failed to create pipeline state, error %@", error);
|
||||
exit(0);
|
||||
}
|
||||
computeStates[computeShaderId] = result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (id<MTLFunction>) getShader:(NSString *)name {
|
||||
id<MTLFunction> result = [self.shaders valueForKey:name];
|
||||
if (result == nil) {
|
||||
result = [[self.library newFunctionWithName:name] autorelease];
|
||||
[self.shaders setValue:result forKey:name];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
[super dealloc];
|
||||
[computeStates release];
|
||||
}
|
||||
@end
|
||||
|
||||
/**
|
||||
* The MTLBlendRule structure encapsulates the two enumerated values that
|
||||
* comprise a given Porter-Duff blending (compositing) rule. For example,
|
||||
* the "SrcOver" rule can be represented by:
|
||||
* rule.src = GL_ONE;
|
||||
* rule.dst = GL_ONE_MINUS_SRC_ALPHA;
|
||||
*
|
||||
* GLenum src;
|
||||
* The constant representing the source factor in this Porter-Duff rule.
|
||||
*
|
||||
* GLenum dst;
|
||||
* The constant representing the destination factor in this Porter-Duff rule.
|
||||
*/
|
||||
struct MTLBlendRule {
|
||||
MTLBlendFactor src;
|
||||
MTLBlendFactor dst;
|
||||
};
|
||||
|
||||
/**
|
||||
* This table contains the standard blending rules (or Porter-Duff compositing
|
||||
* factors) used in setBlendingFactors(), indexed by the rule constants from the
|
||||
* AlphaComposite class.
|
||||
*/
|
||||
static struct MTLBlendRule StdBlendRules[] = {
|
||||
{ MTLBlendFactorZero, MTLBlendFactorZero }, /* 0 - Nothing */
|
||||
{ MTLBlendFactorZero, MTLBlendFactorZero }, /* 1 - RULE_Clear */
|
||||
{ MTLBlendFactorOne, MTLBlendFactorZero }, /* 2 - RULE_Src */
|
||||
{ MTLBlendFactorOne, MTLBlendFactorOneMinusSourceAlpha }, /* 3 - RULE_SrcOver */
|
||||
{ MTLBlendFactorOneMinusDestinationAlpha, MTLBlendFactorOne }, /* 4 - RULE_DstOver */
|
||||
{ MTLBlendFactorDestinationAlpha, MTLBlendFactorZero }, /* 5 - RULE_SrcIn */
|
||||
{ MTLBlendFactorZero, MTLBlendFactorSourceAlpha }, /* 6 - RULE_DstIn */
|
||||
{ MTLBlendFactorOneMinusDestinationAlpha, MTLBlendFactorZero }, /* 7 - RULE_SrcOut */
|
||||
{ MTLBlendFactorZero, MTLBlendFactorOneMinusSourceAlpha }, /* 8 - RULE_DstOut */
|
||||
{ MTLBlendFactorZero, MTLBlendFactorOne }, /* 9 - RULE_Dst */
|
||||
{ MTLBlendFactorDestinationAlpha, MTLBlendFactorOneMinusSourceAlpha }, /*10 - RULE_SrcAtop */
|
||||
{ MTLBlendFactorOneMinusDestinationAlpha, MTLBlendFactorSourceAlpha }, /*11 - RULE_DstAtop */
|
||||
{ MTLBlendFactorOneMinusDestinationAlpha, MTLBlendFactorOneMinusSourceAlpha }, /*12 - RULE_AlphaXor*/
|
||||
};
|
||||
|
||||
static void setBlendingFactors(
|
||||
MTLRenderPipelineColorAttachmentDescriptor * cad,
|
||||
MTLComposite* composite,
|
||||
const RenderOptions * renderOptions
|
||||
) {
|
||||
const long compositeRule = composite != nil ? [composite getRule] : RULE_Src;
|
||||
|
||||
if ((compositeRule == RULE_Src || compositeRule == RULE_SrcOver) &&
|
||||
(composite == nil || FLT_GE([composite getExtraAlpha], 1.0f)) &&
|
||||
(renderOptions->srcFlags.isOpaque))
|
||||
{
|
||||
cad.blendingEnabled = NO;
|
||||
return;
|
||||
}
|
||||
|
||||
cad.blendingEnabled = YES;
|
||||
cad.rgbBlendOperation = MTLBlendOperationAdd;
|
||||
cad.alphaBlendOperation = MTLBlendOperationAdd;
|
||||
|
||||
cad.sourceAlphaBlendFactor = StdBlendRules[compositeRule].src;
|
||||
cad.sourceRGBBlendFactor = StdBlendRules[compositeRule].src;
|
||||
cad.destinationAlphaBlendFactor = StdBlendRules[compositeRule].dst;
|
||||
cad.destinationRGBBlendFactor = StdBlendRules[compositeRule].dst;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLRenderQueue_h_Included
|
||||
#define MTLRenderQueue_h_Included
|
||||
|
||||
#include "MTLContext.h"
|
||||
#include "MTLSurfaceData.h"
|
||||
#include "MTLVertexCache.h"
|
||||
|
||||
/*
|
||||
* The following macros are used to pick values (of the specified type) off
|
||||
* the queue.
|
||||
*/
|
||||
#define NEXT_VAL(buf, type) (((type *)((buf) += sizeof(type)))[-1])
|
||||
#define NEXT_BYTE(buf) NEXT_VAL(buf, unsigned char)
|
||||
#define NEXT_INT(buf) NEXT_VAL(buf, jint)
|
||||
#define NEXT_FLOAT(buf) NEXT_VAL(buf, jfloat)
|
||||
#define NEXT_BOOLEAN(buf) (jboolean)NEXT_INT(buf)
|
||||
#define NEXT_LONG(buf) NEXT_VAL(buf, jlong)
|
||||
#define NEXT_DOUBLE(buf) NEXT_VAL(buf, jdouble)
|
||||
|
||||
// Operations for CheckPreviousOp
|
||||
enum {
|
||||
MTL_OP_INIT,
|
||||
MTL_OP_AA,
|
||||
MTL_OP_SET_COLOR,
|
||||
MTL_OP_RESET_PAINT,
|
||||
MTL_OP_SYNC,
|
||||
MTL_OP_SHAPE_CLIP_SPANS,
|
||||
MTL_OP_MASK_OP,
|
||||
MTL_OP_OTHER
|
||||
};
|
||||
/*
|
||||
* These macros now simply delegate to the CheckPreviousOp() method.
|
||||
*/
|
||||
#define CHECK_PREVIOUS_OP(op) MTLRenderQueue_CheckPreviousOp(op)
|
||||
#define RESET_PREVIOUS_OP() {mtlPreviousOp = MTL_OP_INIT;}
|
||||
|
||||
/*
|
||||
* Increments a pointer (buf) by the given number of bytes.
|
||||
*/
|
||||
#define SKIP_BYTES(buf, numbytes) buf += (numbytes)
|
||||
|
||||
/*
|
||||
* Extracts a value at the given offset from the provided packed value.
|
||||
*/
|
||||
#define EXTRACT_VAL(packedval, offset, mask) \
|
||||
(((packedval) >> (offset)) & (mask))
|
||||
#define EXTRACT_BYTE(packedval, offset) \
|
||||
(unsigned char)EXTRACT_VAL(packedval, offset, 0xff)
|
||||
#define EXTRACT_BOOLEAN(packedval, offset) \
|
||||
(jboolean)EXTRACT_VAL(packedval, offset, 0x1)
|
||||
|
||||
/*
|
||||
* The following macros allow the caller to return (or continue) if the
|
||||
* provided value is NULL. (The strange else clause is included below to
|
||||
* allow for a trailing ';' after RETURN/CONTINUE_IF_NULL() invocations.)
|
||||
*/
|
||||
#define ACT_IF_NULL(ACTION, value) \
|
||||
if ((value) == NULL) { \
|
||||
J2dTraceLn1(J2D_TRACE_ERROR, \
|
||||
"%s is null", #value); \
|
||||
ACTION; \
|
||||
} else do { } while (0)
|
||||
#define RETURN_IF_NULL(value) ACT_IF_NULL(return, value)
|
||||
#define CONTINUE_IF_NULL(value) ACT_IF_NULL(continue, value)
|
||||
|
||||
#define ACT_IF_TRUE(ACTION, value) \
|
||||
if ((value)) { \
|
||||
J2dTraceLn1(J2D_TRACE_ERROR, \
|
||||
"%s is false", #value);\
|
||||
ACTION; \
|
||||
} else do { } while (0)
|
||||
|
||||
#define RETURN_IF_TRUE(value) ACT_IF_TRUE(return, value)
|
||||
|
||||
MTLContext *MTLRenderQueue_GetCurrentContext();
|
||||
BMTLSDOps *MTLRenderQueue_GetCurrentDestination();
|
||||
void commitEncodedCommands();
|
||||
|
||||
extern jint mtlPreviousOp;
|
||||
|
||||
#endif /* MTLRenderQueue_h_Included */
|
||||
@@ -0,0 +1,956 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sun_java2d_pipe_BufferedOpCodes.h"
|
||||
|
||||
#include "jlong.h"
|
||||
#include "MTLBlitLoops.h"
|
||||
#include "MTLBufImgOps.h"
|
||||
#include "MTLMaskBlit.h"
|
||||
#include "MTLMaskFill.h"
|
||||
#include "MTLPaints.h"
|
||||
#include "MTLRenderQueue.h"
|
||||
#include "MTLRenderer.h"
|
||||
#include "MTLTextRenderer.h"
|
||||
#import "ThreadUtilities.h"
|
||||
|
||||
/**
|
||||
* References to the "current" context and destination surface.
|
||||
*/
|
||||
static MTLContext *mtlc = NULL;
|
||||
static BMTLSDOps *dstOps = NULL;
|
||||
jint mtlPreviousOp = MTL_OP_INIT;
|
||||
|
||||
|
||||
/**
|
||||
* The following methods are implemented in the windowing system (i.e. GLX
|
||||
* and WGL) source files.
|
||||
*/
|
||||
extern void MTLGC_DestroyMTLGraphicsConfig(jlong pConfigInfo);
|
||||
|
||||
void MTLRenderQueue_CheckPreviousOp(jint op) {
|
||||
|
||||
if (mtlPreviousOp == op) {
|
||||
// The op is the same as last time, so we can return immediately.
|
||||
return;
|
||||
}
|
||||
|
||||
if (op == MTL_OP_SET_COLOR) {
|
||||
if (mtlPreviousOp != MTL_OP_MASK_OP) {
|
||||
return; // SET_COLOR should not cause endEncoder
|
||||
}
|
||||
} else if (op == MTL_OP_MASK_OP) {
|
||||
MTLVertexCache_EnableMaskCache(mtlc, dstOps);
|
||||
mtlPreviousOp = op;
|
||||
return;
|
||||
}
|
||||
|
||||
J2dTraceLn1(J2D_TRACE_VERBOSE,
|
||||
"MTLRenderQueue_CheckPreviousOp: new op=%d", op);
|
||||
|
||||
switch (mtlPreviousOp) {
|
||||
case MTL_OP_INIT :
|
||||
mtlPreviousOp = op;
|
||||
return;
|
||||
case MTL_OP_MASK_OP :
|
||||
MTLVertexCache_DisableMaskCache(mtlc);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mtlc != NULL) {
|
||||
[mtlc.encoderManager endEncoder];
|
||||
|
||||
if (op == MTL_OP_RESET_PAINT || op == MTL_OP_SYNC || op == MTL_OP_SHAPE_CLIP_SPANS) {
|
||||
MTLCommandBufferWrapper *cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
id <MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
[commandbuf commit];
|
||||
if (op == MTL_OP_SYNC || op == MTL_OP_SHAPE_CLIP_SPANS) {
|
||||
[commandbuf waitUntilCompleted];
|
||||
}
|
||||
}
|
||||
}
|
||||
mtlPreviousOp = op;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
|
||||
(JNIEnv *env, jobject mtlrq,
|
||||
jlong buf, jint limit)
|
||||
{
|
||||
unsigned char *b, *end;
|
||||
|
||||
J2dTraceLn1(J2D_TRACE_INFO,
|
||||
"MTLRenderQueue_flushBuffer: limit=%d", limit);
|
||||
|
||||
b = (unsigned char *)jlong_to_ptr(buf);
|
||||
if (b == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLRenderQueue_flushBuffer: cannot get direct buffer address");
|
||||
return;
|
||||
}
|
||||
|
||||
end = b + limit;
|
||||
@autoreleasepool {
|
||||
while (b < end) {
|
||||
jint opcode = NEXT_INT(b);
|
||||
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE,
|
||||
"MTLRenderQueue_flushBuffer: opcode=%d, rem=%d",
|
||||
opcode, (end-b));
|
||||
|
||||
switch (opcode) {
|
||||
|
||||
// draw ops
|
||||
case sun_java2d_pipe_BufferedOpCodes_DRAW_LINE:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
|
||||
if ([mtlc useXORComposite]) {
|
||||
commitEncodedCommands();
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"DRAW_LINE in XOR mode - Force commit earlier draw calls before DRAW_LINE.");
|
||||
}
|
||||
jint x1 = NEXT_INT(b);
|
||||
jint y1 = NEXT_INT(b);
|
||||
jint x2 = NEXT_INT(b);
|
||||
jint y2 = NEXT_INT(b);
|
||||
MTLRenderer_DrawLine(mtlc, dstOps, x1, y1, x2, y2);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DRAW_RECT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
|
||||
if ([mtlc useXORComposite]) {
|
||||
commitEncodedCommands();
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"DRAW_RECT in XOR mode - Force commit earlier draw calls before DRAW_RECT.");
|
||||
}
|
||||
jint x = NEXT_INT(b);
|
||||
jint y = NEXT_INT(b);
|
||||
jint w = NEXT_INT(b);
|
||||
jint h = NEXT_INT(b);
|
||||
MTLRenderer_DrawRect(mtlc, dstOps, x, y, w, h);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DRAW_POLY:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jint nPoints = NEXT_INT(b);
|
||||
jboolean isClosed = NEXT_BOOLEAN(b);
|
||||
jint transX = NEXT_INT(b);
|
||||
jint transY = NEXT_INT(b);
|
||||
jint *xPoints = (jint *)b;
|
||||
jint *yPoints = ((jint *)b) + nPoints;
|
||||
|
||||
if ([mtlc useXORComposite]) {
|
||||
commitEncodedCommands();
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"DRAW_POLY in XOR mode - Force commit earlier draw calls before DRAW_POLY.");
|
||||
|
||||
// draw separate (N-1) lines using N points
|
||||
for(int point = 0; point < nPoints-1; point++) {
|
||||
jint x1 = xPoints[point] + transX;
|
||||
jint y1 = yPoints[point] + transY;
|
||||
jint x2 = xPoints[point + 1] + transX;
|
||||
jint y2 = yPoints[point + 1] + transY;
|
||||
MTLRenderer_DrawLine(mtlc, dstOps, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
if (isClosed) {
|
||||
MTLRenderer_DrawLine(mtlc, dstOps, xPoints[0] + transX, yPoints[0] + transY,
|
||||
xPoints[nPoints-1] + transX, yPoints[nPoints-1] + transY);
|
||||
}
|
||||
} else {
|
||||
MTLRenderer_DrawPoly(mtlc, dstOps, nPoints, isClosed, transX, transY, xPoints, yPoints);
|
||||
}
|
||||
|
||||
SKIP_BYTES(b, nPoints * BYTES_PER_POLY_POINT);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DRAW_PIXEL:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
|
||||
if ([mtlc useXORComposite]) {
|
||||
commitEncodedCommands();
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"DRAW_PIXEL in XOR mode - Force commit earlier draw calls before DRAW_PIXEL.");
|
||||
}
|
||||
|
||||
jint x = NEXT_INT(b);
|
||||
jint y = NEXT_INT(b);
|
||||
CONTINUE_IF_NULL(mtlc);
|
||||
MTLRenderer_DrawPixel(mtlc, dstOps, x, y);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DRAW_SCANLINES:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
|
||||
if ([mtlc useXORComposite]) {
|
||||
commitEncodedCommands();
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"DRAW_SCANLINES in XOR mode - Force commit earlier draw calls before "
|
||||
"DRAW_SCANLINES.");
|
||||
}
|
||||
|
||||
jint count = NEXT_INT(b);
|
||||
MTLRenderer_DrawScanlines(mtlc, dstOps, count, (jint *)b);
|
||||
|
||||
SKIP_BYTES(b, count * BYTES_PER_SCANLINE);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
|
||||
if ([mtlc useXORComposite]) {
|
||||
commitEncodedCommands();
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"DRAW_PARALLELOGRAM in XOR mode - Force commit earlier draw calls before "
|
||||
"DRAW_PARALLELOGRAM.");
|
||||
}
|
||||
|
||||
jfloat x11 = NEXT_FLOAT(b);
|
||||
jfloat y11 = NEXT_FLOAT(b);
|
||||
jfloat dx21 = NEXT_FLOAT(b);
|
||||
jfloat dy21 = NEXT_FLOAT(b);
|
||||
jfloat dx12 = NEXT_FLOAT(b);
|
||||
jfloat dy12 = NEXT_FLOAT(b);
|
||||
jfloat lwr21 = NEXT_FLOAT(b);
|
||||
jfloat lwr12 = NEXT_FLOAT(b);
|
||||
|
||||
MTLRenderer_DrawParallelogram(mtlc, dstOps,
|
||||
x11, y11,
|
||||
dx21, dy21,
|
||||
dx12, dy12,
|
||||
lwr21, lwr12);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DRAW_AAPARALLELOGRAM:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jfloat x11 = NEXT_FLOAT(b);
|
||||
jfloat y11 = NEXT_FLOAT(b);
|
||||
jfloat dx21 = NEXT_FLOAT(b);
|
||||
jfloat dy21 = NEXT_FLOAT(b);
|
||||
jfloat dx12 = NEXT_FLOAT(b);
|
||||
jfloat dy12 = NEXT_FLOAT(b);
|
||||
jfloat lwr21 = NEXT_FLOAT(b);
|
||||
jfloat lwr12 = NEXT_FLOAT(b);
|
||||
|
||||
MTLRenderer_DrawAAParallelogram(mtlc, dstOps,
|
||||
x11, y11,
|
||||
dx21, dy21,
|
||||
dx12, dy12,
|
||||
lwr21, lwr12);
|
||||
break;
|
||||
}
|
||||
|
||||
// fill ops
|
||||
case sun_java2d_pipe_BufferedOpCodes_FILL_RECT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
|
||||
if ([mtlc useXORComposite]) {
|
||||
commitEncodedCommands();
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"FILL_RECT in XOR mode - Force commit earlier draw calls before FILL_RECT.");
|
||||
}
|
||||
|
||||
jint x = NEXT_INT(b);
|
||||
jint y = NEXT_INT(b);
|
||||
jint w = NEXT_INT(b);
|
||||
jint h = NEXT_INT(b);
|
||||
MTLRenderer_FillRect(mtlc, dstOps, x, y, w, h);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_FILL_SPANS:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
|
||||
if ([mtlc useXORComposite]) {
|
||||
commitEncodedCommands();
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"FILL_SPANS in XOR mode - Force commit earlier draw calls before FILL_SPANS.");
|
||||
}
|
||||
|
||||
jint count = NEXT_INT(b);
|
||||
MTLRenderer_FillSpans(mtlc, dstOps, count, (jint *)b);
|
||||
SKIP_BYTES(b, count * BYTES_PER_SPAN);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
|
||||
if ([mtlc useXORComposite]) {
|
||||
commitEncodedCommands();
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"FILL_PARALLELOGRAM in XOR mode - Force commit earlier draw calls before "
|
||||
"FILL_PARALLELOGRAM.");
|
||||
}
|
||||
|
||||
jfloat x11 = NEXT_FLOAT(b);
|
||||
jfloat y11 = NEXT_FLOAT(b);
|
||||
jfloat dx21 = NEXT_FLOAT(b);
|
||||
jfloat dy21 = NEXT_FLOAT(b);
|
||||
jfloat dx12 = NEXT_FLOAT(b);
|
||||
jfloat dy12 = NEXT_FLOAT(b);
|
||||
MTLRenderer_FillParallelogram(mtlc, dstOps,
|
||||
x11, y11,
|
||||
dx21, dy21,
|
||||
dx12, dy12);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_FILL_AAPARALLELOGRAM:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jfloat x11 = NEXT_FLOAT(b);
|
||||
jfloat y11 = NEXT_FLOAT(b);
|
||||
jfloat dx21 = NEXT_FLOAT(b);
|
||||
jfloat dy21 = NEXT_FLOAT(b);
|
||||
jfloat dx12 = NEXT_FLOAT(b);
|
||||
jfloat dy12 = NEXT_FLOAT(b);
|
||||
MTLRenderer_FillAAParallelogram(mtlc, dstOps,
|
||||
x11, y11,
|
||||
dx21, dy21,
|
||||
dx12, dy12);
|
||||
break;
|
||||
}
|
||||
|
||||
// text-related ops
|
||||
case sun_java2d_pipe_BufferedOpCodes_DRAW_GLYPH_LIST:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
|
||||
if ([mtlc useXORComposite]) {
|
||||
commitEncodedCommands();
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"DRAW_GLYPH_LIST in XOR mode - Force commit earlier draw calls before "
|
||||
"DRAW_GLYPH_LIST.");
|
||||
}
|
||||
|
||||
jint numGlyphs = NEXT_INT(b);
|
||||
jint packedParams = NEXT_INT(b);
|
||||
jfloat glyphListOrigX = NEXT_FLOAT(b);
|
||||
jfloat glyphListOrigY = NEXT_FLOAT(b);
|
||||
jboolean usePositions = EXTRACT_BOOLEAN(packedParams,
|
||||
OFFSET_POSITIONS);
|
||||
jboolean subPixPos = EXTRACT_BOOLEAN(packedParams,
|
||||
OFFSET_SUBPIXPOS);
|
||||
jboolean rgbOrder = EXTRACT_BOOLEAN(packedParams,
|
||||
OFFSET_RGBORDER);
|
||||
jint lcdContrast = EXTRACT_BYTE(packedParams,
|
||||
OFFSET_CONTRAST);
|
||||
unsigned char *images = b;
|
||||
unsigned char *positions;
|
||||
jint bytesPerGlyph;
|
||||
if (usePositions) {
|
||||
positions = (b + numGlyphs * BYTES_PER_GLYPH_IMAGE);
|
||||
bytesPerGlyph = BYTES_PER_POSITIONED_GLYPH;
|
||||
} else {
|
||||
positions = NULL;
|
||||
bytesPerGlyph = BYTES_PER_GLYPH_IMAGE;
|
||||
}
|
||||
MTLTR_DrawGlyphList(env, mtlc, dstOps,
|
||||
numGlyphs, usePositions,
|
||||
subPixPos, rgbOrder, lcdContrast,
|
||||
glyphListOrigX, glyphListOrigY,
|
||||
images, positions);
|
||||
SKIP_BYTES(b, numGlyphs * bytesPerGlyph);
|
||||
break;
|
||||
}
|
||||
|
||||
// copy-related ops
|
||||
case sun_java2d_pipe_BufferedOpCodes_COPY_AREA:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jint x = NEXT_INT(b);
|
||||
jint y = NEXT_INT(b);
|
||||
jint w = NEXT_INT(b);
|
||||
jint h = NEXT_INT(b);
|
||||
jint dx = NEXT_INT(b);
|
||||
jint dy = NEXT_INT(b);
|
||||
MTLBlitLoops_CopyArea(env, mtlc, dstOps,
|
||||
x, y, w, h, dx, dy);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_BLIT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jint packedParams = NEXT_INT(b);
|
||||
jint sx1 = NEXT_INT(b);
|
||||
jint sy1 = NEXT_INT(b);
|
||||
jint sx2 = NEXT_INT(b);
|
||||
jint sy2 = NEXT_INT(b);
|
||||
jdouble dx1 = NEXT_DOUBLE(b);
|
||||
jdouble dy1 = NEXT_DOUBLE(b);
|
||||
jdouble dx2 = NEXT_DOUBLE(b);
|
||||
jdouble dy2 = NEXT_DOUBLE(b);
|
||||
jlong pSrc = NEXT_LONG(b);
|
||||
jlong pDst = NEXT_LONG(b);
|
||||
jint hint = EXTRACT_BYTE(packedParams, OFFSET_HINT);
|
||||
jboolean texture = EXTRACT_BOOLEAN(packedParams,
|
||||
OFFSET_TEXTURE);
|
||||
jboolean xform = EXTRACT_BOOLEAN(packedParams,
|
||||
OFFSET_XFORM);
|
||||
jboolean isoblit = EXTRACT_BOOLEAN(packedParams,
|
||||
OFFSET_ISOBLIT);
|
||||
if (isoblit) {
|
||||
MTLBlitLoops_IsoBlit(env, mtlc, pSrc, pDst,
|
||||
xform, hint, texture,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2);
|
||||
} else {
|
||||
jint srctype = EXTRACT_BYTE(packedParams, OFFSET_SRCTYPE);
|
||||
MTLBlitLoops_Blit(env, mtlc, pSrc, pDst,
|
||||
xform, hint, srctype, texture,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SURFACE_TO_SW_BLIT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jint sx = NEXT_INT(b);
|
||||
jint sy = NEXT_INT(b);
|
||||
jint dx = NEXT_INT(b);
|
||||
jint dy = NEXT_INT(b);
|
||||
jint w = NEXT_INT(b);
|
||||
jint h = NEXT_INT(b);
|
||||
jint dsttype = NEXT_INT(b);
|
||||
jlong pSrc = NEXT_LONG(b);
|
||||
jlong pDst = NEXT_LONG(b);
|
||||
MTLBlitLoops_SurfaceToSwBlit(env, mtlc,
|
||||
pSrc, pDst, dsttype,
|
||||
sx, sy, dx, dy, w, h);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_MASK_FILL:
|
||||
{
|
||||
jint x = NEXT_INT(b);
|
||||
jint y = NEXT_INT(b);
|
||||
jint w = NEXT_INT(b);
|
||||
jint h = NEXT_INT(b);
|
||||
jint maskoff = NEXT_INT(b);
|
||||
jint maskscan = NEXT_INT(b);
|
||||
jint masklen = NEXT_INT(b);
|
||||
unsigned char *pMask = (masklen > 0) ? b : NULL;
|
||||
if (mtlc == nil)
|
||||
return;
|
||||
CHECK_PREVIOUS_OP(MTL_OP_MASK_OP);
|
||||
MTLMaskFill_MaskFill(mtlc, dstOps, x, y, w, h,
|
||||
maskoff, maskscan, masklen, pMask);
|
||||
SKIP_BYTES(b, masklen);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_MASK_BLIT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jint dstx = NEXT_INT(b);
|
||||
jint dsty = NEXT_INT(b);
|
||||
jint width = NEXT_INT(b);
|
||||
jint height = NEXT_INT(b);
|
||||
jint masklen = width * height * sizeof(jint);
|
||||
MTLMaskBlit_MaskBlit(env, mtlc, dstOps,
|
||||
dstx, dsty, width, height, b);
|
||||
SKIP_BYTES(b, masklen);
|
||||
break;
|
||||
}
|
||||
|
||||
// state-related ops
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_RECT_CLIP:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jint x1 = NEXT_INT(b);
|
||||
jint y1 = NEXT_INT(b);
|
||||
jint x2 = NEXT_INT(b);
|
||||
jint y2 = NEXT_INT(b);
|
||||
[mtlc setClipRectX1:x1 Y1:y1 X2:x2 Y2:y2];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_BEGIN_SHAPE_CLIP:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
[mtlc beginShapeClip:dstOps];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_SHAPE_CLIP_SPANS:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_SHAPE_CLIP_SPANS);
|
||||
// This results in creation of new render encoder with
|
||||
// stencil buffer set as render target
|
||||
jint count = NEXT_INT(b);
|
||||
MTLRenderer_FillSpans(mtlc, dstOps, count, (jint *)b);
|
||||
SKIP_BYTES(b, count * BYTES_PER_SPAN);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_END_SHAPE_CLIP:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
[mtlc endShapeClip:dstOps];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_RESET_CLIP:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
[mtlc resetClip];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_ALPHA_COMPOSITE:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jint rule = NEXT_INT(b);
|
||||
jfloat extraAlpha = NEXT_FLOAT(b);
|
||||
jint flags = NEXT_INT(b);
|
||||
[mtlc setAlphaCompositeRule:rule extraAlpha:extraAlpha flags:flags];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_XOR_COMPOSITE:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jint xorPixel = NEXT_INT(b);
|
||||
[mtlc setXorComposite:xorPixel];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_RESET_COMPOSITE:
|
||||
{
|
||||
/* TODO: check whether something needs to be done here if we are moving out of XOR composite
|
||||
commitEncodedCommands();
|
||||
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
[cbwrapper onComplete];
|
||||
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE,
|
||||
"RESET_COMPOSITE - Force commit earlier draw calls before RESET_COMPOSITE.");*/
|
||||
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
[mtlc resetComposite];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_TRANSFORM:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jdouble m00 = NEXT_DOUBLE(b);
|
||||
jdouble m10 = NEXT_DOUBLE(b);
|
||||
jdouble m01 = NEXT_DOUBLE(b);
|
||||
jdouble m11 = NEXT_DOUBLE(b);
|
||||
jdouble m02 = NEXT_DOUBLE(b);
|
||||
jdouble m12 = NEXT_DOUBLE(b);
|
||||
[mtlc setTransformM00:m00 M10:m10 M01:m01 M11:m11 M02:m02 M12:m12];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_RESET_TRANSFORM:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
[mtlc resetTransform];
|
||||
break;
|
||||
}
|
||||
|
||||
// context-related ops
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_SURFACES:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jlong pSrc = NEXT_LONG(b);
|
||||
jlong pDst = NEXT_LONG(b);
|
||||
|
||||
if (mtlc != NULL) {
|
||||
[mtlc.encoderManager endEncoder];
|
||||
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
[commandbuf commit];
|
||||
}
|
||||
mtlc = [MTLContext setSurfacesEnv:env src:pSrc dst:pDst];
|
||||
dstOps = (BMTLSDOps *)jlong_to_ptr(pDst);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_SCRATCH_SURFACE:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jlong pConfigInfo = NEXT_LONG(b);
|
||||
MTLGraphicsConfigInfo *mtlInfo =
|
||||
(MTLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
|
||||
|
||||
if (mtlInfo == NULL) {
|
||||
|
||||
} else {
|
||||
MTLContext *newMtlc = mtlInfo->context;
|
||||
if (newMtlc == NULL) {
|
||||
|
||||
} else {
|
||||
if (mtlc != NULL) {
|
||||
[mtlc.encoderManager endEncoder];
|
||||
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
[commandbuf commit];
|
||||
}
|
||||
mtlc = newMtlc;
|
||||
dstOps = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_FLUSH_SURFACE:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jlong pData = NEXT_LONG(b);
|
||||
BMTLSDOps *mtlsdo = (BMTLSDOps *)jlong_to_ptr(pData);
|
||||
if (mtlsdo != NULL) {
|
||||
CONTINUE_IF_NULL(mtlc);
|
||||
MTLTR_FreeGlyphCaches();
|
||||
MTLSD_Delete(env, mtlsdo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DISPOSE_SURFACE:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jlong pData = NEXT_LONG(b);
|
||||
BMTLSDOps *mtlsdo = (BMTLSDOps *)jlong_to_ptr(pData);
|
||||
if (mtlsdo != NULL) {
|
||||
CONTINUE_IF_NULL(mtlc);
|
||||
MTLSD_Delete(env, mtlsdo);
|
||||
if (mtlsdo->privOps != NULL) {
|
||||
free(mtlsdo->privOps);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DISPOSE_CONFIG:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jlong pConfigInfo = NEXT_LONG(b);
|
||||
CONTINUE_IF_NULL(mtlc);
|
||||
|
||||
if (mtlc != NULL) {
|
||||
[mtlc.encoderManager endEncoder];
|
||||
}
|
||||
|
||||
MTLGC_DestroyMTLGraphicsConfig(pConfigInfo);
|
||||
|
||||
mtlc = NULL;
|
||||
// dstOps = NULL;
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_INVALIDATE_CONTEXT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
// invalidate the references to the current context and
|
||||
// destination surface that are maintained at the native level
|
||||
if (mtlc != NULL) {
|
||||
commitEncodedCommands();
|
||||
RESET_PREVIOUS_OP();
|
||||
[mtlc reset];
|
||||
}
|
||||
|
||||
MTLTR_FreeGlyphCaches();
|
||||
if (dstOps != NULL) {
|
||||
MTLSD_Delete(env, dstOps);
|
||||
}
|
||||
|
||||
mtlc = NULL;
|
||||
dstOps = NULL;
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SYNC:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_SYNC);
|
||||
break;
|
||||
}
|
||||
|
||||
// special no-op (mainly used for achieving 8-byte alignment)
|
||||
case sun_java2d_pipe_BufferedOpCodes_NOOP:
|
||||
break;
|
||||
|
||||
// paint-related ops
|
||||
case sun_java2d_pipe_BufferedOpCodes_RESET_PAINT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_RESET_PAINT);
|
||||
[mtlc resetPaint];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_COLOR:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_SET_COLOR);
|
||||
jint pixel = NEXT_INT(b);
|
||||
[mtlc setColorPaint:pixel];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_GRADIENT_PAINT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jboolean useMask= NEXT_BOOLEAN(b);
|
||||
jboolean cyclic = NEXT_BOOLEAN(b);
|
||||
jdouble p0 = NEXT_DOUBLE(b);
|
||||
jdouble p1 = NEXT_DOUBLE(b);
|
||||
jdouble p3 = NEXT_DOUBLE(b);
|
||||
jint pixel1 = NEXT_INT(b);
|
||||
jint pixel2 = NEXT_INT(b);
|
||||
[mtlc setGradientPaintUseMask:useMask
|
||||
cyclic:cyclic
|
||||
p0:p0
|
||||
p1:p1
|
||||
p3:p3
|
||||
pixel1:pixel1
|
||||
pixel2:pixel2];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_LINEAR_GRADIENT_PAINT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jboolean useMask = NEXT_BOOLEAN(b);
|
||||
jboolean linear = NEXT_BOOLEAN(b);
|
||||
jint cycleMethod = NEXT_INT(b);
|
||||
jint numStops = NEXT_INT(b);
|
||||
jfloat p0 = NEXT_FLOAT(b);
|
||||
jfloat p1 = NEXT_FLOAT(b);
|
||||
jfloat p3 = NEXT_FLOAT(b);
|
||||
void *fractions, *pixels;
|
||||
fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat));
|
||||
pixels = b; SKIP_BYTES(b, numStops * sizeof(jint));
|
||||
[mtlc setLinearGradientPaint:useMask
|
||||
linear:linear
|
||||
cycleMethod:cycleMethod
|
||||
numStops:numStops
|
||||
p0:p0
|
||||
p1:p1
|
||||
p3:p3
|
||||
fractions:fractions
|
||||
pixels:pixels];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_RADIAL_GRADIENT_PAINT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jboolean useMask = NEXT_BOOLEAN(b);
|
||||
jboolean linear = NEXT_BOOLEAN(b);
|
||||
jint numStops = NEXT_INT(b);
|
||||
jint cycleMethod = NEXT_INT(b);
|
||||
jfloat m00 = NEXT_FLOAT(b);
|
||||
jfloat m01 = NEXT_FLOAT(b);
|
||||
jfloat m02 = NEXT_FLOAT(b);
|
||||
jfloat m10 = NEXT_FLOAT(b);
|
||||
jfloat m11 = NEXT_FLOAT(b);
|
||||
jfloat m12 = NEXT_FLOAT(b);
|
||||
jfloat focusX = NEXT_FLOAT(b);
|
||||
void *fractions, *pixels;
|
||||
fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat));
|
||||
pixels = b; SKIP_BYTES(b, numStops * sizeof(jint));
|
||||
[mtlc setRadialGradientPaint:useMask
|
||||
linear:linear
|
||||
cycleMethod:cycleMethod
|
||||
numStops:numStops
|
||||
m00:m00
|
||||
m01:m01
|
||||
m02:m02
|
||||
m10:m10
|
||||
m11:m11
|
||||
m12:m12
|
||||
focusX:focusX
|
||||
fractions:fractions
|
||||
pixels:pixels];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_TEXTURE_PAINT:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jboolean useMask= NEXT_BOOLEAN(b);
|
||||
jboolean filter = NEXT_BOOLEAN(b);
|
||||
jlong pSrc = NEXT_LONG(b);
|
||||
jdouble xp0 = NEXT_DOUBLE(b);
|
||||
jdouble xp1 = NEXT_DOUBLE(b);
|
||||
jdouble xp3 = NEXT_DOUBLE(b);
|
||||
jdouble yp0 = NEXT_DOUBLE(b);
|
||||
jdouble yp1 = NEXT_DOUBLE(b);
|
||||
jdouble yp3 = NEXT_DOUBLE(b);
|
||||
[mtlc setTexturePaint:useMask
|
||||
pSrcOps:pSrc
|
||||
filter:filter
|
||||
xp0:xp0
|
||||
xp1:xp1
|
||||
xp3:xp3
|
||||
yp0:yp0
|
||||
yp1:yp1
|
||||
yp3:yp3];
|
||||
break;
|
||||
}
|
||||
|
||||
// BufferedImageOp-related ops
|
||||
case sun_java2d_pipe_BufferedOpCodes_ENABLE_CONVOLVE_OP:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jlong pSrc = NEXT_LONG(b);
|
||||
jboolean edgeZero = NEXT_BOOLEAN(b);
|
||||
jint kernelWidth = NEXT_INT(b);
|
||||
jint kernelHeight = NEXT_INT(b);
|
||||
|
||||
BMTLSDOps * bmtlsdOps = (BMTLSDOps *)pSrc;
|
||||
MTLConvolveOp * convolveOp = [[MTLConvolveOp alloc] init:edgeZero
|
||||
kernelWidth:kernelWidth
|
||||
kernelHeight:kernelHeight
|
||||
srcWidth:bmtlsdOps->width
|
||||
srcHeight:bmtlsdOps->height
|
||||
kernel:b
|
||||
device:mtlc.device
|
||||
];
|
||||
[mtlc setBufImgOp:convolveOp];
|
||||
SKIP_BYTES(b, kernelWidth * kernelHeight * sizeof(jfloat));
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DISABLE_CONVOLVE_OP:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
[mtlc setBufImgOp:NULL];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_ENABLE_RESCALE_OP:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jlong pSrc = NEXT_LONG(b);
|
||||
jboolean nonPremult = NEXT_BOOLEAN(b);
|
||||
jint numFactors = 4;
|
||||
unsigned char *scaleFactors = b;
|
||||
unsigned char *offsets = (b + numFactors * sizeof(jfloat));
|
||||
MTLRescaleOp * rescaleOp =
|
||||
[[MTLRescaleOp alloc] init:nonPremult factors:scaleFactors offsets:offsets];
|
||||
[mtlc setBufImgOp:rescaleOp];
|
||||
SKIP_BYTES(b, numFactors * sizeof(jfloat) * 2);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DISABLE_RESCALE_OP:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
[mtlc setBufImgOp:NULL];
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_ENABLE_LOOKUP_OP:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jlong pSrc = NEXT_LONG(b);
|
||||
jboolean nonPremult = NEXT_BOOLEAN(b);
|
||||
jboolean shortData = NEXT_BOOLEAN(b);
|
||||
jint numBands = NEXT_INT(b);
|
||||
jint bandLength = NEXT_INT(b);
|
||||
jint offset = NEXT_INT(b);
|
||||
jint bytesPerElem = shortData ? sizeof(jshort):sizeof(jbyte);
|
||||
void *tableValues = b;
|
||||
|
||||
MTLLookupOp * lookupOp = [[MTLLookupOp alloc] init:nonPremult
|
||||
shortData:shortData
|
||||
numBands:numBands
|
||||
bandLength:bandLength
|
||||
offset:offset
|
||||
tableValues:tableValues
|
||||
device:mtlc.device];
|
||||
[mtlc setBufImgOp:lookupOp];
|
||||
SKIP_BYTES(b, numBands * bandLength * bytesPerElem);
|
||||
break;
|
||||
}
|
||||
case sun_java2d_pipe_BufferedOpCodes_DISABLE_LOOKUP_OP:
|
||||
{
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
[mtlc setBufImgOp:NULL];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
J2dRlsTraceLn1(J2D_TRACE_ERROR,
|
||||
"MTLRenderQueue_flushBuffer: invalid opcode=%d", opcode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mtlc != NULL) {
|
||||
if (mtlPreviousOp == MTL_OP_MASK_OP) {
|
||||
MTLVertexCache_DisableMaskCache(mtlc);
|
||||
}
|
||||
[mtlc.encoderManager endEncoder];
|
||||
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
[commandbuf commit];
|
||||
BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();
|
||||
if (dstOps != NULL) {
|
||||
MTLSDOps *dstMTLOps = (MTLSDOps *)dstOps->privOps;
|
||||
MTLLayer *layer = (MTLLayer*)dstMTLOps->layer;
|
||||
if (layer != NULL) {
|
||||
[layer startDisplayLink];
|
||||
}
|
||||
}
|
||||
}
|
||||
RESET_PREVIOUS_OP();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the "current" context, as set by the last SET_SURFACES
|
||||
* or SET_SCRATCH_SURFACE operation.
|
||||
*/
|
||||
MTLContext *
|
||||
MTLRenderQueue_GetCurrentContext()
|
||||
{
|
||||
return mtlc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the "current" destination surface, as set by the last
|
||||
* SET_SURFACES operation.
|
||||
*/
|
||||
BMTLSDOps *
|
||||
MTLRenderQueue_GetCurrentDestination()
|
||||
{
|
||||
return dstOps;
|
||||
}
|
||||
|
||||
/**
|
||||
* commit earlier encoded commmands
|
||||
* these would be rendered to the back-buffer - which is read in shader while rendering in XOR mode
|
||||
*/
|
||||
void commitEncodedCommands() {
|
||||
[mtlc.encoderManager endEncoder];
|
||||
|
||||
MTLCommandBufferWrapper *cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
id <MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
[commandbuf commit];
|
||||
[commandbuf waitUntilCompleted];
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLRenderer_h_Included
|
||||
#define MTLRenderer_h_Included
|
||||
|
||||
#include "sun_java2d_pipe_BufferedRenderPipe.h"
|
||||
#include "MTLContext.h"
|
||||
#include "MTLGraphicsConfig.h"
|
||||
#import "MTLLayer.h"
|
||||
|
||||
#define BYTES_PER_POLY_POINT \
|
||||
sun_java2d_pipe_BufferedRenderPipe_BYTES_PER_POLY_POINT
|
||||
#define BYTES_PER_SCANLINE \
|
||||
sun_java2d_pipe_BufferedRenderPipe_BYTES_PER_SCANLINE
|
||||
#define BYTES_PER_SPAN \
|
||||
sun_java2d_pipe_BufferedRenderPipe_BYTES_PER_SPAN
|
||||
|
||||
void MTLRenderer_DrawLine(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint x1, jint y1, jint x2, jint y2);
|
||||
void MTLRenderer_DrawPixel(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint x, jint y);
|
||||
void MTLRenderer_DrawRect(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint x, jint y, jint w, jint h);
|
||||
void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint nPoints, jint isClosed,
|
||||
jint transX, jint transY,
|
||||
jint *xPoints, jint *yPoints);
|
||||
void MTLRenderer_DrawScanlines(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint count, jint *scanlines);
|
||||
void MTLRenderer_DrawParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jfloat fx11, jfloat fy11,
|
||||
jfloat dx21, jfloat dy21,
|
||||
jfloat dx12, jfloat dy12,
|
||||
jfloat lw21, jfloat lw12);
|
||||
void MTLRenderer_DrawAAParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jfloat fx11, jfloat fy11,
|
||||
jfloat dx21, jfloat dy21,
|
||||
jfloat dx12, jfloat dy12,
|
||||
jfloat lw21, jfloat lw12);
|
||||
void MTLRenderer_FillRect(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint x, jint y, jint w, jint h);
|
||||
void MTLRenderer_FillSpans(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint count, jint *spans);
|
||||
void MTLRenderer_FillParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jfloat fx11, jfloat fy11,
|
||||
jfloat dx21, jfloat dy21,
|
||||
jfloat dx12, jfloat dy12);
|
||||
void MTLRenderer_FillAAParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jfloat fx11, jfloat fy11,
|
||||
jfloat dx21, jfloat dy21,
|
||||
jfloat dx12, jfloat dy12);
|
||||
|
||||
#endif /* MTLRenderer_h_Included */
|
||||
@@ -0,0 +1,961 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <jlong.h>
|
||||
#include <jni_util.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sun_java2d_metal_MTLRenderer.h"
|
||||
|
||||
#include "MTLRenderer.h"
|
||||
#include "MTLRenderQueue.h"
|
||||
#include "MTLSurfaceData.h"
|
||||
#include "MTLUtils.h"
|
||||
#import "MTLLayer.h"
|
||||
|
||||
/**
|
||||
* Note: Some of the methods in this file apply a "magic number"
|
||||
* translation to line segments. It is same as what we have in
|
||||
* OGLrenderer.
|
||||
*
|
||||
* The "magic numbers" you see here have been empirically derived
|
||||
* after testing on a variety of graphics hardware in order to find some
|
||||
* reasonable middle ground between the two specifications. The general
|
||||
* approach is to apply a fractional translation to vertices so that they
|
||||
* hit pixel centers and therefore touch the same pixels as in our other
|
||||
* pipelines. Emphasis was placed on finding values so that MTL lines with
|
||||
* a slope of +/- 1 hit all the same pixels as our other (software) loops.
|
||||
* The stepping in other diagonal lines rendered with MTL may deviate
|
||||
* slightly from those rendered with our software loops, but the most
|
||||
* important thing is that these magic numbers ensure that all MTL lines
|
||||
* hit the same endpoints as our software loops.
|
||||
*
|
||||
* If you find it necessary to change any of these magic numbers in the
|
||||
* future, just be sure that you test the changes across a variety of
|
||||
* hardware to ensure consistent rendering everywhere.
|
||||
*/
|
||||
|
||||
void MTLRenderer_DrawLine(MTLContext *mtlc, BMTLSDOps * dstOps, jint x1, jint y1, jint x2, jint y2) {
|
||||
if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawLine: dest is null");
|
||||
return;
|
||||
}
|
||||
|
||||
J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_DrawLine (x1=%d y1=%d x2=%d y2=%d), dst tex=%p", x1, y1, x2, y2, dstOps->pTexture);
|
||||
|
||||
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
|
||||
if (mtlEncoder == nil)
|
||||
return;
|
||||
|
||||
// DrawLine implementation same as in OGLRenderer.c
|
||||
struct Vertex verts[2];
|
||||
if (y1 == y2) {
|
||||
// horizontal
|
||||
float fx1 = (float)x1;
|
||||
float fx2 = (float)x2;
|
||||
float fy = ((float)y1) + 0.2f;
|
||||
|
||||
if (x1 > x2) {
|
||||
float t = fx1; fx1 = fx2; fx2 = t;
|
||||
}
|
||||
|
||||
verts[0].position[0] = fx1 + 0.2f;
|
||||
verts[0].position[1] = fy;
|
||||
verts[1].position[0] = fx2 + 1.2f;
|
||||
verts[1].position[1] = fy;
|
||||
} else if (x1 == x2) {
|
||||
// vertical
|
||||
float fx = ((float)x1) + 0.2f;
|
||||
float fy1 = (float)y1;
|
||||
float fy2 = (float)y2;
|
||||
|
||||
if (y1 > y2) {
|
||||
float t = fy1; fy1 = fy2; fy2 = t;
|
||||
}
|
||||
|
||||
verts[0].position[0] = fx;
|
||||
verts[0].position[1] = fy1 + 0.2f;
|
||||
verts[1].position[0] = fx;
|
||||
verts[1].position[1] = fy2 + 1.2f;
|
||||
} else {
|
||||
// diagonal
|
||||
float fx1 = (float)x1;
|
||||
float fy1 = (float)y1;
|
||||
float fx2 = (float)x2;
|
||||
float fy2 = (float)y2;
|
||||
|
||||
if (x1 < x2) {
|
||||
fx1 += 0.2f;
|
||||
fx2 += 1.0f;
|
||||
} else {
|
||||
fx1 += 0.8f;
|
||||
fx2 -= 0.2f;
|
||||
}
|
||||
|
||||
if (y1 < y2) {
|
||||
fy1 += 0.2f;
|
||||
fy2 += 1.0f;
|
||||
} else {
|
||||
fy1 += 0.8f;
|
||||
fy2 -= 0.2f;
|
||||
}
|
||||
verts[0].position[0] = fx1;
|
||||
verts[0].position[1] = fy1;
|
||||
verts[1].position[0] = fx2;
|
||||
verts[1].position[1] = fy2;
|
||||
}
|
||||
|
||||
[mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0 vertexCount:2];
|
||||
}
|
||||
|
||||
void MTLRenderer_DrawPixel(MTLContext *mtlc, BMTLSDOps * dstOps, jint x, jint y) {
|
||||
if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawPixel: dest is null");
|
||||
return;
|
||||
}
|
||||
|
||||
id<MTLTexture> dest = dstOps->pTexture;
|
||||
J2dTraceLn3(J2D_TRACE_INFO, "MTLRenderer_DrawPixel (x=%d y=%d), dst tex=%p", x, y, dest);
|
||||
|
||||
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
|
||||
if (mtlEncoder == nil)
|
||||
return;
|
||||
|
||||
// Translate each vertex by a fraction so
|
||||
// that we hit pixel centers.
|
||||
float fx = (float)x + 0.2f;
|
||||
float fy = (float)y + 0.5f;
|
||||
struct Vertex vert = {{fx, fy}};
|
||||
[mtlEncoder setVertexBytes:&vert length:sizeof(vert) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypePoint vertexStart:0 vertexCount:1];
|
||||
}
|
||||
|
||||
void MTLRenderer_DrawRect(MTLContext *mtlc, BMTLSDOps * dstOps, jint x, jint y, jint w, jint h) {
|
||||
if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawRect: dest is null");
|
||||
return;
|
||||
}
|
||||
|
||||
id<MTLTexture> dest = dstOps->pTexture;
|
||||
J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_DrawRect (x=%d y=%d w=%d h=%d), dst tex=%p", x, y, w, h, dest);
|
||||
|
||||
// TODO: use DrawParallelogram(x, y, w, h, lw=1, lh=1)
|
||||
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
|
||||
if (mtlEncoder == nil)
|
||||
return;
|
||||
|
||||
// Translate each vertex by a fraction so
|
||||
// that we hit pixel centers.
|
||||
const int verticesCount = 5;
|
||||
float fx = (float)x + 0.2f;
|
||||
float fy = (float)y + 0.5f;
|
||||
float fw = (float)w;
|
||||
float fh = (float)h;
|
||||
struct Vertex vertices[5] = {
|
||||
{{fx, fy}},
|
||||
{{fx + fw, fy}},
|
||||
{{fx + fw, fy + fh}},
|
||||
{{fx, fy + fh}},
|
||||
{{fx, fy}},
|
||||
};
|
||||
[mtlEncoder setVertexBytes:vertices length:sizeof(vertices) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeLineStrip vertexStart:0 vertexCount:verticesCount];
|
||||
}
|
||||
|
||||
const int POLYLINE_BUF_SIZE = 64;
|
||||
|
||||
NS_INLINE void fillVertex(struct Vertex * vertex, int x, int y) {
|
||||
vertex->position[0] = x;
|
||||
vertex->position[1] = y;
|
||||
}
|
||||
|
||||
void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint nPoints, jint isClosed,
|
||||
jint transX, jint transY,
|
||||
jint *xPoints, jint *yPoints)
|
||||
{
|
||||
// Note that BufferedRenderPipe.drawPoly() has already rejected polys
|
||||
// with nPoints<2, so we can be certain here that we have nPoints>=2.
|
||||
if (xPoints == NULL || yPoints == NULL || nPoints < 2) { // just for insurance
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawPoly: points array is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawPoly: dest is null");
|
||||
return;
|
||||
}
|
||||
|
||||
J2dTraceLn4(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: %d points, transX=%d, transY=%d, dst tex=%p", nPoints, transX, transY, dstOps->pTexture);
|
||||
|
||||
__block struct {
|
||||
struct Vertex verts[POLYLINE_BUF_SIZE];
|
||||
} pointsChunk;
|
||||
|
||||
// We intend to submit draw commands in batches of POLYLINE_BUF_SIZE vertices at a time
|
||||
// Subsequent batches need to be connected - so end point in one batch is repeated as first point in subsequent batch
|
||||
// This inflates the total number of points by a factor of number of batches of size POLYLINE_BUF_SIZE
|
||||
nPoints += (nPoints/POLYLINE_BUF_SIZE);
|
||||
|
||||
jint prevX = *(xPoints++);
|
||||
jint prevY = *(yPoints++);
|
||||
const jint firstX = prevX;
|
||||
const jint firstY = prevY;
|
||||
while (nPoints > 0) {
|
||||
const bool isLastChunk = nPoints <= POLYLINE_BUF_SIZE;
|
||||
__block int chunkSize = isLastChunk ? nPoints : POLYLINE_BUF_SIZE;
|
||||
|
||||
fillVertex(pointsChunk.verts, prevX + transX + 0.5f, prevY + transY + 0.5f);
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: Point - (%1.2f, %1.2f)", prevX + transX + 0.5f, prevY + transY + 0.5f);
|
||||
|
||||
for (int i = 1; i < chunkSize; i++) {
|
||||
prevX = *(xPoints++);
|
||||
prevY = *(yPoints++);
|
||||
fillVertex(pointsChunk.verts + i, prevX + transX + 0.5f, prevY + transY + 0.5f);
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: Point - (%1.2f, %1.2f)", prevX + transX + 0.5f,prevY + transY + 0.5f);
|
||||
}
|
||||
|
||||
bool drawCloseSegment = false;
|
||||
if (isClosed && isLastChunk) {
|
||||
if (chunkSize + 2 <= POLYLINE_BUF_SIZE) {
|
||||
fillVertex(pointsChunk.verts + chunkSize, firstX + transX + 0.5f, firstY + transY + 0.5f);
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: Point - (%1.2f, %1.2f)",firstX + transX + 0.5f, firstY + transY + 0.5f);
|
||||
|
||||
++chunkSize;
|
||||
} else
|
||||
drawCloseSegment = true;
|
||||
}
|
||||
|
||||
nPoints -= chunkSize;
|
||||
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
|
||||
if (mtlEncoder == nil)
|
||||
return;
|
||||
|
||||
[mtlEncoder setVertexBytes:pointsChunk.verts length:sizeof(pointsChunk.verts) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeLineStrip vertexStart:0 vertexCount:chunkSize];
|
||||
|
||||
if (drawCloseSegment) {
|
||||
struct Vertex vertices[2] = {
|
||||
{{prevX + transX + 0.5f, prevY + transY + 0.5f}},
|
||||
{{firstX + transX + 0.5f, firstY + transY + 0.5f}}
|
||||
};
|
||||
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: last segment Point1 - (%1.2f, %1.2f)",prevX + transX + 0.5f, prevY + transY + 0.5f);
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: last segment Point2 - (%1.2f, %1.2f)",firstX + transX + 0.5f, firstY + transY + 0.5f);
|
||||
|
||||
[mtlEncoder setVertexBytes:vertices length:sizeof(vertices) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0 vertexCount:2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLRenderer_drawPoly
|
||||
(JNIEnv *env, jobject mtlr,
|
||||
jintArray xpointsArray, jintArray ypointsArray,
|
||||
jint nPoints, jboolean isClosed,
|
||||
jint transX, jint transY)
|
||||
{
|
||||
jint *xPoints, *yPoints;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_drawPoly");
|
||||
|
||||
xPoints = (jint *)
|
||||
(*env)->GetPrimitiveArrayCritical(env, xpointsArray, NULL);
|
||||
if (xPoints != NULL) {
|
||||
yPoints = (jint *)
|
||||
(*env)->GetPrimitiveArrayCritical(env, ypointsArray, NULL);
|
||||
if (yPoints != NULL) {
|
||||
MTLContext *mtlc = MTLRenderQueue_GetCurrentContext();
|
||||
BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();
|
||||
|
||||
MTLRenderer_DrawPoly(mtlc, dstOps,
|
||||
nPoints, isClosed,
|
||||
transX, transY,
|
||||
xPoints, yPoints);
|
||||
if (mtlc != NULL) {
|
||||
RESET_PREVIOUS_OP();
|
||||
[mtlc.encoderManager endEncoder];
|
||||
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
[commandbuf commit];
|
||||
}
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, ypointsArray, yPoints,
|
||||
JNI_ABORT);
|
||||
}
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, xpointsArray, xPoints,
|
||||
JNI_ABORT);
|
||||
}
|
||||
}
|
||||
|
||||
const int SCANLINE_MAX_VERTEX_SIZE = 4096;
|
||||
const int VERTEX_STRUCT_SIZE = 8;
|
||||
const int NUM_OF_VERTICES_PER_SCANLINE = 2;
|
||||
|
||||
void
|
||||
MTLRenderer_DrawScanlines(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jint scanlineCount, jint *scanlines)
|
||||
{
|
||||
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawScanlines (scanlineCount=%d), dst tex=%p", scanlineCount, dstOps->pTexture);
|
||||
if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawScanlines: dest is null");
|
||||
return;
|
||||
}
|
||||
RETURN_IF_NULL(scanlines);
|
||||
int vertexSize = NUM_OF_VERTICES_PER_SCANLINE
|
||||
* scanlineCount * VERTEX_STRUCT_SIZE;
|
||||
J2dTraceLn1(J2D_TRACE_INFO, "MTLRenderer_DrawScanlines: Total vertex size : %d", vertexSize);
|
||||
if (vertexSize == 0) return;
|
||||
|
||||
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
|
||||
|
||||
if (mtlEncoder == nil) return;
|
||||
|
||||
if (vertexSize <= SCANLINE_MAX_VERTEX_SIZE) {
|
||||
struct Vertex verts[NUM_OF_VERTICES_PER_SCANLINE * scanlineCount];
|
||||
|
||||
for (int j = 0, i = 0; j < scanlineCount; j++) {
|
||||
// Translate each vertex by a fraction so
|
||||
// that we hit pixel centers.
|
||||
float x1 = ((float)*(scanlines++)) + 0.2f;
|
||||
float x2 = ((float)*(scanlines++)) + 1.2f;
|
||||
float y = ((float)*(scanlines++)) + 0.5f;
|
||||
struct Vertex v1 = {{x1, y}};
|
||||
struct Vertex v2 = {{x2, y}};
|
||||
verts[i++] = v1;
|
||||
verts[i++] = v2;
|
||||
}
|
||||
|
||||
[mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0
|
||||
vertexCount:NUM_OF_VERTICES_PER_SCANLINE * scanlineCount];
|
||||
} else {
|
||||
int remainingScanlineCount = vertexSize;
|
||||
do {
|
||||
if (remainingScanlineCount > SCANLINE_MAX_VERTEX_SIZE) {
|
||||
struct Vertex verts[SCANLINE_MAX_VERTEX_SIZE/ VERTEX_STRUCT_SIZE];
|
||||
|
||||
for (int j = 0, i = 0; j < (SCANLINE_MAX_VERTEX_SIZE / (VERTEX_STRUCT_SIZE * 2)); j++) {
|
||||
// Translate each vertex by a fraction so
|
||||
// that we hit pixel centers.
|
||||
float x1 = ((float)*(scanlines++)) + 0.2f;
|
||||
float x2 = ((float)*(scanlines++)) + 1.2f;
|
||||
float y = ((float)*(scanlines++)) + 0.5f;
|
||||
struct Vertex v1 = {{x1, y}};
|
||||
struct Vertex v2 = {{x2, y}};
|
||||
verts[i++] = v1;
|
||||
verts[i++] = v2;
|
||||
}
|
||||
|
||||
[mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0
|
||||
vertexCount:(SCANLINE_MAX_VERTEX_SIZE / VERTEX_STRUCT_SIZE)];
|
||||
remainingScanlineCount -= SCANLINE_MAX_VERTEX_SIZE;
|
||||
} else {
|
||||
struct Vertex verts[remainingScanlineCount / VERTEX_STRUCT_SIZE];
|
||||
|
||||
for (int j = 0, i = 0; j < (remainingScanlineCount / (VERTEX_STRUCT_SIZE * 2)); j++) {
|
||||
// Translate each vertex by a fraction so
|
||||
// that we hit pixel centers.
|
||||
float x1 = ((float)*(scanlines++)) + 0.2f;
|
||||
float x2 = ((float)*(scanlines++)) + 1.2f;
|
||||
float y = ((float)*(scanlines++)) + 0.5f;
|
||||
struct Vertex v1 = {{x1, y}};
|
||||
struct Vertex v2 = {{x2, y}};
|
||||
verts[i++] = v1;
|
||||
verts[i++] = v2;
|
||||
}
|
||||
|
||||
[mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0
|
||||
vertexCount:(remainingScanlineCount / VERTEX_STRUCT_SIZE)];
|
||||
remainingScanlineCount -= remainingScanlineCount;
|
||||
}
|
||||
J2dTraceLn1(J2D_TRACE_INFO,
|
||||
"MTLRenderer_DrawScanlines: Remaining vertex size %d", remainingScanlineCount);
|
||||
} while (remainingScanlineCount != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MTLRenderer_FillRect(MTLContext *mtlc, BMTLSDOps * dstOps, jint x, jint y, jint w, jint h)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_FillRect");
|
||||
|
||||
if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_FillRect: current dest is null");
|
||||
return;
|
||||
}
|
||||
|
||||
struct Vertex verts[QUAD_VERTEX_COUNT] = {
|
||||
{ {x, y}},
|
||||
{ {x, y+h}},
|
||||
{ {x+w, y}},
|
||||
{ {x+w, y+h}
|
||||
}};
|
||||
|
||||
|
||||
id<MTLTexture> dest = dstOps->pTexture;
|
||||
J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_FillRect (x=%d y=%d w=%d h=%d), dst tex=%p", x, y, w, h, dest);
|
||||
|
||||
// Encode render command.
|
||||
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
|
||||
if (mtlEncoder == nil)
|
||||
return;
|
||||
|
||||
[mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount: QUAD_VERTEX_COUNT];
|
||||
}
|
||||
|
||||
void MTLRenderer_FillSpans(MTLContext *mtlc, BMTLSDOps * dstOps, jint spanCount, jint *spans)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_FillSpans");
|
||||
if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_FillSpans: dest is null");
|
||||
return;
|
||||
}
|
||||
|
||||
// MTLRenderCommandEncoder setVertexBytes usage is recommended if the data is of 4KB.
|
||||
|
||||
// We use a buffer that closely matches the 4KB limit size
|
||||
// This buffer is resued multiple times to encode draw calls of a triangle list
|
||||
// NOTE : Due to nature of *spans data - it is not possible to use triangle strip.
|
||||
// We use triangle list to draw spans
|
||||
|
||||
// Destination texture to which render commands are encoded
|
||||
id<MTLTexture> dest = dstOps->pTexture;
|
||||
id<MTLTexture> destAA = nil;
|
||||
BOOL isDestOpaque = dstOps->isOpaque;
|
||||
if (mtlc.clip.stencilMaskGenerationInProgress == JNI_TRUE) {
|
||||
dest = dstOps->pStencilData;
|
||||
isDestOpaque = NO;
|
||||
}
|
||||
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dest isDstOpaque:isDestOpaque];
|
||||
if (mtlEncoder == nil) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_FillSpans: mtlEncoder is nil");
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the max no of vertices (of struct Vertex - 8 bytes) we can accomodate in 4KB
|
||||
const int TOTAL_VERTICES_IN_BLOCK = 510;
|
||||
struct Vertex vertexList[TOTAL_VERTICES_IN_BLOCK]; // a total of 170 triangles ==> 85 spans
|
||||
|
||||
jfloat shapeX1 = mtlc.clip.shapeX;
|
||||
jfloat shapeY1 = mtlc.clip.shapeY;
|
||||
jfloat shapeX2 = shapeX1 + mtlc.clip.shapeWidth;
|
||||
jfloat shapeY2 = shapeY1 + mtlc.clip.shapeHeight;
|
||||
|
||||
int counter = 0;
|
||||
for (int i = 0; i < spanCount; i++) {
|
||||
jfloat x1 = *(spans++);
|
||||
jfloat y1 = *(spans++);
|
||||
jfloat x2 = *(spans++);
|
||||
jfloat y2 = *(spans++);
|
||||
|
||||
if (mtlc.clip.stencilMaskGenerationInProgress == JNI_TRUE) {
|
||||
if (shapeX1 > x1) shapeX1 = x1;
|
||||
if (shapeY1 > y1) shapeY1 = y1;
|
||||
if (shapeX2 < x2) shapeX2 = x2;
|
||||
if (shapeY2 < y2) shapeY2 = y2;
|
||||
}
|
||||
|
||||
struct Vertex verts[6] = {
|
||||
{{x1, y1}},
|
||||
{{x1, y2}},
|
||||
{{x2, y1}},
|
||||
|
||||
{{x1, y2}},
|
||||
{{x2, y1}},
|
||||
{{x2, y2}
|
||||
}};
|
||||
|
||||
memcpy(&vertexList[counter], &verts, sizeof(verts));
|
||||
counter += 6;
|
||||
|
||||
// If vertexList buffer full
|
||||
if (counter % TOTAL_VERTICES_IN_BLOCK == 0) {
|
||||
[mtlEncoder setVertexBytes:vertexList length:sizeof(vertexList) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:TOTAL_VERTICES_IN_BLOCK];
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw triangles using remaining vertices if any
|
||||
if (counter != 0) {
|
||||
[mtlEncoder setVertexBytes:vertexList length:sizeof(vertexList) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:counter];
|
||||
}
|
||||
|
||||
if (mtlc.clip.stencilMaskGenerationInProgress == JNI_TRUE) {
|
||||
if (shapeX1 < 0) shapeX1 = 0;
|
||||
if (shapeY1 < 0) shapeY1 = 0;
|
||||
if (shapeX1 > dest.width) shapeX1 = dest.width;
|
||||
if (shapeY1 > dest.height) shapeY1 = dest.height;
|
||||
if (shapeX2 < 0) shapeX2 = 0;
|
||||
if (shapeY2 < 0) shapeY2 = 0;
|
||||
if (shapeX2 > dest.width) shapeX2 = dest.width;
|
||||
if (shapeY2 > dest.height) shapeY2 = dest.height;
|
||||
|
||||
mtlc.clip.shapeX = (NSUInteger) shapeX1;
|
||||
mtlc.clip.shapeY = (NSUInteger) shapeY1;
|
||||
mtlc.clip.shapeWidth = (NSUInteger) (shapeX2 - shapeX1);
|
||||
mtlc.clip.shapeHeight = (NSUInteger) (shapeY2 - shapeY1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MTLRenderer_FillParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jfloat fx11, jfloat fy11,
|
||||
jfloat dx21, jfloat dy21,
|
||||
jfloat dx12, jfloat dy12)
|
||||
{
|
||||
|
||||
if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_FillParallelogram: current dest is null");
|
||||
return;
|
||||
}
|
||||
|
||||
id<MTLTexture> dest = dstOps->pTexture;
|
||||
J2dTraceLn7(J2D_TRACE_INFO,
|
||||
"MTLRenderer_FillParallelogram"
|
||||
"(x=%6.2f y=%6.2f "
|
||||
"dx1=%6.2f dy1=%6.2f "
|
||||
"dx2=%6.2f dy2=%6.2f dst tex=%p)",
|
||||
fx11, fy11,
|
||||
dx21, dy21,
|
||||
dx12, dy12, dest);
|
||||
|
||||
struct Vertex verts[QUAD_VERTEX_COUNT] = {
|
||||
{ {fx11, fy11}},
|
||||
{ {fx11+dx21, fy11+dy21}},
|
||||
{ {fx11+dx12, fy11+dy12}},
|
||||
{ {fx11 + dx21 + dx12, fy11+ dy21 + dy12}
|
||||
}};
|
||||
|
||||
// Encode render command.
|
||||
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];;
|
||||
|
||||
if (mtlEncoder == nil) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_FillParallelogram: error creating MTLRenderCommandEncoder.");
|
||||
return;
|
||||
}
|
||||
|
||||
[mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount: QUAD_VERTEX_COUNT];
|
||||
}
|
||||
|
||||
void
|
||||
MTLRenderer_DrawParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jfloat fx11, jfloat fy11,
|
||||
jfloat dx21, jfloat dy21,
|
||||
jfloat dx12, jfloat dy12,
|
||||
jfloat lwr21, jfloat lwr12)
|
||||
{
|
||||
// dx,dy for line width in the "21" and "12" directions.
|
||||
jfloat ldx21 = dx21 * lwr21;
|
||||
jfloat ldy21 = dy21 * lwr21;
|
||||
jfloat ldx12 = dx12 * lwr12;
|
||||
jfloat ldy12 = dy12 * lwr12;
|
||||
|
||||
// calculate origin of the outer parallelogram
|
||||
jfloat ox11 = fx11 - (ldx21 + ldx12) / 2.0f;
|
||||
jfloat oy11 = fy11 - (ldy21 + ldy12) / 2.0f;
|
||||
|
||||
J2dTraceLn8(J2D_TRACE_INFO,
|
||||
"MTLRenderer_DrawParallelogram"
|
||||
"(x=%6.2f y=%6.2f "
|
||||
"dx1=%6.2f dy1=%6.2f lwr1=%6.2f "
|
||||
"dx2=%6.2f dy2=%6.2f lwr2=%6.2f)",
|
||||
fx11, fy11,
|
||||
dx21, dy21, lwr21,
|
||||
dx12, dy12, lwr12);
|
||||
|
||||
|
||||
// Only need to generate 4 quads if the interior still
|
||||
// has a hole in it (i.e. if the line width ratio was
|
||||
// less than 1.0)
|
||||
if (lwr21 < 1.0f && lwr12 < 1.0f) {
|
||||
|
||||
// Note: "TOP", "BOTTOM", "LEFT" and "RIGHT" here are
|
||||
// relative to whether the dxNN variables are positive
|
||||
// and negative. The math works fine regardless of
|
||||
// their signs, but for conceptual simplicity the
|
||||
// comments will refer to the sides as if the dxNN
|
||||
// were all positive. "TOP" and "BOTTOM" segments
|
||||
// are defined by the dxy21 deltas. "LEFT" and "RIGHT"
|
||||
// segments are defined by the dxy12 deltas.
|
||||
|
||||
// Each segment includes its starting corner and comes
|
||||
// to just short of the following corner. Thus, each
|
||||
// corner is included just once and the only lengths
|
||||
// needed are the original parallelogram delta lengths
|
||||
// and the "line width deltas". The sides will cover
|
||||
// the following relative territories:
|
||||
//
|
||||
// T T T T T R
|
||||
// L R
|
||||
// L R
|
||||
// L R
|
||||
// L R
|
||||
// L B B B B B
|
||||
|
||||
// Every segment is drawn as a filled Parallelogram quad
|
||||
// Each quad is encoded using two triangles
|
||||
// For 4 segments - there are 8 triangles in total
|
||||
// Each triangle has 3 vertices
|
||||
const int TOTAL_VERTICES = 8 * 3;
|
||||
struct Vertex vertexList[TOTAL_VERTICES];
|
||||
int i = 0;
|
||||
|
||||
// TOP segment, to left side of RIGHT edge
|
||||
// "width" of original pgram, "height" of hor. line size
|
||||
fx11 = ox11;
|
||||
fy11 = oy11;
|
||||
|
||||
fillVertex(vertexList + (i++), fx11, fy11);
|
||||
fillVertex(vertexList + (i++), fx11 + dx21, fy11 + dy21);
|
||||
fillVertex(vertexList + (i++), fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
|
||||
|
||||
fillVertex(vertexList + (i++), fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
|
||||
fillVertex(vertexList + (i++), fx11 + ldx12, fy11 + ldy12);
|
||||
fillVertex(vertexList + (i++), fx11, fy11);
|
||||
|
||||
// RIGHT segment, to top of BOTTOM edge
|
||||
// "width" of vert. line size , "height" of original pgram
|
||||
fx11 = ox11 + dx21;
|
||||
fy11 = oy11 + dy21;
|
||||
fillVertex(vertexList + (i++), fx11, fy11);
|
||||
fillVertex(vertexList + (i++), fx11 + ldx21, fy11 + ldy21);
|
||||
fillVertex(vertexList + (i++), fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
|
||||
|
||||
fillVertex(vertexList + (i++), fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
|
||||
fillVertex(vertexList + (i++), fx11 + dx12, fy11 + dy12);
|
||||
fillVertex(vertexList + (i++), fx11, fy11);
|
||||
|
||||
// BOTTOM segment, from right side of LEFT edge
|
||||
// "width" of original pgram, "height" of hor. line size
|
||||
fx11 = ox11 + dx12 + ldx21;
|
||||
fy11 = oy11 + dy12 + ldy21;
|
||||
fillVertex(vertexList + (i++), fx11, fy11);
|
||||
fillVertex(vertexList + (i++), fx11 + dx21, fy11 + dy21);
|
||||
fillVertex(vertexList + (i++), fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
|
||||
|
||||
fillVertex(vertexList + (i++), fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
|
||||
fillVertex(vertexList + (i++), fx11 + ldx12, fy11 + ldy12);
|
||||
fillVertex(vertexList + (i++), fx11, fy11);
|
||||
|
||||
// LEFT segment, from bottom of TOP edge
|
||||
// "width" of vert. line size , "height" of inner pgram
|
||||
fx11 = ox11 + ldx12;
|
||||
fy11 = oy11 + ldy12;
|
||||
fillVertex(vertexList + (i++), fx11, fy11);
|
||||
fillVertex(vertexList + (i++), fx11 + ldx21, fy11 + ldy21);
|
||||
fillVertex(vertexList + (i++), fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
|
||||
|
||||
fillVertex(vertexList + (i++), fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
|
||||
fillVertex(vertexList + (i++), fx11 + dx12, fy11 + dy12);
|
||||
fillVertex(vertexList + (i++), fx11, fy11);
|
||||
|
||||
// Encode render command.
|
||||
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
|
||||
|
||||
if (mtlEncoder == nil) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawParallelogram: error creating MTLRenderCommandEncoder.");
|
||||
return;
|
||||
}
|
||||
|
||||
[mtlEncoder setVertexBytes:vertexList length:sizeof(vertexList) atIndex:MeshVertexBuffer];
|
||||
[mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:TOTAL_VERTICES];
|
||||
} else {
|
||||
// The line width ratios were large enough to consume
|
||||
// the entire hole in the middle of the parallelogram
|
||||
// so we can just issue one large quad for the outer
|
||||
// parallelogram.
|
||||
dx21 += ldx21;
|
||||
dy21 += ldy21;
|
||||
dx12 += ldx12;
|
||||
dy12 += ldy12;
|
||||
MTLRenderer_FillParallelogram(mtlc, dstOps, ox11, oy11, dx21, dy21, dx12, dy12);
|
||||
}
|
||||
}
|
||||
|
||||
static struct AAVertex aaVertices[6];
|
||||
static jint vertexCacheIndex = 0;
|
||||
|
||||
#define AA_ADD_VERTEX(OU, OV, IU, IV, DX, DY) \
|
||||
do { \
|
||||
struct AAVertex *v = &aaVertices[vertexCacheIndex++]; \
|
||||
v->otxtpos[0] = OU; \
|
||||
v->otxtpos[1] = OV; \
|
||||
v->itxtpos[0] = IU; \
|
||||
v->itxtpos[1] = IV; \
|
||||
v->position[0]= DX; \
|
||||
v->position[1] = DY; \
|
||||
} while (0)
|
||||
|
||||
#define AA_ADD_TRIANGLES(ou11, ov11, iu11, iv11, ou21, ov21, iu21, iv21, ou22, ov22, iu22, iv22, ou12, ov12, iu12, iv12, DX1, DY1, DX2, DY2) \
|
||||
do { \
|
||||
AA_ADD_VERTEX(ou11, ov11, iu11, iv11, DX1, DY1); \
|
||||
AA_ADD_VERTEX(ou21, ov21, iu21, iv21, DX2, DY1); \
|
||||
AA_ADD_VERTEX(ou22, ov22, iu22, iv22, DX2, DY2); \
|
||||
AA_ADD_VERTEX(ou22, ov22, iu22, iv22, DX2, DY2); \
|
||||
AA_ADD_VERTEX(ou12, ov12, iu12, iv12, DX1, DY2); \
|
||||
AA_ADD_VERTEX(ou11, ov11, iu11, iv11, DX1, DY1); \
|
||||
} while (0)
|
||||
|
||||
#define ADJUST_PGRAM(V1, DV, V2) \
|
||||
do { \
|
||||
if ((DV) >= 0) { \
|
||||
(V2) += (DV); \
|
||||
} else { \
|
||||
(V1) += (DV); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Invert the following transform:
|
||||
// DeltaT(0, 0) == (0, 0)
|
||||
// DeltaT(1, 0) == (DX1, DY1)
|
||||
// DeltaT(0, 1) == (DX2, DY2)
|
||||
// DeltaT(1, 1) == (DX1+DX2, DY1+DY2)
|
||||
// TM00 = DX1, TM01 = DX2, (TM02 = X11)
|
||||
// TM10 = DY1, TM11 = DY2, (TM12 = Y11)
|
||||
// Determinant = TM00*TM11 - TM01*TM10
|
||||
// = DX1*DY2 - DX2*DY1
|
||||
// Inverse is:
|
||||
// IM00 = TM11/det, IM01 = -TM01/det
|
||||
// IM10 = -TM10/det, IM11 = TM00/det
|
||||
// IM02 = (TM01 * TM12 - TM11 * TM02) / det,
|
||||
// IM12 = (TM10 * TM02 - TM00 * TM12) / det,
|
||||
|
||||
#define DECLARE_MATRIX(MAT) \
|
||||
jfloat MAT ## 00, MAT ## 01, MAT ## 02, MAT ## 10, MAT ## 11, MAT ## 12
|
||||
|
||||
#define GET_INVERTED_MATRIX(MAT, X11, Y11, DX1, DY1, DX2, DY2, RET_CODE) \
|
||||
do { \
|
||||
jfloat det = DX1*DY2 - DX2*DY1; \
|
||||
if (det == 0) { \
|
||||
RET_CODE; \
|
||||
} \
|
||||
MAT ## 00 = DY2/det; \
|
||||
MAT ## 01 = -DX2/det; \
|
||||
MAT ## 10 = -DY1/det; \
|
||||
MAT ## 11 = DX1/det; \
|
||||
MAT ## 02 = (DX2 * Y11 - DY2 * X11) / det; \
|
||||
MAT ## 12 = (DY1 * X11 - DX1 * Y11) / det; \
|
||||
} while (0)
|
||||
|
||||
#define TRANSFORM(MAT, TX, TY, X, Y) \
|
||||
do { \
|
||||
TX = (X) * MAT ## 00 + (Y) * MAT ## 01 + MAT ## 02; \
|
||||
TY = (X) * MAT ## 10 + (Y) * MAT ## 11 + MAT ## 12; \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
MTLRenderer_FillAAParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jfloat fx11, jfloat fy11,
|
||||
jfloat dx21, jfloat dy21,
|
||||
jfloat dx12, jfloat dy12)
|
||||
{
|
||||
DECLARE_MATRIX(om);
|
||||
// parameters for parallelogram bounding box
|
||||
jfloat bx11, by11, bx22, by22;
|
||||
// parameters for uv texture coordinates of parallelogram corners
|
||||
jfloat ou11, ov11, ou12, ov12, ou21, ov21, ou22, ov22;
|
||||
|
||||
J2dTraceLn6(J2D_TRACE_INFO,
|
||||
"MTLRenderer_FillAAParallelogram "
|
||||
"(x=%6.2f y=%6.2f "
|
||||
"dx1=%6.2f dy1=%6.2f "
|
||||
"dx2=%6.2f dy2=%6.2f)",
|
||||
fx11, fy11,
|
||||
dx21, dy21,
|
||||
dx12, dy12);
|
||||
|
||||
RETURN_IF_NULL(mtlc);
|
||||
RETURN_IF_NULL(dstOps);
|
||||
|
||||
GET_INVERTED_MATRIX(om, fx11, fy11, dx21, dy21, dx12, dy12,
|
||||
return);
|
||||
|
||||
bx11 = bx22 = fx11;
|
||||
by11 = by22 = fy11;
|
||||
ADJUST_PGRAM(bx11, dx21, bx22);
|
||||
ADJUST_PGRAM(by11, dy21, by22);
|
||||
ADJUST_PGRAM(bx11, dx12, bx22);
|
||||
ADJUST_PGRAM(by11, dy12, by22);
|
||||
bx11 = (jfloat) floor(bx11);
|
||||
by11 = (jfloat) floor(by11);
|
||||
bx22 = (jfloat) ceil(bx22);
|
||||
by22 = (jfloat) ceil(by22);
|
||||
|
||||
TRANSFORM(om, ou11, ov11, bx11, by11);
|
||||
TRANSFORM(om, ou21, ov21, bx22, by11);
|
||||
TRANSFORM(om, ou12, ov12, bx11, by22);
|
||||
TRANSFORM(om, ou22, ov22, bx22, by22);
|
||||
|
||||
id<MTLRenderCommandEncoder> encoder =
|
||||
[mtlc.encoderManager getAAShaderRenderEncoder:dstOps];
|
||||
|
||||
AA_ADD_TRIANGLES(ou11, ov11, 5.f, 5.f, ou21, ov21, 6.f, 5.f, ou22, ov22, 6.f, 6.f, ou12, ov12, 5.f, 5.f, bx11, by11, bx22, by22);
|
||||
[encoder setVertexBytes:aaVertices length:sizeof(aaVertices) atIndex:MeshVertexBuffer];
|
||||
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
|
||||
vertexCacheIndex = 0;
|
||||
}
|
||||
|
||||
void
|
||||
MTLRenderer_FillAAParallelogramInnerOuter(MTLContext *mtlc, MTLSDOps *dstOps,
|
||||
jfloat ox11, jfloat oy11,
|
||||
jfloat ox21, jfloat oy21,
|
||||
jfloat ox12, jfloat oy12,
|
||||
jfloat ix11, jfloat iy11,
|
||||
jfloat ix21, jfloat iy21,
|
||||
jfloat ix12, jfloat iy12)
|
||||
{
|
||||
DECLARE_MATRIX(om);
|
||||
DECLARE_MATRIX(im);
|
||||
// parameters for parallelogram bounding box
|
||||
jfloat bx11, by11, bx22, by22;
|
||||
// parameters for uv texture coordinates of outer parallelogram corners
|
||||
jfloat ou11, ov11, ou12, ov12, ou21, ov21, ou22, ov22;
|
||||
// parameters for uv texture coordinates of inner parallelogram corners
|
||||
jfloat iu11, iv11, iu12, iv12, iu21, iv21, iu22, iv22;
|
||||
|
||||
RETURN_IF_NULL(mtlc);
|
||||
RETURN_IF_NULL(dstOps);
|
||||
|
||||
GET_INVERTED_MATRIX(im, ix11, iy11, ix21, iy21, ix12, iy12,
|
||||
// inner parallelogram is degenerate
|
||||
// therefore it encloses no area
|
||||
// fill outer
|
||||
MTLRenderer_FillAAParallelogram(mtlc, dstOps,
|
||||
ox11, oy11,
|
||||
ox21, oy21,
|
||||
ox12, oy12);
|
||||
return);
|
||||
GET_INVERTED_MATRIX(om, ox11, oy11, ox21, oy21, ox12, oy12,
|
||||
return);
|
||||
|
||||
bx11 = bx22 = ox11;
|
||||
by11 = by22 = oy11;
|
||||
ADJUST_PGRAM(bx11, ox21, bx22);
|
||||
ADJUST_PGRAM(by11, oy21, by22);
|
||||
ADJUST_PGRAM(bx11, ox12, bx22);
|
||||
ADJUST_PGRAM(by11, oy12, by22);
|
||||
bx11 = (jfloat) floor(bx11);
|
||||
by11 = (jfloat) floor(by11);
|
||||
bx22 = (jfloat) ceil(bx22);
|
||||
by22 = (jfloat) ceil(by22);
|
||||
|
||||
TRANSFORM(om, ou11, ov11, bx11, by11);
|
||||
TRANSFORM(om, ou21, ov21, bx22, by11);
|
||||
TRANSFORM(om, ou12, ov12, bx11, by22);
|
||||
TRANSFORM(om, ou22, ov22, bx22, by22);
|
||||
|
||||
TRANSFORM(im, iu11, iv11, bx11, by11);
|
||||
TRANSFORM(im, iu21, iv21, bx22, by11);
|
||||
TRANSFORM(im, iu12, iv12, bx11, by22);
|
||||
TRANSFORM(im, iu22, iv22, bx22, by22);
|
||||
|
||||
id<MTLRenderCommandEncoder> encoder =
|
||||
[mtlc.encoderManager getAAShaderRenderEncoder:dstOps];
|
||||
|
||||
AA_ADD_TRIANGLES(ou11, ov11, iu11, iv11, ou21, ov21, iu21, iv21, ou22, ov22, iu22, iv22, ou12, ov12, iu12, iv12, bx11, by11, bx22, by22);
|
||||
[encoder setVertexBytes:aaVertices length:sizeof(aaVertices) atIndex:MeshVertexBuffer];
|
||||
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
|
||||
vertexCacheIndex = 0;
|
||||
}
|
||||
|
||||
void
|
||||
MTLRenderer_DrawAAParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
|
||||
jfloat fx11, jfloat fy11,
|
||||
jfloat dx21, jfloat dy21,
|
||||
jfloat dx12, jfloat dy12,
|
||||
jfloat lwr21, jfloat lwr12)
|
||||
{
|
||||
// dx,dy for line width in the "21" and "12" directions.
|
||||
jfloat ldx21, ldy21, ldx12, ldy12;
|
||||
// parameters for "outer" parallelogram
|
||||
jfloat ofx11, ofy11, odx21, ody21, odx12, ody12;
|
||||
// parameters for "inner" parallelogram
|
||||
jfloat ifx11, ify11, idx21, idy21, idx12, idy12;
|
||||
|
||||
J2dTraceLn8(J2D_TRACE_INFO,
|
||||
"MTLRenderer_DrawAAParallelogram "
|
||||
"(x=%6.2f y=%6.2f "
|
||||
"dx1=%6.2f dy1=%6.2f lwr1=%6.2f "
|
||||
"dx2=%6.2f dy2=%6.2f lwr2=%6.2f)",
|
||||
fx11, fy11,
|
||||
dx21, dy21, lwr21,
|
||||
dx12, dy12, lwr12);
|
||||
|
||||
RETURN_IF_NULL(mtlc);
|
||||
RETURN_IF_NULL(dstOps);
|
||||
|
||||
// calculate true dx,dy for line widths from the "line width ratios"
|
||||
ldx21 = dx21 * lwr21;
|
||||
ldy21 = dy21 * lwr21;
|
||||
ldx12 = dx12 * lwr12;
|
||||
ldy12 = dy12 * lwr12;
|
||||
|
||||
// calculate coordinates of the outer parallelogram
|
||||
ofx11 = fx11 - (ldx21 + ldx12) / 2.0f;
|
||||
ofy11 = fy11 - (ldy21 + ldy12) / 2.0f;
|
||||
odx21 = dx21 + ldx21;
|
||||
ody21 = dy21 + ldy21;
|
||||
odx12 = dx12 + ldx12;
|
||||
ody12 = dy12 + ldy12;
|
||||
|
||||
// Only process the inner parallelogram if the line width ratio
|
||||
// did not consume the entire interior of the parallelogram
|
||||
// (i.e. if the width ratio was less than 1.0)
|
||||
if (lwr21 < 1.0f && lwr12 < 1.0f) {
|
||||
// calculate coordinates of the inner parallelogram
|
||||
ifx11 = fx11 + (ldx21 + ldx12) / 2.0f;
|
||||
ify11 = fy11 + (ldy21 + ldy12) / 2.0f;
|
||||
idx21 = dx21 - ldx21;
|
||||
idy21 = dy21 - ldy21;
|
||||
idx12 = dx12 - ldx12;
|
||||
idy12 = dy12 - ldy12;
|
||||
|
||||
MTLRenderer_FillAAParallelogramInnerOuter(mtlc, dstOps,
|
||||
ofx11, ofy11,
|
||||
odx21, ody21,
|
||||
odx12, ody12,
|
||||
ifx11, ify11,
|
||||
idx21, idy21,
|
||||
idx12, idy12);
|
||||
} else {
|
||||
MTLRenderer_FillAAParallelogram(mtlc, dstOps,
|
||||
ofx11, ofy11,
|
||||
odx21, ody21,
|
||||
odx12, ody12);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLSamplerManager_h_Included
|
||||
#define MTLSamplerManager_h_Included
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
#include "RenderOptions.h"
|
||||
|
||||
@class MTLContex;
|
||||
|
||||
|
||||
@interface MTLSamplerManager : NSObject
|
||||
- (id _Nonnull)initWithDevice:(_Nonnull id<MTLDevice>) device;
|
||||
- (void)dealloc;
|
||||
|
||||
- (void) setSamplerWithEncoder:(_Nonnull id<MTLRenderCommandEncoder>) encoder
|
||||
interpolation:(int) interpolation
|
||||
repeat:(bool) repeat;
|
||||
@end
|
||||
|
||||
#endif // MTLSamplerManager_h_Included
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "MTLSamplerManager.h"
|
||||
#include "MTLContext.h"
|
||||
#include "sun_java2d_SunGraphics2D.h"
|
||||
#import "common.h"
|
||||
|
||||
@implementation MTLSamplerManager {
|
||||
id<MTLSamplerState> _samplerNearestClamp;
|
||||
id<MTLSamplerState> _samplerLinearClamp;
|
||||
id<MTLSamplerState> _samplerNearestRepeat;
|
||||
id<MTLSamplerState> _samplerLinearRepeat;
|
||||
}
|
||||
|
||||
- (id _Nonnull)initWithDevice:(id<MTLDevice>) device {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
MTLSamplerDescriptor *samplerDescriptor = [[MTLSamplerDescriptor new] autorelease];
|
||||
|
||||
samplerDescriptor.rAddressMode = MTLSamplerAddressModeClampToEdge;
|
||||
samplerDescriptor.sAddressMode = MTLSamplerAddressModeClampToEdge;
|
||||
samplerDescriptor.tAddressMode = MTLSamplerAddressModeClampToEdge;
|
||||
|
||||
samplerDescriptor.minFilter = MTLSamplerMinMagFilterNearest;
|
||||
samplerDescriptor.magFilter = MTLSamplerMinMagFilterNearest;
|
||||
_samplerNearestClamp = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||
|
||||
samplerDescriptor.minFilter = MTLSamplerMinMagFilterLinear;
|
||||
samplerDescriptor.magFilter = MTLSamplerMinMagFilterLinear;
|
||||
_samplerLinearClamp = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||
|
||||
samplerDescriptor.rAddressMode = MTLSamplerAddressModeRepeat;
|
||||
samplerDescriptor.sAddressMode = MTLSamplerAddressModeRepeat;
|
||||
samplerDescriptor.tAddressMode = MTLSamplerAddressModeRepeat;
|
||||
|
||||
samplerDescriptor.minFilter = MTLSamplerMinMagFilterNearest;
|
||||
samplerDescriptor.magFilter = MTLSamplerMinMagFilterNearest;
|
||||
_samplerNearestRepeat = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||
|
||||
samplerDescriptor.minFilter = MTLSamplerMinMagFilterLinear;
|
||||
samplerDescriptor.magFilter = MTLSamplerMinMagFilterLinear;
|
||||
_samplerLinearRepeat = [device newSamplerStateWithDescriptor:samplerDescriptor];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) setSamplerWithEncoder:(id<MTLRenderCommandEncoder>) encoder
|
||||
interpolation:(int) interpolation
|
||||
repeat:(bool) repeat {
|
||||
id<MTLSamplerState> sampler;
|
||||
if (repeat) {
|
||||
sampler = interpolation == INTERPOLATION_BILINEAR ? _samplerLinearRepeat : _samplerNearestRepeat;
|
||||
} else {
|
||||
sampler = interpolation == INTERPOLATION_BILINEAR ? _samplerLinearClamp : _samplerNearestClamp;
|
||||
}
|
||||
[encoder setFragmentSamplerState:sampler atIndex:0];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_samplerNearestClamp release];
|
||||
[_samplerLinearClamp release];
|
||||
[_samplerNearestRepeat release];
|
||||
[_samplerLinearRepeat release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLStencilManager_h_Included
|
||||
#define MTLStencilManager_h_Included
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
#include "RenderOptions.h"
|
||||
|
||||
@class MTLContex;
|
||||
|
||||
|
||||
@interface MTLStencilManager : NSObject
|
||||
- (id _Nonnull)initWithDevice:(_Nonnull id<MTLDevice>) device;
|
||||
- (void)dealloc;
|
||||
@property (readonly) _Nonnull id<MTLDepthStencilState> stencilState;
|
||||
@end
|
||||
|
||||
#endif // MTLSamplerManager_h_Included
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "MTLStencilManager.h"
|
||||
//#include "MTLContext.h"
|
||||
//#include "sun_java2d_SunGraphics2D.h"
|
||||
//#import "common.h"
|
||||
|
||||
@implementation MTLStencilManager {
|
||||
id<MTLDepthStencilState> _stencilState;
|
||||
}
|
||||
|
||||
@synthesize stencilState = _stencilState;
|
||||
|
||||
- (id _Nonnull)initWithDevice:(id<MTLDevice>) device {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
MTLDepthStencilDescriptor* stencilDescriptor;
|
||||
stencilDescriptor = [[MTLDepthStencilDescriptor new] autorelease];
|
||||
stencilDescriptor.frontFaceStencil.stencilCompareFunction = MTLCompareFunctionEqual;
|
||||
stencilDescriptor.frontFaceStencil.stencilFailureOperation = MTLStencilOperationKeep;
|
||||
|
||||
// TODO : backFaceStencil can be set to nil if all primitives are drawn as front-facing primitives
|
||||
// currently, fill parallelogram uses back-facing primitive drawing - that needs to be changed.
|
||||
// Once that part is changed, set backFaceStencil to nil
|
||||
//stencilDescriptor.backFaceStencil = nil;
|
||||
|
||||
stencilDescriptor.backFaceStencil.stencilCompareFunction = MTLCompareFunctionEqual;
|
||||
stencilDescriptor.backFaceStencil.stencilFailureOperation = MTLStencilOperationKeep;
|
||||
_stencilState = [device newDepthStencilStateWithDescriptor:stencilDescriptor];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_stencilState release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLSurfaceData_h_Included
|
||||
#define MTLSurfaceData_h_Included
|
||||
|
||||
#import "MTLSurfaceDataBase.h"
|
||||
#import "MTLGraphicsConfig.h"
|
||||
#import "AWTWindow.h"
|
||||
#import "MTLLayer.h"
|
||||
|
||||
/**
|
||||
* The MTLSDOps structure contains the MTL-specific information for a given
|
||||
* MTLSurfaceData. It is referenced by the native MTLSDOps structure.
|
||||
*/
|
||||
typedef struct _MTLSDOps {
|
||||
AWTView *peerData;
|
||||
MTLLayer *layer;
|
||||
jint argb[4]; // background clear color
|
||||
MTLGraphicsConfigInfo *configInfo;
|
||||
} MTLSDOps;
|
||||
|
||||
// debug-method
|
||||
NSString * getSurfaceDescription(const BMTLSDOps * bmtlsdOps);
|
||||
|
||||
#endif /* MTLSurfaceData_h_Included */
|
||||
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#import <stdlib.h>
|
||||
|
||||
#import "sun_java2d_metal_MTLSurfaceData.h"
|
||||
|
||||
#import "jni_util.h"
|
||||
#import "MTLRenderQueue.h"
|
||||
#import "MTLGraphicsConfig.h"
|
||||
#import "MTLSurfaceData.h"
|
||||
#import "ThreadUtilities.h"
|
||||
#include "jlong.h"
|
||||
|
||||
/**
|
||||
* The following methods are implemented in the windowing system (i.e. GLX
|
||||
* and WGL) source files.
|
||||
*/
|
||||
extern jlong MTLSD_GetNativeConfigInfo(BMTLSDOps *bmtlsdo);
|
||||
extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, BMTLSDOps *bmtlsdo);
|
||||
extern void MTLSD_DestroyMTLSurface(JNIEnv *env, BMTLSDOps *bmtlsdo);
|
||||
|
||||
void MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *bmtlsdo, jint w, jint h);
|
||||
|
||||
static jboolean MTLSurfaceData_initTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque, jboolean rtt, jint width, jint height) {
|
||||
@autoreleasepool {
|
||||
if (bmtlsdo == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: ops are null");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
if (width <= 0 || height <= 0) {
|
||||
J2dRlsTraceLn2(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: texture dimensions is incorrect, w=%d, h=%d", width, height);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps;
|
||||
|
||||
if (mtlsdo == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: MTLSDOps are null");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
if (mtlsdo->configInfo == NULL || mtlsdo->configInfo->context == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: MTLSDOps wasn't initialized (context is null)");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
MTLContext* ctx = mtlsdo->configInfo->context;
|
||||
|
||||
width = (width <= MaxTextureSize) ? width : 0;
|
||||
height = (height <= MaxTextureSize) ? height : 0;
|
||||
|
||||
J2dTraceLn3(J2D_TRACE_VERBOSE, " desired texture dimensions: w=%d h=%d max=%d",
|
||||
width, height, MaxTextureSize);
|
||||
|
||||
// if either dimension is 0, we cannot allocate a texture with the
|
||||
// requested dimensions
|
||||
if ((width == 0 || height == 0)) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: texture dimensions too large");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatBGRA8Unorm width: width height: height mipmapped: NO];
|
||||
textureDescriptor.usage = MTLTextureUsageUnknown;
|
||||
textureDescriptor.storageMode = MTLStorageModePrivate;
|
||||
bmtlsdo->pTexture = [ctx.device newTextureWithDescriptor: textureDescriptor];
|
||||
|
||||
MTLTextureDescriptor *stencilDataDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint width:width height:height mipmapped:NO];
|
||||
stencilDataDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
||||
stencilDataDescriptor.storageMode = MTLStorageModePrivate;
|
||||
bmtlsdo->pStencilData = [ctx.device newTextureWithDescriptor:stencilDataDescriptor];
|
||||
bmtlsdo->pAAStencilData = [ctx.device newTextureWithDescriptor:textureDescriptor];
|
||||
bmtlsdo->pStencilDataBuf = [ctx.device newBufferWithLength:width*height options:MTLResourceStorageModePrivate];
|
||||
bmtlsdo->pAAStencilDataBuf = [ctx.device newBufferWithLength:width*height*4 options:MTLResourceStorageModePrivate];
|
||||
|
||||
|
||||
MTLTextureDescriptor *stencilTextureDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatStencil8 width:width height:height mipmapped:NO];
|
||||
stencilTextureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite;
|
||||
stencilTextureDescriptor.storageMode = MTLStorageModePrivate;
|
||||
bmtlsdo->pStencilTexture = [ctx.device newTextureWithDescriptor:stencilTextureDescriptor];
|
||||
|
||||
bmtlsdo->isOpaque = isOpaque;
|
||||
bmtlsdo->xOffset = 0;
|
||||
bmtlsdo->yOffset = 0;
|
||||
bmtlsdo->width = width;
|
||||
bmtlsdo->height = height;
|
||||
bmtlsdo->textureWidth = width;
|
||||
bmtlsdo->textureHeight = height;
|
||||
bmtlsdo->drawableType = rtt ? MTLSD_RT_TEXTURE : MTLSD_TEXTURE;
|
||||
|
||||
J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLSurfaceData_initTexture: w=%d h=%d bp=%p [tex=%p] opaque=%d rtt=%d", width, height, bmtlsdo, bmtlsdo->pTexture, isOpaque, rtt);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an MTL texture, using the given width and height as
|
||||
* a guide.
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_java2d_metal_MTLSurfaceData_initTexture(
|
||||
JNIEnv *env, jobject mtlsd,
|
||||
jlong pData, jboolean isOpaque,
|
||||
jint width, jint height
|
||||
) {
|
||||
if (!MTLSurfaceData_initTexture((BMTLSDOps *)pData, isOpaque, JNI_FALSE, width, height))
|
||||
return JNI_FALSE;
|
||||
MTLSD_SetNativeDimensions(env, (BMTLSDOps *)pData, width, height);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a framebuffer object, using the given width and height as
|
||||
* a guide. See MTLSD_InitTextureObject() and MTLSD_initRTexture()
|
||||
* for more information.
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_java2d_metal_MTLSurfaceData_initRTexture
|
||||
(JNIEnv *env, jobject mtlsd,
|
||||
jlong pData, jboolean isOpaque,
|
||||
jint width, jint height)
|
||||
{
|
||||
if (!MTLSurfaceData_initTexture((BMTLSDOps *)pData, isOpaque, JNI_TRUE, width, height))
|
||||
return JNI_FALSE;
|
||||
MTLSD_SetNativeDimensions(env, (BMTLSDOps *)pData, width, height);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_java2d_metal_MTLSurfaceData_getMTLTexturePointer(JNIEnv *env, jobject mtlsd, jlong pData) {
|
||||
if (pData == 0)
|
||||
return 0;
|
||||
return ptr_to_jlong(((BMTLSDOps *)pData)->pTexture);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes nativeWidth/Height fields of the surfaceData object with
|
||||
* passed arguments.
|
||||
*/
|
||||
void
|
||||
MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *mtlsdo,
|
||||
jint width, jint height)
|
||||
{
|
||||
jobject sdObject;
|
||||
|
||||
sdObject = (*env)->NewLocalRef(env, mtlsdo->sdOps.sdObject);
|
||||
if (sdObject == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width);
|
||||
if (!((*env)->ExceptionOccurred(env))) {
|
||||
JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height);
|
||||
}
|
||||
|
||||
(*env)->DeleteLocalRef(env, sdObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes native Metal resources associated with this surface.
|
||||
*/
|
||||
void
|
||||
MTLSD_Delete(JNIEnv *env, BMTLSDOps *bmtlsdo)
|
||||
{
|
||||
J2dTraceLn3(J2D_TRACE_VERBOSE, "MTLSD_Delete: type=%d %p [tex=%p]", bmtlsdo->drawableType, bmtlsdo, bmtlsdo->pTexture);
|
||||
if (bmtlsdo->drawableType == MTLSD_WINDOW) {
|
||||
MTLSD_DestroyMTLSurface(env, bmtlsdo);
|
||||
} else if (
|
||||
bmtlsdo->drawableType == MTLSD_RT_TEXTURE
|
||||
|| bmtlsdo->drawableType == MTLSD_TEXTURE
|
||||
|| bmtlsdo->drawableType == MTLSD_FLIP_BACKBUFFER
|
||||
) {
|
||||
[(NSObject *)bmtlsdo->pTexture release];
|
||||
[(NSObject *)bmtlsdo->pStencilTexture release];
|
||||
[(NSObject *)bmtlsdo->pStencilData release];
|
||||
[(NSObject *)bmtlsdo->pStencilDataBuf release];
|
||||
[(NSObject *)bmtlsdo->pAAStencilData release];
|
||||
[(NSObject *)bmtlsdo->pAAStencilDataBuf release];
|
||||
bmtlsdo->pTexture = NULL;
|
||||
bmtlsdo->drawableType = MTLSD_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the implementation of the general DisposeFunc defined in
|
||||
* SurfaceData.h and used by the Disposer mechanism. It first flushes all
|
||||
* native Metal resources and then frees any memory allocated within the
|
||||
* native MTLSDOps structure.
|
||||
*/
|
||||
void
|
||||
MTLSD_Dispose(JNIEnv *env, SurfaceDataOps *ops)
|
||||
{
|
||||
BMTLSDOps *bmtlsdo = (BMTLSDOps *)ops;
|
||||
jobject graphicsConfig = bmtlsdo->graphicsConfig;
|
||||
|
||||
JNU_CallStaticMethodByName(env, NULL, "sun/java2d/metal/MTLSurfaceData",
|
||||
"dispose",
|
||||
"(JLsun/java2d/metal/MTLGraphicsConfig;)V",
|
||||
ptr_to_jlong(ops), graphicsConfig);
|
||||
(*env)->DeleteGlobalRef(env, graphicsConfig);
|
||||
bmtlsdo->graphicsConfig = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the implementation of the general surface LockFunc defined in
|
||||
* SurfaceData.h.
|
||||
*/
|
||||
jint
|
||||
MTLSD_Lock(JNIEnv *env,
|
||||
SurfaceDataOps *ops,
|
||||
SurfaceDataRasInfo *pRasInfo,
|
||||
jint lockflags)
|
||||
{
|
||||
JNU_ThrowInternalError(env, "MTLSD_Lock not implemented!");
|
||||
return SD_FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the implementation of the general GetRasInfoFunc defined in
|
||||
* SurfaceData.h.
|
||||
*/
|
||||
void
|
||||
MTLSD_GetRasInfo(JNIEnv *env,
|
||||
SurfaceDataOps *ops,
|
||||
SurfaceDataRasInfo *pRasInfo)
|
||||
{
|
||||
JNU_ThrowInternalError(env, "MTLSD_GetRasInfo not implemented!");
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the implementation of the general surface UnlockFunc defined in
|
||||
* SurfaceData.h.
|
||||
*/
|
||||
void
|
||||
MTLSD_Unlock(JNIEnv *env,
|
||||
SurfaceDataOps *ops,
|
||||
SurfaceDataRasInfo *pRasInfo)
|
||||
{
|
||||
JNU_ThrowInternalError(env, "MTLSD_Unlock not implemented!");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function disposes of any native windowing system resources associated
|
||||
* with this surface.
|
||||
*/
|
||||
void
|
||||
MTLSD_DestroyMTLSurface(JNIEnv *env, BMTLSDOps * bmtlsdo)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "MTLSD_DestroyMTLSurface not implemented!");
|
||||
JNI_COCOA_ENTER(env);
|
||||
bmtlsdo->drawableType = MTLSD_UNDEFINED;
|
||||
JNI_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function initializes a native window surface and caches the window
|
||||
* bounds in the given BMTLSDOps. Returns JNI_TRUE if the operation was
|
||||
* successful; JNI_FALSE otherwise.
|
||||
*/
|
||||
jboolean
|
||||
MTLSD_InitMTLWindow(JNIEnv *env, BMTLSDOps *bmtlsdo)
|
||||
{
|
||||
if (bmtlsdo == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSD_InitMTLWindow: ops are null");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps;
|
||||
if (mtlsdo == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSD_InitMTLWindow: priv ops are null");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
AWTView *v = mtlsdo->peerData;
|
||||
if (v == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSD_InitMTLWindow: view is invalid");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
JNI_COCOA_ENTER(env);
|
||||
NSRect surfaceBounds = [v bounds];
|
||||
bmtlsdo->drawableType = MTLSD_WINDOW;
|
||||
bmtlsdo->isOpaque = JNI_TRUE;
|
||||
bmtlsdo->width = surfaceBounds.size.width;
|
||||
bmtlsdo->height = surfaceBounds.size.height;
|
||||
JNI_COCOA_EXIT(env);
|
||||
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", bmtlsdo->width, bmtlsdo->height);
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark "--- MTLSurfaceData methods ---"
|
||||
|
||||
extern LockFunc MTLSD_Lock;
|
||||
extern GetRasInfoFunc MTLSD_GetRasInfo;
|
||||
extern UnlockFunc MTLSD_Unlock;
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLSurfaceData_initOps
|
||||
(JNIEnv *env, jobject mtlsd, jobject gc,
|
||||
jlong pConfigInfo, jlong pPeerData, jlong layerPtr,
|
||||
jint xoff, jint yoff, jboolean isOpaque)
|
||||
{
|
||||
BMTLSDOps *bmtlsdo = (BMTLSDOps *)SurfaceData_InitOps(env, mtlsd, sizeof(BMTLSDOps));
|
||||
MTLSDOps *mtlsdo = (MTLSDOps *)malloc(sizeof(MTLSDOps));
|
||||
|
||||
J2dTraceLn1(J2D_TRACE_INFO, "MTLSurfaceData_initOps p=%p", bmtlsdo);
|
||||
J2dTraceLn1(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData));
|
||||
J2dTraceLn1(J2D_TRACE_INFO, " layerPtr=%p", jlong_to_ptr(layerPtr));
|
||||
J2dTraceLn2(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff);
|
||||
|
||||
gc = (*env)->NewGlobalRef(env, gc);
|
||||
if (gc == NULL) {
|
||||
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mtlsdo == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, gc);
|
||||
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
// later the graphicsConfig will be used for deallocation of mtlsdo
|
||||
bmtlsdo->privOps = mtlsdo;
|
||||
bmtlsdo->graphicsConfig = gc;
|
||||
|
||||
bmtlsdo->sdOps.Lock = MTLSD_Lock;
|
||||
bmtlsdo->sdOps.GetRasInfo = MTLSD_GetRasInfo;
|
||||
bmtlsdo->sdOps.Unlock = MTLSD_Unlock;
|
||||
bmtlsdo->sdOps.Dispose = MTLSD_Dispose;
|
||||
|
||||
bmtlsdo->drawableType = MTLSD_UNDEFINED;
|
||||
bmtlsdo->xOffset = xoff;
|
||||
bmtlsdo->yOffset = yoff;
|
||||
bmtlsdo->isOpaque = isOpaque;
|
||||
|
||||
mtlsdo->peerData = (AWTView *)jlong_to_ptr(pPeerData);
|
||||
mtlsdo->layer = (MTLLayer *)jlong_to_ptr(layerPtr);
|
||||
mtlsdo->configInfo = (MTLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
|
||||
|
||||
if (mtlsdo->configInfo == NULL) {
|
||||
free(mtlsdo);
|
||||
JNU_ThrowNullPointerException(env, "Config info is null in initOps");
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLSurfaceData_clearWindow
|
||||
(JNIEnv *env, jobject mtlsd)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLSurfaceData_clearWindow");
|
||||
|
||||
BMTLSDOps *bmtlsdo = (MTLSDOps*) SurfaceData_GetOps(env, mtlsd);
|
||||
MTLSDOps *mtlsdo = (MTLSDOps*) bmtlsdo->privOps;
|
||||
|
||||
mtlsdo->peerData = NULL;
|
||||
mtlsdo->layer = NULL;
|
||||
}
|
||||
|
||||
NSString * getSurfaceDescription(const BMTLSDOps * bmtlsdOps) {
|
||||
if (bmtlsdOps == NULL)
|
||||
return @"NULL";
|
||||
return [NSString stringWithFormat:@"%p [tex=%p, %dx%d, O=%d]", bmtlsdOps, bmtlsdOps->pTexture, bmtlsdOps->width, bmtlsdOps->height, bmtlsdOps->isOpaque];
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLSurfaceDataBase_h_Included
|
||||
#define MTLSurfaceDataBase_h_Included
|
||||
|
||||
#include "java_awt_image_AffineTransformOp.h"
|
||||
#include "sun_java2d_metal_MTLSurfaceData.h"
|
||||
#include "sun_java2d_pipe_hw_AccelSurface.h"
|
||||
|
||||
#include "SurfaceData.h"
|
||||
#include "Trace.h"
|
||||
|
||||
/**
|
||||
* The MTLSDOps structure describes a native Metal surface and contains all
|
||||
* information pertaining to the native surface. Some information about
|
||||
* the more important/different fields:
|
||||
*
|
||||
* void *privOps;
|
||||
* Pointer to native-specific (Metal) SurfaceData info, such as the
|
||||
* native Drawable handle and GraphicsConfig data.
|
||||
*
|
||||
* jint drawableType;
|
||||
* The surface type; can be any one of the surface type constants defined
|
||||
* below (MTLSD_WINDOW, MTLSD_TEXTURE, etc).
|
||||
*
|
||||
* jboolean isOpaque;
|
||||
* If true, the surface should be treated as being fully opaque. If
|
||||
* the underlying surface (e.g. pbuffer) has an alpha channel and isOpaque
|
||||
* is true, then we should take appropriate action (i.e. call glColorMask()
|
||||
* to disable writes into the alpha channel) to ensure that the surface
|
||||
* remains fully opaque.
|
||||
*
|
||||
* jint x/yOffset
|
||||
* The offset in pixels of the Metal viewport origin from the lower-left
|
||||
* corner of the heavyweight drawable. For example, a top-level frame on
|
||||
* Windows XP has lower-left insets of (4,4). The Metal viewport origin
|
||||
* would typically begin at the lower-left corner of the client region (inside
|
||||
* the frame decorations), but AWT/Swing will take the insets into account
|
||||
* when rendering into that window. So in order to account for this, we
|
||||
* need to adjust the Metal viewport origin by an x/yOffset of (-4,-4). On
|
||||
* X11, top-level frames typically don't have this insets issue, so their
|
||||
* x/yOffset would be (0,0) (the same applies to pbuffers).
|
||||
*
|
||||
* jint width/height;
|
||||
* The cached surface bounds. For offscreen surface types (MTLSD_FBOBJECT,
|
||||
* MTLSD_TEXTURE, etc.) these values must remain constant. Onscreen window
|
||||
* surfaces (MTLSD_WINDOW, MTLSD_FLIP_BACKBUFFER, etc.) may have their
|
||||
* bounds changed in response to a programmatic or user-initiated event, so
|
||||
* these values represent the last known dimensions. To determine the true
|
||||
* current bounds of this surface, query the native Drawable through the
|
||||
* privOps field.
|
||||
*
|
||||
* void* pTexture;
|
||||
* The texture object handle, as generated by MTLTextureDescriptor(). If this
|
||||
* value is null, the texture has not yet been initialized.
|
||||
*
|
||||
* jint textureWidth/Height;
|
||||
* The actual bounds of the texture object for this surface.
|
||||
* The texture image that we care about has dimensions specified by the width
|
||||
* and height fields in this MTLSDOps structure.
|
||||
*/
|
||||
typedef struct {
|
||||
SurfaceDataOps sdOps;
|
||||
void *privOps;
|
||||
jobject graphicsConfig;
|
||||
jint drawableType;
|
||||
jboolean isOpaque;
|
||||
jint xOffset;
|
||||
jint yOffset;
|
||||
jint width;
|
||||
jint height;
|
||||
void* pTexture;
|
||||
void* pStencilData; // stencil data to be rendered to this buffer
|
||||
void* pStencilDataBuf; // MTLBuffer with stencil data
|
||||
void* pStencilTexture; // stencil texture byte buffer stencil mask used in main rendering
|
||||
void* pAAStencilData; // stencil data for AA rendering
|
||||
void* pAAStencilDataBuf; // MTLBuffer with AA stencil data
|
||||
jint textureWidth;
|
||||
jint textureHeight;
|
||||
} BMTLSDOps;
|
||||
|
||||
#define MTLSD_UNDEFINED sun_java2d_pipe_hw_AccelSurface_UNDEFINED
|
||||
#define MTLSD_WINDOW sun_java2d_pipe_hw_AccelSurface_WINDOW
|
||||
#define MTLSD_TEXTURE sun_java2d_pipe_hw_AccelSurface_TEXTURE
|
||||
#define MTLSD_FLIP_BACKBUFFER sun_java2d_pipe_hw_AccelSurface_FLIP_BACKBUFFER
|
||||
#define MTLSD_RT_TEXTURE sun_java2d_pipe_hw_AccelSurface_RT_TEXTURE
|
||||
|
||||
/**
|
||||
* These are shorthand names for the filtering method constants used by
|
||||
* image transform methods.
|
||||
*/
|
||||
#define MTLSD_XFORM_DEFAULT 0
|
||||
#define MTLSD_XFORM_NEAREST_NEIGHBOR \
|
||||
java_awt_image_AffineTransformOp_TYPE_NEAREST_NEIGHBOR
|
||||
#define MTLSD_XFORM_BILINEAR \
|
||||
java_awt_image_AffineTransformOp_TYPE_BILINEAR
|
||||
|
||||
/**
|
||||
* The SurfaceRasterFlags structure contains information about raster (of some MTLTexture):
|
||||
*
|
||||
* jboolean isOpaque;
|
||||
* If true, indicates that this pixel format hasn't alpha component (and values of this component can contain garbage).
|
||||
*
|
||||
* jboolean isPremultiplied;
|
||||
* If true, indicates that this pixel format contains color components that have been pre-multiplied by their
|
||||
* corresponding alpha component.
|
||||
*/
|
||||
typedef struct {
|
||||
jboolean isOpaque;
|
||||
jboolean isPremultiplied;
|
||||
} SurfaceRasterFlags;
|
||||
|
||||
/**
|
||||
* Exported methods.
|
||||
*/
|
||||
jint MTLSD_Lock(JNIEnv *env,
|
||||
SurfaceDataOps *ops, SurfaceDataRasInfo *pRasInfo,
|
||||
jint lockflags);
|
||||
void MTLSD_GetRasInfo(JNIEnv *env,
|
||||
SurfaceDataOps *ops, SurfaceDataRasInfo *pRasInfo);
|
||||
void MTLSD_Unlock(JNIEnv *env,
|
||||
SurfaceDataOps *ops, SurfaceDataRasInfo *pRasInfo);
|
||||
void MTLSD_Dispose(JNIEnv *env, SurfaceDataOps *ops);
|
||||
void MTLSD_Delete(JNIEnv *env, BMTLSDOps *mtlsdo);
|
||||
jint MTLSD_NextPowerOfTwo(jint val, jint max);
|
||||
|
||||
#endif /* MTLSurfaceDataBase_h_Included */
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLTextRenderer_h_Included
|
||||
#define MTLTextRenderer_h_Included
|
||||
|
||||
#include <jni.h>
|
||||
#include <jlong.h>
|
||||
#include "sun_java2d_pipe_BufferedTextPipe.h"
|
||||
#include "MTLContext.h"
|
||||
#include "MTLSurfaceData.h"
|
||||
|
||||
#define BYTES_PER_GLYPH_IMAGE \
|
||||
sun_java2d_pipe_BufferedTextPipe_BYTES_PER_GLYPH_IMAGE
|
||||
#define BYTES_PER_GLYPH_POSITION \
|
||||
sun_java2d_pipe_BufferedTextPipe_BYTES_PER_GLYPH_POSITION
|
||||
#define BYTES_PER_POSITIONED_GLYPH \
|
||||
(BYTES_PER_GLYPH_IMAGE + BYTES_PER_GLYPH_POSITION)
|
||||
|
||||
#define OFFSET_CONTRAST sun_java2d_pipe_BufferedTextPipe_OFFSET_CONTRAST
|
||||
#define OFFSET_RGBORDER sun_java2d_pipe_BufferedTextPipe_OFFSET_RGBORDER
|
||||
#define OFFSET_SUBPIXPOS sun_java2d_pipe_BufferedTextPipe_OFFSET_SUBPIXPOS
|
||||
#define OFFSET_POSITIONS sun_java2d_pipe_BufferedTextPipe_OFFSET_POSITIONS
|
||||
|
||||
void MTLTR_EnableGlyphVertexCache(MTLContext *mtlc, BMTLSDOps *dstOps);
|
||||
void MTLTR_DisableGlyphVertexCache(MTLContext *mtlc);
|
||||
id<MTLTexture> MTLTR_GetGlyphCacheTexture();
|
||||
void MTLTR_FreeGlyphCaches();
|
||||
|
||||
void MTLTR_DrawGlyphList(JNIEnv *env, MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
jint totalGlyphs, jboolean usePositions,
|
||||
jboolean subPixPos, jboolean rgbOrder,
|
||||
jint lcdContrast,
|
||||
jfloat glyphListOrigX, jfloat glyphListOrigY,
|
||||
unsigned char *images, unsigned char *positions);
|
||||
|
||||
#endif /* MTLTextRenderer_h_Included */
|
||||
@@ -0,0 +1,777 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <jlong.h>
|
||||
|
||||
#include "sun_java2d_metal_MTLTextRenderer.h"
|
||||
|
||||
#include "SurfaceData.h"
|
||||
#include "MTLContext.h"
|
||||
#include "MTLRenderQueue.h"
|
||||
#include "MTLTextRenderer.h"
|
||||
#include "MTLVertexCache.h"
|
||||
#include "MTLGlyphCache.h"
|
||||
#include "MTLBlitLoops.h"
|
||||
|
||||
/**
|
||||
* The following constants define the inner and outer bounds of the
|
||||
* accelerated glyph cache.
|
||||
*/
|
||||
#define MTLTR_CACHE_WIDTH 512
|
||||
#define MTLTR_CACHE_HEIGHT 512
|
||||
#define MTLTR_CACHE_CELL_WIDTH 32
|
||||
#define MTLTR_CACHE_CELL_HEIGHT 32
|
||||
|
||||
/**
|
||||
* The current "glyph mode" state. This variable is used to track the
|
||||
* codepath used to render a particular glyph. This variable is reset to
|
||||
* MODE_NOT_INITED at the beginning of every call to MTLTR_DrawGlyphList().
|
||||
* As each glyph is rendered, the glyphMode variable is updated to reflect
|
||||
* the current mode, so if the current mode is the same as the mode used
|
||||
* to render the previous glyph, we can avoid doing costly setup operations
|
||||
* each time.
|
||||
*/
|
||||
typedef enum {
|
||||
MODE_NOT_INITED,
|
||||
MODE_USE_CACHE_GRAY,
|
||||
MODE_USE_CACHE_LCD,
|
||||
MODE_NO_CACHE_GRAY,
|
||||
MODE_NO_CACHE_LCD,
|
||||
MODE_NO_CACHE_COLOR
|
||||
} GlyphMode;
|
||||
static GlyphMode glyphMode = MODE_NOT_INITED;
|
||||
|
||||
/**
|
||||
* There are two separate glyph caches: for AA and for LCD.
|
||||
* Once one of them is initialized as either GRAY or LCD, it
|
||||
* stays in that mode for the duration of the application. It should
|
||||
* be safe to use this one glyph cache for all screens in a multimon
|
||||
* environment, since the glyph cache texture is shared between all contexts,
|
||||
* and (in theory) Metal drivers should be smart enough to manage that
|
||||
* texture across all screens.
|
||||
*/
|
||||
|
||||
static MTLGlyphCacheInfo *glyphCacheLCD = NULL;
|
||||
static MTLGlyphCacheInfo *glyphCacheAA = NULL;
|
||||
|
||||
/**
|
||||
* This value tracks the previous LCD rgbOrder setting, so if the rgbOrder
|
||||
* value has changed since the last time, it indicates that we need to
|
||||
* invalidate the cache, which may already store glyph images in the reverse
|
||||
* order. Note that in most real world applications this value will not
|
||||
* change over the course of the application, but tests like Font2DTest
|
||||
* allow for changing the ordering at runtime, so we need to handle that case.
|
||||
*/
|
||||
static jboolean lastRGBOrder = JNI_TRUE;
|
||||
|
||||
/**
|
||||
* This constant defines the size of the tile to use in the
|
||||
* MTLTR_DrawLCDGlyphNoCache() method. See below for more on why we
|
||||
* restrict this value to a particular size.
|
||||
*/
|
||||
#define MTLTR_NOCACHE_TILE_SIZE 32
|
||||
|
||||
static struct TxtVertex txtVertices[6];
|
||||
static jint vertexCacheIndex = 0;
|
||||
static id<MTLRenderCommandEncoder> lcdCacheEncoder = nil;
|
||||
|
||||
#define LCD_ADD_VERTEX(TX, TY, DX, DY, DZ) \
|
||||
do { \
|
||||
struct TxtVertex *v = &txtVertices[vertexCacheIndex++]; \
|
||||
v->txtpos[0] = TX; \
|
||||
v->txtpos[1] = TY; \
|
||||
v->position[0]= DX; \
|
||||
v->position[1] = DY; \
|
||||
} while (0)
|
||||
|
||||
#define LCD_ADD_TRIANGLES(TX1, TY1, TX2, TY2, DX1, DY1, DX2, DY2) \
|
||||
do { \
|
||||
LCD_ADD_VERTEX(TX1, TY1, DX1, DY1, 0); \
|
||||
LCD_ADD_VERTEX(TX2, TY1, DX2, DY1, 0); \
|
||||
LCD_ADD_VERTEX(TX2, TY2, DX2, DY2, 0); \
|
||||
LCD_ADD_VERTEX(TX2, TY2, DX2, DY2, 0); \
|
||||
LCD_ADD_VERTEX(TX1, TY2, DX1, DY2, 0); \
|
||||
LCD_ADD_VERTEX(TX1, TY1, DX1, DY1, 0); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Initializes the one glyph cache (texture and data structure).
|
||||
* If lcdCache is JNI_TRUE, the texture will contain RGB data,
|
||||
* otherwise we will simply store the grayscale/monochrome glyph images
|
||||
* as intensity values.
|
||||
*/
|
||||
static jboolean
|
||||
MTLTR_InitGlyphCache(MTLContext *mtlc, jboolean lcdCache)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_InitGlyphCache");
|
||||
// TODO : Need to verify RGB order in case of LCD
|
||||
MTLPixelFormat pixelFormat =
|
||||
lcdCache ? MTLPixelFormatBGRA8Unorm : MTLPixelFormatA8Unorm;
|
||||
|
||||
MTLGlyphCacheInfo *gcinfo;
|
||||
// init glyph cache data structure
|
||||
gcinfo = MTLGlyphCache_Init(MTLTR_CACHE_WIDTH,
|
||||
MTLTR_CACHE_HEIGHT,
|
||||
MTLTR_CACHE_CELL_WIDTH,
|
||||
MTLTR_CACHE_CELL_HEIGHT,
|
||||
MTLVertexCache_FlushGlyphVertexCache);
|
||||
|
||||
if (gcinfo == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLTR_InitGlyphCache: could not init MTL glyph cache");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
MTLTextureDescriptor *textureDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixelFormat
|
||||
width:MTLTR_CACHE_WIDTH
|
||||
height:MTLTR_CACHE_HEIGHT
|
||||
mipmapped:NO];
|
||||
|
||||
gcinfo->texture = [mtlc.device newTextureWithDescriptor:textureDescriptor];
|
||||
|
||||
if (lcdCache) {
|
||||
glyphCacheLCD = gcinfo;
|
||||
} else {
|
||||
glyphCacheAA = gcinfo;
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
id<MTLTexture>
|
||||
MTLTR_GetGlyphCacheTexture()
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_GetGlyphCacheTexture");
|
||||
if (glyphCacheAA != NULL) {
|
||||
return glyphCacheAA->texture;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given glyph to the glyph cache (texture and data structure)
|
||||
* associated with the given MTLContext.
|
||||
*/
|
||||
static void
|
||||
MTLTR_AddToGlyphCache(GlyphInfo *glyph, MTLContext *mtlc,
|
||||
jboolean lcdCache)
|
||||
{
|
||||
MTLCacheCellInfo *ccinfo;
|
||||
MTLGlyphCacheInfo *gcinfo;
|
||||
jint w = glyph->width;
|
||||
jint h = glyph->height;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_AddToGlyphCache");
|
||||
if (!lcdCache) {
|
||||
gcinfo = glyphCacheAA;
|
||||
} else {
|
||||
gcinfo = glyphCacheLCD;
|
||||
}
|
||||
|
||||
if ((gcinfo == NULL) || (glyph->image == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool isCacheFull = MTLGlyphCache_IsCacheFull(gcinfo, glyph);
|
||||
if (isCacheFull) {
|
||||
MTLGlyphCache_Free(gcinfo);
|
||||
if (!lcdCache) {
|
||||
MTLTR_InitGlyphCache(mtlc, JNI_FALSE);
|
||||
gcinfo = glyphCacheAA;
|
||||
} else {
|
||||
MTLTR_InitGlyphCache(mtlc, JNI_TRUE);
|
||||
gcinfo = glyphCacheLCD;
|
||||
}
|
||||
}
|
||||
MTLGlyphCache_AddGlyph(gcinfo, glyph);
|
||||
ccinfo = (MTLCacheCellInfo *) glyph->cellInfo;
|
||||
|
||||
if (ccinfo != NULL) {
|
||||
// store glyph image in texture cell
|
||||
MTLRegion region = {
|
||||
{ccinfo->x, ccinfo->y, 0},
|
||||
{w, h, 1}
|
||||
};
|
||||
if (!lcdCache) {
|
||||
NSUInteger bytesPerRow = 1 * w;
|
||||
[gcinfo->texture replaceRegion:region
|
||||
mipmapLevel:0
|
||||
withBytes:glyph->image
|
||||
bytesPerRow:bytesPerRow];
|
||||
} else {
|
||||
unsigned int imageBytes = w * h * 4;
|
||||
unsigned char imageData[imageBytes];
|
||||
memset(&imageData, 0, sizeof(imageData));
|
||||
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < w; j++) {
|
||||
imageData[(i * w * 4) + j * 4] = glyph->image[(i * w * 3) + j * 3];
|
||||
imageData[(i * w * 4) + j * 4 + 1] = glyph->image[(i * w * 3) + j * 3 + 1];
|
||||
imageData[(i * w * 4) + j * 4 + 2] = glyph->image[(i * w * 3) + j * 3 + 2];
|
||||
imageData[(i * w * 4) + j * 4 + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
NSUInteger bytesPerRow = 4 * w;
|
||||
[gcinfo->texture replaceRegion:region
|
||||
mipmapLevel:0
|
||||
withBytes:imageData
|
||||
bytesPerRow:bytesPerRow];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static jboolean
|
||||
MTLTR_SetLCDContrast(MTLContext *mtlc,
|
||||
jint contrast,
|
||||
id<MTLRenderCommandEncoder> encoder)
|
||||
{
|
||||
if (![mtlc.paint isKindOfClass:[MTLColorPaint class]]) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
MTLColorPaint* cPaint = (MTLColorPaint *) mtlc.paint;
|
||||
// update the current color settings
|
||||
double gamma = ((double)contrast) / 100.0;
|
||||
double invgamma = 1.0/gamma;
|
||||
jfloat radj, gadj, badj;
|
||||
jfloat clr[4];
|
||||
jint col = cPaint.color;
|
||||
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "primary color %x, contrast %d", col, contrast);
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "gamma %f, invgamma %f", gamma, invgamma);
|
||||
|
||||
clr[0] = ((col >> 16) & 0xFF)/255.0f;
|
||||
clr[1] = ((col >> 8) & 0xFF)/255.0f;
|
||||
clr[2] = ((col) & 0xFF)/255.0f;
|
||||
|
||||
// gamma adjust the primary color
|
||||
radj = (float)pow(clr[0], gamma);
|
||||
gadj = (float)pow(clr[1], gamma);
|
||||
badj = (float)pow(clr[2], gamma);
|
||||
|
||||
struct LCDFrameUniforms uf = {
|
||||
{radj, gadj, badj},
|
||||
{gamma, gamma, gamma},
|
||||
{invgamma, invgamma, invgamma}};
|
||||
[encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
MTLTR_EnableGlyphVertexCache(MTLContext *mtlc, BMTLSDOps *dstOps)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_EnableGlyphVertexCache");
|
||||
|
||||
if (!MTLVertexCache_InitVertexCache()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (glyphCacheAA == NULL) {
|
||||
if (!MTLTR_InitGlyphCache(mtlc, JNI_FALSE)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
MTLVertexCache_CreateSamplingEncoder(mtlc, dstOps);
|
||||
}
|
||||
|
||||
void
|
||||
MTLTR_DisableGlyphVertexCache(MTLContext *mtlc)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DisableGlyphVertexCache");
|
||||
MTLVertexCache_FlushGlyphVertexCache();
|
||||
MTLVertexCache_FreeVertexCache();
|
||||
}
|
||||
|
||||
void MTLTR_FreeGlyphCaches() {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_FreeGlyphCaches : freeing glyph caches.");
|
||||
|
||||
if (glyphCacheAA != NULL) {
|
||||
[glyphCacheAA->texture release];
|
||||
MTLGlyphCache_Free(glyphCacheAA);
|
||||
glyphCacheAA = NULL;
|
||||
}
|
||||
|
||||
if (glyphCacheLCD != NULL) {
|
||||
[glyphCacheLCD->texture release];
|
||||
MTLGlyphCache_Free(glyphCacheLCD);
|
||||
glyphCacheLCD = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static jboolean
|
||||
MTLTR_DrawGrayscaleGlyphViaCache(MTLContext *mtlc,
|
||||
GlyphInfo *ginfo, jint x, jint y, BMTLSDOps *dstOps)
|
||||
{
|
||||
MTLCacheCellInfo *cell;
|
||||
jfloat x1, y1, x2, y2;
|
||||
|
||||
if (glyphMode != MODE_USE_CACHE_GRAY) {
|
||||
if (glyphMode == MODE_NO_CACHE_GRAY) {
|
||||
MTLVertexCache_DisableMaskCache(mtlc);
|
||||
} else if (glyphMode == MODE_USE_CACHE_LCD) {
|
||||
[mtlc.encoderManager endEncoder];
|
||||
lcdCacheEncoder = nil;
|
||||
}
|
||||
MTLTR_EnableGlyphVertexCache(mtlc, dstOps);
|
||||
glyphMode = MODE_USE_CACHE_GRAY;
|
||||
}
|
||||
|
||||
if (ginfo->cellInfo == NULL) {
|
||||
// attempt to add glyph to accelerated glyph cache
|
||||
MTLTR_AddToGlyphCache(ginfo, mtlc, JNI_FALSE);
|
||||
|
||||
if (ginfo->cellInfo == NULL) {
|
||||
// we'll just no-op in the rare case that the cell is NULL
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
cell = (MTLCacheCellInfo *) (ginfo->cellInfo);
|
||||
cell->timesRendered++;
|
||||
|
||||
x1 = (jfloat)x;
|
||||
y1 = (jfloat)y;
|
||||
x2 = x1 + ginfo->width;
|
||||
y2 = y1 + ginfo->height;
|
||||
|
||||
MTLVertexCache_AddGlyphQuad(mtlc,
|
||||
cell->tx1, cell->ty1,
|
||||
cell->tx2, cell->ty2,
|
||||
x1, y1, x2, y2);
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static jboolean
|
||||
MTLTR_DrawLCDGlyphViaCache(MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
GlyphInfo *ginfo, jint x, jint y,
|
||||
jboolean rgbOrder, jint contrast)
|
||||
{
|
||||
CacheCellInfo *cell;
|
||||
jfloat tx1, ty1, tx2, ty2;
|
||||
jint w = ginfo->width;
|
||||
jint h = ginfo->height;
|
||||
|
||||
if (glyphMode != MODE_USE_CACHE_LCD) {
|
||||
if (glyphMode == MODE_NO_CACHE_GRAY) {
|
||||
MTLVertexCache_DisableMaskCache(mtlc);
|
||||
} else if (glyphMode == MODE_USE_CACHE_GRAY) {
|
||||
MTLTR_DisableGlyphVertexCache(mtlc);
|
||||
}
|
||||
|
||||
if (glyphCacheLCD == NULL) {
|
||||
if (!MTLTR_InitGlyphCache(mtlc, JNI_TRUE)) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
if (lcdCacheEncoder == nil) {
|
||||
lcdCacheEncoder = [mtlc.encoderManager getLCDEncoder:dstOps->pTexture isSrcOpaque:YES isDstOpaque:YES];
|
||||
}
|
||||
if (rgbOrder != lastRGBOrder) {
|
||||
// need to invalidate the cache in this case; see comments
|
||||
// for lastRGBOrder above
|
||||
MTLGlyphCache_Invalidate(glyphCacheLCD);
|
||||
lastRGBOrder = rgbOrder;
|
||||
}
|
||||
|
||||
glyphMode = MODE_USE_CACHE_LCD;
|
||||
}
|
||||
|
||||
if (ginfo->cellInfo == NULL) {
|
||||
// attempt to add glyph to accelerated glyph cache
|
||||
// TODO : Handle RGB order
|
||||
MTLTR_AddToGlyphCache(ginfo, mtlc, JNI_TRUE);
|
||||
|
||||
if (ginfo->cellInfo == NULL) {
|
||||
// we'll just no-op in the rare case that the cell is NULL
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
cell = (CacheCellInfo *) (ginfo->cellInfo);
|
||||
cell->timesRendered++;
|
||||
|
||||
MTLTR_SetLCDContrast(mtlc, contrast, lcdCacheEncoder);
|
||||
tx1 = cell->tx1;
|
||||
ty1 = cell->ty1;
|
||||
tx2 = cell->tx2;
|
||||
ty2 = cell->ty2;
|
||||
|
||||
J2dTraceLn4(J2D_TRACE_INFO, "tx1 %f, ty1 %f, tx2 %f, ty2 %f", tx1, ty1, tx2, ty2);
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "textureWidth %d textureHeight %d", dstOps->textureWidth, dstOps->textureHeight);
|
||||
|
||||
LCD_ADD_TRIANGLES(tx1, ty1, tx2, ty2, x, y, x+w, y+h);
|
||||
|
||||
[lcdCacheEncoder setVertexBytes:txtVertices length:sizeof(txtVertices) atIndex:MeshVertexBuffer];
|
||||
[lcdCacheEncoder setFragmentTexture:glyphCacheLCD->texture atIndex:0];
|
||||
[lcdCacheEncoder setFragmentTexture:dstOps->pTexture atIndex:1];
|
||||
|
||||
[lcdCacheEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
|
||||
|
||||
vertexCacheIndex = 0;
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static jboolean
|
||||
MTLTR_DrawGrayscaleGlyphNoCache(MTLContext *mtlc,
|
||||
GlyphInfo *ginfo, jint x, jint y, BMTLSDOps *dstOps)
|
||||
{
|
||||
jint tw, th;
|
||||
jint sx, sy, sw, sh;
|
||||
jint x0;
|
||||
jint w = ginfo->width;
|
||||
jint h = ginfo->height;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DrawGrayscaleGlyphNoCache");
|
||||
if (glyphMode != MODE_NO_CACHE_GRAY) {
|
||||
if (glyphMode == MODE_USE_CACHE_GRAY) {
|
||||
MTLTR_DisableGlyphVertexCache(mtlc);
|
||||
} else if (glyphMode == MODE_USE_CACHE_LCD) {
|
||||
[mtlc.encoderManager endEncoder];
|
||||
lcdCacheEncoder = nil;
|
||||
}
|
||||
MTLVertexCache_EnableMaskCache(mtlc, dstOps);
|
||||
glyphMode = MODE_NO_CACHE_GRAY;
|
||||
}
|
||||
|
||||
x0 = x;
|
||||
tw = MTLVC_MASK_CACHE_TILE_WIDTH;
|
||||
th = MTLVC_MASK_CACHE_TILE_HEIGHT;
|
||||
|
||||
for (sy = 0; sy < h; sy += th, y += th) {
|
||||
x = x0;
|
||||
sh = ((sy + th) > h) ? (h - sy) : th;
|
||||
|
||||
for (sx = 0; sx < w; sx += tw, x += tw) {
|
||||
sw = ((sx + tw) > w) ? (w - sx) : tw;
|
||||
|
||||
J2dTraceLn7(J2D_TRACE_INFO, "sx = %d sy = %d x = %d y = %d sw = %d sh = %d w = %d", sx, sy, x, y, sw, sh, w);
|
||||
MTLVertexCache_AddMaskQuad(mtlc,
|
||||
sx, sy, x, y, sw, sh,
|
||||
w, ginfo->image,
|
||||
dstOps);
|
||||
}
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static jboolean
|
||||
MTLTR_DrawLCDGlyphNoCache(MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
GlyphInfo *ginfo, jint x, jint y,
|
||||
jint rowBytesOffset,
|
||||
jboolean rgbOrder, jint contrast)
|
||||
{
|
||||
jfloat tx1, ty1, tx2, ty2;
|
||||
jint tw, th;
|
||||
jint w = ginfo->width;
|
||||
jint h = ginfo->height;
|
||||
id<MTLTexture> blitTexture = nil;
|
||||
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "MTLTR_DrawLCDGlyphNoCache x %d, y%d", x, y);
|
||||
J2dTraceLn3(J2D_TRACE_INFO, "MTLTR_DrawLCDGlyphNoCache rowBytesOffset=%d, rgbOrder=%d, contrast=%d", rowBytesOffset, rgbOrder, contrast);
|
||||
|
||||
|
||||
id<MTLRenderCommandEncoder> encoder = nil;
|
||||
|
||||
MTLTextureDescriptor *textureDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
||||
width:w
|
||||
height:h
|
||||
mipmapped:NO];
|
||||
|
||||
blitTexture = [mtlc.device newTextureWithDescriptor:textureDescriptor];
|
||||
|
||||
if (glyphMode != MODE_NO_CACHE_LCD) {
|
||||
if (glyphMode == MODE_NO_CACHE_GRAY) {
|
||||
MTLVertexCache_DisableMaskCache(mtlc);
|
||||
} else if (glyphMode == MODE_USE_CACHE_GRAY) {
|
||||
MTLTR_DisableGlyphVertexCache(mtlc);
|
||||
} else if (glyphMode == MODE_USE_CACHE_LCD) {
|
||||
[mtlc.encoderManager endEncoder];
|
||||
lcdCacheEncoder = nil;
|
||||
}
|
||||
|
||||
if (blitTexture == nil) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR, "can't obtain temporary texture object from pool");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
|
||||
glyphMode = MODE_NO_CACHE_LCD;
|
||||
}
|
||||
encoder = [mtlc.encoderManager getLCDEncoder:dstOps->pTexture isSrcOpaque:YES isDstOpaque:YES];
|
||||
MTLTR_SetLCDContrast(mtlc, contrast, encoder);
|
||||
|
||||
unsigned int imageBytes = w * h *4;
|
||||
unsigned char imageData[imageBytes];
|
||||
memset(&imageData, 0, sizeof(imageData));
|
||||
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < w; j++) {
|
||||
imageData[(i * w * 4) + j * 4] = ginfo->image[((i * w * 3) + j * 3) + rowBytesOffset];
|
||||
imageData[(i * w * 4) + j * 4 + 1] = ginfo->image[((i * w * 3) + j * 3 + 1) + rowBytesOffset];
|
||||
imageData[(i * w * 4) + j * 4 + 2] = ginfo->image[((i * w * 3) + j * 3 + 2) + rowBytesOffset];
|
||||
imageData[(i * w * 4) + j * 4 + 3] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
// copy LCD mask into glyph texture tile
|
||||
MTLRegion region = MTLRegionMake2D(0, 0, w, h);
|
||||
|
||||
NSUInteger bytesPerRow = 4 * ginfo->width;
|
||||
[blitTexture replaceRegion:region
|
||||
mipmapLevel:0
|
||||
withBytes:imageData
|
||||
bytesPerRow:bytesPerRow];
|
||||
|
||||
tx1 = 0.0f;
|
||||
ty1 = 0.0f;
|
||||
tx2 = 1.0f;
|
||||
ty2 = 1.0f;
|
||||
|
||||
J2dTraceLn3(J2D_TRACE_INFO, "xOffset %d yOffset %d, dstOps->height %d", dstOps->xOffset, dstOps->yOffset, dstOps->height);
|
||||
J2dTraceLn4(J2D_TRACE_INFO, "tx1 %f, ty1 %f, tx2 %f, ty2 %f", tx1, ty1, tx2, ty2);
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "textureWidth %d textureHeight %d", dstOps->textureWidth, dstOps->textureHeight);
|
||||
|
||||
LCD_ADD_TRIANGLES(tx1, ty1, tx2, ty2, x, y, x+w, y+h);
|
||||
|
||||
[encoder setVertexBytes:txtVertices length:sizeof(txtVertices) atIndex:MeshVertexBuffer];
|
||||
[encoder setFragmentTexture:blitTexture atIndex:0];
|
||||
[encoder setFragmentTexture:dstOps->pTexture atIndex:1];
|
||||
|
||||
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
|
||||
|
||||
vertexCacheIndex = 0;
|
||||
[mtlc.encoderManager endEncoder];
|
||||
[blitTexture release];
|
||||
|
||||
MTLCommandBufferWrapper* cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
|
||||
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
|
||||
[commandbuf commit];
|
||||
[commandbuf waitUntilCompleted];
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
// see DrawGlyphList.c for more on this macro...
|
||||
#define FLOOR_ASSIGN(l, r) \
|
||||
if ((r)<0) (l) = ((int)floor(r)); else (l) = ((int)(r))
|
||||
|
||||
void
|
||||
MTLTR_DrawGlyphList(JNIEnv *env, MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
jint totalGlyphs, jboolean usePositions,
|
||||
jboolean subPixPos, jboolean rgbOrder, jint lcdContrast,
|
||||
jfloat glyphListOrigX, jfloat glyphListOrigY,
|
||||
unsigned char *images, unsigned char *positions)
|
||||
{
|
||||
int glyphCounter;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DrawGlyphList");
|
||||
|
||||
RETURN_IF_NULL(mtlc);
|
||||
RETURN_IF_NULL(dstOps);
|
||||
RETURN_IF_NULL(images);
|
||||
if (usePositions) {
|
||||
RETURN_IF_NULL(positions);
|
||||
}
|
||||
|
||||
glyphMode = MODE_NOT_INITED;
|
||||
J2dTraceLn1(J2D_TRACE_INFO, "totalGlyphs = %d", totalGlyphs);
|
||||
jboolean flushBeforeLCD = JNI_FALSE;
|
||||
|
||||
for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "Entered for loop for glyph list");
|
||||
jint x, y;
|
||||
jfloat glyphx, glyphy;
|
||||
jboolean grayscale, ok;
|
||||
GlyphInfo *ginfo = (GlyphInfo *)jlong_to_ptr(NEXT_LONG(images));
|
||||
|
||||
if (ginfo == NULL) {
|
||||
// this shouldn't happen, but if it does we'll just break out...
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLTR_DrawGlyphList: glyph info is null");
|
||||
break;
|
||||
}
|
||||
|
||||
grayscale = (ginfo->rowBytes == ginfo->width);
|
||||
|
||||
if (usePositions) {
|
||||
jfloat posx = NEXT_FLOAT(positions);
|
||||
jfloat posy = NEXT_FLOAT(positions);
|
||||
glyphx = glyphListOrigX + posx + ginfo->topLeftX;
|
||||
glyphy = glyphListOrigY + posy + ginfo->topLeftY;
|
||||
FLOOR_ASSIGN(x, glyphx);
|
||||
FLOOR_ASSIGN(y, glyphy);
|
||||
} else {
|
||||
glyphx = glyphListOrigX + ginfo->topLeftX;
|
||||
glyphy = glyphListOrigY + ginfo->topLeftY;
|
||||
FLOOR_ASSIGN(x, glyphx);
|
||||
FLOOR_ASSIGN(y, glyphy);
|
||||
glyphListOrigX += ginfo->advanceX;
|
||||
glyphListOrigY += ginfo->advanceY;
|
||||
}
|
||||
|
||||
if (ginfo->image == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "Glyph image is null");
|
||||
continue;
|
||||
}
|
||||
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "Glyph width = %d height = %d", ginfo->width, ginfo->height);
|
||||
J2dTraceLn1(J2D_TRACE_INFO, "rowBytes = %d", ginfo->rowBytes);
|
||||
if (grayscale) {
|
||||
// grayscale or monochrome glyph data
|
||||
if (ginfo->width <= MTLTR_CACHE_CELL_WIDTH &&
|
||||
ginfo->height <= MTLTR_CACHE_CELL_HEIGHT)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DrawGlyphList Grayscale cache");
|
||||
ok = MTLTR_DrawGrayscaleGlyphViaCache(mtlc, ginfo, x, y, dstOps);
|
||||
} else {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DrawGlyphList Grayscale no cache");
|
||||
ok = MTLTR_DrawGrayscaleGlyphNoCache(mtlc, ginfo, x, y, dstOps);
|
||||
}
|
||||
} else {
|
||||
if (!flushBeforeLCD) {
|
||||
[mtlc.encoderManager endEncoder];
|
||||
MTLCommandBufferWrapper* cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
|
||||
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
|
||||
[commandbuf commit];
|
||||
flushBeforeLCD = JNI_TRUE;
|
||||
}
|
||||
|
||||
// LCD-optimized glyph data
|
||||
jint rowBytesOffset = 0;
|
||||
|
||||
if (subPixPos) {
|
||||
jint frac = (jint)((glyphx - x) * 3);
|
||||
if (frac != 0) {
|
||||
rowBytesOffset = 3 - frac;
|
||||
x += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rowBytesOffset == 0 &&
|
||||
ginfo->width <= MTLTR_CACHE_CELL_WIDTH &&
|
||||
ginfo->height <= MTLTR_CACHE_CELL_HEIGHT)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DrawGlyphList LCD cache");
|
||||
ok = MTLTR_DrawLCDGlyphViaCache(mtlc, dstOps,
|
||||
ginfo, x, y,
|
||||
rgbOrder, lcdContrast);
|
||||
} else {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DrawGlyphList LCD no cache");
|
||||
ok = MTLTR_DrawLCDGlyphNoCache(mtlc, dstOps,
|
||||
ginfo, x, y,
|
||||
rowBytesOffset,
|
||||
rgbOrder, lcdContrast);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Only in case of grayscale text drawing we need to flush
|
||||
* cache. Still in case of LCD we are not using any intermediate
|
||||
* cache.
|
||||
*/
|
||||
if (glyphMode == MODE_NO_CACHE_GRAY) {
|
||||
MTLVertexCache_DisableMaskCache(mtlc);
|
||||
} else if (glyphMode == MODE_USE_CACHE_GRAY) {
|
||||
MTLTR_DisableGlyphVertexCache(mtlc);
|
||||
} else if (glyphMode == MODE_USE_CACHE_LCD) {
|
||||
[mtlc.encoderManager endEncoder];
|
||||
lcdCacheEncoder = nil;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLTextRenderer_drawGlyphList
|
||||
(JNIEnv *env, jobject self,
|
||||
jint numGlyphs, jboolean usePositions,
|
||||
jboolean subPixPos, jboolean rgbOrder, jint lcdContrast,
|
||||
jfloat glyphListOrigX, jfloat glyphListOrigY,
|
||||
jlongArray imgArray, jfloatArray posArray)
|
||||
{
|
||||
unsigned char *images;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTextRenderer_drawGlyphList");
|
||||
|
||||
images = (unsigned char *)
|
||||
(*env)->GetPrimitiveArrayCritical(env, imgArray, NULL);
|
||||
if (images != NULL) {
|
||||
MTLContext *mtlc = MTLRenderQueue_GetCurrentContext();
|
||||
BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination();
|
||||
|
||||
if (usePositions) {
|
||||
unsigned char *positions = (unsigned char *)
|
||||
(*env)->GetPrimitiveArrayCritical(env, posArray, NULL);
|
||||
if (positions != NULL) {
|
||||
MTLTR_DrawGlyphList(env, mtlc, dstOps,
|
||||
numGlyphs, usePositions,
|
||||
subPixPos, rgbOrder, lcdContrast,
|
||||
glyphListOrigX, glyphListOrigY,
|
||||
images, positions);
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, posArray,
|
||||
positions, JNI_ABORT);
|
||||
}
|
||||
} else {
|
||||
MTLTR_DrawGlyphList(env, mtlc, dstOps,
|
||||
numGlyphs, usePositions,
|
||||
subPixPos, rgbOrder, lcdContrast,
|
||||
glyphListOrigX, glyphListOrigY,
|
||||
images, NULL);
|
||||
}
|
||||
if (mtlc != NULL) {
|
||||
RESET_PREVIOUS_OP();
|
||||
[mtlc.encoderManager endEncoder];
|
||||
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
|
||||
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
|
||||
[commandbuf addCompletedHandler:^(id <MTLCommandBuffer> commandbuf) {
|
||||
[cbwrapper release];
|
||||
}];
|
||||
[commandbuf commit];
|
||||
}
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, imgArray,
|
||||
images, JNI_ABORT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLTexturePool_h_Included
|
||||
#define MTLTexturePool_h_Included
|
||||
#include <time.h>
|
||||
#import "MTLUtils.h"
|
||||
|
||||
@class MTLPoolCell;
|
||||
|
||||
@interface MTLTexturePoolItem : NSObject
|
||||
@property (readwrite, retain) id<MTLTexture> texture;
|
||||
@property (readwrite) bool isBusy;
|
||||
@property (readwrite) time_t lastUsed;
|
||||
@property (readwrite) bool isMultiSample;
|
||||
@property (readwrite, assign) MTLTexturePoolItem* prev;
|
||||
@property (readwrite, retain) MTLTexturePoolItem* next;
|
||||
@property (readwrite, assign) MTLPoolCell* cell;
|
||||
|
||||
- (id) initWithTexture:(id<MTLTexture>)tex cell:(MTLPoolCell*)cell;
|
||||
@end
|
||||
|
||||
@interface MTLPooledTextureHandle : NSObject
|
||||
@property (readonly, assign) id<MTLTexture> texture;
|
||||
@property (readonly) MTLRegion rect;
|
||||
- (void) releaseTexture;
|
||||
@end
|
||||
|
||||
// NOTE: owns all MTLTexture objects
|
||||
@interface MTLTexturePool : NSObject
|
||||
@property (readwrite, retain) id<MTLDevice> device;
|
||||
|
||||
- (id) initWithDevice:(id<MTLDevice>)device;
|
||||
- (MTLPooledTextureHandle *) getTexture:(int)width height:(int)height format:(MTLPixelFormat)format;
|
||||
- (MTLPooledTextureHandle *) getTexture:(int)width height:(int)height format:(MTLPixelFormat)format
|
||||
isMultiSample:(bool)isMultiSample;
|
||||
@end
|
||||
|
||||
@interface MTLPoolCell : NSObject
|
||||
@property (readwrite, retain) MTLTexturePoolItem* available;
|
||||
@property (readwrite, assign) MTLTexturePoolItem* availableTail;
|
||||
@property (readwrite, retain) MTLTexturePoolItem* occupied;
|
||||
- (MTLTexturePoolItem *)createItem:(id<MTLDevice>)dev
|
||||
width:(int)width
|
||||
height:(int)height
|
||||
format:(MTLPixelFormat)format
|
||||
isMultiSample:(bool)isMultiSample;
|
||||
- (NSUInteger)cleanIfBefore:(time_t)lastUsedTimeToRemove;
|
||||
- (void)releaseItem:(MTLTexturePoolItem *)item;
|
||||
@end
|
||||
|
||||
#endif /* MTLTexturePool_h_Included */
|
||||
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#import "MTLTexturePool.h"
|
||||
#import "Trace.h"
|
||||
|
||||
#define SCREEN_MEMORY_SIZE_4K (4096*2160*4) //~33,7 mb
|
||||
#define MAX_POOL_MEMORY SCREEN_MEMORY_SIZE_4K/2
|
||||
#define MAX_POOL_ITEM_LIFETIME_SEC 30
|
||||
|
||||
#define CELL_WIDTH_BITS 5 // ~ 32 pixel
|
||||
#define CELL_HEIGHT_BITS 5 // ~ 32 pixel
|
||||
|
||||
@implementation MTLTexturePoolItem
|
||||
|
||||
@synthesize texture, isBusy, lastUsed, isMultiSample, next, cell;
|
||||
|
||||
- (id) initWithTexture:(id<MTLTexture>)tex cell:(MTLPoolCell*)c{
|
||||
self = [super init];
|
||||
if (self == nil) return self;
|
||||
self.texture = tex;
|
||||
isBusy = NO;
|
||||
self.next = nil;
|
||||
self.prev = nil;
|
||||
self.cell = c;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
[texture release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTLPooledTextureHandle
|
||||
{
|
||||
MTLRegion _rect;
|
||||
id<MTLTexture> _texture;
|
||||
MTLTexturePoolItem * _poolItem;
|
||||
}
|
||||
@synthesize texture = _texture, rect = _rect;
|
||||
|
||||
- (id) initWithPoolItem:(id<MTLTexture>)texture rect:(MTLRegion)rectangle poolItem:(MTLTexturePoolItem *)poolItem {
|
||||
self = [super init];
|
||||
if (self == nil) return self;
|
||||
|
||||
_rect = rectangle;
|
||||
_texture = texture;
|
||||
_poolItem = poolItem;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) releaseTexture {
|
||||
[_poolItem.cell releaseItem:_poolItem];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTLPoolCell {
|
||||
NSLock* _lock;
|
||||
}
|
||||
@synthesize available, availableTail, occupied;
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.available = nil;
|
||||
self.availableTail = nil;
|
||||
self.occupied = nil;
|
||||
_lock = [[NSLock alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)occupyItem:(MTLTexturePoolItem *)item {
|
||||
if (item.isBusy) return;
|
||||
[item retain];
|
||||
if (item.prev == nil) {
|
||||
self.available = item.next;
|
||||
if (item.next) {
|
||||
item.next.prev = nil;
|
||||
} else {
|
||||
self.availableTail = item.prev;
|
||||
}
|
||||
} else {
|
||||
item.prev.next = item.next;
|
||||
if (item.next) {
|
||||
item.next.prev = item.prev;
|
||||
} else {
|
||||
self.availableTail = item.prev;
|
||||
}
|
||||
item.prev = nil;
|
||||
}
|
||||
if (occupied) occupied.prev = item;
|
||||
item.next = occupied;
|
||||
self.occupied = item;
|
||||
[item release];
|
||||
item.isBusy = YES;
|
||||
}
|
||||
|
||||
- (void)releaseItem:(MTLTexturePoolItem *)item {
|
||||
[_lock lock];
|
||||
@try {
|
||||
if (!item.isBusy) return;
|
||||
[item retain];
|
||||
if (item.prev == nil) {
|
||||
self.occupied = item.next;
|
||||
if (item.next) item.next.prev = nil;
|
||||
} else {
|
||||
item.prev.next = item.next;
|
||||
if (item.next) item.next.prev = item.prev;
|
||||
item.prev = nil;
|
||||
}
|
||||
if (self.available) {
|
||||
self.available.prev = item;
|
||||
} else {
|
||||
self.availableTail = item;
|
||||
}
|
||||
item.next = self.available;
|
||||
self.available = item;
|
||||
item.isBusy = NO;
|
||||
[item release];
|
||||
} @finally {
|
||||
[_lock unlock];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addOccupiedItem:(MTLTexturePoolItem *)item {
|
||||
if (self.occupied) self.occupied.prev = item;
|
||||
item.next = self.occupied;
|
||||
item.isBusy = YES;
|
||||
self.occupied = item;
|
||||
}
|
||||
|
||||
- (void)removeAvailableItem:(MTLTexturePoolItem*)item {
|
||||
[item retain];
|
||||
if (item.prev == nil) {
|
||||
self.available = item.next;
|
||||
if (item.next) {
|
||||
item.next.prev = nil;
|
||||
item.next = nil;
|
||||
} else {
|
||||
self.availableTail = item.prev;
|
||||
}
|
||||
} else {
|
||||
item.prev.next = item.next;
|
||||
if (item.next) {
|
||||
item.next.prev = item.prev;
|
||||
item.next = nil;
|
||||
} else {
|
||||
self.availableTail = item.prev;
|
||||
}
|
||||
}
|
||||
[item release];
|
||||
}
|
||||
|
||||
- (void)removeAllItems {
|
||||
MTLTexturePoolItem *cur = self.available;
|
||||
while (cur != nil) {
|
||||
cur = cur.next;
|
||||
self.available = cur;
|
||||
}
|
||||
cur = self.occupied;
|
||||
while (cur != nil) {
|
||||
cur = cur.next;
|
||||
self.occupied = cur;
|
||||
}
|
||||
self.availableTail = nil;
|
||||
}
|
||||
|
||||
- (MTLTexturePoolItem *)createItem:(id<MTLDevice>)dev
|
||||
width:(int)width
|
||||
height:(int)height
|
||||
format:(MTLPixelFormat)format
|
||||
isMultiSample:(bool)isMultiSample
|
||||
{
|
||||
MTLTextureDescriptor *textureDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
|
||||
width:(NSUInteger) width
|
||||
height:(NSUInteger) height
|
||||
mipmapped:NO];
|
||||
if (isMultiSample) {
|
||||
textureDescriptor.textureType = MTLTextureType2DMultisample;
|
||||
textureDescriptor.sampleCount = MTLAASampleCount;
|
||||
textureDescriptor.storageMode = MTLStorageModePrivate;
|
||||
}
|
||||
|
||||
id <MTLTexture> tex = (id <MTLTexture>) [[dev newTextureWithDescriptor:textureDescriptor] autorelease];
|
||||
MTLTexturePoolItem* item = [[[MTLTexturePoolItem alloc] initWithTexture:tex cell:self] autorelease];
|
||||
item.isMultiSample = isMultiSample;
|
||||
[_lock lock];
|
||||
@try {
|
||||
[self addOccupiedItem:item];
|
||||
} @finally {
|
||||
[_lock unlock];
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
- (NSUInteger)cleanIfBefore:(time_t)lastUsedTimeToRemove {
|
||||
NSUInteger deallocMem = 0;
|
||||
[_lock lock];
|
||||
MTLTexturePoolItem *cur = availableTail;
|
||||
@try {
|
||||
while (cur != nil) {
|
||||
MTLTexturePoolItem *prev = cur.prev;
|
||||
if (lastUsedTimeToRemove <= 0 ||
|
||||
cur.lastUsed < lastUsedTimeToRemove) {
|
||||
#ifdef DEBUG
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE,
|
||||
"MTLTexturePool: remove pool item: tex=%p, w=%d h=%d, elapsed=%d",
|
||||
cur.texture, cur.texture.width, cur.texture.height,
|
||||
time(NULL) - cur.lastUsed);
|
||||
#endif //DEBUG
|
||||
deallocMem += cur.texture.width * cur.texture.height * 4;
|
||||
[self removeAvailableItem:cur];
|
||||
} else {
|
||||
if (lastUsedTimeToRemove > 0) break;
|
||||
}
|
||||
cur = prev;
|
||||
}
|
||||
} @finally {
|
||||
[_lock unlock];
|
||||
}
|
||||
return deallocMem;
|
||||
}
|
||||
|
||||
- (MTLTexturePoolItem *)occupyItem:(int)width height:(int)height format:(MTLPixelFormat)format
|
||||
isMultiSample:(bool)isMultiSample {
|
||||
int minDeltaArea = -1;
|
||||
const int requestedPixels = width*height;
|
||||
MTLTexturePoolItem *minDeltaTpi = nil;
|
||||
[_lock lock];
|
||||
@try {
|
||||
for (MTLTexturePoolItem *cur = available; cur != nil; cur = cur.next) {
|
||||
if (cur.texture.pixelFormat != format
|
||||
|| cur.isMultiSample != isMultiSample) { // TODO: use swizzle when formats are not equal
|
||||
continue;
|
||||
}
|
||||
if (cur.texture.width < width || cur.texture.height < height) {
|
||||
continue;
|
||||
}
|
||||
const int deltaArea = (const int) (cur.texture.width * cur.texture.height - requestedPixels);
|
||||
if (minDeltaArea < 0 || deltaArea < minDeltaArea) {
|
||||
minDeltaArea = deltaArea;
|
||||
minDeltaTpi = cur;
|
||||
if (deltaArea == 0) {
|
||||
// found exact match in current cell
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minDeltaTpi) {
|
||||
[self occupyItem:minDeltaTpi];
|
||||
}
|
||||
} @finally {
|
||||
[_lock unlock];
|
||||
}
|
||||
return minDeltaTpi;
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
[_lock lock];
|
||||
@try {
|
||||
[self removeAllItems];
|
||||
} @finally {
|
||||
[_lock unlock];
|
||||
}
|
||||
[_lock release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTLTexturePool {
|
||||
int _memoryTotalAllocated;
|
||||
|
||||
void ** _cells;
|
||||
int _poolCellWidth;
|
||||
int _poolCellHeight;
|
||||
}
|
||||
|
||||
@synthesize device;
|
||||
|
||||
- (id) initWithDevice:(id<MTLDevice>)dev {
|
||||
self = [super init];
|
||||
if (self == nil) return self;
|
||||
|
||||
_memoryTotalAllocated = 0;
|
||||
_poolCellWidth = 10;
|
||||
_poolCellHeight = 10;
|
||||
const int cellsCount = _poolCellWidth * _poolCellHeight;
|
||||
_cells = (void **)malloc(cellsCount * sizeof(void*));
|
||||
memset(_cells, 0, cellsCount * sizeof(void*));
|
||||
self.device = dev;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
for (int c = 0; c < _poolCellWidth * _poolCellHeight; ++c) {
|
||||
MTLPoolCell * cell = _cells[c];
|
||||
if (cell != NULL) {
|
||||
[cell release];
|
||||
}
|
||||
}
|
||||
free(_cells);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
// NOTE: called from RQ-thread (on blit operations)
|
||||
- (MTLPooledTextureHandle *) getTexture:(int)width height:(int)height format:(MTLPixelFormat)format {
|
||||
return [self getTexture:width height:height format:format isMultiSample:NO];
|
||||
}
|
||||
|
||||
// NOTE: called from RQ-thread (on blit operations)
|
||||
- (MTLPooledTextureHandle *) getTexture:(int)width height:(int)height format:(MTLPixelFormat)format
|
||||
isMultiSample:(bool)isMultiSample {
|
||||
// 1. clean pool if necessary
|
||||
const int requestedPixels = width*height;
|
||||
const int requestedBytes = requestedPixels*4;
|
||||
if (_memoryTotalAllocated + requestedBytes > MAX_POOL_MEMORY) {
|
||||
[self cleanIfNecessary:0]; // release all free textures
|
||||
} else if (_memoryTotalAllocated + requestedBytes > MAX_POOL_MEMORY/2) {
|
||||
[self cleanIfNecessary:MAX_POOL_ITEM_LIFETIME_SEC]; // release only old free textures
|
||||
}
|
||||
|
||||
// 2. find free item
|
||||
const int cellX0 = width >> CELL_WIDTH_BITS;
|
||||
const int cellY0 = height >> CELL_HEIGHT_BITS;
|
||||
const int cellX1 = cellX0 + 1;
|
||||
const int cellY1 = cellY0 + 1;
|
||||
if (cellX1 > _poolCellWidth || cellY1 > _poolCellHeight) {
|
||||
const int newCellWidth = cellX1 <= _poolCellWidth ? _poolCellWidth : cellX1;
|
||||
const int newCellHeight = cellY1 <= _poolCellHeight ? _poolCellHeight : cellY1;
|
||||
const int newCellsCount = newCellWidth*newCellHeight;
|
||||
#ifdef DEBUG
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE, "MTLTexturePool: resize: %d -> %d", _poolCellWidth * _poolCellHeight, newCellsCount);
|
||||
#endif
|
||||
void ** newcells = malloc(newCellsCount*sizeof(void*));
|
||||
const int strideBytes = _poolCellWidth * sizeof(void*);
|
||||
for (int cy = 0; cy < _poolCellHeight; ++cy) {
|
||||
void ** dst = newcells + cy*newCellWidth;
|
||||
void ** src = _cells + cy * _poolCellWidth;
|
||||
memcpy(dst, src, strideBytes);
|
||||
if (newCellWidth > _poolCellWidth)
|
||||
memset(dst + _poolCellWidth, 0, (newCellWidth - _poolCellWidth) * sizeof(void*));
|
||||
}
|
||||
if (newCellHeight > _poolCellHeight) {
|
||||
void ** dst = newcells + _poolCellHeight * newCellWidth;
|
||||
memset(dst, 0, (newCellHeight - _poolCellHeight) * newCellWidth * sizeof(void*));
|
||||
}
|
||||
free(_cells);
|
||||
_cells = newcells;
|
||||
_poolCellWidth = newCellWidth;
|
||||
_poolCellHeight = newCellHeight;
|
||||
}
|
||||
|
||||
MTLTexturePoolItem * minDeltaTpi = nil;
|
||||
int minDeltaArea = -1;
|
||||
for (int cy = cellY0; cy < cellY1; ++cy) {
|
||||
for (int cx = cellX0; cx < cellX1; ++cx) {
|
||||
MTLPoolCell * cell = _cells[cy * _poolCellWidth + cx];
|
||||
if (cell != NULL) {
|
||||
MTLTexturePoolItem* tpi = [cell occupyItem:width height:height
|
||||
format:format isMultiSample:isMultiSample];
|
||||
if (!tpi) continue;
|
||||
const int deltaArea = (const int) (tpi.texture.width * tpi.texture.height - requestedPixels);
|
||||
if (minDeltaArea < 0 || deltaArea < minDeltaArea) {
|
||||
minDeltaArea = deltaArea;
|
||||
minDeltaTpi = tpi;
|
||||
if (deltaArea == 0) {
|
||||
// found exact match in current cell
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (minDeltaTpi != nil) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (minDeltaTpi == NULL) {
|
||||
MTLPoolCell* cell = _cells[cellY0 * _poolCellWidth + cellX0];
|
||||
if (cell == NULL) {
|
||||
cell = [[MTLPoolCell alloc] init];
|
||||
_cells[cellY0 * _poolCellWidth + cellX0] = cell;
|
||||
}
|
||||
minDeltaTpi = [cell createItem:device width:width height:height format:format isMultiSample:isMultiSample];
|
||||
_memoryTotalAllocated += requestedBytes;
|
||||
J2dTraceLn5(J2D_TRACE_VERBOSE, "MTLTexturePool: created pool item: tex=%p, w=%d h=%d, pf=%d | total memory = %d Kb", minDeltaTpi.texture, width, height, format, _memoryTotalAllocated/1024);
|
||||
}
|
||||
|
||||
minDeltaTpi.isBusy = YES;
|
||||
minDeltaTpi.lastUsed = time(NULL);
|
||||
return [[[MTLPooledTextureHandle alloc] initWithPoolItem:minDeltaTpi.texture
|
||||
rect:MTLRegionMake2D(0, 0,
|
||||
minDeltaTpi.texture.width,
|
||||
minDeltaTpi.texture.height)
|
||||
poolItem:minDeltaTpi] autorelease];
|
||||
}
|
||||
|
||||
- (void) cleanIfNecessary:(int)lastUsedTimeThreshold {
|
||||
time_t lastUsedTimeToRemove =
|
||||
lastUsedTimeThreshold > 0 ?
|
||||
time(NULL) - lastUsedTimeThreshold :
|
||||
lastUsedTimeThreshold;
|
||||
for (int cy = 0; cy < _poolCellHeight; ++cy) {
|
||||
for (int cx = 0; cx < _poolCellWidth; ++cx) {
|
||||
MTLPoolCell * cell = _cells[cy * _poolCellWidth + cx];
|
||||
if (cell != NULL) {
|
||||
_memoryTotalAllocated -= [cell cleanIfBefore:lastUsedTimeToRemove];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLTransform_h_Included
|
||||
#define MTLTransform_h_Included
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
@interface MTLTransform : NSObject
|
||||
- (id)init;
|
||||
- (BOOL)isEqual:(MTLTransform *)other;
|
||||
- (void)copyFrom:(MTLTransform *)other;
|
||||
|
||||
- (void)setTransformM00:(jdouble) m00 M10:(jdouble) m10
|
||||
M01:(jdouble) m01 M11:(jdouble) m11
|
||||
M02:(jdouble) m02 M12:(jdouble) m12;
|
||||
- (void)resetTransform;
|
||||
|
||||
- (void)setVertexMatrix:(id<MTLRenderCommandEncoder>)encoder
|
||||
destWidth:(NSUInteger)dw
|
||||
destHeight:(NSUInteger)dh;
|
||||
@end
|
||||
|
||||
#endif // MTLTransform_h_Included
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "MTLTransform.h"
|
||||
|
||||
#include <jni.h>
|
||||
#include <simd/simd.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@implementation MTLTransform {
|
||||
jboolean _useTransform;
|
||||
simd_float4x4 _transform4x4;
|
||||
simd_float4x4 _normalize4x4; // just a buffer for setVertexMatrix
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
memset(&_normalize4x4, 0, sizeof(_normalize4x4));
|
||||
_normalize4x4.columns[3][0] = -1.f;
|
||||
_normalize4x4.columns[3][1] = 1.f;
|
||||
_normalize4x4.columns[3][3] = 1.0;
|
||||
|
||||
_useTransform = JNI_FALSE;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(MTLTransform *)other {
|
||||
if (self == other)
|
||||
return YES;
|
||||
return _useTransform == other->_useTransform
|
||||
&& simd_equal(_transform4x4, other->_transform4x4);
|
||||
}
|
||||
|
||||
- (void)copyFrom:(MTLTransform *)other {
|
||||
_useTransform = other->_useTransform;
|
||||
if (_useTransform) {
|
||||
_transform4x4 = other->_transform4x4;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTransformM00:(jdouble) m00 M10:(jdouble) m10
|
||||
M01:(jdouble) m01 M11:(jdouble) m11
|
||||
M02:(jdouble) m02 M12:(jdouble) m12 {
|
||||
memset(&(_transform4x4), 0, sizeof(_transform4x4));
|
||||
_transform4x4.columns[0][0] = m00;
|
||||
_transform4x4.columns[0][1] = m10;
|
||||
_transform4x4.columns[1][0] = m01;
|
||||
_transform4x4.columns[1][1] = m11;
|
||||
_transform4x4.columns[3][0] = m02;
|
||||
_transform4x4.columns[3][1] = m12;
|
||||
_transform4x4.columns[3][3] = 1.0;
|
||||
_useTransform = JNI_TRUE;
|
||||
}
|
||||
|
||||
- (void)resetTransform {
|
||||
_useTransform = JNI_FALSE;
|
||||
}
|
||||
|
||||
- (void)setVertexMatrix:(id<MTLRenderCommandEncoder>)encoder
|
||||
destWidth:(NSUInteger)dw
|
||||
destHeight:(NSUInteger)dh {
|
||||
// update matrix for vertex shader
|
||||
_normalize4x4.columns[0][0] = 2/(double)dw;
|
||||
_normalize4x4.columns[1][1] = -2/(double)dh;
|
||||
|
||||
if (_useTransform) {
|
||||
simd_float4x4 vertexMatrix = simd_mul(_normalize4x4, _transform4x4);
|
||||
[encoder setVertexBytes:&(vertexMatrix) length:sizeof(vertexMatrix) atIndex:MatrixBuffer];
|
||||
} else {
|
||||
[encoder setVertexBytes:&(_normalize4x4) length:sizeof(_normalize4x4) atIndex:MatrixBuffer];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLUtils_h_Included
|
||||
#define MTLUtils_h_Included
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
#define MTLAASampleCount 4
|
||||
|
||||
#endif /* MTLUtils_h_Included */
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "MTLUtils.h"
|
||||
|
||||
#include <jni.h>
|
||||
#include <simd/simd.h>
|
||||
#import <ThreadUtilities.h>
|
||||
#import <PropertiesUtilities.h>
|
||||
#include "common.h"
|
||||
#include "Trace.h"
|
||||
|
||||
extern void J2dTraceImpl(int level, jboolean cr, const char *string, ...);
|
||||
void J2dTraceTraceVector(simd_float4 pt) {
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE, "[%lf %lf %lf %lf]", pt.x, pt.y, pt.z, pt.w);
|
||||
}
|
||||
|
||||
void checkTransform(float * position, simd_float4x4 transform4x4) {
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE, "check transform: ");
|
||||
|
||||
simd_float4 fpt = simd_make_float4(position[0], position[1], position[2], 1.f);
|
||||
simd_float4 fpt_trans = simd_mul(transform4x4, fpt);
|
||||
J2dTraceTraceVector(fpt);
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE, " ===>>> ");
|
||||
J2dTraceTraceVector(fpt_trans);
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE, " ");
|
||||
}
|
||||
|
||||
static void traceMatrix(simd_float4x4 * mtx) {
|
||||
for (int row = 0; row < 4; ++row) {
|
||||
J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE, " [%lf %lf %lf %lf]",
|
||||
mtx->columns[0][row], mtx->columns[1][row], mtx->columns[2][row], mtx->columns[3][row]);
|
||||
}
|
||||
}
|
||||
|
||||
void traceRaster(char * p, int width, int height, int stride) {
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
unsigned char pix0 = p[y*stride + x*4];
|
||||
unsigned char pix1 = p[y*stride + x*4 + 1];
|
||||
unsigned char pix2 = p[y*stride + x*4 + 2];
|
||||
unsigned char pix3 = p[y*stride + x*4 + 3];
|
||||
J2dTraceImpl(J2D_TRACE_INFO, JNI_FALSE,"[%u,%u,%u,%u], ", pix0, pix1, pix2, pix3);
|
||||
}
|
||||
J2dTraceImpl(J2D_TRACE_INFO, JNI_TRUE, "");
|
||||
}
|
||||
}
|
||||
|
||||
void tracePoints(jint nPoints, jint *xPoints, jint *yPoints) {
|
||||
for (int i = 0; i < nPoints; i++)
|
||||
J2dTraceImpl(J2D_TRACE_INFO, JNI_TRUE, "\t(%d, %d)", *(xPoints++), *(yPoints++));
|
||||
}
|
||||
|
||||
|
||||
jboolean isOptionEnabled(const char * option) {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
|
||||
NSString * optionProp = [PropertiesUtilities
|
||||
javaSystemPropertyForKey:[NSString stringWithUTF8String:option] withEnv:env];
|
||||
NSString * lowerCaseProp = [optionProp localizedLowercaseString];
|
||||
return [@"true" isEqual:lowerCaseProp];
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef MTLVertexCache_h_Included
|
||||
#define MTLVertexCache_h_Included
|
||||
#include "j2d_md.h"
|
||||
#include "MTLContext.h"
|
||||
#include "fontscalerdefs.h"
|
||||
|
||||
/**
|
||||
* Constants that control the size of the vertex cache.
|
||||
*/
|
||||
#define MTLVC_MAX_INDEX 250
|
||||
|
||||
/**
|
||||
* Constants that control the size of the texture tile cache used for
|
||||
* mask operations.
|
||||
*/
|
||||
#define MTLVC_MASK_CACHE_TILE_WIDTH 32
|
||||
#define MTLVC_MASK_CACHE_TILE_HEIGHT 32
|
||||
#define MTLVC_MASK_CACHE_TILE_SIZE \
|
||||
(MTLVC_MASK_CACHE_TILE_WIDTH * MTLVC_MASK_CACHE_TILE_HEIGHT)
|
||||
|
||||
#define MTLVC_MASK_CACHE_WIDTH_IN_TILES 8
|
||||
#define MTLVC_MASK_CACHE_HEIGHT_IN_TILES 4
|
||||
|
||||
#define MTLVC_MASK_CACHE_WIDTH_IN_TEXELS \
|
||||
(MTLVC_MASK_CACHE_TILE_WIDTH * MTLVC_MASK_CACHE_WIDTH_IN_TILES)
|
||||
#define MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS \
|
||||
(MTLVC_MASK_CACHE_TILE_HEIGHT * MTLVC_MASK_CACHE_HEIGHT_IN_TILES)
|
||||
|
||||
/*
|
||||
* We reserve one (fully opaque) tile in the upper-right corner for
|
||||
* operations where the mask is null.
|
||||
*/
|
||||
#define MTLVC_MASK_CACHE_MAX_INDEX \
|
||||
((MTLVC_MASK_CACHE_WIDTH_IN_TILES * MTLVC_MASK_CACHE_HEIGHT_IN_TILES) - 1)
|
||||
#define MTLVC_MASK_CACHE_SPECIAL_TILE_X \
|
||||
(MTLVC_MASK_CACHE_WIDTH_IN_TEXELS - MTLVC_MASK_CACHE_TILE_WIDTH)
|
||||
#define MTLVC_MASK_CACHE_SPECIAL_TILE_Y \
|
||||
(MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS - MTLVC_MASK_CACHE_TILE_HEIGHT)
|
||||
|
||||
/**
|
||||
* Exported methods.
|
||||
*/
|
||||
jboolean MTLVertexCache_InitVertexCache();
|
||||
void MTLVertexCache_FlushVertexCache(MTLContext *mtlc);
|
||||
void MTLVertexCache_FlushGlyphVertexCache();
|
||||
void MTLVertexCache_FreeVertexCache();
|
||||
|
||||
void MTLVertexCache_EnableMaskCache(MTLContext *mtlc, BMTLSDOps *dstOps);
|
||||
void MTLVertexCache_DisableMaskCache(MTLContext *mtlc);
|
||||
void MTLVertexCache_AddMaskQuad(MTLContext *mtlc,
|
||||
jint srcx, jint srcy,
|
||||
jint dstx, jint dsty,
|
||||
jint width, jint height,
|
||||
jint maskscan, void *mask,
|
||||
BMTLSDOps *dstOps);
|
||||
void
|
||||
MTLVertexCache_AddGlyphQuad(MTLContext *mtlc,
|
||||
jfloat tx1, jfloat ty1, jfloat tx2, jfloat ty2,
|
||||
jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2);
|
||||
void MTLVertexCache_CreateSamplingEncoder(MTLContext *mtlc, BMTLSDOps *dstOps);
|
||||
#endif /* MTLVertexCache_h_Included */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user