mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2025-12-20 07:00:09 +01:00
Compare commits
839 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6389c1ce55 | ||
|
|
9364282ebd | ||
|
|
af59ce4058 | ||
|
|
75d75ac6cd | ||
|
|
f709b8a798 | ||
|
|
adaffa980e | ||
|
|
104cd2e813 | ||
|
|
e8b7997223 | ||
|
|
b736066dc9 | ||
|
|
2613db2426 | ||
|
|
32f6148afd | ||
|
|
f7aa35e9d2 | ||
|
|
cdb011ee53 | ||
|
|
7c8b745249 | ||
|
|
85d8c7a5e5 | ||
|
|
a3f0e97a71 | ||
|
|
65227cb7d4 | ||
|
|
ed77aca2d8 | ||
|
|
e286cf6e15 | ||
|
|
37256645d6 | ||
|
|
0a76cb86ca | ||
|
|
37acb0c0fd | ||
|
|
2bbe222883 | ||
|
|
eb61323aa1 | ||
|
|
2dce06179f | ||
|
|
75f2ec4747 | ||
|
|
f36a3a91a8 | ||
|
|
01b7e9d015 | ||
|
|
f1bcedd089 | ||
|
|
d88efaea66 | ||
|
|
fc2e365c1d | ||
|
|
2e66195546 | ||
|
|
6af97ec150 | ||
|
|
66eaeb0c3f | ||
|
|
92c15464aa | ||
|
|
c23d028300 | ||
|
|
6955752b95 | ||
|
|
c0a6b7c1c9 | ||
|
|
1e55fd2449 | ||
|
|
0680683539 | ||
|
|
613558e69e | ||
|
|
d830ce962a | ||
|
|
025f5a7c45 | ||
|
|
582ae5385b | ||
|
|
119ce40714 | ||
|
|
e2cda4570e | ||
|
|
eda7e524fd | ||
|
|
aefdbb0278 | ||
|
|
57ad320d86 | ||
|
|
87776413ba | ||
|
|
2bb8cdba83 | ||
|
|
42aeea2220 | ||
|
|
54217f5d88 | ||
|
|
85315c4841 | ||
|
|
e4a51996d8 | ||
|
|
0126a5b4fc | ||
|
|
cb97abd4f7 | ||
|
|
23204eca75 | ||
|
|
f50296d4e9 | ||
|
|
73e0bb2829 | ||
|
|
61134fa151 | ||
|
|
6a280a8fad | ||
|
|
7bfedba650 | ||
|
|
08f9d791b5 | ||
|
|
5eb5c4991d | ||
|
|
e4be014f93 | ||
|
|
b700c7cbee | ||
|
|
5e0099ddbb | ||
|
|
7bb3a7b969 | ||
|
|
015d73cb54 | ||
|
|
4b61e44ad1 | ||
|
|
a691dc51d2 | ||
|
|
9215a537e0 | ||
|
|
cfb459c2c9 | ||
|
|
6db55fe7e4 | ||
|
|
6a2ddee844 | ||
|
|
4479b3c96d | ||
|
|
b44cf1b6af | ||
|
|
9b89e7d94e | ||
|
|
f85008bb86 | ||
|
|
881ac6a5cf | ||
|
|
87d2d3e442 | ||
|
|
8da9b0baec | ||
|
|
c6484574a6 | ||
|
|
d69e816b54 | ||
|
|
1a868b7244 | ||
|
|
12334b3e75 | ||
|
|
65554abd88 | ||
|
|
6d18e86b06 | ||
|
|
53895cac2f | ||
|
|
68d3d3badc | ||
|
|
7fa306dd81 | ||
|
|
777a52ef4d | ||
|
|
0bfcb700b9 | ||
|
|
683d7df164 | ||
|
|
6070dd8069 | ||
|
|
008884f289 | ||
|
|
6155981cc6 | ||
|
|
58614d4f5b | ||
|
|
b688767680 | ||
|
|
fcb4c2a85b | ||
|
|
c7cdcedbf0 | ||
|
|
564f6687eb | ||
|
|
c9a6e2721a | ||
|
|
37a427e4e0 | ||
|
|
727d976e3c | ||
|
|
095f511d53 | ||
|
|
37db081f82 | ||
|
|
21f1c575b3 | ||
|
|
26cab9d562 | ||
|
|
485e1796af | ||
|
|
e8b2033d82 | ||
|
|
d4e39210a3 | ||
|
|
f69bb08738 | ||
|
|
33ee2c9fb4 | ||
|
|
120b88aa0a | ||
|
|
e87eb19877 | ||
|
|
bef29b8774 | ||
|
|
11f7273545 | ||
|
|
8591578090 | ||
|
|
3ec1e38a62 | ||
|
|
58298e2346 | ||
|
|
48aaf6434d | ||
|
|
3bd055145b | ||
|
|
de0527bce0 | ||
|
|
2abd161023 | ||
|
|
dc27dd7e95 | ||
|
|
8cdf3fb709 | ||
|
|
5a3f3c7ca7 | ||
|
|
52503ba9e6 | ||
|
|
2c7fd792b5 | ||
|
|
0664d5bdc1 | ||
|
|
7f8c5f984e | ||
|
|
abfe874a51 | ||
|
|
562a368fbd | ||
|
|
64c938f5d6 | ||
|
|
4cb7347407 | ||
|
|
900ab0d39f | ||
|
|
56aeb48f6d | ||
|
|
e9fc189189 | ||
|
|
c2b60e6651 | ||
|
|
5ee711d374 | ||
|
|
9700ec3bc4 | ||
|
|
992ab893f9 | ||
|
|
62e76ee5fb | ||
|
|
25a281a0a8 | ||
|
|
99ab4ceaca | ||
|
|
889a564695 | ||
|
|
cb49b386f2 | ||
|
|
59e2a111fa | ||
|
|
4ebb06a94f | ||
|
|
2259ac4e93 | ||
|
|
4843199479 | ||
|
|
c00997979c | ||
|
|
fe4cb8a546 | ||
|
|
4d98190a98 | ||
|
|
087315e242 | ||
|
|
2c5dd92533 | ||
|
|
42a9a54665 | ||
|
|
e2b3ab38bd | ||
|
|
ef6747a951 | ||
|
|
47f1c1e694 | ||
|
|
ec6c67780e | ||
|
|
79ade4c165 | ||
|
|
1465362e9f | ||
|
|
e5cbd8536a | ||
|
|
8c4e3b7de5 | ||
|
|
3ae7a7b457 | ||
|
|
18076228d3 | ||
|
|
a1c0d33700 | ||
|
|
a60169e239 | ||
|
|
a06ef0f8aa | ||
|
|
d00b758cee | ||
|
|
854457524c | ||
|
|
360eef9663 | ||
|
|
9b68277b77 | ||
|
|
c0f79189dd | ||
|
|
f0be8d94a5 | ||
|
|
af5f2370af | ||
|
|
1377fdf20d | ||
|
|
30a807b86f | ||
|
|
452f148b6c | ||
|
|
6ffb4358e1 | ||
|
|
c6b519ab12 | ||
|
|
e96a970e56 | ||
|
|
8fc62e9ab8 | ||
|
|
b9e31d03ba | ||
|
|
11d721e748 | ||
|
|
930f768bdb | ||
|
|
847952b711 | ||
|
|
200f4cf461 | ||
|
|
de3a3fca1b | ||
|
|
dc473a4131 | ||
|
|
516f4b9b2f | ||
|
|
4890cd6a3d | ||
|
|
fe85ed48fc | ||
|
|
6ec30279f7 | ||
|
|
e76da2ccd0 | ||
|
|
e75873d376 | ||
|
|
b8ac69eef1 | ||
|
|
a17d5b4eb2 | ||
|
|
6fbc1376ee | ||
|
|
3f150b090b | ||
|
|
d180517ae4 | ||
|
|
8e30a7efc7 | ||
|
|
a9fc1fc0f7 | ||
|
|
a09895e907 | ||
|
|
722f0a2664 | ||
|
|
e6b67d2c72 | ||
|
|
203dbd3393 | ||
|
|
23f396aa30 | ||
|
|
e27929e3b3 | ||
|
|
618bfad1d4 | ||
|
|
ad0f4cf94b | ||
|
|
6cc8f48cd8 | ||
|
|
2497377af4 | ||
|
|
cb17b87a65 | ||
|
|
1560cc3f0b | ||
|
|
4ba62103a6 | ||
|
|
9c67c8c0d8 | ||
|
|
0b540ba8d6 | ||
|
|
5e7835bf2b | ||
|
|
e187420e38 | ||
|
|
b6c1bc872e | ||
|
|
be71b5a094 | ||
|
|
d7030571c5 | ||
|
|
daec4a0994 | ||
|
|
f3badf2c2d | ||
|
|
7b5053f7fa | ||
|
|
bcfa2724d2 | ||
|
|
bcb7676ed7 | ||
|
|
fdb43447a2 | ||
|
|
794c1eb490 | ||
|
|
aa04d9d4ad | ||
|
|
b6f890d249 | ||
|
|
9ea205e007 | ||
|
|
07a5ec8157 | ||
|
|
00902a5921 | ||
|
|
967537d525 | ||
|
|
3706d860f1 | ||
|
|
042aa06b28 | ||
|
|
b0c99998ef | ||
|
|
41823d237b | ||
|
|
3026c44897 | ||
|
|
6fe0cfc2b8 | ||
|
|
1a9cf3bfb6 | ||
|
|
a38cc9982b | ||
|
|
6f1d9cdffd | ||
|
|
39108501b3 | ||
|
|
6d8a15839d | ||
|
|
81d68a561e | ||
|
|
a4cefa69a2 | ||
|
|
b268b3827c | ||
|
|
1a68480421 | ||
|
|
aff309fa9f | ||
|
|
dfad00e8c4 | ||
|
|
d2cf5a7ba5 | ||
|
|
208157f2e4 | ||
|
|
41bef3caaa | ||
|
|
02a6e45ce5 | ||
|
|
7722b9f443 | ||
|
|
5af8340a00 | ||
|
|
658f66216a | ||
|
|
67de2a1967 | ||
|
|
516e86222f | ||
|
|
68d036e2b1 | ||
|
|
811edc0a8c | ||
|
|
f42ccf2140 | ||
|
|
9341192f51 | ||
|
|
6d20e480a0 | ||
|
|
fef0de7d72 | ||
|
|
8c9f395c6c | ||
|
|
b717030a10 | ||
|
|
439aea0188 | ||
|
|
eac3d78bc6 | ||
|
|
ac71d40dec | ||
|
|
cfaa19a292 | ||
|
|
628e860ffa | ||
|
|
37c94a12d9 | ||
|
|
6e7b4d63c2 | ||
|
|
b4529320ff | ||
|
|
38e6a292a2 | ||
|
|
a2a6030902 | ||
|
|
23b9f92398 | ||
|
|
8966ea79fe | ||
|
|
f322b41b3d | ||
|
|
ed1edb7b5c | ||
|
|
760ca22e8f | ||
|
|
cd58c45daa | ||
|
|
f4bad074e6 | ||
|
|
0ea8141195 | ||
|
|
72f73f6692 | ||
|
|
3b017341b7 | ||
|
|
76dc730d3d | ||
|
|
e79c9ceee5 | ||
|
|
b76e6ebd82 | ||
|
|
98253554c8 | ||
|
|
93ad388414 | ||
|
|
fb7b3e2880 | ||
|
|
051f0ac7d9 | ||
|
|
ae9b99352c | ||
|
|
8479772d2d | ||
|
|
3db7d41642 | ||
|
|
26625a4928 | ||
|
|
c0053057db | ||
|
|
b5970e6e68 | ||
|
|
1326428f41 | ||
|
|
4afd8961fc | ||
|
|
2deb5e1dfd | ||
|
|
3674d9665b | ||
|
|
a84db969f4 | ||
|
|
ee90650c8c | ||
|
|
ed6beb1dbf | ||
|
|
ccce6cfdda | ||
|
|
4d43e63ab5 | ||
|
|
106beccc91 | ||
|
|
af834d1419 | ||
|
|
6951ff578b | ||
|
|
bf311ff232 | ||
|
|
724d3707ec | ||
|
|
c54c421d21 | ||
|
|
263290c677 | ||
|
|
d2bab8a5ee | ||
|
|
48cc12cfc5 | ||
|
|
13e7a3addb | ||
|
|
4e286bd297 | ||
|
|
dfea094772 | ||
|
|
0974359b8f | ||
|
|
9500bbe844 | ||
|
|
c594aa22cb | ||
|
|
996ec58ce3 | ||
|
|
e77ca25a80 | ||
|
|
fceb4151a3 | ||
|
|
6f969623eb | ||
|
|
56c27ea248 | ||
|
|
ed7ceef37e | ||
|
|
c10857df5d | ||
|
|
dd5e1f5047 | ||
|
|
fba356e44d | ||
|
|
b5ed927960 | ||
|
|
0c986257f9 | ||
|
|
ec646f34d6 | ||
|
|
3cad1c7716 | ||
|
|
6b1b3d167d | ||
|
|
98d4438265 | ||
|
|
092fe3f7ec | ||
|
|
e91252a943 | ||
|
|
683eabb61e | ||
|
|
ead6c5b319 | ||
|
|
72d2b14e6a | ||
|
|
28808401b2 | ||
|
|
1c14c4ef70 | ||
|
|
6d2ca22a6c | ||
|
|
868c25b591 | ||
|
|
8694665f4f | ||
|
|
0787422248 | ||
|
|
03e7cdb43d | ||
|
|
66cdb7d9bc | ||
|
|
2a7b4f52e7 | ||
|
|
afc19c2e94 | ||
|
|
d076f2c519 | ||
|
|
b5843ed366 | ||
|
|
5b37b09c8a | ||
|
|
f132462df7 | ||
|
|
28bdcb46be | ||
|
|
3a1101be34 | ||
|
|
72ed2c12d8 | ||
|
|
8c2c429fd5 | ||
|
|
3737c9adb6 | ||
|
|
3b3fa61c31 | ||
|
|
b32f353003 | ||
|
|
37bee3050e | ||
|
|
3999d685bc | ||
|
|
67cfcaa0ac | ||
|
|
15a9daad9a | ||
|
|
a5a2b3abb1 | ||
|
|
b55a1d5bff | ||
|
|
ef52b0adb4 | ||
|
|
d254ccdcc5 | ||
|
|
5a1e925759 | ||
|
|
a9958154a9 | ||
|
|
1939c732e8 | ||
|
|
7bc103e5a1 | ||
|
|
3f81d2fd38 | ||
|
|
3eed20254c | ||
|
|
2efc1838cb | ||
|
|
44533f0ed6 | ||
|
|
0f969fd6b0 | ||
|
|
088c8ec21b | ||
|
|
5db61f07aa | ||
|
|
87dea962b8 | ||
|
|
624d8b2d3d | ||
|
|
675bb24a57 | ||
|
|
a1360d72f4 | ||
|
|
86517d36d3 | ||
|
|
28f1dfae95 | ||
|
|
8618a29649 | ||
|
|
56b768d934 | ||
|
|
5a48cedc7b | ||
|
|
2d34d32893 | ||
|
|
33c418a85b | ||
|
|
4685cb1d1c | ||
|
|
1a9d46e3bc | ||
|
|
a79e7c3e8d | ||
|
|
feb4fd1386 | ||
|
|
0a76b639fe | ||
|
|
c8f71ff503 | ||
|
|
0add10986d | ||
|
|
37bf61c68c | ||
|
|
3dce9e8c24 | ||
|
|
275155812c | ||
|
|
6b051ce76b | ||
|
|
c533be60d6 | ||
|
|
4d6e690fd0 | ||
|
|
2fc5e8b2e9 | ||
|
|
fec6a3c51e | ||
|
|
5f22ba7e2e | ||
|
|
acd3e557af | ||
|
|
16e958607a | ||
|
|
ddd03a3606 | ||
|
|
a4494f2ea3 | ||
|
|
c0dfeaf156 | ||
|
|
fc3e3cf653 | ||
|
|
0286b37d76 | ||
|
|
dc33a296b8 | ||
|
|
0600265c64 | ||
|
|
2dd870adac | ||
|
|
762e286a44 | ||
|
|
a3ab74028a | ||
|
|
1181d638ac | ||
|
|
413e471fb1 | ||
|
|
e91eccd709 | ||
|
|
cf44b691c6 | ||
|
|
c24685d14b | ||
|
|
556272bae9 | ||
|
|
718f7f56df | ||
|
|
8468289fa3 | ||
|
|
015533bac5 | ||
|
|
338d727d99 | ||
|
|
b2bc30034b | ||
|
|
bf1d8c458b | ||
|
|
63264ae3f4 | ||
|
|
b2c8f35c23 | ||
|
|
135b95808c | ||
|
|
a124b19a01 | ||
|
|
cc0edfd13d | ||
|
|
1683d7a9d2 | ||
|
|
601a72dd8c | ||
|
|
7900235fee | ||
|
|
e70cfe319c | ||
|
|
b3480f5b30 | ||
|
|
300d059044 | ||
|
|
816e4180bc | ||
|
|
653182759f | ||
|
|
9a5b4087c8 | ||
|
|
179aae34f7 | ||
|
|
44c2c3ce72 | ||
|
|
0aafc50419 | ||
|
|
d90eed2b99 | ||
|
|
c71ae0c89b | ||
|
|
8e7ca3a470 | ||
|
|
508d5f0bea | ||
|
|
3c2ff4324b | ||
|
|
30aacca3ff | ||
|
|
f8af0dbf72 | ||
|
|
4e4d7993ba | ||
|
|
df8af39a2a | ||
|
|
5536a98e97 | ||
|
|
75c37afa62 | ||
|
|
ec52e0cdda | ||
|
|
8f56d03d4b | ||
|
|
60f7b59d8f | ||
|
|
76431a952f | ||
|
|
ad4746101a | ||
|
|
2f35f84d8e | ||
|
|
87ae07b63f | ||
|
|
4ab8d6d2c4 | ||
|
|
f71db77341 | ||
|
|
381bc2761f | ||
|
|
33d82b6b79 | ||
|
|
55a85e8e16 | ||
|
|
fe5a846512 | ||
|
|
d24caf5f32 | ||
|
|
65e3a7324a | ||
|
|
68aed0775e | ||
|
|
e476276bf6 | ||
|
|
244f930365 | ||
|
|
e6289aee68 | ||
|
|
4393bec40a | ||
|
|
8ef3423bf7 | ||
|
|
df07af056d | ||
|
|
3187999208 | ||
|
|
0945ac3fa8 | ||
|
|
9f1cf0db24 | ||
|
|
b3fae5ae6b | ||
|
|
4fe16c1bec | ||
|
|
334ae04614 | ||
|
|
209a5b8400 | ||
|
|
14d95cd6ce | ||
|
|
6f6576dec2 | ||
|
|
0c84f990d6 | ||
|
|
d76a89c9d8 | ||
|
|
a40c638003 | ||
|
|
ac2bbe24cb | ||
|
|
35da5ca5a6 | ||
|
|
7bb9fc5b62 | ||
|
|
1296690ede | ||
|
|
3b7d29f871 | ||
|
|
5ca78cdf05 | ||
|
|
b15dcfe790 | ||
|
|
42059ce258 | ||
|
|
eadc3d32ce | ||
|
|
e837179f14 | ||
|
|
e57eb5b15d | ||
|
|
303d88448a | ||
|
|
33db73f134 | ||
|
|
cd35c6c780 | ||
|
|
d6f1b2a6a4 | ||
|
|
9f0ac15ce6 | ||
|
|
6f94022e8c | ||
|
|
edd00d9652 | ||
|
|
294d4cabd4 | ||
|
|
107e9ed69c | ||
|
|
dcb4a1012d | ||
|
|
52204f55ea | ||
|
|
09c8902225 | ||
|
|
4e1e922a28 | ||
|
|
007a1e1def | ||
|
|
95cb915d32 | ||
|
|
cf6735a761 | ||
|
|
9ce3ce4250 | ||
|
|
77015ae226 | ||
|
|
d1e4ae5e1d | ||
|
|
05f5e400e9 | ||
|
|
a47fabeaa4 | ||
|
|
70b5ec5bfe | ||
|
|
98ec0d9b6c | ||
|
|
f7bf732004 | ||
|
|
e1ac6139ca | ||
|
|
5eb316d77c | ||
|
|
8762c3bab5 | ||
|
|
0af48f0415 | ||
|
|
2ac863397c | ||
|
|
0ebd2b5e0e | ||
|
|
ccf6db49b7 | ||
|
|
209882c7d4 | ||
|
|
0fe575b4a9 | ||
|
|
46920d8a61 | ||
|
|
037f2dbff1 | ||
|
|
52262cb06c | ||
|
|
d9893c6af2 | ||
|
|
81800294a9 | ||
|
|
682d420b50 | ||
|
|
57f48ab91c | ||
|
|
9675ef49f2 | ||
|
|
cb43a086b5 | ||
|
|
d3ef4f9576 | ||
|
|
25a10fa2cd | ||
|
|
98becedfcd | ||
|
|
d26ab4360d | ||
|
|
ce80a059f1 | ||
|
|
5ef1432195 | ||
|
|
385334b77a | ||
|
|
1030268c6d | ||
|
|
83053f0ce4 | ||
|
|
9aa910c4d4 | ||
|
|
ae47d27f06 | ||
|
|
4fa4665d7a | ||
|
|
5a56856866 | ||
|
|
b872c71820 | ||
|
|
d3561621e3 | ||
|
|
adfe772db2 | ||
|
|
3fefb5ba44 | ||
|
|
92d7caa767 | ||
|
|
e8b7ade58b | ||
|
|
2bbd2e4364 | ||
|
|
f0567654d6 | ||
|
|
6bbc6c1256 | ||
|
|
9d841e39e8 | ||
|
|
fbf026653b | ||
|
|
f0ee8be804 | ||
|
|
46f25304c1 | ||
|
|
1a2c25116b | ||
|
|
82c5b386d8 | ||
|
|
9f21128d78 | ||
|
|
76e659f45e | ||
|
|
c706e1f8c8 | ||
|
|
5beca735b0 | ||
|
|
cda8de1089 | ||
|
|
5f1c43de29 | ||
|
|
bbe0b74ebd | ||
|
|
e850e97ab7 | ||
|
|
ad3957ddf8 | ||
|
|
af95899121 | ||
|
|
9660a4f315 | ||
|
|
013c21ec38 | ||
|
|
77dcbe381f | ||
|
|
5ab5582981 | ||
|
|
a97ccc4a1a | ||
|
|
6773ffa758 | ||
|
|
ed51e9ae43 | ||
|
|
2733a95962 | ||
|
|
1b7655636d | ||
|
|
4134685257 | ||
|
|
fbe2f27915 | ||
|
|
9373e76655 | ||
|
|
c855bc7af0 | ||
|
|
d92560a0e4 | ||
|
|
1f169c044c | ||
|
|
12819c4151 | ||
|
|
57c3cee7ed | ||
|
|
9124a98aec | ||
|
|
6d9c42a7d2 | ||
|
|
7e941cf6f1 | ||
|
|
2b69bc0811 | ||
|
|
bfb2dfae63 | ||
|
|
c7cf87fe85 | ||
|
|
8e26bf1ce9 | ||
|
|
85d1ca7fab | ||
|
|
c321cc3020 | ||
|
|
de6f0b870a | ||
|
|
e72839f52c | ||
|
|
62c25e8ca0 | ||
|
|
7974f8f46e | ||
|
|
0ca40593dc | ||
|
|
b947955499 | ||
|
|
51ed256d26 | ||
|
|
24b5d91316 | ||
|
|
de2a4ebc3c | ||
|
|
dd66debd46 | ||
|
|
d254cb14fc | ||
|
|
89e20bcda6 | ||
|
|
73d6c2cc85 | ||
|
|
ad85a4a2d1 | ||
|
|
b9ae1eb4a9 | ||
|
|
20f246eaef | ||
|
|
cf43e7da9f | ||
|
|
5e267afa6d | ||
|
|
da393fd468 | ||
|
|
e18e3b6c4a | ||
|
|
e8160e059d | ||
|
|
be5c662bae | ||
|
|
a990e8ceda | ||
|
|
815ccaff92 | ||
|
|
891736793a | ||
|
|
5342945bb8 | ||
|
|
acc40ce2bb | ||
|
|
c112760368 | ||
|
|
59c6015c52 | ||
|
|
6e88a851a4 | ||
|
|
94dd926b99 | ||
|
|
3d5772fb06 | ||
|
|
8993f5eabb | ||
|
|
f36a0c2cb8 | ||
|
|
c335ec70af | ||
|
|
10f8b4ba81 | ||
|
|
b3f6491b3a | ||
|
|
3d8edc15ce | ||
|
|
672178dc24 | ||
|
|
ccf3fda334 | ||
|
|
ca7e21bb94 | ||
|
|
0c8b6ce945 | ||
|
|
7e73234313 | ||
|
|
85dd477466 | ||
|
|
dcee21f02f | ||
|
|
43bbd15437 | ||
|
|
db25130e15 | ||
|
|
46603446d7 | ||
|
|
e505bbe017 | ||
|
|
b2d737f1f0 | ||
|
|
e72d7d963d | ||
|
|
58494e5ba2 | ||
|
|
8162058c8d | ||
|
|
2fc9a47e09 | ||
|
|
37a5c249e5 | ||
|
|
9048d752c5 | ||
|
|
eaf2ec3888 | ||
|
|
177efc7a59 | ||
|
|
0cede83390 | ||
|
|
a7611efce9 | ||
|
|
8c74b48493 | ||
|
|
dc7299d69c | ||
|
|
1dc6868947 | ||
|
|
c39799b684 | ||
|
|
7f3969c823 | ||
|
|
e3a5589975 | ||
|
|
6394f7d1ca | ||
|
|
1b7462011d | ||
|
|
ce79976dfc | ||
|
|
5fae3a5141 | ||
|
|
e22a11513d | ||
|
|
0be4403f65 | ||
|
|
313aa041e4 | ||
|
|
485cb4ab12 | ||
|
|
b3635c17f4 | ||
|
|
da1dca9d77 | ||
|
|
bdfe7a3e58 | ||
|
|
738d4b9509 | ||
|
|
5d51042e6b | ||
|
|
0c31f7dfd2 | ||
|
|
cfbf49d7e0 | ||
|
|
d17e61546e | ||
|
|
7f87268474 | ||
|
|
e8dae983b7 | ||
|
|
1656158d6d | ||
|
|
4ee40b653f | ||
|
|
8567b960fd | ||
|
|
1d167d883f | ||
|
|
96c49d91a5 | ||
|
|
4eddce5557 | ||
|
|
91da8560eb | ||
|
|
1f1c219d5c | ||
|
|
51d217a9b4 | ||
|
|
1f4d291850 | ||
|
|
0688343dec | ||
|
|
1c7274deed | ||
|
|
092076f6f5 | ||
|
|
c5e6fa7103 | ||
|
|
83a1a0293a | ||
|
|
2bfaac0f5c | ||
|
|
47035a776c | ||
|
|
e3878c8214 | ||
|
|
f6bc92571e | ||
|
|
c7ec967d12 | ||
|
|
a2e6086bc6 | ||
|
|
f2fc277fb2 | ||
|
|
a49b2e5a0d | ||
|
|
b9e199b47d | ||
|
|
1619a4a1e5 | ||
|
|
c01a1f7c64 | ||
|
|
70ad4cd901 | ||
|
|
277082dbd9 | ||
|
|
5d7e2710a2 | ||
|
|
06e1241948 | ||
|
|
9dcc5f20f8 | ||
|
|
b852744977 | ||
|
|
0ed8294881 | ||
|
|
9db8ad6ad1 | ||
|
|
9ae0a7ec05 | ||
|
|
1082ef328a | ||
|
|
3f0de3bdf4 | ||
|
|
432b9af0cd | ||
|
|
43f7b7b3bb | ||
|
|
207fed2710 | ||
|
|
c77a5d386a | ||
|
|
eabc19bc3b | ||
|
|
5c3067ad54 | ||
|
|
306033616b | ||
|
|
4cc489c6af | ||
|
|
5fcedcf5ef | ||
|
|
d3ead778de | ||
|
|
8b83bb5ceb | ||
|
|
3210cec531 | ||
|
|
b347af2ce0 | ||
|
|
a2dba7ff00 | ||
|
|
4be294bd69 | ||
|
|
8d21829f49 | ||
|
|
169bb00bbd | ||
|
|
7f01f9e18e | ||
|
|
090c01da87 | ||
|
|
68a70bf9c4 | ||
|
|
d7dcc2eaa7 | ||
|
|
0026986cce | ||
|
|
aaf968bf58 | ||
|
|
02b4eccd05 | ||
|
|
4ae493ff25 | ||
|
|
db5c06bd16 | ||
|
|
4f7f888d6c | ||
|
|
0361ddf13e | ||
|
|
94ca770c2a | ||
|
|
c29e2a7928 | ||
|
|
d38f45c6b6 | ||
|
|
3d0d850980 | ||
|
|
4a4a9b94d6 | ||
|
|
9d9d09a04d | ||
|
|
2852c92d89 | ||
|
|
c56c104f7a | ||
|
|
54dfa0743e | ||
|
|
12b9c65011 | ||
|
|
14d5406a90 | ||
|
|
00f7bf91d8 | ||
|
|
39a199293e | ||
|
|
ddb6225338 | ||
|
|
89f77176b6 | ||
|
|
ca894ab44f | ||
|
|
5aae333bbb | ||
|
|
0aeb8e5910 | ||
|
|
b2b8dd6215 | ||
|
|
5b35631545 | ||
|
|
16e5406877 | ||
|
|
264c205add | ||
|
|
68761d3f11 | ||
|
|
0ff5ac0f7b | ||
|
|
483a5a73cb | ||
|
|
3866ecc5d3 | ||
|
|
67253b30e8 | ||
|
|
53189ebb89 | ||
|
|
8dbb3e17d0 | ||
|
|
b14461b13b | ||
|
|
bf7b2311e7 | ||
|
|
dae61f3321 | ||
|
|
8634c7e349 | ||
|
|
fc278fb3cc | ||
|
|
c313543364 | ||
|
|
4f2cc67fde | ||
|
|
b4386289d6 | ||
|
|
4f4011d79e | ||
|
|
10ecf60848 | ||
|
|
d30683341c | ||
|
|
1ee1b93bac | ||
|
|
fe35be5013 | ||
|
|
a3fd8f3c97 | ||
|
|
8fdc55c03f | ||
|
|
16dc3b2b7f | ||
|
|
80e47a7161 | ||
|
|
8b5bb588df | ||
|
|
a501acd291 | ||
|
|
9a536962a5 | ||
|
|
486d96a162 | ||
|
|
217fb30847 | ||
|
|
04f27f1be2 | ||
|
|
68bbc4cf51 | ||
|
|
f86ff8c07d | ||
|
|
fe64eee3ae | ||
|
|
312c8bea66 | ||
|
|
067e977fe1 | ||
|
|
0e451e8dc3 | ||
|
|
2e51def212 | ||
|
|
a266c5fff5 | ||
|
|
53419eb991 | ||
|
|
e026fd6540 | ||
|
|
60981998b2 | ||
|
|
186937dc95 | ||
|
|
50d92f9d6f | ||
|
|
f81c0358c5 | ||
|
|
3dc28308e6 | ||
|
|
6bcf9ca6ba | ||
|
|
fe2ea233b1 | ||
|
|
b4726ef024 |
341 changed files with 52440 additions and 16610 deletions
206
.gitlab-ci.yml
206
.gitlab-ci.yml
|
|
@ -1,6 +1,6 @@
|
||||||
# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0:
|
# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0:
|
||||||
|
|
||||||
.templates_sha: &template_sha 184ca628f89f3193c249b4e34e45afee2773a833 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
|
.templates_sha: &template_sha 32afe5644697e503af18a736587c8619fa036a72 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
|
||||||
# This file uses the freedesktop ci-templates to build Weston and run our
|
# This file uses the freedesktop ci-templates to build Weston and run our
|
||||||
# tests in CI.
|
# tests in CI.
|
||||||
#
|
#
|
||||||
|
|
@ -43,7 +43,7 @@
|
||||||
variables:
|
variables:
|
||||||
FDO_UPSTREAM_REPO: wayland/weston
|
FDO_UPSTREAM_REPO: wayland/weston
|
||||||
FDO_REPO_SUFFIX: "$BUILD_OS-$FDO_DISTRIBUTION_VERSION/$BUILD_ARCH"
|
FDO_REPO_SUFFIX: "$BUILD_OS-$FDO_DISTRIBUTION_VERSION/$BUILD_ARCH"
|
||||||
FDO_DISTRIBUTION_TAG: '2024-08-14-00-freerdp3.x'
|
FDO_DISTRIBUTION_TAG: '2025-12-19-mesa-25.3.2'
|
||||||
|
|
||||||
|
|
||||||
include:
|
include:
|
||||||
|
|
@ -66,6 +66,11 @@ include:
|
||||||
# we need a default case though, so all the rest still run
|
# we need a default case though, so all the rest still run
|
||||||
- when: on_success
|
- when: on_success
|
||||||
|
|
||||||
|
default:
|
||||||
|
retry:
|
||||||
|
max: 2
|
||||||
|
when: runner_system_failure
|
||||||
|
|
||||||
.merge-rules:
|
.merge-rules:
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||||
|
|
@ -79,7 +84,7 @@ stages:
|
||||||
- "Pre Base container"
|
- "Pre Base container"
|
||||||
- "Base container"
|
- "Base container"
|
||||||
- "Full build and test"
|
- "Full build and test"
|
||||||
- "No-GL build and test"
|
- "No-GL/Vulkan build and test"
|
||||||
- "Other builds"
|
- "Other builds"
|
||||||
- pages
|
- pages
|
||||||
|
|
||||||
|
|
@ -88,20 +93,23 @@ stages:
|
||||||
.os-debian-lts:
|
.os-debian-lts:
|
||||||
variables:
|
variables:
|
||||||
BUILD_OS: debian
|
BUILD_OS: debian
|
||||||
LLVM_VERSION: 11
|
LLVM_VERSION: 15
|
||||||
|
USE_DEBIAN_BACKPORTS: y
|
||||||
|
PACKAGES_SPECIFIC: vulkan-validationlayers-dev
|
||||||
FREERDP_VERSION: 2
|
FREERDP_VERSION: 2
|
||||||
FDO_DISTRIBUTION_VERSION: bullseye
|
FDO_DISTRIBUTION_VERSION: bookworm
|
||||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
|
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
|
||||||
|
|
||||||
.os-debian:
|
.os-debian:
|
||||||
variables:
|
variables:
|
||||||
BUILD_OS: debian
|
BUILD_OS: debian
|
||||||
LLVM_VERSION: 15
|
LLVM_VERSION: 19
|
||||||
FREERDP_VERSION: 3
|
FREERDP_VERSION: 3
|
||||||
USE_BOOKWORM_BACKPORTS: y
|
USE_DEBIAN_BACKPORTS: y
|
||||||
# If you upgrade from bookworm, see the use_tls=0 notes in tests/meson.build.
|
PACKAGES_SPECIFIC: vulkan-utility-libraries-dev libpolly-19-dev libclang-rt-19-dev python3-standard-imghdr
|
||||||
FDO_DISTRIBUTION_VERSION: bookworm
|
# If you upgrade from trixie, see the use_tls=0 notes in tests/meson.build.
|
||||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
|
FDO_DISTRIBUTION_VERSION: trixie
|
||||||
|
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
|
||||||
|
|
||||||
# Does not inherit .default-rules as we only want it to run in MR context.
|
# Does not inherit .default-rules as we only want it to run in MR context.
|
||||||
check-commit:
|
check-commit:
|
||||||
|
|
@ -111,7 +119,6 @@ check-commit:
|
||||||
stage: "Merge request checks"
|
stage: "Merge request checks"
|
||||||
script:
|
script:
|
||||||
- ci-fairy check-commits --signed-off-by --junit-xml=results.xml
|
- ci-fairy check-commits --signed-off-by --junit-xml=results.xml
|
||||||
- ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
|
|
||||||
variables:
|
variables:
|
||||||
GIT_DEPTH: 100
|
GIT_DEPTH: 100
|
||||||
artifacts:
|
artifacts:
|
||||||
|
|
@ -139,12 +146,14 @@ check-commit:
|
||||||
- .os-debian-lts
|
- .os-debian-lts
|
||||||
variables:
|
variables:
|
||||||
BUILD_ARCH: "armv7"
|
BUILD_ARCH: "armv7"
|
||||||
|
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
|
||||||
|
|
||||||
.debian-armv7:
|
.debian-armv7:
|
||||||
extends:
|
extends:
|
||||||
- .os-debian
|
- .os-debian
|
||||||
variables:
|
variables:
|
||||||
BUILD_ARCH: "armv7"
|
BUILD_ARCH: "armv7"
|
||||||
|
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
|
||||||
# Armv7 doesn't have freerdp3 in bookworm-backports so we don't build FreeRDP
|
# Armv7 doesn't have freerdp3 in bookworm-backports so we don't build FreeRDP
|
||||||
MESON_DIST_OPTIONS: "-Dbackend-rdp=false"
|
MESON_DIST_OPTIONS: "-Dbackend-rdp=false"
|
||||||
# Inhibit installation of freerdp-dev
|
# Inhibit installation of freerdp-dev
|
||||||
|
|
@ -211,8 +220,6 @@ armv7-debian-lts-container_prep:
|
||||||
- .fdo.container-build@debian
|
- .fdo.container-build@debian
|
||||||
tags:
|
tags:
|
||||||
- aarch64
|
- aarch64
|
||||||
variables:
|
|
||||||
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
|
|
||||||
needs:
|
needs:
|
||||||
- job: base-container-pre
|
- job: base-container-pre
|
||||||
timeout: 30m
|
timeout: 30m
|
||||||
|
|
@ -225,8 +232,6 @@ armv7-debian-container_prep:
|
||||||
- .fdo.container-build@debian
|
- .fdo.container-build@debian
|
||||||
tags:
|
tags:
|
||||||
- aarch64
|
- aarch64
|
||||||
variables:
|
|
||||||
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
|
|
||||||
needs:
|
needs:
|
||||||
- job: base-container-pre
|
- job: base-container-pre
|
||||||
timeout: 30m
|
timeout: 30m
|
||||||
|
|
@ -262,17 +267,23 @@ aarch64-debian-container_prep:
|
||||||
timeout: 15m
|
timeout: 15m
|
||||||
variables:
|
variables:
|
||||||
BUILDDIR: $CI_PROJECT_DIR/build-weston-$CI_JOB_NAME
|
BUILDDIR: $CI_PROJECT_DIR/build-weston-$CI_JOB_NAME
|
||||||
|
BUILDDIR_WESTINY: $CI_PROJECT_DIR/build-westiny-$CI_JOB_NAME
|
||||||
PREFIX: $CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
|
PREFIX: $CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
|
||||||
|
PREFIX_WESTINY: $CI_PROJECT_DIR/prefix-westiny-$CI_JOB_NAME
|
||||||
before_script:
|
before_script:
|
||||||
- export PATH=~/.local/bin:$PATH
|
- export PATH=~/.local/bin:$PATH
|
||||||
- export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
|
- export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
|
||||||
- export TESTS_RES_PATH="$BUILDDIR/tests-res.txt"
|
- export TESTS_RES_PATH="$BUILDDIR/tests-res.txt"
|
||||||
|
- export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
|
||||||
- mkdir "$BUILDDIR" "$PREFIX"
|
- mkdir "$BUILDDIR" "$PREFIX"
|
||||||
|
- mkdir "$BUILDDIR_WESTINY" "$PREFIX_WESTINY"
|
||||||
|
|
||||||
.build-with-clang:
|
.build-with-clang:
|
||||||
variables:
|
variables:
|
||||||
CC: clang-$LLVM_VERSION
|
CC: clang-$LLVM_VERSION
|
||||||
CC_LD: lld-$LLVM_VERSION
|
CC_LD: lld-$LLVM_VERSION
|
||||||
|
CXX: clang++-$LLVM_VERSION
|
||||||
|
CXX_LD: lld-$LLVM_VERSION
|
||||||
MESON_TOOLCHAIN_OPTIONS: "$MESON_OPTIONS -Db_lundef=false" # clang+ASan+undef=boom
|
MESON_TOOLCHAIN_OPTIONS: "$MESON_OPTIONS -Db_lundef=false" # clang+ASan+undef=boom
|
||||||
|
|
||||||
# Extends the core build templates to also provide for running our testing. We
|
# Extends the core build templates to also provide for running our testing. We
|
||||||
|
|
@ -282,17 +293,8 @@ aarch64-debian-container_prep:
|
||||||
extends:
|
extends:
|
||||||
- .default-rules
|
- .default-rules
|
||||||
script:
|
script:
|
||||||
- cd "$BUILDDIR"
|
"${CI_PROJECT_DIR}/.gitlab-ci/build-and-test.sh"
|
||||||
- meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
|
|
||||||
- ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
|
||||||
- ninja install
|
|
||||||
- test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
|
|
||||||
- virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
|
|
||||||
- TEST_RES=$(cat $TESTS_RES_PATH)
|
|
||||||
- rm $TESTS_RES_PATH
|
|
||||||
- cp -R /weston-virtme ./
|
|
||||||
- rm weston-virtme/${KERNEL_IMAGE}
|
|
||||||
- exit $TEST_RES
|
|
||||||
artifacts:
|
artifacts:
|
||||||
name: weston-$CI_COMMIT_SHA
|
name: weston-$CI_COMMIT_SHA
|
||||||
when: always
|
when: always
|
||||||
|
|
@ -303,7 +305,7 @@ aarch64-debian-container_prep:
|
||||||
- $BUILDDIR/weston-virtme
|
- $BUILDDIR/weston-virtme
|
||||||
- $PREFIX
|
- $PREFIX
|
||||||
reports:
|
reports:
|
||||||
junit: $BUILDDIR/meson-logs/testlog-junit.xml
|
junit: $BUILDDIR/meson-logs/testlog.junit.xml
|
||||||
|
|
||||||
# Same as above, but without running any tests.
|
# Same as above, but without running any tests.
|
||||||
.build-no-test:
|
.build-no-test:
|
||||||
|
|
@ -425,67 +427,79 @@ aarch64-debian-container_prep:
|
||||||
- job: aarch64-debian-container_prep
|
- job: aarch64-debian-container_prep
|
||||||
artifacts: false
|
artifacts: false
|
||||||
|
|
||||||
# Full build, used for testing under KVM.
|
# Full build (gcov + perfetto) used for testing under KVM.
|
||||||
.build-options-full:
|
.build-options-full:
|
||||||
stage: "Full build and test"
|
stage: "Full build and test"
|
||||||
variables:
|
variables:
|
||||||
MESON_OPTIONS: >
|
MESON_OPTIONS: >
|
||||||
-Doptimization=0
|
-Doptimization=0
|
||||||
-Db_coverage=true
|
-Db_coverage=true
|
||||||
|
--force-fallback-for=perfetto
|
||||||
|
-Dperfetto=true
|
||||||
|
-Dperfetto:werror=false
|
||||||
-Dwerror=true
|
-Dwerror=true
|
||||||
-Dtest-skip-is-failure=true
|
-Dtest-skip-is-failure=true
|
||||||
after_script:
|
after_script:
|
||||||
- ninja -C "$BUILDDIR" coverage-html > "$BUILDDIR/meson-logs/ninja-coverage-html.txt"
|
- ninja -C "$BUILDDIR" coverage-html > "$BUILDDIR/meson-logs/ninja-coverage-html.txt"
|
||||||
- ninja -C "$BUILDDIR" coverage-xml
|
- ninja -C "$BUILDDIR" coverage-xml
|
||||||
|
|
||||||
|
# Full build, (without gcov and perfetto)
|
||||||
|
.build-options-full-v2:
|
||||||
|
stage: "Full build and test"
|
||||||
|
variables:
|
||||||
|
MESON_OPTIONS: >
|
||||||
|
-Doptimization=0
|
||||||
|
-Dwerror=true
|
||||||
|
-Dtest-skip-is-failure=true
|
||||||
|
|
||||||
x86_64-debian-lts-full-build:
|
x86_64-debian-lts-full-build:
|
||||||
extends:
|
extends:
|
||||||
- .test-env-debian-lts-x86_64
|
- .test-env-debian-lts-x86_64
|
||||||
- .build-options-full
|
- .build-options-full
|
||||||
|
|
||||||
x86_64-debian-full-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-x86_64
|
|
||||||
- .build-options-full
|
|
||||||
artifacts:
|
artifacts:
|
||||||
reports:
|
reports:
|
||||||
coverage_report:
|
coverage_report:
|
||||||
coverage_format: cobertura
|
coverage_format: cobertura
|
||||||
path: $BUILDDIR/meson-logs/coverage.xml
|
path: $BUILDDIR/meson-logs/coverage.xml
|
||||||
|
|
||||||
|
x86_64-debian-full-build:
|
||||||
|
extends:
|
||||||
|
- .test-env-debian-x86_64
|
||||||
|
- .build-options-full-v2
|
||||||
|
|
||||||
aarch64-debian-lts-full-build:
|
aarch64-debian-lts-full-build:
|
||||||
extends:
|
extends:
|
||||||
- .test-env-debian-lts-aarch64
|
- .test-env-debian-lts-aarch64
|
||||||
- .build-options-full
|
- .build-options-full-v2
|
||||||
|
|
||||||
aarch64-debian-full-build:
|
aarch64-debian-full-build:
|
||||||
extends:
|
extends:
|
||||||
- .test-env-debian-aarch64
|
- .test-env-debian-aarch64
|
||||||
- .build-options-full
|
- .build-options-full-v2
|
||||||
|
|
||||||
x86_64-clang-debian-lts-full-build:
|
x86_64-clang-debian-lts-full-build:
|
||||||
extends:
|
extends:
|
||||||
- .test-env-debian-lts-x86_64
|
- .test-env-debian-lts-x86_64
|
||||||
- .build-with-clang
|
- .build-with-clang
|
||||||
- .build-options-full
|
- .build-options-full-v2
|
||||||
|
|
||||||
x86_64-clang-debian-full-build:
|
x86_64-clang-debian-full-build:
|
||||||
extends:
|
extends:
|
||||||
- .test-env-debian-x86_64
|
- .test-env-debian-x86_64
|
||||||
- .build-with-clang
|
- .build-with-clang
|
||||||
- .build-options-full
|
- .build-options-full-v2
|
||||||
|
|
||||||
aarch64-clang-debian-lts-full-build:
|
aarch64-clang-debian-lts-full-build:
|
||||||
extends:
|
extends:
|
||||||
- .test-env-debian-lts-aarch64
|
- .test-env-debian-lts-aarch64
|
||||||
- .build-with-clang
|
- .build-with-clang
|
||||||
- .build-options-full
|
- .build-options-full-v2
|
||||||
|
|
||||||
aarch64-clang-debian-full-build:
|
aarch64-clang-debian-full-build:
|
||||||
extends:
|
extends:
|
||||||
- .test-env-debian-aarch64
|
- .test-env-debian-aarch64
|
||||||
- .build-with-clang
|
- .build-with-clang
|
||||||
- .build-options-full
|
- .build-options-full-v2
|
||||||
|
|
||||||
# Docs should be invariant on all architectures, so we only do it on Debian
|
# Docs should be invariant on all architectures, so we only do it on Debian
|
||||||
# x86-64.
|
# x86-64.
|
||||||
|
|
@ -499,9 +513,20 @@ docs-build:
|
||||||
- .build-env-debian-x86_64
|
- .build-env-debian-x86_64
|
||||||
- .build-no-test
|
- .build-no-test
|
||||||
|
|
||||||
# Building without gl-renderer, to make sure this keeps working.
|
# Building without gl-renderer and/or vulkan-renderer, to make sure this keeps working.
|
||||||
|
.build-options-no-gl-no-vulkan:
|
||||||
|
stage: "No-GL/Vulkan build and test"
|
||||||
|
variables:
|
||||||
|
MESON_OPTIONS: >
|
||||||
|
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
||||||
|
-Drenderer-gl=false
|
||||||
|
-Drenderer-vulkan=false
|
||||||
|
-Dremoting=false
|
||||||
|
-Dpipewire=false
|
||||||
|
-Dwerror=true
|
||||||
|
|
||||||
.build-options-no-gl:
|
.build-options-no-gl:
|
||||||
stage: "No-GL build and test"
|
stage: "No-GL/Vulkan build and test"
|
||||||
variables:
|
variables:
|
||||||
MESON_OPTIONS: >
|
MESON_OPTIONS: >
|
||||||
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
||||||
|
|
@ -510,51 +535,72 @@ docs-build:
|
||||||
-Dpipewire=false
|
-Dpipewire=false
|
||||||
-Dwerror=true
|
-Dwerror=true
|
||||||
|
|
||||||
x86_64-debian-lts-no-gl-build:
|
.build-options-no-vulkan:
|
||||||
|
stage: "No-GL/Vulkan build and test"
|
||||||
|
variables:
|
||||||
|
MESON_OPTIONS: >
|
||||||
|
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
||||||
|
-Drenderer-vulkan=false
|
||||||
|
-Dremoting=false
|
||||||
|
-Dpipewire=false
|
||||||
|
-Dwerror=true
|
||||||
|
|
||||||
|
x86_64-debian-lts-no-gl-no-vulkan-build:
|
||||||
extends:
|
extends:
|
||||||
- .test-env-debian-lts-x86_64
|
- .test-env-debian-lts-x86_64
|
||||||
- .build-options-no-gl
|
- .build-options-no-gl-no-vulkan
|
||||||
|
|
||||||
|
x86_64-debian-no-gl-no-vulkan-build:
|
||||||
|
extends:
|
||||||
|
- .test-env-debian-x86_64
|
||||||
|
- .build-options-no-gl-no-vulkan
|
||||||
|
|
||||||
|
armv7-debian-lts-no-gl-no-vulkan-build:
|
||||||
|
extends:
|
||||||
|
- .build-env-debian-lts-armv7
|
||||||
|
- .build-no-test
|
||||||
|
- .build-options-no-gl-no-vulkan
|
||||||
|
|
||||||
|
armv7-debian-no-gl-no-vulkan-build:
|
||||||
|
extends:
|
||||||
|
- .build-env-debian-armv7
|
||||||
|
- .build-no-test
|
||||||
|
- .build-options-no-gl-no-vulkan
|
||||||
|
|
||||||
|
armv7-clang-debian-lts-no-gl-no-vulkan-build:
|
||||||
|
extends:
|
||||||
|
- .build-env-debian-lts-armv7
|
||||||
|
- .build-with-clang
|
||||||
|
- .build-no-test
|
||||||
|
- .build-options-no-gl-no-vulkan
|
||||||
|
|
||||||
|
armv7-clang-debian-no-gl-no-vulkan-build:
|
||||||
|
extends:
|
||||||
|
- .build-env-debian-armv7
|
||||||
|
- .build-with-clang
|
||||||
|
- .build-no-test
|
||||||
|
- .build-options-no-gl-no-vulkan
|
||||||
|
|
||||||
|
aarch64-debian-lts-no-gl-no-vulkan-build:
|
||||||
|
extends:
|
||||||
|
- .test-env-debian-lts-aarch64
|
||||||
|
- .build-options-no-gl-no-vulkan
|
||||||
|
|
||||||
|
aarch64-debian-no-gl-no-vulkan-build:
|
||||||
|
extends:
|
||||||
|
- .test-env-debian-aarch64
|
||||||
|
- .build-options-no-gl-no-vulkan
|
||||||
|
|
||||||
x86_64-debian-no-gl-build:
|
x86_64-debian-no-gl-build:
|
||||||
extends:
|
extends:
|
||||||
- .test-env-debian-x86_64
|
- .test-env-debian-x86_64
|
||||||
- .build-options-no-gl
|
- .build-options-no-gl
|
||||||
|
|
||||||
armv7-debian-lts-no-gl-build:
|
x86_64-debian-no-vulkan-build:
|
||||||
extends:
|
extends:
|
||||||
- .build-env-debian-lts-armv7
|
- .test-env-debian-x86_64
|
||||||
- .build-no-test
|
- .build-options-no-vulkan
|
||||||
- .build-options-no-gl
|
|
||||||
|
|
||||||
armv7-debian-no-gl-build:
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-armv7
|
|
||||||
- .build-no-test
|
|
||||||
- .build-options-no-gl
|
|
||||||
|
|
||||||
armv7-clang-debian-lts-no-gl-build:
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-lts-armv7
|
|
||||||
- .build-with-clang
|
|
||||||
- .build-no-test
|
|
||||||
- .build-options-no-gl
|
|
||||||
|
|
||||||
armv7-clang-debian-no-gl-build:
|
|
||||||
extends:
|
|
||||||
- .build-env-debian-armv7
|
|
||||||
- .build-with-clang
|
|
||||||
- .build-no-test
|
|
||||||
- .build-options-no-gl
|
|
||||||
|
|
||||||
aarch64-debian-lts-no-gl-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-lts-aarch64
|
|
||||||
- .build-options-no-gl
|
|
||||||
|
|
||||||
aarch64-debian-no-gl-build:
|
|
||||||
extends:
|
|
||||||
- .test-env-debian-aarch64
|
|
||||||
- .build-options-no-gl
|
|
||||||
|
|
||||||
# Expose docs and coverage reports, so we can show users any changes to these
|
# Expose docs and coverage reports, so we can show users any changes to these
|
||||||
# inside their merge requests, letting us check them before merge.
|
# inside their merge requests, letting us check them before merge.
|
||||||
|
|
@ -566,18 +612,18 @@ aarch64-debian-no-gl-build:
|
||||||
docs-and-coverage:
|
docs-and-coverage:
|
||||||
extends:
|
extends:
|
||||||
- .default-rules
|
- .default-rules
|
||||||
- .debian-x86_64
|
- .debian-lts-x86_64
|
||||||
- .fdo.suffixed-image@debian
|
- .fdo.suffixed-image@debian
|
||||||
stage: pages
|
stage: pages
|
||||||
needs:
|
needs:
|
||||||
- job: docs-build
|
- job: docs-build
|
||||||
artifacts: true
|
artifacts: true
|
||||||
- job: x86_64-debian-full-build
|
- job: x86_64-debian-lts-full-build
|
||||||
artifacts: true
|
artifacts: true
|
||||||
timeout: 5m
|
timeout: 5m
|
||||||
script:
|
script:
|
||||||
- mv prefix-weston-docs-build/share/doc/weston Documentation
|
- mv prefix-weston-docs-build/share/doc/weston Documentation
|
||||||
- mv build-weston-x86_64-debian-full-build/meson-logs/coveragereport Test_Coverage
|
- mv build-weston-x86_64-debian-lts-full-build/meson-logs/coveragereport Test_Coverage
|
||||||
- rm Test_Coverage/gcov.css
|
- rm Test_Coverage/gcov.css
|
||||||
- cp doc/style/lcov-style.css Test_Coverage/gcov.css
|
- cp doc/style/lcov-style.css Test_Coverage/gcov.css
|
||||||
- cp doc/style/*.png Test_Coverage/
|
- cp doc/style/*.png Test_Coverage/
|
||||||
|
|
|
||||||
29
.gitlab-ci/build-and-test.sh
Executable file
29
.gitlab-ci/build-and-test.sh
Executable file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source "${FDO_CI_BASH_HELPERS}"
|
||||||
|
|
||||||
|
fdo_log_section_start_collapsed build_weston "build_weston"
|
||||||
|
cd "$BUILDDIR"
|
||||||
|
meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
|
||||||
|
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||||
|
ninja install
|
||||||
|
|
||||||
|
if [ "$CI_JOB_NAME" == "x86_64-debian-full-build" ]; then
|
||||||
|
cd "$BUILDDIR_WESTINY"
|
||||||
|
export NPREFIX=$CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
|
||||||
|
export PKG_CONFIG_PATH=$NPREFIX/lib/pkgconfig/:$NPREFIX/share/pkgconfig/:$NPREFIX/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH
|
||||||
|
meson setup --prefix="$PREFIX_WESTINY" --wrap-mode=nofallback ../westinyplus/
|
||||||
|
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||||
|
ninja install
|
||||||
|
ninja clean
|
||||||
|
cd -
|
||||||
|
fi
|
||||||
|
fdo_log_section_end build_weston
|
||||||
|
|
||||||
|
test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
|
||||||
|
virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
|
||||||
|
TEST_RES=$(cat $TESTS_RES_PATH)
|
||||||
|
rm $TESTS_RES_PATH
|
||||||
|
cp -R /weston-virtme ./
|
||||||
|
rm weston-virtme/${KERNEL_IMAGE}
|
||||||
|
exit $TEST_RES
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
# .gitlab-ci.yml for more information. This script is called from an
|
# .gitlab-ci.yml for more information. This script is called from an
|
||||||
# OS-specific build scripts like debian-install.sh.
|
# OS-specific build scripts like debian-install.sh.
|
||||||
|
|
||||||
|
source "${FDO_CI_BASH_HELPERS}"
|
||||||
|
|
||||||
set -o xtrace -o errexit
|
set -o xtrace -o errexit
|
||||||
|
|
||||||
# Set concurrency to an appropriate level for our shared runners, falling back
|
# Set concurrency to an appropriate level for our shared runners, falling back
|
||||||
|
|
@ -25,7 +27,8 @@ esac
|
||||||
|
|
||||||
# Build and install Meson. Generally we want to keep this in sync with what
|
# Build and install Meson. Generally we want to keep this in sync with what
|
||||||
# we require inside meson.build.
|
# we require inside meson.build.
|
||||||
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.0.0
|
fdo_log_section_start_collapsed install_meson "install_meson"
|
||||||
|
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.4.2
|
||||||
export PATH=$HOME/.local/bin:$PATH
|
export PATH=$HOME/.local/bin:$PATH
|
||||||
|
|
||||||
# Our docs are built using Sphinx (top-level organisation and final HTML/CSS
|
# Our docs are built using Sphinx (top-level organisation and final HTML/CSS
|
||||||
|
|
@ -41,31 +44,22 @@ pip3 install $PIP_ARGS sphinxcontrib-qthelp==1.0.3
|
||||||
pip3 install $PIP_ARGS sphinxcontrib-serializinghtml==1.1.5
|
pip3 install $PIP_ARGS sphinxcontrib-serializinghtml==1.1.5
|
||||||
pip3 install $PIP_ARGS breathe==4.31.0
|
pip3 install $PIP_ARGS breathe==4.31.0
|
||||||
pip3 install $PIP_ARGS sphinx_rtd_theme==1.0.0
|
pip3 install $PIP_ARGS sphinx_rtd_theme==1.0.0
|
||||||
|
fdo_log_section_end install_meson
|
||||||
|
|
||||||
|
|
||||||
# Build a Linux kernel for use in testing. We enable the VKMS module so we can
|
# Build a Linux kernel for use in testing. We enable the VKMS module so we can
|
||||||
# predictably test the DRM backend in the absence of real hardware. We lock the
|
# predictably test the DRM backend in the absence of real hardware. We lock the
|
||||||
# version here so we see predictable results.
|
# version here so we see predictable results.
|
||||||
#
|
#
|
||||||
# To run this we use virtme, a QEMU wrapper: https://github.com/amluto/virtme
|
# To run this we use virtme-ng, a QEMU wrapper. It is a fork from virtme, whose
|
||||||
|
# development stalled.
|
||||||
#
|
#
|
||||||
# virtme makes our lives easier by abstracting handling of the console,
|
# virtme-ng makes our lives easier by abstracting handling of the console,
|
||||||
# filesystem, etc, so we can pretend that the VM we execute in is actually
|
# filesystem, etc, so we can pretend that the VM we execute in is actually
|
||||||
# just a regular container.
|
# just a regular container.
|
||||||
#
|
fdo_log_section_start_collapsed install_kernel "install_kernel"
|
||||||
# The reason why we are using a fork here is that it adds a patch to have the
|
|
||||||
# --script-dir command line option. With that we can run scripts that are in a
|
|
||||||
# certain folder when virtme starts, which is necessary in our use case.
|
|
||||||
#
|
|
||||||
# The upstream also has some commands that could help us to reach the same
|
|
||||||
# results: --script-sh and --script-exec. Unfornutately they are not completely
|
|
||||||
# implemented yet, so we had some trouble to use them and it was becoming
|
|
||||||
# hackery.
|
|
||||||
#
|
|
||||||
# The fork pulls in this support from the original GitHub PR, rebased on top of
|
|
||||||
# a newer upstream version which fixes AArch64 support.
|
|
||||||
if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
||||||
# 6.3 is (still) used as >= 6.5 drm-writeback test will timeout
|
git clone --depth=1 --branch=v6.18 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux
|
||||||
git clone --depth=1 --branch=v6.3 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux
|
|
||||||
cd linux
|
cd linux
|
||||||
|
|
||||||
if [[ "${BUILD_ARCH}" = "x86-64" ]]; then
|
if [[ "${BUILD_ARCH}" = "x86-64" ]]; then
|
||||||
|
|
@ -91,9 +85,8 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
||||||
./scripts/config \
|
./scripts/config \
|
||||||
--enable CONFIG_DRM \
|
--enable CONFIG_DRM \
|
||||||
--enable CONFIG_DRM_KMS_HELPER \
|
--enable CONFIG_DRM_KMS_HELPER \
|
||||||
--enable CONFIG_DRM_KMS_FB_HELPER \
|
|
||||||
--enable CONFIG_DRM_VKMS \
|
--enable CONFIG_DRM_VKMS \
|
||||||
--enable CONFIG_DRM_VGEM
|
--enable CONFIG_UDMABUF
|
||||||
make ARCH=${LINUX_ARCH} oldconfig
|
make ARCH=${LINUX_ARCH} oldconfig
|
||||||
make ARCH=${LINUX_ARCH}
|
make ARCH=${LINUX_ARCH}
|
||||||
|
|
||||||
|
|
@ -108,14 +101,15 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
||||||
./setup.py install
|
./setup.py install
|
||||||
cd ..
|
cd ..
|
||||||
fi
|
fi
|
||||||
|
fdo_log_section_end install_kernel
|
||||||
|
|
||||||
# Build and install Wayland; keep this version in sync with our dependency
|
# Build and install Wayland; keep this version in sync with our dependency
|
||||||
# in meson.build.
|
# in meson.build.
|
||||||
|
fdo_log_section_start_collapsed install_wayland "install_wayland"
|
||||||
git clone --branch 1.22.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
|
git clone --branch 1.22.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
|
||||||
cd wayland
|
cd wayland
|
||||||
git show -s HEAD
|
git show -s HEAD
|
||||||
mkdir build
|
meson setup build --wrap-mode=nofallback -Ddocumentation=false
|
||||||
meson build --wrap-mode=nofallback -Ddocumentation=false
|
|
||||||
ninja ${NINJAFLAGS} -C build install
|
ninja ${NINJAFLAGS} -C build install
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf wayland
|
rm -rf wayland
|
||||||
|
|
@ -123,24 +117,39 @@ rm -rf wayland
|
||||||
# Keep this version in sync with our dependency in meson.build. If you wish to
|
# Keep this version in sync with our dependency in meson.build. If you wish to
|
||||||
# raise a MR against custom protocol, please change this reference to clone
|
# raise a MR against custom protocol, please change this reference to clone
|
||||||
# your relevant tree, and make sure you bump $FDO_DISTRIBUTION_TAG.
|
# your relevant tree, and make sure you bump $FDO_DISTRIBUTION_TAG.
|
||||||
git clone --branch 1.33 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
|
git clone --branch 1.46 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
|
||||||
cd wayland-protocols
|
cd wayland-protocols
|
||||||
git show -s HEAD
|
git show -s HEAD
|
||||||
meson build --wrap-mode=nofallback
|
meson setup build --wrap-mode=nofallback -Dtests=false
|
||||||
ninja ${NINJAFLAGS} -C build install
|
ninja ${NINJAFLAGS} -C build install
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf wayland-protocols
|
rm -rf wayland-protocols
|
||||||
|
fdo_log_section_end install_wayland
|
||||||
|
|
||||||
# Build and install our own version of libdrm. Debian 11 (bullseye) provides
|
# Build and install our own version of libdrm. Debian 11 (bullseye) provides
|
||||||
# libdrm 2.4.104 which doesn't have the IN_FORMATS iterator api, and Mesa
|
# libdrm 2.4.104 which doesn't have the IN_FORMATS iterator api, and Mesa
|
||||||
# depends on 2.4.109 as well.
|
# depends on 2.4.109 as well.
|
||||||
git clone --branch libdrm-2.4.109 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
|
# Bump to 2.4.118 to include DRM_FORMAT_NV{15,20,30}
|
||||||
|
fdo_log_section_start_collapsed install_libdrm "install_libdrm"
|
||||||
|
git clone --branch libdrm-2.4.118 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
|
||||||
cd drm
|
cd drm
|
||||||
meson build --wrap-mode=nofallback -Dauto_features=disabled \
|
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||||
-Dvc4=false -Dfreedreno=false -Detnaviv=false
|
-Dvc4=disabled -Dfreedreno=disabled -Detnaviv=disabled
|
||||||
ninja ${NINJAFLAGS} -C build install
|
ninja ${NINJAFLAGS} -C build install
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf drm
|
rm -rf drm
|
||||||
|
fdo_log_section_end install_libdrm
|
||||||
|
|
||||||
|
# Build and install Vulkan-Headers with a defined version, mostly because
|
||||||
|
# the version in Debian 11 (bullseye) is too old to build vulkan-renderer.
|
||||||
|
fdo_log_section_start_collapsed install_vulkan_headers "install_vulkan_headers"
|
||||||
|
git clone --branch sdk-1.3.239.0 --depth=1 https://github.com/KhronosGroup/Vulkan-Headers
|
||||||
|
cd Vulkan-Headers
|
||||||
|
cmake -G Ninja -B build
|
||||||
|
ninja ${NINJAFLAGS} -C build install
|
||||||
|
cd ..
|
||||||
|
rm -rf Vulkan-Headers
|
||||||
|
fdo_log_section_end install_vulkan_headers
|
||||||
|
|
||||||
# Build and install our own version of Mesa. Debian provides a perfectly usable
|
# Build and install our own version of Mesa. Debian provides a perfectly usable
|
||||||
# Mesa, however llvmpipe's rendering behaviour can change subtly over time.
|
# Mesa, however llvmpipe's rendering behaviour can change subtly over time.
|
||||||
|
|
@ -149,64 +158,89 @@ rm -rf drm
|
||||||
# features from Mesa then bump this version and $FDO_DISTRIBUTION_TAG, however
|
# features from Mesa then bump this version and $FDO_DISTRIBUTION_TAG, however
|
||||||
# please be prepared for some of the tests to change output, which will need to
|
# please be prepared for some of the tests to change output, which will need to
|
||||||
# be manually inspected for correctness.
|
# be manually inspected for correctness.
|
||||||
git clone --branch 23.0 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
|
fdo_log_section_start_collapsed install_mesa "install_mesa"
|
||||||
|
|
||||||
|
# Needed for Mesa >= 25.3
|
||||||
|
git clone --branch 12.2.0 --depth=1 https://github.com/KhronosGroup/glslang
|
||||||
|
cd glslang
|
||||||
|
cmake -G Ninja -B build
|
||||||
|
ninja ${NINJAFLAGS} -C build install
|
||||||
|
cd ..
|
||||||
|
rm -rf glslang
|
||||||
|
|
||||||
|
# The 25.3 was the first stable release where the Vulkan backend works with
|
||||||
|
# vkms+lavapipe.
|
||||||
|
git clone --branch mesa-25.3.2 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
|
||||||
cd mesa
|
cd mesa
|
||||||
meson build --wrap-mode=nofallback -Dauto_features=disabled \
|
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||||
-Dgallium-drivers=swrast -Dvulkan-drivers= -Ddri-drivers=
|
-Dgallium-drivers=llvmpipe -Dvulkan-drivers=swrast -Dvideo-codecs= \
|
||||||
|
-Degl=enabled -Dgbm=enabled -Dgles2=enabled -Dllvm=enabled \
|
||||||
|
-Dshared-glapi=enabled -Dglx=disabled
|
||||||
ninja ${NINJAFLAGS} -C build install
|
ninja ${NINJAFLAGS} -C build install
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf mesa
|
rm -rf mesa
|
||||||
|
fdo_log_section_end install_mesa
|
||||||
|
|
||||||
# PipeWire is used for remoting support. Unlike our other dependencies its
|
# PipeWire is used for remoting support. Unlike our other dependencies its
|
||||||
# behaviour will be stable, however as a pre-1.0 project its API is not yet
|
# behaviour will be stable, however as a pre-1.0 project its API is not yet
|
||||||
# stable, so again we lock it to a fixed version.
|
# stable, so again we lock it to a fixed version.
|
||||||
#
|
#
|
||||||
# ... the version chosen is 0.3.32 with a small Clang-specific build fix.
|
# ... the version chosen is 0.3.32 with a small Clang-specific build fix.
|
||||||
|
fdo_log_section_start_collapsed install_pipewire "install_pipewire"
|
||||||
git clone --single-branch --branch master https://gitlab.freedesktop.org/pipewire/pipewire.git pipewire-src
|
git clone --single-branch --branch master https://gitlab.freedesktop.org/pipewire/pipewire.git pipewire-src
|
||||||
cd pipewire-src
|
cd pipewire-src
|
||||||
git checkout -b snapshot bf112940d0bf8f526dd6229a619c1283835b49c2
|
git checkout -b snapshot bf112940d0bf8f526dd6229a619c1283835b49c2
|
||||||
meson build --wrap-mode=nofallback
|
meson setup build --wrap-mode=nofallback
|
||||||
ninja ${NINJAFLAGS} -C build install
|
ninja ${NINJAFLAGS} -C build install
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf pipewire-src
|
rm -rf pipewire-src
|
||||||
|
fdo_log_section_end install_pipewire
|
||||||
|
|
||||||
# seatd lets us avoid the pain of open-coding TTY assignment within Weston.
|
# seatd lets us avoid the pain of open-coding TTY assignment within Weston.
|
||||||
# We use this for our tests using the DRM backend.
|
# We use this for our tests using the DRM backend.
|
||||||
|
fdo_log_section_start_collapsed install_seatd "install_seatd"
|
||||||
git clone --depth=1 --branch 0.6.1 https://git.sr.ht/~kennylevinsen/seatd
|
git clone --depth=1 --branch 0.6.1 https://git.sr.ht/~kennylevinsen/seatd
|
||||||
cd seatd
|
cd seatd
|
||||||
meson build --wrap-mode=nofallback -Dauto_features=disabled \
|
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||||
-Dlibseat-seatd=enabled -Dlibseat-logind=systemd -Dserver=enabled
|
-Dlibseat-seatd=enabled -Dlibseat-logind=systemd -Dserver=enabled
|
||||||
ninja ${NINJAFLAGS} -C build install
|
ninja ${NINJAFLAGS} -C build install
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf seatd
|
rm -rf seatd
|
||||||
|
fdo_log_section_end install_seatd
|
||||||
|
|
||||||
# Build and install aml and neatvnc, which are required for the VNC backend
|
# Build and install aml and neatvnc, which are required for the VNC backend
|
||||||
|
fdo_log_section_start_collapsed install_aml_neatvnc "install_aml_neatvnc"
|
||||||
git clone --branch v0.3.0 --depth=1 https://github.com/any1/aml.git
|
git clone --branch v0.3.0 --depth=1 https://github.com/any1/aml.git
|
||||||
cd aml
|
cd aml
|
||||||
meson build --wrap-mode=nofallback
|
meson setup build --wrap-mode=nofallback
|
||||||
ninja ${NINJAFLAGS} -C build install
|
ninja ${NINJAFLAGS} -C build install
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf aml
|
rm -rf aml
|
||||||
git clone --branch v0.7.0 --depth=1 https://github.com/any1/neatvnc.git
|
git clone --branch v0.7.0 --depth=1 https://github.com/any1/neatvnc.git
|
||||||
cd neatvnc
|
cd neatvnc
|
||||||
meson build --wrap-mode=nofallback -Dauto_features=disabled
|
meson setup build --wrap-mode=nofallback -Dauto_features=disabled
|
||||||
ninja ${NINJAFLAGS} -C build install
|
ninja ${NINJAFLAGS} -C build install
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf neatvnc
|
rm -rf neatvnc
|
||||||
|
fdo_log_section_end install_aml_neatvnc
|
||||||
|
|
||||||
# Build and install libdisplay-info, used by drm-backend
|
# Build and install libdisplay-info, used by drm-backend
|
||||||
git clone --branch 0.1.1 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
|
fdo_log_section_start_collapsed install_libdisplay-info "install_libdisplay-info"
|
||||||
|
git clone --branch 0.2.0 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
|
||||||
cd libdisplay-info
|
cd libdisplay-info
|
||||||
meson build --wrap-mode=nofallback
|
meson setup build --wrap-mode=nofallback
|
||||||
ninja ${NINJAFLAGS} -C build install
|
ninja ${NINJAFLAGS} -C build install
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf libdisplay-info
|
rm -rf libdisplay-info
|
||||||
|
fdo_log_section_end install_libdisplay-info
|
||||||
|
|
||||||
# Build and install lcms2, which we use to support color-management.
|
# Build and install lcms2, which we use to support color-management.
|
||||||
|
fdo_log_section_start_collapsed install_lcms2 "install_lcms2"
|
||||||
git clone --branch master https://github.com/mm2/Little-CMS.git lcms2
|
git clone --branch master https://github.com/mm2/Little-CMS.git lcms2
|
||||||
cd lcms2
|
cd lcms2
|
||||||
git checkout -b snapshot lcms2.16
|
git checkout -b snapshot lcms2.16
|
||||||
meson build --wrap-mode=nofallback
|
meson setup build --wrap-mode=nofallback
|
||||||
ninja ${NINJAFLAGS} -C build install
|
ninja ${NINJAFLAGS} -C build install
|
||||||
cd ..
|
cd ..
|
||||||
rm -rf lcms2
|
rm -rf lcms2
|
||||||
|
fdo_log_section_end install_lcms2
|
||||||
|
|
|
||||||
|
|
@ -26,14 +26,22 @@ MESA_DEV_PKGS="
|
||||||
python3-mako
|
python3-mako
|
||||||
"
|
"
|
||||||
|
|
||||||
|
# These get temporarily installed for other build dependencies and then
|
||||||
|
# force-removed.
|
||||||
|
# cmake is used by Vulkan-Headers
|
||||||
|
BUILD_DEV_PKGS="
|
||||||
|
cmake
|
||||||
|
"
|
||||||
|
|
||||||
# Needed for running the custom-built mesa
|
# Needed for running the custom-built mesa
|
||||||
MESA_RUNTIME_PKGS="
|
MESA_RUNTIME_PKGS="
|
||||||
libllvm${LLVM_VERSION}
|
libllvm${LLVM_VERSION}
|
||||||
"
|
"
|
||||||
|
|
||||||
if [ x"$USE_BOOKWORM_BACKPORTS" = "xy" ] ; then
|
if [ x"$USE_DEBIAN_BACKPORTS" = "xy" ] ; then
|
||||||
echo 'deb http://deb.debian.org/debian bookworm-backports main' >> /etc/apt/sources.list
|
echo 'deb http://deb.debian.org/debian '${FDO_DISTRIBUTION_VERSION}'-backports main' >> /etc/apt/sources.list
|
||||||
fi
|
fi
|
||||||
|
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get -y --no-install-recommends install \
|
apt-get -y --no-install-recommends install \
|
||||||
autoconf \
|
autoconf \
|
||||||
|
|
@ -45,6 +53,7 @@ apt-get -y --no-install-recommends install \
|
||||||
graphviz \
|
graphviz \
|
||||||
gcovr \
|
gcovr \
|
||||||
git \
|
git \
|
||||||
|
glslang-tools \
|
||||||
hwdata \
|
hwdata \
|
||||||
lcov \
|
lcov \
|
||||||
libasound2-dev \
|
libasound2-dev \
|
||||||
|
|
@ -59,7 +68,7 @@ apt-get -y --no-install-recommends install \
|
||||||
libexpat1-dev \
|
libexpat1-dev \
|
||||||
libffi-dev \
|
libffi-dev \
|
||||||
libgbm-dev \
|
libgbm-dev \
|
||||||
libgdk-pixbuf2.0-dev \
|
libgdk-pixbuf-xlib-2.0-dev \
|
||||||
libgles2-mesa-dev \
|
libgles2-mesa-dev \
|
||||||
libglu1-mesa-dev \
|
libglu1-mesa-dev \
|
||||||
libgstreamer1.0-dev \
|
libgstreamer1.0-dev \
|
||||||
|
|
@ -68,6 +77,7 @@ apt-get -y --no-install-recommends install \
|
||||||
libjack-jackd2-dev \
|
libjack-jackd2-dev \
|
||||||
libjpeg-dev \
|
libjpeg-dev \
|
||||||
libjpeg-dev \
|
libjpeg-dev \
|
||||||
|
liblua5.4-dev \
|
||||||
libmtdev-dev \
|
libmtdev-dev \
|
||||||
libpam0g-dev \
|
libpam0g-dev \
|
||||||
libpango1.0-dev \
|
libpango1.0-dev \
|
||||||
|
|
@ -122,7 +132,9 @@ apt-get -y --no-install-recommends install \
|
||||||
cargo rustc \
|
cargo rustc \
|
||||||
iproute2 udev \
|
iproute2 udev \
|
||||||
$MESA_DEV_PKGS \
|
$MESA_DEV_PKGS \
|
||||||
|
$BUILD_DEV_PKGS \
|
||||||
$MESA_RUNTIME_PKGS \
|
$MESA_RUNTIME_PKGS \
|
||||||
|
$PACKAGES_SPECIFIC \
|
||||||
$LINUX_DEV_PKGS \
|
$LINUX_DEV_PKGS \
|
||||||
|
|
||||||
if [ "$FREERDP_VERSION" -ne 0 ] ; then
|
if [ "$FREERDP_VERSION" -ne 0 ] ; then
|
||||||
|
|
@ -135,4 +147,4 @@ fi
|
||||||
|
|
||||||
# And remove packages which are only required for our build dependencies,
|
# And remove packages which are only required for our build dependencies,
|
||||||
# which we don't need bloating the image whilst we build and run Weston.
|
# which we don't need bloating the image whilst we build and run Weston.
|
||||||
apt-get -y --autoremove purge $LINUX_DEV_PKGS $MESA_DEV_PKGS
|
apt-get -y --autoremove purge $LINUX_DEV_PKGS $MESA_DEV_PKGS $BUILD_DEV_PKGS
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,16 @@ leak:wl_shm_buffer_begin_access
|
||||||
leak:g_malloc0
|
leak:g_malloc0
|
||||||
leak:sysprof_collector_get
|
leak:sysprof_collector_get
|
||||||
leak:/ld-*.so*
|
leak:/ld-*.so*
|
||||||
|
|
||||||
|
# Add all of perfetto, since it's not easy to clean up after it
|
||||||
|
leak:perfetto
|
||||||
|
|
||||||
|
# lavapipe inexplicably leaks when Vulkan physical devices are enumerated,
|
||||||
|
# despite us a) not using that device and b) freeing the instance. This is
|
||||||
|
# apparently a known issue. (Also when ASan creates threads ...)
|
||||||
|
leak:vkEnumeratePhysicalDevices
|
||||||
|
leak:asan_thread_start
|
||||||
|
|
||||||
|
# glib/pangoft for Trixie update
|
||||||
|
leak:libpangoft2
|
||||||
|
leak:libglib
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,7 @@ export LIBSEAT_BACKEND=seatd
|
||||||
# devices are loaded is not predictable, so the DRM node that VKMS takes can
|
# devices are loaded is not predictable, so the DRM node that VKMS takes can
|
||||||
# change across each boot. That's why we have this one-liner shell script to get
|
# change across each boot. That's why we have this one-liner shell script to get
|
||||||
# the appropriate node for VKMS.
|
# the appropriate node for VKMS.
|
||||||
export WESTON_TEST_SUITE_DRM_DEVICE=$(basename /sys/devices/platform/vkms/drm/card*)
|
export WESTON_TEST_SUITE_DRM_DEVICE=$(basename /sys/bus/faux/devices/vkms/drm/card*)
|
||||||
# To run tests in the CI that exercise the zwp_linux_dmabuf_v1 implementation in
|
|
||||||
# Weston, we use VGEM to allocate buffers.
|
|
||||||
export WESTON_TEST_SUITE_ALLOC_DEVICE=$(basename /sys/devices/platform/vgem/drm/card*)
|
|
||||||
|
|
||||||
# ninja test depends on meson, and meson itself looks for its modules on folder
|
# ninja test depends on meson, and meson itself looks for its modules on folder
|
||||||
# $HOME/.local/lib/pythonX.Y/site-packages (the Python version may differ).
|
# $HOME/.local/lib/pythonX.Y/site-packages (the Python version may differ).
|
||||||
|
|
@ -26,11 +23,11 @@ export HOME=/root
|
||||||
export PATH=$HOME/.local/bin:$PATH
|
export PATH=$HOME/.local/bin:$PATH
|
||||||
export PATH=/usr/local/bin:$PATH
|
export PATH=/usr/local/bin:$PATH
|
||||||
|
|
||||||
export SEATD_LOGLEVEL=debug
|
|
||||||
|
|
||||||
# Terrible hack, per comment in weston-test-runner.c's main(): find Mesa's
|
# Terrible hack, per comment in weston-test-runner.c's main(): find Mesa's
|
||||||
# llvmpipe driver module location
|
# llvmpipe/lavapipe driver module location
|
||||||
export WESTON_CI_LEAK_DL_HANDLE=$(find /usr/local -name swrast_dri.so -print 2>/dev/null || true)
|
export WESTON_CI_LEAK_DL_HANDLES=$(find /usr/local -name swrast_dri.so -print 2>/dev/null || true):
|
||||||
|
export WESTON_CI_LEAK_DL_HANDLES=$WESTON_CI_LEAK_DL_HANDLES:$(find /usr/local -name libvulkan_lvp.so -print 2>/dev/null || true)
|
||||||
|
export WESTON_CI_LEAK_DL_HANDLES=$WESTON_CI_LEAK_DL_HANDLES:$(find /usr/local -name libgallium\*.so -print 2>/dev/null || true)
|
||||||
|
|
||||||
# run the tests and save the exit status
|
# run the tests and save the exit status
|
||||||
# we give ourselves a very generous timeout multiplier due to ASan overhead
|
# we give ourselves a very generous timeout multiplier due to ASan overhead
|
||||||
|
|
|
||||||
|
|
@ -117,11 +117,11 @@ finish_calibration (struct calibrator *calibrator)
|
||||||
*/
|
*/
|
||||||
memset(&m, 0, sizeof(m));
|
memset(&m, 0, sizeof(m));
|
||||||
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
|
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
|
||||||
m.d[i] = calibrator->tests[i].clicked_x;
|
m.M.col[0].el[i] = calibrator->tests[i].clicked_x;
|
||||||
m.d[i + 4] = calibrator->tests[i].clicked_y;
|
m.M.col[1].el[i] = calibrator->tests[i].clicked_y;
|
||||||
m.d[i + 8] = 1;
|
m.M.col[2].el[i] = 1;
|
||||||
}
|
}
|
||||||
m.d[15] = 1;
|
m.M.col[3].el[3] = 1;
|
||||||
|
|
||||||
weston_matrix_invert(&inverse, &m);
|
weston_matrix_invert(&inverse, &m);
|
||||||
|
|
||||||
|
|
@ -129,8 +129,8 @@ finish_calibration (struct calibrator *calibrator)
|
||||||
memset(&y_calib, 0, sizeof(y_calib));
|
memset(&y_calib, 0, sizeof(y_calib));
|
||||||
|
|
||||||
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
|
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
|
||||||
x_calib.f[i] = calibrator->tests[i].drawn_x;
|
x_calib.v.el[i] = calibrator->tests[i].drawn_x;
|
||||||
y_calib.f[i] = calibrator->tests[i].drawn_y;
|
y_calib.v.el[i] = calibrator->tests[i].drawn_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Multiples into the vector */
|
/* Multiples into the vector */
|
||||||
|
|
@ -138,8 +138,8 @@ finish_calibration (struct calibrator *calibrator)
|
||||||
weston_matrix_transform(&inverse, &y_calib);
|
weston_matrix_transform(&inverse, &y_calib);
|
||||||
|
|
||||||
printf ("Calibration values: %f %f %f %f %f %f\n",
|
printf ("Calibration values: %f %f %f %f %f %f\n",
|
||||||
x_calib.f[0], x_calib.f[1], x_calib.f[2],
|
x_calib.v.el[0], x_calib.v.el[1], x_calib.v.el[2],
|
||||||
y_calib.f[0], y_calib.f[1], y_calib.f[2]);
|
y_calib.v.el[0], y_calib.v.el[1], y_calib.v.el[2]);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
584
clients/color.c
Normal file
584
clients/color.c
Normal file
|
|
@ -0,0 +1,584 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 SUSE Software Solutions Germany GmbH
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "color-management-v1-client-protocol.h"
|
||||||
|
#include "shared/helpers.h"
|
||||||
|
#include "shared/xalloc.h"
|
||||||
|
#include "single-pixel-buffer-v1-client-protocol.h"
|
||||||
|
#include "viewporter-client-protocol.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
enum image_description_status {
|
||||||
|
IMAGE_DESCRIPTION_NOT_CREATED = 0,
|
||||||
|
IMAGE_DESCRIPTION_READY,
|
||||||
|
IMAGE_DESCRIPTION_FAILED,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pixel_color {
|
||||||
|
uint32_t r;
|
||||||
|
uint32_t g;
|
||||||
|
uint32_t b;
|
||||||
|
uint32_t a;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct color {
|
||||||
|
struct display *display;
|
||||||
|
struct window *window;
|
||||||
|
struct widget *parent_widget;
|
||||||
|
struct widget *widget;
|
||||||
|
|
||||||
|
struct wp_color_manager_v1 *color_manager;
|
||||||
|
struct wp_color_management_surface_v1 *color_surface;
|
||||||
|
struct wp_single_pixel_buffer_manager_v1 *single_pixel_manager;
|
||||||
|
struct wp_viewporter *viewporter;
|
||||||
|
struct wp_viewport *viewport;
|
||||||
|
|
||||||
|
struct pixel_color pixel_color;
|
||||||
|
|
||||||
|
enum wp_color_manager_v1_primaries primaries;
|
||||||
|
enum wp_color_manager_v1_transfer_function transfer_function;
|
||||||
|
float min_lum;
|
||||||
|
float max_lum;
|
||||||
|
float ref_lum;
|
||||||
|
|
||||||
|
uint32_t supported_color_features;
|
||||||
|
uint32_t supported_rendering_intents;
|
||||||
|
uint32_t supported_primaries_named;
|
||||||
|
uint32_t supported_tf_named;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct valid_enum {
|
||||||
|
const char *name;
|
||||||
|
uint32_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool opt_help = false;
|
||||||
|
static uint32_t opt_width = 250;
|
||||||
|
static uint32_t opt_height = 250;
|
||||||
|
static const char *opt_r = NULL;
|
||||||
|
static const char *opt_g = NULL;
|
||||||
|
static const char *opt_b = NULL;
|
||||||
|
static const char *opt_a = NULL;
|
||||||
|
static const char *opt_primaries = NULL;
|
||||||
|
static const char *opt_transfer_function = NULL;
|
||||||
|
static const char *opt_min_lum = NULL;
|
||||||
|
static const char *opt_max_lum = NULL;
|
||||||
|
static const char *opt_ref_lum = NULL;
|
||||||
|
static const struct weston_option cli_options[] = {
|
||||||
|
{ WESTON_OPTION_BOOLEAN, "help", 0, &opt_help },
|
||||||
|
{ WESTON_OPTION_UNSIGNED_INTEGER, "width", 'w', &opt_width },
|
||||||
|
{ WESTON_OPTION_UNSIGNED_INTEGER, "height", 'h', &opt_height },
|
||||||
|
{ WESTON_OPTION_STRING, 0, 'R', &opt_r },
|
||||||
|
{ WESTON_OPTION_STRING, 0, 'G', &opt_g },
|
||||||
|
{ WESTON_OPTION_STRING, 0, 'B', &opt_b },
|
||||||
|
{ WESTON_OPTION_STRING, 0, 'A', &opt_a },
|
||||||
|
{ WESTON_OPTION_STRING, "primaries", 'p', &opt_primaries },
|
||||||
|
{ WESTON_OPTION_STRING, "transfer-function", 't', &opt_transfer_function },
|
||||||
|
{ WESTON_OPTION_STRING, "min-lum", 'm', &opt_min_lum },
|
||||||
|
{ WESTON_OPTION_STRING, "max-lum", 'M', &opt_max_lum },
|
||||||
|
{ WESTON_OPTION_STRING, "ref-lum", 'r', &opt_ref_lum },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct valid_enum valid_primaries[] = {
|
||||||
|
{ "srgb", WP_COLOR_MANAGER_V1_PRIMARIES_SRGB },
|
||||||
|
{ "bt2020", WP_COLOR_MANAGER_V1_PRIMARIES_BT2020 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct valid_enum valid_transfer_functions[] = {
|
||||||
|
{ "srgb", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB },
|
||||||
|
{ "pq", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ },
|
||||||
|
{ "linear", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR },
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
validate_color(const char *c, uint32_t *dest, uint32_t fallback)
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
double value;
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
*dest = fallback;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = strtod(c, &end);
|
||||||
|
if (value < 0.0 || value > 1.0 || *end != '\0') {
|
||||||
|
fprintf(stderr, "Validating color failed, it should be between 0.0 and 1.0\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest = value * UINT32_MAX;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
validate_option(const char *option, uint32_t *dest,
|
||||||
|
const struct valid_enum *valid_options,
|
||||||
|
int count, uint32_t fallback)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!option) {
|
||||||
|
*dest = fallback;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (strcmp(valid_options[i].name, option) == 0) {
|
||||||
|
*dest = valid_options[i].value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Validating option '%s' failed, valid options:\n", option);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
fprintf(stderr, "'%s' ", valid_options[i].name);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
validate_luminance(const char *c, float *dest, float fallback)
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
float value;
|
||||||
|
|
||||||
|
if (!c) {
|
||||||
|
*dest = fallback;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = strtof(c, &end);
|
||||||
|
if (value < 0.f || value > 10000.f || *end != '\0') {
|
||||||
|
fprintf(stderr, "Validating luminance failed, it should be between 0 and 10,000\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest = value;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
validate_options(struct color *color)
|
||||||
|
{
|
||||||
|
return validate_color(opt_r, &color->pixel_color.r, 0) &&
|
||||||
|
validate_color(opt_g, &color->pixel_color.g, 0) &&
|
||||||
|
validate_color(opt_b, &color->pixel_color.b, 0) &&
|
||||||
|
validate_color(opt_a, &color->pixel_color.a, UINT32_MAX) &&
|
||||||
|
validate_option(opt_primaries, &color->primaries,
|
||||||
|
valid_primaries,
|
||||||
|
ARRAY_LENGTH(valid_primaries),
|
||||||
|
WP_COLOR_MANAGER_V1_PRIMARIES_SRGB) &&
|
||||||
|
validate_option(opt_transfer_function, &color->transfer_function,
|
||||||
|
valid_transfer_functions,
|
||||||
|
ARRAY_LENGTH(valid_transfer_functions),
|
||||||
|
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB) &&
|
||||||
|
validate_luminance(opt_min_lum, &color->min_lum, -1.f) &&
|
||||||
|
validate_luminance(opt_max_lum, &color->max_lum, -1.f) &&
|
||||||
|
validate_luminance(opt_ref_lum, &color->ref_lum, -1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(const char *program_name, int exit_code)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
fprintf(stderr, "Usage: %s [OPTIONS]\n", program_name);
|
||||||
|
fprintf(stderr, " --help\n");
|
||||||
|
fprintf(stderr, " --width or -w\n");
|
||||||
|
fprintf(stderr, " --height or -h\n");
|
||||||
|
fprintf(stderr, " -R (0.0 to 1.0)\n");
|
||||||
|
fprintf(stderr, " -G (0.0 to 1.0)\n");
|
||||||
|
fprintf(stderr, " -B (0.0 to 1.0)\n");
|
||||||
|
fprintf(stderr, " -A (0.0 to 1.0)\n");
|
||||||
|
fprintf(stderr, " --primaries or -p:");
|
||||||
|
fprintf(stderr, "\n ");
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(valid_primaries); i++)
|
||||||
|
fprintf(stderr, " '%s'", valid_primaries[i].name);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, " --transfer-function or -t:");
|
||||||
|
fprintf(stderr, "\n ");
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(valid_transfer_functions); i++)
|
||||||
|
fprintf(stderr, " '%s'", valid_transfer_functions[i].name);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, " --min-lum or -m (0.0 to 10000.0)\n");
|
||||||
|
fprintf(stderr, " --max-lum or -M (0.0 to 10000.0)\n");
|
||||||
|
fprintf(stderr, " --ref-lum or -r (0.0 to 10000.0)\n");
|
||||||
|
|
||||||
|
exit(exit_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||||
|
uint32_t render_intent)
|
||||||
|
{
|
||||||
|
struct color *color = data;
|
||||||
|
|
||||||
|
color->supported_rendering_intents |= 1 << render_intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||||
|
uint32_t feature)
|
||||||
|
{
|
||||||
|
struct color *color = data;
|
||||||
|
|
||||||
|
color->supported_color_features |= 1 << feature;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||||
|
uint32_t tf)
|
||||||
|
{
|
||||||
|
struct color *color = data;
|
||||||
|
|
||||||
|
color->supported_tf_named |= 1 << tf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
supported_primaries_named(void *data,
|
||||||
|
struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||||
|
uint32_t primaries)
|
||||||
|
{
|
||||||
|
struct color *color = data;
|
||||||
|
|
||||||
|
color->supported_primaries_named |= 1 << primaries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_color_manager_v1_listener color_manager_listener = {
|
||||||
|
supported_intent,
|
||||||
|
supported_feature,
|
||||||
|
supported_tf_named,
|
||||||
|
supported_primaries_named,
|
||||||
|
done,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
global_handler(struct display *display, uint32_t name,
|
||||||
|
const char *interface, uint32_t version, void *data)
|
||||||
|
{
|
||||||
|
struct color *color = data;
|
||||||
|
struct wl_surface *surface = widget_get_wl_surface(color->widget);
|
||||||
|
|
||||||
|
if (strcmp(interface, wp_color_manager_v1_interface.name) == 0) {
|
||||||
|
color->color_manager = display_bind(display, name,
|
||||||
|
&wp_color_manager_v1_interface, 1);
|
||||||
|
color->color_surface = wp_color_manager_v1_get_surface(color->color_manager,
|
||||||
|
surface);
|
||||||
|
wp_color_manager_v1_add_listener(color->color_manager,
|
||||||
|
&color_manager_listener, color);
|
||||||
|
} else if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
|
||||||
|
color->single_pixel_manager =
|
||||||
|
display_bind(display, name,
|
||||||
|
&wp_single_pixel_buffer_manager_v1_interface, 1);
|
||||||
|
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
|
||||||
|
color->viewporter = display_bind(display, name,
|
||||||
|
&wp_viewporter_interface, 1);
|
||||||
|
color->viewport = wp_viewporter_get_viewport(color->viewporter, surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
check_color_requirements(struct color *color)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!color->color_manager) {
|
||||||
|
fprintf(stderr, "The compositor doesn't expose %s\n",
|
||||||
|
wp_color_manager_v1_interface.name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_PARAMETRIC))) {
|
||||||
|
fprintf(stderr, "The color manager doesn't support the parametric creator\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(color->supported_primaries_named & (1 << color->primaries))) {
|
||||||
|
fprintf(stderr, "The color manager doesn't support the primaries name\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(color->supported_tf_named & (1 << color->transfer_function))) {
|
||||||
|
fprintf(stderr, "The color manager doesn't support the transfer function\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(color->supported_rendering_intents & (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL))) {
|
||||||
|
fprintf(stderr, "The color manager doesn't support perceptual render intent\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (color->min_lum != -1.f || color->max_lum != -1.f || color->ref_lum != -1.f) {
|
||||||
|
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_SET_LUMINANCES))) {
|
||||||
|
fprintf(stderr, "The color manager doesn't support setting luminances\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (color->min_lum == -1.f || color->max_lum == -1.f || color->ref_lum == -1.f) {
|
||||||
|
fprintf(stderr, "To set the luminances it is required min-lum, max-lum and ref-lum\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
color_destroy(struct color *color)
|
||||||
|
{
|
||||||
|
if (color->color_surface)
|
||||||
|
wp_color_management_surface_v1_destroy(color->color_surface);
|
||||||
|
|
||||||
|
if (color->color_manager)
|
||||||
|
wp_color_manager_v1_destroy(color->color_manager);
|
||||||
|
|
||||||
|
if (color->single_pixel_manager)
|
||||||
|
wp_single_pixel_buffer_manager_v1_destroy(color->single_pixel_manager);
|
||||||
|
|
||||||
|
if (color->viewport)
|
||||||
|
wp_viewport_destroy(color->viewport);
|
||||||
|
|
||||||
|
if (color->viewporter)
|
||||||
|
wp_viewporter_destroy(color->viewporter);
|
||||||
|
|
||||||
|
if (color->widget)
|
||||||
|
widget_destroy(color->widget);
|
||||||
|
|
||||||
|
if (color->parent_widget)
|
||||||
|
widget_destroy(color->parent_widget);
|
||||||
|
|
||||||
|
if (color->window)
|
||||||
|
window_destroy(color->window);
|
||||||
|
|
||||||
|
if (color->display)
|
||||||
|
display_destroy(color->display);
|
||||||
|
|
||||||
|
free(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
resize_handler(struct widget *parent_widget, int32_t width, int32_t height, void *data)
|
||||||
|
{
|
||||||
|
struct color *color = data;
|
||||||
|
struct rectangle allocation;
|
||||||
|
struct wl_surface *surface = widget_get_wl_surface(color->widget);
|
||||||
|
struct wl_subsurface *subsurface = widget_get_wl_subsurface(color->widget);
|
||||||
|
|
||||||
|
widget_get_allocation(parent_widget, &allocation);
|
||||||
|
wl_subsurface_set_position(subsurface, allocation.x, allocation.y);
|
||||||
|
|
||||||
|
wp_viewport_set_destination(color->viewport, width, height);
|
||||||
|
|
||||||
|
wl_surface_commit(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_empty_input_region(struct color *color, struct widget *widget)
|
||||||
|
{
|
||||||
|
struct wl_region *region;
|
||||||
|
struct wl_compositor *compositor;
|
||||||
|
struct wl_surface *surface = widget_get_wl_surface(widget);
|
||||||
|
|
||||||
|
compositor = display_get_compositor(color->display);
|
||||||
|
region = wl_compositor_create_region(compositor);
|
||||||
|
wl_surface_set_input_region(surface, region);
|
||||||
|
wl_region_destroy(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_release(void *data, struct wl_buffer *buffer)
|
||||||
|
{
|
||||||
|
wl_buffer_destroy(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_buffer_listener buffer_listener = {
|
||||||
|
buffer_release
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_single_pixel(struct color *color, struct widget *widget)
|
||||||
|
{
|
||||||
|
struct wl_surface *surface = widget_get_wl_surface(widget);
|
||||||
|
struct wl_buffer *buffer =
|
||||||
|
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(color->single_pixel_manager,
|
||||||
|
color->pixel_color.r,
|
||||||
|
color->pixel_color.g,
|
||||||
|
color->pixel_color.b,
|
||||||
|
color->pixel_color.a);
|
||||||
|
wl_buffer_add_listener(buffer, &buffer_listener, NULL);
|
||||||
|
wl_surface_attach(surface, buffer, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
image_description_failed(void *data,
|
||||||
|
struct wp_image_description_v1 *wp_image_description_v1,
|
||||||
|
uint32_t cause, const char *msg)
|
||||||
|
{
|
||||||
|
enum image_description_status *image_desc_status = data;
|
||||||
|
|
||||||
|
fprintf(stderr, "Failed to create image description: %u - %s\n",
|
||||||
|
cause, msg);
|
||||||
|
|
||||||
|
*image_desc_status = IMAGE_DESCRIPTION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
image_description_ready(void *data, struct wp_image_description_v1 *wp_image_description_v1,
|
||||||
|
uint32_t identity)
|
||||||
|
{
|
||||||
|
enum image_description_status *image_desc_status = data;
|
||||||
|
|
||||||
|
*image_desc_status = IMAGE_DESCRIPTION_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_image_description_v1_listener image_description_listener = {
|
||||||
|
image_description_failed,
|
||||||
|
image_description_ready,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct wp_image_description_v1 *
|
||||||
|
create_image_description(struct color *color, uint32_t primaries_named, uint32_t tf_named)
|
||||||
|
{
|
||||||
|
struct wp_image_description_creator_params_v1 *params_creator;
|
||||||
|
struct wp_image_description_v1 *image_description;
|
||||||
|
enum image_description_status image_desc_status = IMAGE_DESCRIPTION_NOT_CREATED;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
params_creator = wp_color_manager_v1_create_parametric_creator(color->color_manager);
|
||||||
|
wp_image_description_creator_params_v1_set_primaries_named(params_creator, primaries_named);
|
||||||
|
wp_image_description_creator_params_v1_set_tf_named(params_creator, tf_named);
|
||||||
|
if (color->min_lum != -1 && color->max_lum != -1 && color->ref_lum != -1)
|
||||||
|
wp_image_description_creator_params_v1_set_luminances(params_creator,
|
||||||
|
color->min_lum * 10000,
|
||||||
|
color->max_lum,
|
||||||
|
color->ref_lum);
|
||||||
|
|
||||||
|
image_description = wp_image_description_creator_params_v1_create(params_creator);
|
||||||
|
wp_image_description_v1_add_listener(image_description,
|
||||||
|
&image_description_listener,
|
||||||
|
&image_desc_status);
|
||||||
|
|
||||||
|
while (ret != -1 && image_desc_status == IMAGE_DESCRIPTION_NOT_CREATED)
|
||||||
|
ret = wl_display_dispatch(display_get_display(color->display));
|
||||||
|
if (ret == -1) {
|
||||||
|
wp_image_description_v1_destroy(image_description);
|
||||||
|
fprintf(stderr, "Error when creating the image description: %s\n", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image_desc_status == IMAGE_DESCRIPTION_FAILED) {
|
||||||
|
wp_image_description_v1_destroy(image_description);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(image_desc_status == IMAGE_DESCRIPTION_READY);
|
||||||
|
|
||||||
|
return image_description;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
set_image_description(struct color *color, struct widget *widget)
|
||||||
|
{
|
||||||
|
struct wp_image_description_v1 *image_description;
|
||||||
|
|
||||||
|
image_description =
|
||||||
|
create_image_description(color,
|
||||||
|
color->primaries,
|
||||||
|
color->transfer_function);
|
||||||
|
if (!image_description)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wp_color_management_surface_v1_set_image_description(
|
||||||
|
color->color_surface,
|
||||||
|
image_description,
|
||||||
|
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
|
||||||
|
|
||||||
|
wp_image_description_v1_destroy(image_description);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct color *color;
|
||||||
|
|
||||||
|
if (parse_options(cli_options, ARRAY_LENGTH(cli_options), &argc, argv) > 1)
|
||||||
|
usage(argv[0], EXIT_FAILURE);
|
||||||
|
|
||||||
|
if (opt_help)
|
||||||
|
usage(argv[0], EXIT_SUCCESS);
|
||||||
|
|
||||||
|
color = xzalloc(sizeof *color);
|
||||||
|
if (!validate_options(color)) {
|
||||||
|
color_destroy(color);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
color->display = display_create(&argc, argv);
|
||||||
|
if (!color->display) {
|
||||||
|
color_destroy(color);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
color->window = window_create(color->display);
|
||||||
|
color->parent_widget = window_frame_create(color->window, color);
|
||||||
|
color->widget = window_add_subsurface(color->window, color, SUBSURFACE_SYNCHRONIZED);
|
||||||
|
|
||||||
|
display_set_user_data(color->display, color);
|
||||||
|
display_set_global_handler(color->display, global_handler);
|
||||||
|
wl_display_roundtrip(display_get_display(color->display));
|
||||||
|
|
||||||
|
if (!check_color_requirements(color)) {
|
||||||
|
color_destroy(color);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
window_unset_shadow(color->window);
|
||||||
|
window_set_title(color->window, "Color");
|
||||||
|
window_set_appid(color->window, "org.freedesktop.weston.color");
|
||||||
|
/* The first resize call sets the min size,
|
||||||
|
* setting 0, 0 sets a default size */
|
||||||
|
window_schedule_resize(color->window, 0, 0);
|
||||||
|
window_schedule_resize(color->window, opt_width, opt_height);
|
||||||
|
|
||||||
|
widget_set_resize_handler(color->parent_widget, resize_handler);
|
||||||
|
widget_set_use_cairo(color->widget, 0);
|
||||||
|
|
||||||
|
set_empty_input_region(color, color->widget);
|
||||||
|
set_single_pixel(color, color->widget);
|
||||||
|
|
||||||
|
if (set_image_description(color, color->widget))
|
||||||
|
display_run(color->display);
|
||||||
|
|
||||||
|
color_destroy(color);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -53,6 +53,7 @@
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
|
#include "single-pixel-buffer-v1-client-protocol.h"
|
||||||
#include "tablet-unstable-v2-client-protocol.h"
|
#include "tablet-unstable-v2-client-protocol.h"
|
||||||
#include "weston-desktop-shell-client-protocol.h"
|
#include "weston-desktop-shell-client-protocol.h"
|
||||||
|
|
||||||
|
|
@ -777,94 +778,147 @@ panel_add_launcher(struct panel *panel, const char *icon, const char *path, cons
|
||||||
enum {
|
enum {
|
||||||
BACKGROUND_SCALE,
|
BACKGROUND_SCALE,
|
||||||
BACKGROUND_SCALE_CROP,
|
BACKGROUND_SCALE_CROP,
|
||||||
|
BACKGROUND_SCALE_FIT,
|
||||||
BACKGROUND_TILE,
|
BACKGROUND_TILE,
|
||||||
BACKGROUND_CENTERED
|
BACKGROUND_CENTERED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_release(void *data, struct wl_buffer *buffer)
|
||||||
|
{
|
||||||
|
wl_buffer_destroy(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_buffer_listener buffer_listener = {
|
||||||
|
buffer_release
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
background_draw(struct widget *widget, void *data)
|
background_draw(struct widget *widget, void *data)
|
||||||
{
|
{
|
||||||
struct background *background = data;
|
struct background *background = data;
|
||||||
cairo_surface_t *surface, *image;
|
|
||||||
cairo_pattern_t *pattern;
|
|
||||||
cairo_matrix_t matrix;
|
|
||||||
cairo_t *cr;
|
|
||||||
double im_w, im_h;
|
|
||||||
double sx, sy, s;
|
|
||||||
double tx, ty;
|
|
||||||
struct rectangle allocation;
|
|
||||||
|
|
||||||
surface = window_get_surface(background->window);
|
if (!background->image && background->color) {
|
||||||
|
struct display *display = window_get_display(background->window);
|
||||||
|
struct wp_single_pixel_buffer_manager_v1 *sp_manager;
|
||||||
|
struct wl_surface *wl_surface;
|
||||||
|
struct wl_buffer *wl_buffer;
|
||||||
|
uint32_t r8, g8, b8;
|
||||||
|
uint32_t r32, g32, b32;
|
||||||
|
|
||||||
cr = widget_cairo_create(background->widget);
|
/* Single pixel buffer must use scale 1 */
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
window_set_buffer_scale(background->window, 1);
|
||||||
if (background->color == 0)
|
|
||||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
|
|
||||||
else
|
|
||||||
set_hex_color(cr, background->color);
|
|
||||||
cairo_paint(cr);
|
|
||||||
|
|
||||||
widget_get_allocation(widget, &allocation);
|
sp_manager = display_get_single_pixel_buffer_manager(display);
|
||||||
image = NULL;
|
assert(sp_manager);
|
||||||
if (background->image)
|
wl_surface = widget_get_wl_surface(background->widget);
|
||||||
image = load_cairo_surface(background->image);
|
assert(wl_surface);
|
||||||
else if (background->color == 0) {
|
|
||||||
char *name = file_name_with_datadir("pattern.png");
|
|
||||||
|
|
||||||
image = load_cairo_surface(name);
|
r8 = (background->color >> 16) & 0xff;
|
||||||
free(name);
|
g8 = (background->color >> 8) & 0xff;
|
||||||
}
|
b8 = (background->color >> 0) & 0xff;
|
||||||
|
|
||||||
if (image && background->type != -1) {
|
r32 = r8 << 24 | r8 << 16 | r8 << 8 | r8;
|
||||||
im_w = cairo_image_surface_get_width(image);
|
g32 = g8 << 24 | g8 << 16 | g8 << 8 | g8;
|
||||||
im_h = cairo_image_surface_get_height(image);
|
b32 = b8 << 24 | b8 << 16 | b8 << 8 | b8;
|
||||||
sx = im_w / allocation.width;
|
|
||||||
sy = im_h / allocation.height;
|
|
||||||
|
|
||||||
pattern = cairo_pattern_create_for_surface(image);
|
wl_buffer =
|
||||||
|
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(sp_manager,
|
||||||
|
r32,
|
||||||
|
g32,
|
||||||
|
b32,
|
||||||
|
0xffffffff);
|
||||||
|
assert(wl_buffer);
|
||||||
|
|
||||||
switch (background->type) {
|
wl_surface_attach(wl_surface, wl_buffer, 0, 0);
|
||||||
case BACKGROUND_SCALE:
|
wl_buffer_add_listener(wl_buffer, &buffer_listener, NULL);
|
||||||
cairo_matrix_init_scale(&matrix, sx, sy);
|
widget_surface_flush(widget);
|
||||||
cairo_pattern_set_matrix(pattern, &matrix);
|
} else {
|
||||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
|
cairo_surface_t *surface, *image;
|
||||||
break;
|
cairo_pattern_t *pattern;
|
||||||
case BACKGROUND_SCALE_CROP:
|
cairo_matrix_t matrix;
|
||||||
s = (sx < sy) ? sx : sy;
|
cairo_t *cr;
|
||||||
/* align center */
|
double im_w, im_h;
|
||||||
tx = (im_w - s * allocation.width) * 0.5;
|
double sx, sy, s;
|
||||||
ty = (im_h - s * allocation.height) * 0.5;
|
double tx, ty;
|
||||||
cairo_matrix_init_translate(&matrix, tx, ty);
|
struct rectangle allocation;
|
||||||
cairo_matrix_scale(&matrix, s, s);
|
|
||||||
cairo_pattern_set_matrix(pattern, &matrix);
|
|
||||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
|
|
||||||
break;
|
|
||||||
case BACKGROUND_TILE:
|
|
||||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
|
|
||||||
break;
|
|
||||||
case BACKGROUND_CENTERED:
|
|
||||||
s = (sx < sy) ? sx : sy;
|
|
||||||
if (s < 1.0)
|
|
||||||
s = 1.0;
|
|
||||||
|
|
||||||
/* align center */
|
surface = window_get_surface(background->window);
|
||||||
tx = (im_w - s * allocation.width) * 0.5;
|
|
||||||
ty = (im_h - s * allocation.height) * 0.5;
|
|
||||||
|
|
||||||
cairo_matrix_init_translate(&matrix, tx, ty);
|
cr = widget_cairo_create(background->widget);
|
||||||
cairo_matrix_scale(&matrix, s, s);
|
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||||
cairo_pattern_set_matrix(pattern, &matrix);
|
if (background->color == 0)
|
||||||
break;
|
cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
|
||||||
|
else
|
||||||
|
set_hex_color(cr, background->color);
|
||||||
|
cairo_paint(cr);
|
||||||
|
|
||||||
|
widget_get_allocation(widget, &allocation);
|
||||||
|
image = NULL;
|
||||||
|
if (background->image)
|
||||||
|
image = load_cairo_surface(background->image);
|
||||||
|
else if (background->color == 0) {
|
||||||
|
char *name = file_name_with_datadir("pattern.png");
|
||||||
|
|
||||||
|
image = load_cairo_surface(name);
|
||||||
|
free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_set_source(cr, pattern);
|
if (image && background->type != -1) {
|
||||||
cairo_pattern_destroy (pattern);
|
im_w = cairo_image_surface_get_width(image);
|
||||||
cairo_surface_destroy(image);
|
im_h = cairo_image_surface_get_height(image);
|
||||||
cairo_mask(cr, pattern);
|
sx = im_w / allocation.width;
|
||||||
}
|
sy = im_h / allocation.height;
|
||||||
|
|
||||||
cairo_destroy(cr);
|
pattern = cairo_pattern_create_for_surface(image);
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
|
switch (background->type) {
|
||||||
|
case BACKGROUND_SCALE:
|
||||||
|
cairo_matrix_init_scale(&matrix, sx, sy);
|
||||||
|
cairo_pattern_set_matrix(pattern, &matrix);
|
||||||
|
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
|
||||||
|
break;
|
||||||
|
case BACKGROUND_SCALE_CROP:
|
||||||
|
case BACKGROUND_SCALE_FIT:
|
||||||
|
if (background->type == BACKGROUND_SCALE_CROP)
|
||||||
|
s = (sx < sy) ? sx : sy;
|
||||||
|
else
|
||||||
|
s = (sx > sy) ? sx : sy;
|
||||||
|
/* align center */
|
||||||
|
tx = (im_w - s * allocation.width) * 0.5;
|
||||||
|
ty = (im_h - s * allocation.height) * 0.5;
|
||||||
|
cairo_matrix_init_translate(&matrix, tx, ty);
|
||||||
|
cairo_matrix_scale(&matrix, s, s);
|
||||||
|
cairo_pattern_set_matrix(pattern, &matrix);
|
||||||
|
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
|
||||||
|
break;
|
||||||
|
case BACKGROUND_TILE:
|
||||||
|
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
|
||||||
|
break;
|
||||||
|
case BACKGROUND_CENTERED:
|
||||||
|
s = (sx < sy) ? sx : sy;
|
||||||
|
if (s < 1.0)
|
||||||
|
s = 1.0;
|
||||||
|
|
||||||
|
/* align center */
|
||||||
|
tx = (im_w - s * allocation.width) * 0.5;
|
||||||
|
ty = (im_h - s * allocation.height) * 0.5;
|
||||||
|
|
||||||
|
cairo_matrix_init_translate(&matrix, tx, ty);
|
||||||
|
cairo_matrix_scale(&matrix, s, s);
|
||||||
|
cairo_pattern_set_matrix(pattern, &matrix);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_set_source(cr, pattern);
|
||||||
|
cairo_pattern_destroy (pattern);
|
||||||
|
cairo_surface_destroy(image);
|
||||||
|
cairo_mask(cr, pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_destroy(cr);
|
||||||
|
cairo_surface_destroy(surface);
|
||||||
|
}
|
||||||
|
|
||||||
background->painted = 1;
|
background->painted = 1;
|
||||||
check_desktop_ready(background->window);
|
check_desktop_ready(background->window);
|
||||||
|
|
@ -892,6 +946,7 @@ background_configure(void *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!background->image && background->color) {
|
if (!background->image && background->color) {
|
||||||
|
widget_set_use_cairo(background->widget, 0);
|
||||||
widget_set_viewport_destination(background->widget, width, height);
|
widget_set_viewport_destination(background->widget, width, height);
|
||||||
width = 1;
|
width = 1;
|
||||||
height = 1;
|
height = 1;
|
||||||
|
|
@ -1191,6 +1246,10 @@ background_create(struct desktop *desktop, struct output *output)
|
||||||
weston_config_section_get_color(s, "background-color",
|
weston_config_section_get_color(s, "background-color",
|
||||||
&background->color, 0x00000000);
|
&background->color, 0x00000000);
|
||||||
|
|
||||||
|
/* Backgrounds must be fully opaque. */
|
||||||
|
if (background->color != 0)
|
||||||
|
background->color |= 0xFF000000;
|
||||||
|
|
||||||
weston_config_section_get_string(s, "background-type",
|
weston_config_section_get_string(s, "background-type",
|
||||||
&type, "tile");
|
&type, "tile");
|
||||||
if (type == NULL) {
|
if (type == NULL) {
|
||||||
|
|
@ -1202,6 +1261,8 @@ background_create(struct desktop *desktop, struct output *output)
|
||||||
background->type = BACKGROUND_SCALE;
|
background->type = BACKGROUND_SCALE;
|
||||||
} else if (strcmp(type, "scale-crop") == 0) {
|
} else if (strcmp(type, "scale-crop") == 0) {
|
||||||
background->type = BACKGROUND_SCALE_CROP;
|
background->type = BACKGROUND_SCALE_CROP;
|
||||||
|
} else if (strcmp(type, "scale-fit") == 0) {
|
||||||
|
background->type = BACKGROUND_SCALE_FIT;
|
||||||
} else if (strcmp(type, "tile") == 0) {
|
} else if (strcmp(type, "tile") == 0) {
|
||||||
background->type = BACKGROUND_TILE;
|
background->type = BACKGROUND_TILE;
|
||||||
} else if (strcmp(type, "centered") == 0) {
|
} else if (strcmp(type, "centered") == 0) {
|
||||||
|
|
@ -1321,10 +1382,11 @@ output_handle_scale(void *data,
|
||||||
int32_t scale)
|
int32_t scale)
|
||||||
{
|
{
|
||||||
struct output *output = data;
|
struct output *output = data;
|
||||||
|
struct background *background = output->background;
|
||||||
|
|
||||||
if (output->panel)
|
if (output->panel)
|
||||||
window_set_buffer_scale(output->panel->window, scale);
|
window_set_buffer_scale(output->panel->window, scale);
|
||||||
if (output->background)
|
if (background && !background->color)
|
||||||
window_set_buffer_scale(output->background->window, scale);
|
window_set_buffer_scale(output->background->window, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -515,7 +515,7 @@ create_drag_source(struct dnd *dnd,
|
||||||
dnd_drag->drag_surface =
|
dnd_drag->drag_surface =
|
||||||
wl_compositor_create_surface(compositor);
|
wl_compositor_create_surface(compositor);
|
||||||
|
|
||||||
if (display_get_data_device_manager_version(display) <
|
if (dnd->self_only || display_get_data_device_manager_version(display) <
|
||||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
|
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
|
||||||
/* Data sources version < 3 will not get action
|
/* Data sources version < 3 will not get action
|
||||||
* nor dnd_finished events, as we can't honor
|
* nor dnd_finished events, as we can't honor
|
||||||
|
|
@ -546,11 +546,11 @@ create_drag_source(struct dnd *dnd,
|
||||||
flower_mime_type);
|
flower_mime_type);
|
||||||
wl_data_source_offer(dnd_drag->data_source,
|
wl_data_source_offer(dnd_drag->data_source,
|
||||||
text_mime_type);
|
text_mime_type);
|
||||||
}
|
|
||||||
|
|
||||||
if (display_get_data_device_manager_version(display) >=
|
if (display_get_data_device_manager_version(display) >=
|
||||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
|
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
|
||||||
wl_data_source_set_actions(dnd_drag->data_source, actions);
|
wl_data_source_set_actions(dnd_drag->data_source, actions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_data_device_start_drag(input_get_data_device(input),
|
wl_data_device_start_drag(input_get_data_device(input),
|
||||||
|
|
|
||||||
|
|
@ -346,6 +346,7 @@ usage(int error_code)
|
||||||
fprintf(stderr, "Usage: fullscreen [OPTIONS]\n\n"
|
fprintf(stderr, "Usage: fullscreen [OPTIONS]\n\n"
|
||||||
" -w <width>\tSet window width to <width>\n"
|
" -w <width>\tSet window width to <width>\n"
|
||||||
" -h <height>\tSet window height to <height>\n"
|
" -h <height>\tSet window height to <height>\n"
|
||||||
|
" -f\t\tMap window as fullscreen\n"
|
||||||
" --help\tShow this help text\n\n");
|
" --help\tShow this help text\n\n");
|
||||||
|
|
||||||
exit(error_code);
|
exit(error_code);
|
||||||
|
|
@ -394,6 +395,8 @@ int main(int argc, char *argv[])
|
||||||
usage(EXIT_FAILURE);
|
usage(EXIT_FAILURE);
|
||||||
|
|
||||||
fullscreen.height = atol(argv[i]);
|
fullscreen.height = atol(argv[i]);
|
||||||
|
} else if (strcmp(argv[i], "-f") == 0) {
|
||||||
|
fullscreen.fullscreen = 1;
|
||||||
} else if (strcmp(argv[i], "--help") == 0)
|
} else if (strcmp(argv[i], "--help") == 0)
|
||||||
usage(EXIT_SUCCESS);
|
usage(EXIT_SUCCESS);
|
||||||
else
|
else
|
||||||
|
|
@ -434,6 +437,8 @@ int main(int argc, char *argv[])
|
||||||
window_set_fullscreen_handler(fullscreen.window, fullscreen_handler);
|
window_set_fullscreen_handler(fullscreen.window, fullscreen_handler);
|
||||||
|
|
||||||
window_set_user_data(fullscreen.window, &fullscreen);
|
window_set_user_data(fullscreen.window, &fullscreen);
|
||||||
|
if (fullscreen.fullscreen)
|
||||||
|
window_set_fullscreen(fullscreen.window, fullscreen.fullscreen);
|
||||||
/* Hack to set minimum allocation so we can shrink later */
|
/* Hack to set minimum allocation so we can shrink later */
|
||||||
window_schedule_resize(fullscreen.window,
|
window_schedule_resize(fullscreen.window,
|
||||||
1, 1);
|
1, 1);
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,8 @@ hmi_homescreen_launcher {
|
||||||
uint32_t workspace_id;
|
uint32_t workspace_id;
|
||||||
char *icon;
|
char *icon;
|
||||||
char *path;
|
char *path;
|
||||||
|
char **argv;
|
||||||
|
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -308,12 +310,10 @@ launcher_button(uint32_t surfaceId, struct wl_list *launcher_list)
|
||||||
struct hmi_homescreen_launcher *launcher = NULL;
|
struct hmi_homescreen_launcher *launcher = NULL;
|
||||||
|
|
||||||
wl_list_for_each(launcher, launcher_list, link) {
|
wl_list_for_each(launcher, launcher_list, link) {
|
||||||
char *argv[] = { NULL };
|
|
||||||
|
|
||||||
if (surfaceId != launcher->icon_surface_id)
|
if (surfaceId != launcher->icon_surface_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
execute_process(launcher->path, argv);
|
execute_process(launcher->path, launcher->argv);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -1065,6 +1065,32 @@ create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)
|
||||||
free(launchers);
|
free(launchers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char **
|
||||||
|
parse_command(char *str)
|
||||||
|
{
|
||||||
|
char **argv;
|
||||||
|
char *saveptr;
|
||||||
|
char *token;
|
||||||
|
int i;
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
|
for (i = 1; str[i]; i++)
|
||||||
|
if (str[i] == ' ' && str[i-1] != ' ')
|
||||||
|
count++;
|
||||||
|
|
||||||
|
argv = xcalloc(count + 1, sizeof(char*));
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
token = strtok_r(str, " ", &saveptr);
|
||||||
|
while (token != NULL) {
|
||||||
|
argv[i++] = token;
|
||||||
|
|
||||||
|
token = strtok_r(NULL, " ", &saveptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return argv;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal method to read out weston.ini to get configuration
|
* Internal method to read out weston.ini to get configuration
|
||||||
*/
|
*/
|
||||||
|
|
@ -1177,6 +1203,7 @@ hmi_homescreen_setting_create(void)
|
||||||
|
|
||||||
while (weston_config_next_section(config, §ion, &name)) {
|
while (weston_config_next_section(config, §ion, &name)) {
|
||||||
struct hmi_homescreen_launcher *launcher;
|
struct hmi_homescreen_launcher *launcher;
|
||||||
|
char *command;
|
||||||
|
|
||||||
if (strcmp(name, "ivi-launcher") != 0)
|
if (strcmp(name, "ivi-launcher") != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1186,8 +1213,18 @@ hmi_homescreen_setting_create(void)
|
||||||
|
|
||||||
weston_config_section_get_string(section, "icon",
|
weston_config_section_get_string(section, "icon",
|
||||||
&launcher->icon, NULL);
|
&launcher->icon, NULL);
|
||||||
weston_config_section_get_string(section, "path",
|
|
||||||
&launcher->path, NULL);
|
weston_config_section_get_string(section, "command",
|
||||||
|
&command, NULL);
|
||||||
|
if (command == NULL) {
|
||||||
|
weston_config_section_get_string(section, "path",
|
||||||
|
&launcher->path, NULL);
|
||||||
|
launcher->argv = NULL;
|
||||||
|
} else {
|
||||||
|
launcher->argv = parse_command(command);
|
||||||
|
launcher->path = launcher->argv[0];
|
||||||
|
}
|
||||||
|
|
||||||
weston_config_section_get_uint(section, "workspace-id",
|
weston_config_section_get_uint(section, "workspace-id",
|
||||||
&launcher->workspace_id, 0);
|
&launcher->workspace_id, 0);
|
||||||
weston_config_section_get_uint(section, "icon-id",
|
weston_config_section_get_uint(section, "icon-id",
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ srcs_toytoolkit = [
|
||||||
relative_pointer_unstable_v1_protocol_c,
|
relative_pointer_unstable_v1_protocol_c,
|
||||||
pointer_constraints_unstable_v1_client_protocol_h,
|
pointer_constraints_unstable_v1_client_protocol_h,
|
||||||
pointer_constraints_unstable_v1_protocol_c,
|
pointer_constraints_unstable_v1_protocol_c,
|
||||||
|
single_pixel_buffer_v1_client_protocol_h,
|
||||||
|
single_pixel_buffer_v1_protocol_c,
|
||||||
tablet_unstable_v2_client_protocol_h,
|
tablet_unstable_v2_client_protocol_h,
|
||||||
tablet_unstable_v2_protocol_c,
|
tablet_unstable_v2_protocol_c,
|
||||||
ivi_application_client_protocol_h,
|
ivi_application_client_protocol_h,
|
||||||
|
|
@ -161,6 +163,21 @@ simple_clients = [
|
||||||
],
|
],
|
||||||
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'name': 'timing',
|
||||||
|
'sources': [
|
||||||
|
'simple-timing.c',
|
||||||
|
xdg_shell_client_protocol_h,
|
||||||
|
xdg_shell_protocol_c,
|
||||||
|
commit_timing_v1_client_protocol_h,
|
||||||
|
commit_timing_v1_protocol_c,
|
||||||
|
fifo_v1_client_protocol_h,
|
||||||
|
fifo_v1_protocol_c,
|
||||||
|
presentation_time_client_protocol_h,
|
||||||
|
presentation_time_protocol_c,
|
||||||
|
],
|
||||||
|
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'name': 'touch',
|
'name': 'touch',
|
||||||
'sources': [
|
'sources': [
|
||||||
|
|
@ -172,6 +189,89 @@ simple_clients = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if dep_vulkan.found() and prog_glslang.found()
|
||||||
|
srcs_simple_vulkan_shaders = [
|
||||||
|
'simple_vulkan_vertex_shader.vert',
|
||||||
|
'simple_vulkan_fragment_shader.frag',
|
||||||
|
]
|
||||||
|
|
||||||
|
simple_vulkan_shaders = []
|
||||||
|
foreach s : srcs_simple_vulkan_shaders
|
||||||
|
simple_vulkan_shaders += custom_target(s + '.spv.h',
|
||||||
|
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
|
||||||
|
input: s,
|
||||||
|
output: '@BASENAME@.spv.h',
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
simple_clients += {
|
||||||
|
'name': 'vulkan',
|
||||||
|
'sources': [
|
||||||
|
'simple-vulkan.c',
|
||||||
|
simple_vulkan_shaders,
|
||||||
|
fractional_scale_v1_client_protocol_h,
|
||||||
|
fractional_scale_v1_protocol_c,
|
||||||
|
tearing_control_v1_client_protocol_h,
|
||||||
|
tearing_control_v1_protocol_c,
|
||||||
|
viewporter_client_protocol_h,
|
||||||
|
viewporter_protocol_c,
|
||||||
|
xdg_shell_client_protocol_h,
|
||||||
|
xdg_shell_protocol_c,
|
||||||
|
],
|
||||||
|
'dep_objs': [
|
||||||
|
dep_vulkan,
|
||||||
|
dep_libm,
|
||||||
|
dep_libshared,
|
||||||
|
dep_matrix_c,
|
||||||
|
dep_wayland_client,
|
||||||
|
],
|
||||||
|
'deps': [ 'vulkan', 'wayland-cursor' ],
|
||||||
|
'options': [ 'renderer-gl' ]
|
||||||
|
}
|
||||||
|
|
||||||
|
srcs_simple_dmabuf_vulkan_shaders = [
|
||||||
|
'simple_dmabuf_vulkan_vertex_shader.vert',
|
||||||
|
'simple_dmabuf_vulkan_fragment_shader.frag',
|
||||||
|
]
|
||||||
|
|
||||||
|
simple_dmabuf_vulkan_shaders = []
|
||||||
|
foreach s : srcs_simple_dmabuf_vulkan_shaders
|
||||||
|
simple_dmabuf_vulkan_shaders += custom_target(s + '.spv.h',
|
||||||
|
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
|
||||||
|
input: s,
|
||||||
|
output: '@BASENAME@.spv.h',
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
simple_clients += {
|
||||||
|
'name': 'dmabuf-vulkan',
|
||||||
|
'sources': [
|
||||||
|
'simple-dmabuf-vulkan.c',
|
||||||
|
simple_dmabuf_vulkan_shaders,
|
||||||
|
linux_dmabuf_unstable_v1_client_protocol_h,
|
||||||
|
linux_dmabuf_unstable_v1_protocol_c,
|
||||||
|
linux_explicit_synchronization_unstable_v1_client_protocol_h,
|
||||||
|
linux_explicit_synchronization_unstable_v1_protocol_c,
|
||||||
|
xdg_shell_client_protocol_h,
|
||||||
|
xdg_shell_protocol_c,
|
||||||
|
weston_direct_display_client_protocol_h,
|
||||||
|
weston_direct_display_protocol_c,
|
||||||
|
],
|
||||||
|
'dep_objs': [
|
||||||
|
dep_vulkan,
|
||||||
|
dep_libdrm_headers,
|
||||||
|
dep_libm,
|
||||||
|
dep_libdrm,
|
||||||
|
dep_libshared,
|
||||||
|
dep_matrix_c,
|
||||||
|
dep_wayland_client,
|
||||||
|
dep_libweston_private, # for pixel-formats.h
|
||||||
|
],
|
||||||
|
'deps': [ 'vulkan', 'wayland-cursor', 'gbm' ],
|
||||||
|
'options': [ 'renderer-gl' ]
|
||||||
|
}
|
||||||
|
endif
|
||||||
|
|
||||||
foreach t : simple_clients
|
foreach t : simple_clients
|
||||||
if simple_build_all or simple_clients_enabled.contains(t.get('name'))
|
if simple_build_all or simple_clients_enabled.contains(t.get('name'))
|
||||||
t_name = 'weston-simple-' + t.get('name')
|
t_name = 'weston-simple-' + t.get('name')
|
||||||
|
|
@ -269,6 +369,15 @@ demo_clients = [
|
||||||
'basename': 'cliptest',
|
'basename': 'cliptest',
|
||||||
'dep_objs': [ dep_vertex_clipping, dep_matrix_c ]
|
'dep_objs': [ dep_vertex_clipping, dep_matrix_c ]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'basename': 'color',
|
||||||
|
'add_sources': [
|
||||||
|
color_management_v1_client_protocol_h,
|
||||||
|
color_management_v1_protocol_c,
|
||||||
|
single_pixel_buffer_v1_client_protocol_h,
|
||||||
|
single_pixel_buffer_v1_protocol_c,
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'basename': 'constraints',
|
'basename': 'constraints',
|
||||||
'add_sources': [
|
'add_sources': [
|
||||||
|
|
@ -391,7 +500,7 @@ if get_option('shell-desktop')
|
||||||
env_modmap += 'weston-desktop-shell=@0@;'.format(exe_shell_desktop.full_path())
|
env_modmap += 'weston-desktop-shell=@0@;'.format(exe_shell_desktop.full_path())
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get_option('shell-desktop') or get_option('shell-fullscreen') or get_option('shell-kiosk') or get_option('shell-ivi')
|
if get_option('shell-desktop') or get_option('deprecated-shell-fullscreen') or get_option('shell-kiosk') or get_option('shell-ivi')
|
||||||
exe_shooter = executable(
|
exe_shooter = executable(
|
||||||
'weston-screenshooter',
|
'weston-screenshooter',
|
||||||
'screenshot.c',
|
'screenshot.c',
|
||||||
|
|
@ -399,6 +508,7 @@ if get_option('shell-desktop') or get_option('shell-fullscreen') or get_option('
|
||||||
weston_output_capture_protocol_c,
|
weston_output_capture_protocol_c,
|
||||||
include_directories: common_inc,
|
include_directories: common_inc,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
dep_client_buffer,
|
||||||
dep_toytoolkit,
|
dep_toytoolkit,
|
||||||
dep_libweston_private, # for pixel-formats.h
|
dep_libweston_private, # for pixel-formats.h
|
||||||
dep_pixman,
|
dep_pixman,
|
||||||
|
|
|
||||||
|
|
@ -775,7 +775,7 @@ registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
|
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
|
||||||
d->presentation =
|
d->presentation =
|
||||||
wl_registry_bind(registry,
|
wl_registry_bind(registry,
|
||||||
name, &wp_presentation_interface, 1);
|
name, &wp_presentation_interface, 2);
|
||||||
wp_presentation_add_listener(d->presentation,
|
wp_presentation_add_listener(d->presentation,
|
||||||
&presentation_listener, d);
|
&presentation_listener, d);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,33 +24,44 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <pixman.h>
|
|
||||||
#include <cairo.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <pixman.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include "weston-output-capture-client-protocol.h"
|
|
||||||
#include "shared/os-compatibility.h"
|
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||||
#include "shared/xalloc.h"
|
|
||||||
#include "shared/file-util.h"
|
|
||||||
#include "pixel-formats.h"
|
#include "pixel-formats.h"
|
||||||
|
#include "shared/client-buffer-util.h"
|
||||||
|
#include "shared/file-util.h"
|
||||||
|
#include "shared/os-compatibility.h"
|
||||||
|
#include "shared/string-helpers.h"
|
||||||
|
#include "shared/xalloc.h"
|
||||||
|
#include "weston-output-capture-client-protocol.h"
|
||||||
|
|
||||||
struct screenshooter_app {
|
struct screenshooter_app {
|
||||||
|
struct wl_display *display;
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
|
struct zwp_linux_dmabuf_v1 *dmabuf;
|
||||||
struct weston_capture_v1 *capture_factory;
|
struct weston_capture_v1 *capture_factory;
|
||||||
|
|
||||||
|
bool verbose;
|
||||||
|
const struct pixel_format_info *requested_format;
|
||||||
|
enum weston_capture_v1_source src_type;
|
||||||
|
enum client_buffer_type buffer_type;
|
||||||
|
|
||||||
struct wl_list output_list; /* struct screenshooter_output::link */
|
struct wl_list output_list; /* struct screenshooter_output::link */
|
||||||
|
|
||||||
bool retry;
|
bool retry;
|
||||||
|
|
@ -59,14 +70,14 @@ struct screenshooter_app {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct screenshooter_buffer {
|
struct screenshooter_buffer {
|
||||||
size_t len;
|
struct client_buffer *buf;
|
||||||
void *data;
|
|
||||||
struct wl_buffer *wl_buffer;
|
|
||||||
pixman_image_t *image;
|
pixman_image_t *image;
|
||||||
|
enum weston_capture_v1_source src_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct screenshooter_output {
|
struct screenshooter_output {
|
||||||
struct screenshooter_app *app;
|
struct screenshooter_app *app;
|
||||||
|
uint32_t name;
|
||||||
struct wl_list link; /* struct screenshooter_app::output_list */
|
struct wl_list link; /* struct screenshooter_app::output_list */
|
||||||
|
|
||||||
struct wl_output *wl_output;
|
struct wl_output *wl_output;
|
||||||
|
|
@ -76,7 +87,8 @@ struct screenshooter_output {
|
||||||
|
|
||||||
int buffer_width;
|
int buffer_width;
|
||||||
int buffer_height;
|
int buffer_height;
|
||||||
const struct pixel_format_info *fmt;
|
struct wl_array formats;
|
||||||
|
bool formats_done;
|
||||||
struct screenshooter_buffer *buffer;
|
struct screenshooter_buffer *buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -93,10 +105,6 @@ screenshot_create_shm_buffer(struct screenshooter_app *app,
|
||||||
const struct pixel_format_info *fmt)
|
const struct pixel_format_info *fmt)
|
||||||
{
|
{
|
||||||
struct screenshooter_buffer *buffer;
|
struct screenshooter_buffer *buffer;
|
||||||
struct wl_shm_pool *pool;
|
|
||||||
int fd;
|
|
||||||
size_t bytes_pp;
|
|
||||||
size_t stride;
|
|
||||||
|
|
||||||
assert(width > 0);
|
assert(width > 0);
|
||||||
assert(height > 0);
|
assert(height > 0);
|
||||||
|
|
@ -105,54 +113,60 @@ screenshot_create_shm_buffer(struct screenshooter_app *app,
|
||||||
|
|
||||||
buffer = xzalloc(sizeof *buffer);
|
buffer = xzalloc(sizeof *buffer);
|
||||||
|
|
||||||
bytes_pp = fmt->bpp / 8;
|
buffer->buf = client_buffer_util_create_shm_buffer(app->shm,
|
||||||
stride = width * bytes_pp;
|
fmt,
|
||||||
buffer->len = stride * height;
|
width,
|
||||||
|
height);
|
||||||
assert(width == stride / bytes_pp);
|
|
||||||
assert(height == buffer->len / stride);
|
|
||||||
|
|
||||||
fd = os_create_anonymous_file(buffer->len);
|
|
||||||
if (fd < 0) {
|
|
||||||
fprintf(stderr, "creating a buffer file for %zd B failed: %s\n",
|
|
||||||
buffer->len, strerror(errno));
|
|
||||||
free(buffer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->data = mmap(NULL, buffer->len, PROT_READ | PROT_WRITE,
|
|
||||||
MAP_SHARED, fd, 0);
|
|
||||||
if (buffer->data == MAP_FAILED) {
|
|
||||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
|
||||||
close(fd);
|
|
||||||
free(buffer);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pool = wl_shm_create_pool(app->shm, fd, buffer->len);
|
|
||||||
close(fd);
|
|
||||||
buffer->wl_buffer =
|
|
||||||
wl_shm_pool_create_buffer(pool, 0, width, height, stride,
|
|
||||||
pixel_format_get_shm_format(fmt));
|
|
||||||
wl_shm_pool_destroy(pool);
|
|
||||||
|
|
||||||
buffer->image = pixman_image_create_bits(fmt->pixman_format,
|
buffer->image = pixman_image_create_bits(fmt->pixman_format,
|
||||||
width, height,
|
width, height,
|
||||||
buffer->data, stride);
|
buffer->buf->data,
|
||||||
|
buffer->buf->strides[0]);
|
||||||
abort_oom_if_null(buffer->image);
|
abort_oom_if_null(buffer->image);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct screenshooter_buffer *
|
||||||
|
screenshot_create_udmabuf(struct screenshooter_app *app,
|
||||||
|
int width, int height,
|
||||||
|
const struct pixel_format_info *fmt)
|
||||||
|
{
|
||||||
|
struct screenshooter_buffer* buffer = NULL;
|
||||||
|
|
||||||
|
assert(width > 0);
|
||||||
|
assert(height > 0);
|
||||||
|
assert(fmt);
|
||||||
|
|
||||||
|
buffer = xzalloc(sizeof *buffer);
|
||||||
|
|
||||||
|
buffer->buf = client_buffer_util_create_dmabuf_buffer(app->display,
|
||||||
|
app->dmabuf,
|
||||||
|
fmt,
|
||||||
|
width,
|
||||||
|
height);
|
||||||
|
|
||||||
|
if (fmt->pixman_format) {
|
||||||
|
buffer->image = pixman_image_create_bits(fmt->pixman_format,
|
||||||
|
width, height,
|
||||||
|
buffer->buf->data,
|
||||||
|
buffer->buf->strides[0]);
|
||||||
|
abort_oom_if_null(buffer->image);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
screenshooter_buffer_destroy(struct screenshooter_buffer *buffer)
|
screenshooter_buffer_destroy(struct screenshooter_buffer *buffer)
|
||||||
{
|
{
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pixman_image_unref(buffer->image);
|
if (buffer->image)
|
||||||
munmap(buffer->data, buffer->len);
|
pixman_image_unref(buffer->image);
|
||||||
wl_buffer_destroy(buffer->wl_buffer);
|
|
||||||
|
client_buffer_util_destroy_buffer(buffer->buf);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,10 +176,37 @@ capture_source_handle_format(void *data,
|
||||||
uint32_t drm_format)
|
uint32_t drm_format)
|
||||||
{
|
{
|
||||||
struct screenshooter_output *output = data;
|
struct screenshooter_output *output = data;
|
||||||
|
uint32_t *fmt;
|
||||||
|
|
||||||
assert(output->source == proxy);
|
assert(output->source == proxy);
|
||||||
|
|
||||||
output->fmt = pixel_format_get_info(drm_format);
|
if (output->formats_done) {
|
||||||
|
wl_array_release(&output->formats);
|
||||||
|
wl_array_init(&output->formats);
|
||||||
|
output->formats_done = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt = wl_array_add(&output->formats, sizeof(uint32_t));
|
||||||
|
assert(fmt);
|
||||||
|
*fmt = drm_format;
|
||||||
|
|
||||||
|
if (output->app->verbose) {
|
||||||
|
const struct pixel_format_info *fmt_info;
|
||||||
|
|
||||||
|
fmt_info = pixel_format_get_info(drm_format);
|
||||||
|
assert(fmt_info);
|
||||||
|
printf("Got format %s / 0x%x\n", fmt_info->drm_format_name,
|
||||||
|
drm_format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
capture_source_handle_formats_done(void *data,
|
||||||
|
struct weston_capture_source_v1 *proxy)
|
||||||
|
{
|
||||||
|
struct screenshooter_output *output = data;
|
||||||
|
|
||||||
|
output->formats_done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -180,6 +221,9 @@ capture_source_handle_size(void *data,
|
||||||
|
|
||||||
output->buffer_width = width;
|
output->buffer_width = width;
|
||||||
output->buffer_height = height;
|
output->buffer_height = height;
|
||||||
|
|
||||||
|
if (output->app->verbose)
|
||||||
|
printf("Got size %dx%d\n", width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -209,7 +253,9 @@ capture_source_handle_failed(void *data,
|
||||||
struct screenshooter_output *output = data;
|
struct screenshooter_output *output = data;
|
||||||
|
|
||||||
output->app->waitcount--;
|
output->app->waitcount--;
|
||||||
output->app->failed = true;
|
/* We don't set app.failed here because there could be other
|
||||||
|
* outputs we still want to capture!
|
||||||
|
*/
|
||||||
|
|
||||||
if (msg)
|
if (msg)
|
||||||
fprintf(stderr, "Output capture error: %s\n", msg);
|
fprintf(stderr, "Output capture error: %s\n", msg);
|
||||||
|
|
@ -217,6 +263,7 @@ capture_source_handle_failed(void *data,
|
||||||
|
|
||||||
static const struct weston_capture_source_v1_listener capture_source_handlers = {
|
static const struct weston_capture_source_v1_listener capture_source_handlers = {
|
||||||
.format = capture_source_handle_format,
|
.format = capture_source_handle_format,
|
||||||
|
.formats_done = capture_source_handle_formats_done,
|
||||||
.size = capture_source_handle_size,
|
.size = capture_source_handle_size,
|
||||||
.complete = capture_source_handle_complete,
|
.complete = capture_source_handle_complete,
|
||||||
.retry = capture_source_handle_retry,
|
.retry = capture_source_handle_retry,
|
||||||
|
|
@ -231,17 +278,20 @@ create_output(struct screenshooter_app *app, uint32_t output_name, uint32_t vers
|
||||||
version = MIN(version, 4);
|
version = MIN(version, 4);
|
||||||
output = xzalloc(sizeof *output);
|
output = xzalloc(sizeof *output);
|
||||||
output->app = app;
|
output->app = app;
|
||||||
|
output->name = output_name;
|
||||||
output->wl_output = wl_registry_bind(app->registry, output_name,
|
output->wl_output = wl_registry_bind(app->registry, output_name,
|
||||||
&wl_output_interface, version);
|
&wl_output_interface, version);
|
||||||
abort_oom_if_null(output->wl_output);
|
abort_oom_if_null(output->wl_output);
|
||||||
|
|
||||||
output->source = weston_capture_v1_create(app->capture_factory,
|
output->source = weston_capture_v1_create(app->capture_factory,
|
||||||
output->wl_output,
|
output->wl_output,
|
||||||
WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER);
|
app->src_type);
|
||||||
abort_oom_if_null(output->source);
|
abort_oom_if_null(output->source);
|
||||||
weston_capture_source_v1_add_listener(output->source,
|
weston_capture_source_v1_add_listener(output->source,
|
||||||
&capture_source_handlers, output);
|
&capture_source_handlers, output);
|
||||||
|
|
||||||
|
wl_array_init(&output->formats);
|
||||||
|
|
||||||
wl_list_insert(&app->output_list, &output->link);
|
wl_list_insert(&app->output_list, &output->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,6 +300,8 @@ destroy_output(struct screenshooter_output *output)
|
||||||
{
|
{
|
||||||
weston_capture_source_v1_destroy(output->source);
|
weston_capture_source_v1_destroy(output->source);
|
||||||
|
|
||||||
|
wl_array_release(&output->formats);
|
||||||
|
|
||||||
if (wl_output_get_version(output->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
|
if (wl_output_get_version(output->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
|
||||||
wl_output_release(output->wl_output);
|
wl_output_release(output->wl_output);
|
||||||
else
|
else
|
||||||
|
|
@ -277,7 +329,13 @@ handle_global(void *data, struct wl_registry *registry,
|
||||||
} else if (strcmp(interface, weston_capture_v1_interface.name) == 0) {
|
} else if (strcmp(interface, weston_capture_v1_interface.name) == 0) {
|
||||||
app->capture_factory = wl_registry_bind(registry, name,
|
app->capture_factory = wl_registry_bind(registry, name,
|
||||||
&weston_capture_v1_interface,
|
&weston_capture_v1_interface,
|
||||||
1);
|
2);
|
||||||
|
} else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0) {
|
||||||
|
if (version < 3)
|
||||||
|
return;
|
||||||
|
app->dmabuf = wl_registry_bind(registry, name,
|
||||||
|
&zwp_linux_dmabuf_v1_interface,
|
||||||
|
3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,15 +353,46 @@ static const struct wl_registry_listener registry_listener = {
|
||||||
static void
|
static void
|
||||||
screenshooter_output_capture(struct screenshooter_output *output)
|
screenshooter_output_capture(struct screenshooter_output *output)
|
||||||
{
|
{
|
||||||
|
const struct pixel_format_info *fmt_info = NULL;
|
||||||
|
uint32_t *fmt;
|
||||||
|
|
||||||
screenshooter_buffer_destroy(output->buffer);
|
screenshooter_buffer_destroy(output->buffer);
|
||||||
output->buffer = screenshot_create_shm_buffer(output->app,
|
|
||||||
output->buffer_width,
|
wl_array_for_each(fmt, &output->formats) {
|
||||||
output->buffer_height,
|
fmt_info = pixel_format_get_info(*fmt);
|
||||||
output->fmt);
|
assert(fmt_info);
|
||||||
|
|
||||||
|
if (fmt_info == output->app->requested_format ||
|
||||||
|
output->app->requested_format == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
fmt_info = NULL;
|
||||||
|
}
|
||||||
|
if (!fmt_info) {
|
||||||
|
fprintf(stderr, "No supported format found\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output->app->verbose)
|
||||||
|
printf("Creating buffer with format %s / 0x%x and size %ux%u\n",
|
||||||
|
fmt_info->drm_format_name, fmt_info->format,
|
||||||
|
output->buffer_width, output->buffer_height);
|
||||||
|
|
||||||
|
if (output->app->buffer_type == CLIENT_BUFFER_TYPE_SHM) {
|
||||||
|
output->buffer = screenshot_create_shm_buffer(output->app,
|
||||||
|
output->buffer_width,
|
||||||
|
output->buffer_height,
|
||||||
|
fmt_info);
|
||||||
|
} else if (output->app->buffer_type == CLIENT_BUFFER_TYPE_DMABUF) {
|
||||||
|
output->buffer = screenshot_create_udmabuf(output->app,
|
||||||
|
output->buffer_width,
|
||||||
|
output->buffer_height,
|
||||||
|
fmt_info);
|
||||||
|
}
|
||||||
abort_oom_if_null(output->buffer);
|
abort_oom_if_null(output->buffer);
|
||||||
|
|
||||||
weston_capture_source_v1_capture(output->source,
|
weston_capture_source_v1_capture(output->source,
|
||||||
output->buffer->wl_buffer);
|
output->buffer->buf->wl_buffer);
|
||||||
output->app->waitcount++;
|
output->app->waitcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -323,6 +412,8 @@ screenshot_write_png(const struct buffer_size *buff_size,
|
||||||
abort_oom_if_null(shot);
|
abort_oom_if_null(shot);
|
||||||
|
|
||||||
wl_list_for_each(output, output_list, link) {
|
wl_list_for_each(output, output_list, link) {
|
||||||
|
client_buffer_util_maybe_sync_dmabuf_start(output->buffer->buf);
|
||||||
|
|
||||||
pixman_image_composite32(PIXMAN_OP_SRC,
|
pixman_image_composite32(PIXMAN_OP_SRC,
|
||||||
output->buffer->image, /* src */
|
output->buffer->image, /* src */
|
||||||
NULL, /* mask */
|
NULL, /* mask */
|
||||||
|
|
@ -331,6 +422,8 @@ screenshot_write_png(const struct buffer_size *buff_size,
|
||||||
0, 0, /* mask x,y */
|
0, 0, /* mask x,y */
|
||||||
output->offset_x, output->offset_y, /* dst x,y */
|
output->offset_x, output->offset_y, /* dst x,y */
|
||||||
output->buffer_width, output->buffer_height);
|
output->buffer_width, output->buffer_height);
|
||||||
|
|
||||||
|
client_buffer_util_maybe_sync_dmabuf_end(output->buffer->buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
surface = cairo_image_surface_create_for_data((void *)pixman_image_get_data(shot),
|
surface = cairo_image_surface_create_for_data((void *)pixman_image_get_data(shot),
|
||||||
|
|
@ -349,6 +442,59 @@ screenshot_write_png(const struct buffer_size *buff_size,
|
||||||
pixman_image_unref(shot);
|
pixman_image_unref(shot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
screenshot_write_yuv(const struct buffer_size *buff_size,
|
||||||
|
struct wl_list *output_list)
|
||||||
|
{
|
||||||
|
struct screenshooter_output *output;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
wl_list_for_each(output, output_list, link) {
|
||||||
|
struct screenshooter_buffer *buffer = output->buffer;
|
||||||
|
char filepath[PATH_MAX];
|
||||||
|
char filepath_prefix[100];
|
||||||
|
int write_offset = 0;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
sprintf(filepath_prefix, "wayland-screenshot-output-%d-", i++);
|
||||||
|
fp = file_create_dated(getenv("XDG_PICTURES_DIR"),
|
||||||
|
filepath_prefix, ".yuv", filepath,
|
||||||
|
sizeof(filepath));
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "Writing yuv file for output %d failed\n", i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client_buffer_util_maybe_sync_dmabuf_start(buffer->buf);
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < pixel_format_get_plane_count(buffer->buf->fmt); j++) {
|
||||||
|
int plane_height =
|
||||||
|
buffer->buf->height / pixel_format_hsub(buffer->buf->fmt, j);
|
||||||
|
|
||||||
|
for (int k = 0; k < plane_height; k++) {
|
||||||
|
size_t lines_written;
|
||||||
|
|
||||||
|
lines_written = fwrite(buffer->buf->data + write_offset,
|
||||||
|
buffer->buf->bytes_per_line[j],
|
||||||
|
1, fp);
|
||||||
|
if (lines_written != 1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Writing yuv file for output %d " \
|
||||||
|
"failed during write(): %s\n",
|
||||||
|
i, strerror(errno));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_offset += buffer->buf->strides[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
client_buffer_util_maybe_sync_dmabuf_end(buffer->buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
screenshot_set_buffer_size(struct buffer_size *buff_size,
|
screenshot_set_buffer_size(struct buffer_size *buff_size,
|
||||||
struct wl_list *output_list)
|
struct wl_list *output_list)
|
||||||
|
|
@ -382,41 +528,182 @@ screenshot_set_buffer_size(struct buffer_size *buff_size,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
received_formats_for_all_outputs(struct screenshooter_app *app)
|
||||||
|
{
|
||||||
|
struct screenshooter_output *output;
|
||||||
|
|
||||||
|
wl_list_for_each(output, &app->output_list, link) {
|
||||||
|
if (!output->formats_done)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
all_output_formats_are_yuv(struct wl_list *output_list)
|
||||||
|
{
|
||||||
|
struct screenshooter_output *output;
|
||||||
|
int color_model = -1;
|
||||||
|
|
||||||
|
wl_list_for_each(output, output_list, link) {
|
||||||
|
if (color_model == -1) {
|
||||||
|
color_model = output->buffer->buf->fmt->color_model;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int)output->buffer->buf->fmt->color_model != color_model) {
|
||||||
|
fprintf(stderr, "Mixing of RGB and YUV output formats not supported\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(color_model == (int)COLOR_MODEL_RGB ||
|
||||||
|
color_model == (int)COLOR_MODEL_YUV);
|
||||||
|
return color_model == COLOR_MODEL_YUV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_usage_and_exit(void)
|
||||||
|
{
|
||||||
|
printf("usage flags:\n"
|
||||||
|
"\t'-h,--help'"
|
||||||
|
"\n\t\tprint this help output\n"
|
||||||
|
"\t'-v,--verbose'"
|
||||||
|
"\n\t\tprint additional output\n"
|
||||||
|
"\t'-f,--format=<>'"
|
||||||
|
"\n\t\tthe DRM format name to use without the DRM_FORMAT_ prefix, e.g. RGBA8888 or NV12\n"
|
||||||
|
"\n\t\tIn case of YCbCr formats like NV12, instead of a single .png, the output will consist of raw .yuv files for each output."
|
||||||
|
"\n\t\tThese files do not contain any metadata, however that can be added by converting to .y4m with a command like:"
|
||||||
|
"\n\t\tffmpeg -s 1024x768 -r 1 -pix_fmt yuv420p -i ~/wayland-screenshot-output-0-2025-08-01_15-58-24.yuv -c:v copy screenshot.y4m\n"
|
||||||
|
"\n\t\tNote that this may not work for all YCbCr pixel formats.\n"
|
||||||
|
"\t'-s,--source-type=<>'"
|
||||||
|
"\n\t\tframebuffer to use framebuffer source (default), "
|
||||||
|
"\n\t\twriteback to use writeback source\n"
|
||||||
|
"\t'-b,--buffer-type=<>'"
|
||||||
|
"\n\t\tshm to use a SHM buffer (default), "
|
||||||
|
"\n\t\tdmabuf to use a DMA buffer\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct weston_enum_map source_types [] = {
|
||||||
|
{ "framebuffer", WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER },
|
||||||
|
{ "writeback", WESTON_CAPTURE_V1_SOURCE_WRITEBACK },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct weston_enum_map buffer_types [] = {
|
||||||
|
{ "shm", CLIENT_BUFFER_TYPE_SHM },
|
||||||
|
{ "dmabuf", CLIENT_BUFFER_TYPE_DMABUF },
|
||||||
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct wl_display *display;
|
|
||||||
struct screenshooter_output *output;
|
struct screenshooter_output *output;
|
||||||
struct screenshooter_output *tmp_output;
|
struct screenshooter_output *tmp_output;
|
||||||
struct buffer_size buff_size = {};
|
struct buffer_size buff_size = {};
|
||||||
struct screenshooter_app app = {};
|
struct screenshooter_app app = {};
|
||||||
|
int c, option_index;
|
||||||
|
|
||||||
|
app.src_type = WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER;
|
||||||
|
app.buffer_type = CLIENT_BUFFER_TYPE_SHM;
|
||||||
|
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"help", no_argument, NULL, 'h'},
|
||||||
|
{"verbose", no_argument, NULL, 'v'},
|
||||||
|
{"format", required_argument, NULL, 'f'},
|
||||||
|
{"source-type", required_argument, NULL, 's'},
|
||||||
|
{"buffer-type", required_argument, NULL, 'b'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
while ((c = getopt_long(argc, argv, "hvf:s:b:",
|
||||||
|
long_options, &option_index)) != -1) {
|
||||||
|
const struct weston_enum_map *entry;
|
||||||
|
|
||||||
|
switch(c) {
|
||||||
|
case 'v':
|
||||||
|
app.verbose = true;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
app.requested_format = pixel_format_get_info_by_drm_name(optarg);
|
||||||
|
if (!app.requested_format) {
|
||||||
|
fprintf(stderr, "Unknown format %s\n", optarg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
entry = weston_enum_map_find_name(source_types,
|
||||||
|
optarg);
|
||||||
|
if (!entry)
|
||||||
|
print_usage_and_exit();
|
||||||
|
|
||||||
|
app.src_type = entry->value;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
entry = weston_enum_map_find_name(buffer_types,
|
||||||
|
optarg);
|
||||||
|
if (!entry)
|
||||||
|
print_usage_and_exit();
|
||||||
|
|
||||||
|
app.buffer_type = entry->value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print_usage_and_exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wl_list_init(&app.output_list);
|
wl_list_init(&app.output_list);
|
||||||
|
|
||||||
display = wl_display_connect(NULL);
|
app.display = wl_display_connect(NULL);
|
||||||
if (display == NULL) {
|
if (app.display == NULL) {
|
||||||
fprintf(stderr, "failed to create display: %s\n",
|
fprintf(stderr, "failed to create display: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.registry = wl_display_get_registry(display);
|
app.registry = wl_display_get_registry(app.display);
|
||||||
wl_registry_add_listener(app.registry, ®istry_listener, &app);
|
wl_registry_add_listener(app.registry, ®istry_listener, &app);
|
||||||
|
|
||||||
/* Process wl_registry advertisements */
|
/* Process wl_registry advertisements */
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(app.display);
|
||||||
|
|
||||||
if (!app.shm) {
|
|
||||||
fprintf(stderr, "Error: display does not support wl_shm\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!app.capture_factory) {
|
if (!app.capture_factory) {
|
||||||
fprintf(stderr, "Error: display does not support weston_capture_v1\n");
|
fprintf(stderr, "Error: display does not support weston_capture_v1\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (app.src_type == WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER &&
|
||||||
|
app.buffer_type != CLIENT_BUFFER_TYPE_SHM) {
|
||||||
|
fprintf(stderr, "Error: Only support shm buffer with framebuffer source\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(app.buffer_type == CLIENT_BUFFER_TYPE_SHM && !app.shm) {
|
||||||
|
fprintf(stderr, "Error: display does not support wl_shm\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (app.buffer_type == CLIENT_BUFFER_TYPE_DMABUF && !app.dmabuf) {
|
||||||
|
fprintf(stderr, "Error: Compositor does not support zwp_linux_dmabuf_v1\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app.verbose) {
|
||||||
|
printf("Taking screenshot with %s source %s buffer\n",
|
||||||
|
(app.src_type == WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER) ? "framebuffer" : "writeback",
|
||||||
|
(app.buffer_type == CLIENT_BUFFER_TYPE_SHM) ? "shm" : "dma");
|
||||||
|
}
|
||||||
|
|
||||||
/* Process initial events for wl_output and weston_capture_source_v1 */
|
/* Process initial events for wl_output and weston_capture_source_v1 */
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(app.display);
|
||||||
|
|
||||||
|
while (!received_formats_for_all_outputs(&app)) {
|
||||||
|
if (app.verbose)
|
||||||
|
printf("Waiting for compositor to send capture source data\n");
|
||||||
|
|
||||||
|
if (wl_display_dispatch(app.display) < 0) {
|
||||||
|
fprintf(stderr, "Error: connection terminated\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
app.retry = false;
|
app.retry = false;
|
||||||
|
|
@ -425,7 +712,7 @@ main(int argc, char *argv[])
|
||||||
screenshooter_output_capture(output);
|
screenshooter_output_capture(output);
|
||||||
|
|
||||||
while (app.waitcount > 0 && !app.failed) {
|
while (app.waitcount > 0 && !app.failed) {
|
||||||
if (wl_display_dispatch(display) < 0)
|
if (wl_display_dispatch(app.display) < 0)
|
||||||
app.failed = true;
|
app.failed = true;
|
||||||
assert(app.waitcount >= 0);
|
assert(app.waitcount >= 0);
|
||||||
}
|
}
|
||||||
|
|
@ -434,7 +721,11 @@ main(int argc, char *argv[])
|
||||||
if (!app.failed) {
|
if (!app.failed) {
|
||||||
if (screenshot_set_buffer_size(&buff_size, &app.output_list) < 0)
|
if (screenshot_set_buffer_size(&buff_size, &app.output_list) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
screenshot_write_png(&buff_size, &app.output_list);
|
|
||||||
|
if (all_output_formats_are_yuv(&app.output_list))
|
||||||
|
screenshot_write_yuv(&buff_size, &app.output_list);
|
||||||
|
else
|
||||||
|
screenshot_write_png(&buff_size, &app.output_list);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Error: screenshot or protocol failure\n");
|
fprintf(stderr, "Error: screenshot or protocol failure\n");
|
||||||
}
|
}
|
||||||
|
|
@ -444,8 +735,10 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
weston_capture_v1_destroy(app.capture_factory);
|
weston_capture_v1_destroy(app.capture_factory);
|
||||||
wl_shm_destroy(app.shm);
|
wl_shm_destroy(app.shm);
|
||||||
|
if (app.dmabuf)
|
||||||
|
zwp_linux_dmabuf_v1_destroy(app.dmabuf);
|
||||||
wl_registry_destroy(app.registry);
|
wl_registry_destroy(app.registry);
|
||||||
wl_display_disconnect(display);
|
wl_display_disconnect(app.display);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -815,7 +815,7 @@ render(struct window *window, struct buffer *buffer)
|
||||||
|
|
||||||
glUniform1f(window->gl.offset_uniform, offset);
|
glUniform1f(window->gl.offset_uniform, offset);
|
||||||
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
|
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
|
||||||
(GLfloat *) reflection.d);
|
(GLfloat *) reflection.M.colmaj);
|
||||||
|
|
||||||
glClearColor(0.0,0.0, 0.0, 1.0);
|
glClearColor(0.0,0.0, 0.0, 1.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
@ -864,7 +864,7 @@ render_mandelbrot(struct window *window, struct buffer *buffer)
|
||||||
|
|
||||||
glUniform1f(window->gl.offset_uniform, offset);
|
glUniform1f(window->gl.offset_uniform, offset);
|
||||||
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
|
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
|
||||||
(GLfloat *) reflection.d);
|
(GLfloat *) reflection.M.colmaj);
|
||||||
|
|
||||||
glClearColor(0.6, 0.6, 0.6, 1.0);
|
glClearColor(0.6, 0.6, 0.6, 1.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
@ -1110,6 +1110,12 @@ destroy_display(struct display *display)
|
||||||
|
|
||||||
free(display->modifiers);
|
free(display->modifiers);
|
||||||
|
|
||||||
|
if (display->direct_display)
|
||||||
|
weston_direct_display_v1_destroy(display->direct_display);
|
||||||
|
|
||||||
|
if (display->explicit_sync)
|
||||||
|
zwp_linux_explicit_synchronization_v1_destroy(display->explicit_sync);
|
||||||
|
|
||||||
if (display->dmabuf)
|
if (display->dmabuf)
|
||||||
zwp_linux_dmabuf_v1_destroy(display->dmabuf);
|
zwp_linux_dmabuf_v1_destroy(display->dmabuf);
|
||||||
|
|
||||||
|
|
|
||||||
2168
clients/simple-dmabuf-vulkan.c
Normal file
2168
clients/simple-dmabuf-vulkan.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -564,7 +564,6 @@ init_gl(struct window *window)
|
||||||
|
|
||||||
glBindAttribLocation(program, window->gl.pos, "pos");
|
glBindAttribLocation(program, window->gl.pos, "pos");
|
||||||
glBindAttribLocation(program, window->gl.col, "color");
|
glBindAttribLocation(program, window->gl.col, "color");
|
||||||
glLinkProgram(program);
|
|
||||||
|
|
||||||
window->gl.rotation_uniform =
|
window->gl.rotation_uniform =
|
||||||
glGetUniformLocation(program, "rotation");
|
glGetUniformLocation(program, "rotation");
|
||||||
|
|
@ -940,10 +939,10 @@ redraw(struct window *window)
|
||||||
angle = ((time - window->initial_frame_time) / speed_div)
|
angle = ((time - window->initial_frame_time) / speed_div)
|
||||||
% 360 * M_PI / 180.0;
|
% 360 * M_PI / 180.0;
|
||||||
}
|
}
|
||||||
rotation.d[0] = cos(angle);
|
rotation.M.col[0].el[0] = cos(angle);
|
||||||
rotation.d[2] = sin(angle);
|
rotation.M.col[0].el[2] = sin(angle);
|
||||||
rotation.d[8] = -sin(angle);
|
rotation.M.col[2].el[0] = -sin(angle);
|
||||||
rotation.d[10] = cos(angle);
|
rotation.M.col[2].el[2] = cos(angle);
|
||||||
|
|
||||||
switch (window->buffer_transform) {
|
switch (window->buffer_transform) {
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||||
|
|
@ -982,7 +981,7 @@ redraw(struct window *window)
|
||||||
glViewport(0, 0, window->buffer_size.width, window->buffer_size.height);
|
glViewport(0, 0, window->buffer_size.width, window->buffer_size.height);
|
||||||
|
|
||||||
glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE,
|
glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE,
|
||||||
(GLfloat *) rotation.d);
|
(GLfloat *) rotation.M.colmaj);
|
||||||
|
|
||||||
if (window->opaque || window->fullscreen)
|
if (window->opaque || window->fullscreen)
|
||||||
glClearColor(0.0, 0.0, 0.0, 1);
|
glClearColor(0.0, 0.0, 0.0, 1);
|
||||||
|
|
@ -1474,15 +1473,10 @@ main(int argc, char **argv)
|
||||||
create_surface(&window);
|
create_surface(&window);
|
||||||
|
|
||||||
/* we already have wait_for_configure set after create_surface() */
|
/* we already have wait_for_configure set after create_surface() */
|
||||||
while (running && ret != -1 && window.wait_for_configure) {
|
while (running && ret != -1 && window.wait_for_configure)
|
||||||
ret = wl_display_dispatch(display.display);
|
ret = wl_display_dispatch(display.display);
|
||||||
|
|
||||||
/* wait until xdg_surface::configure acks the new dimensions */
|
init_gl(&window);
|
||||||
if (window.wait_for_configure)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
init_gl(&window);
|
|
||||||
}
|
|
||||||
|
|
||||||
display.cursor_surface =
|
display.cursor_surface =
|
||||||
wl_compositor_create_surface(display.compositor);
|
wl_compositor_create_surface(display.compositor);
|
||||||
|
|
@ -1530,6 +1524,9 @@ out_no_xdg_shell:
|
||||||
if (display.compositor)
|
if (display.compositor)
|
||||||
wl_compositor_destroy(display.compositor);
|
wl_compositor_destroy(display.compositor);
|
||||||
|
|
||||||
|
if (display.tearing_manager)
|
||||||
|
wp_tearing_control_manager_v1_destroy(display.tearing_manager);
|
||||||
|
|
||||||
if (display.viewporter)
|
if (display.viewporter)
|
||||||
wp_viewporter_destroy(display.viewporter);
|
wp_viewporter_destroy(display.viewporter);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
||||||
|
|
@ -42,8 +43,20 @@
|
||||||
#include <libweston/zalloc.h>
|
#include <libweston/zalloc.h>
|
||||||
#include "xdg-shell-client-protocol.h"
|
#include "xdg-shell-client-protocol.h"
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||||
|
#define FMT(fmt, bpp, r, g, b, a) { WL_SHM_FORMAT_ ## fmt, #fmt, bpp, { r, g, b, a } }
|
||||||
|
|
||||||
#define MAX_BUFFER_ALLOC 2
|
#define MAX_BUFFER_ALLOC 2
|
||||||
|
|
||||||
|
struct window;
|
||||||
|
|
||||||
|
struct format {
|
||||||
|
uint32_t code;
|
||||||
|
const char *string;
|
||||||
|
int bpp;
|
||||||
|
uint64_t color[4];
|
||||||
|
};
|
||||||
|
|
||||||
struct display {
|
struct display {
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
|
|
@ -52,7 +65,10 @@ struct display {
|
||||||
struct wl_seat *seat;
|
struct wl_seat *seat;
|
||||||
struct wl_keyboard *keyboard;
|
struct wl_keyboard *keyboard;
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
bool has_xrgb;
|
const struct format *format;
|
||||||
|
bool paint_format;
|
||||||
|
bool has_format;
|
||||||
|
struct window *window;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
|
|
@ -81,6 +97,68 @@ struct window {
|
||||||
bool needs_update_buffer;
|
bool needs_update_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct format shm_formats[] = {
|
||||||
|
/* 8 bpp formats */
|
||||||
|
FMT(R8, 8, 0x00, 0x55, 0xaa, 0xff ),
|
||||||
|
|
||||||
|
/* 16 bpp formats */
|
||||||
|
FMT(R16, 16, 0x0000, 0x5555, 0xaaaa, 0xffff ),
|
||||||
|
FMT(GR88, 16, 0x00ff, 0xff00, 0x0000, 0xffff ),
|
||||||
|
FMT(RG88, 16, 0xff00, 0x00ff, 0x0000, 0xffff ),
|
||||||
|
FMT(RGB565, 16, 0xf800, 0x07e0, 0x001f, 0xffff ),
|
||||||
|
FMT(BGR565, 16, 0x001f, 0x07e0, 0xf800, 0xffff ),
|
||||||
|
FMT(XRGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ),
|
||||||
|
FMT(ARGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ),
|
||||||
|
FMT(XBGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ),
|
||||||
|
FMT(ABGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ),
|
||||||
|
FMT(RGBX4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ),
|
||||||
|
FMT(RGBA4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ),
|
||||||
|
FMT(BGRX4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ),
|
||||||
|
FMT(BGRA4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ),
|
||||||
|
FMT(XRGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ),
|
||||||
|
FMT(ARGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ),
|
||||||
|
FMT(XBGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ),
|
||||||
|
FMT(ABGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ),
|
||||||
|
FMT(RGBX5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ),
|
||||||
|
FMT(RGBA5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ),
|
||||||
|
FMT(BGRX5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ),
|
||||||
|
FMT(BGRA5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ),
|
||||||
|
|
||||||
|
/* 24 bpp formats */
|
||||||
|
FMT(RGB888, 24, 0xff0000, 0x00ff00, 0x0000ff, 0xffffff ),
|
||||||
|
FMT(BGR888, 24, 0x0000ff, 0x00ff00, 0xff0000, 0xffffff ),
|
||||||
|
|
||||||
|
/* 32 bpp formats */
|
||||||
|
FMT(GR1616, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0xffffffff ),
|
||||||
|
FMT(RG1616, 32, 0xffff0000, 0x0000ffff, 0x00000000, 0xffffffff ),
|
||||||
|
FMT(XRGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ),
|
||||||
|
FMT(ARGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ),
|
||||||
|
FMT(XBGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ),
|
||||||
|
FMT(ABGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ),
|
||||||
|
FMT(RGBX8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ),
|
||||||
|
FMT(RGBA8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ),
|
||||||
|
FMT(BGRX8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ),
|
||||||
|
FMT(BGRA8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ),
|
||||||
|
FMT(XRGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ),
|
||||||
|
FMT(ARGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ),
|
||||||
|
FMT(XBGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ),
|
||||||
|
FMT(ABGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ),
|
||||||
|
FMT(RGBX1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ),
|
||||||
|
FMT(RGBA1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ),
|
||||||
|
FMT(BGRX1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ),
|
||||||
|
FMT(BGRA1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ),
|
||||||
|
|
||||||
|
/* 64 bpp formats */
|
||||||
|
FMT(XRGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ),
|
||||||
|
FMT(ARGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ),
|
||||||
|
FMT(XBGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ),
|
||||||
|
FMT(ABGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ),
|
||||||
|
FMT(XRGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ),
|
||||||
|
FMT(ARGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ),
|
||||||
|
FMT(XBGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ),
|
||||||
|
FMT(ABGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ),
|
||||||
|
};
|
||||||
|
|
||||||
static int running = 1;
|
static int running = 1;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -151,7 +229,8 @@ static const struct wl_buffer_listener buffer_listener = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format)
|
create_shm_buffer(struct window *window, struct buffer *buffer,
|
||||||
|
const struct format *format)
|
||||||
{
|
{
|
||||||
struct wl_shm_pool *pool;
|
struct wl_shm_pool *pool;
|
||||||
int fd, size, stride;
|
int fd, size, stride;
|
||||||
|
|
@ -161,7 +240,7 @@ create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format)
|
||||||
|
|
||||||
width = window->width;
|
width = window->width;
|
||||||
height = window->height;
|
height = window->height;
|
||||||
stride = width * 4;
|
stride = width * (format->bpp / 8);
|
||||||
size = stride * height;
|
size = stride * height;
|
||||||
display = window->display;
|
display = window->display;
|
||||||
|
|
||||||
|
|
@ -182,7 +261,7 @@ create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format)
|
||||||
pool = wl_shm_create_pool(display->shm, fd, size);
|
pool = wl_shm_create_pool(display->shm, fd, size);
|
||||||
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
|
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
|
||||||
width, height,
|
width, height,
|
||||||
stride, format);
|
stride, format->code);
|
||||||
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
|
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
|
||||||
wl_shm_pool_destroy(pool);
|
wl_shm_pool_destroy(pool);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
@ -219,8 +298,16 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
||||||
uint32_t serial, uint32_t time, uint32_t key,
|
uint32_t serial, uint32_t time, uint32_t key,
|
||||||
uint32_t state)
|
uint32_t state)
|
||||||
{
|
{
|
||||||
if (key == KEY_ESC && state)
|
struct display *d = data;
|
||||||
|
|
||||||
|
if (key == KEY_F11 && state) {
|
||||||
|
if (d->window->fullscreen)
|
||||||
|
xdg_toplevel_unset_fullscreen(d->window->xdg_toplevel);
|
||||||
|
else
|
||||||
|
xdg_toplevel_set_fullscreen(d->window->xdg_toplevel, NULL);
|
||||||
|
} else if (key == KEY_ESC && state) {
|
||||||
running = 0;
|
running = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -416,14 +503,16 @@ window_next_buffer(struct window *window)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!buffer->buffer) {
|
if (!buffer->buffer) {
|
||||||
ret = create_shm_buffer(window, buffer, WL_SHM_FORMAT_XRGB8888);
|
ret = create_shm_buffer(window, buffer,
|
||||||
|
window->display->format);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* paint the padding */
|
/* paint the padding */
|
||||||
memset(buffer->shm_data, 0xff,
|
memset(buffer->shm_data, 0xff,
|
||||||
window->width * window->height * 4);
|
window->width * window->height *
|
||||||
|
(window->display->format->bpp / 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
@ -475,6 +564,122 @@ paint_pixels(void *image, int padding, int width, int height, uint32_t time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paint_format(void *image, const struct format *format, int width, int height)
|
||||||
|
{
|
||||||
|
uint64_t *img64 = (uint64_t*) image;
|
||||||
|
uint32_t *img32 = (uint32_t*) image;
|
||||||
|
uint16_t *img16 = (uint16_t*) image;
|
||||||
|
uint8_t *img8 = (uint8_t*) image;
|
||||||
|
uint64_t color;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
#define GET_COLOR(y) \
|
||||||
|
(y < (1 * (height / 4))) ? format->color[0] : \
|
||||||
|
(y < (2 * (height / 4))) ? format->color[1] : \
|
||||||
|
(y < (3 * (height / 4))) ? format->color[2] : \
|
||||||
|
format->color[3]
|
||||||
|
|
||||||
|
switch (format->code) {
|
||||||
|
case WL_SHM_FORMAT_R8:
|
||||||
|
for (i = 0; i < height; i++) {
|
||||||
|
color = GET_COLOR(i);
|
||||||
|
for (j = 0; j < width; j++)
|
||||||
|
img8[i * width + j] = color;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WL_SHM_FORMAT_R16:
|
||||||
|
case WL_SHM_FORMAT_GR88:
|
||||||
|
case WL_SHM_FORMAT_RG88:
|
||||||
|
case WL_SHM_FORMAT_RGB565:
|
||||||
|
case WL_SHM_FORMAT_BGR565:
|
||||||
|
case WL_SHM_FORMAT_XRGB4444:
|
||||||
|
case WL_SHM_FORMAT_ARGB4444:
|
||||||
|
case WL_SHM_FORMAT_XBGR4444:
|
||||||
|
case WL_SHM_FORMAT_ABGR4444:
|
||||||
|
case WL_SHM_FORMAT_RGBX4444:
|
||||||
|
case WL_SHM_FORMAT_RGBA4444:
|
||||||
|
case WL_SHM_FORMAT_BGRX4444:
|
||||||
|
case WL_SHM_FORMAT_BGRA4444:
|
||||||
|
case WL_SHM_FORMAT_XRGB1555:
|
||||||
|
case WL_SHM_FORMAT_ARGB1555:
|
||||||
|
case WL_SHM_FORMAT_XBGR1555:
|
||||||
|
case WL_SHM_FORMAT_ABGR1555:
|
||||||
|
case WL_SHM_FORMAT_RGBX5551:
|
||||||
|
case WL_SHM_FORMAT_RGBA5551:
|
||||||
|
case WL_SHM_FORMAT_BGRX5551:
|
||||||
|
case WL_SHM_FORMAT_BGRA5551:
|
||||||
|
for (i = 0; i < height; i++) {
|
||||||
|
color = GET_COLOR(i);
|
||||||
|
for (j = 0; j < width; j++)
|
||||||
|
img16[i * width + j] = color;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WL_SHM_FORMAT_RGB888:
|
||||||
|
case WL_SHM_FORMAT_BGR888:
|
||||||
|
for (i = 0; i < height; i++) {
|
||||||
|
color = GET_COLOR(i);
|
||||||
|
for (j = 0; j < width; j++) {
|
||||||
|
img8[(i * width + j) * 3 + 0] =
|
||||||
|
(color >> 0) & 0xff;
|
||||||
|
img8[(i * width + j) * 3 + 1] =
|
||||||
|
(color >> 8) & 0xff;
|
||||||
|
img8[(i * width + j) * 3 + 2] =
|
||||||
|
(color >> 16) & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WL_SHM_FORMAT_GR1616:
|
||||||
|
case WL_SHM_FORMAT_RG1616:
|
||||||
|
case WL_SHM_FORMAT_XRGB8888:
|
||||||
|
case WL_SHM_FORMAT_ARGB8888:
|
||||||
|
case WL_SHM_FORMAT_XBGR8888:
|
||||||
|
case WL_SHM_FORMAT_ABGR8888:
|
||||||
|
case WL_SHM_FORMAT_RGBX8888:
|
||||||
|
case WL_SHM_FORMAT_RGBA8888:
|
||||||
|
case WL_SHM_FORMAT_BGRX8888:
|
||||||
|
case WL_SHM_FORMAT_BGRA8888:
|
||||||
|
case WL_SHM_FORMAT_XRGB2101010:
|
||||||
|
case WL_SHM_FORMAT_ARGB2101010:
|
||||||
|
case WL_SHM_FORMAT_XBGR2101010:
|
||||||
|
case WL_SHM_FORMAT_ABGR2101010:
|
||||||
|
case WL_SHM_FORMAT_RGBX1010102:
|
||||||
|
case WL_SHM_FORMAT_RGBA1010102:
|
||||||
|
case WL_SHM_FORMAT_BGRX1010102:
|
||||||
|
case WL_SHM_FORMAT_BGRA1010102:
|
||||||
|
for (i = 0; i < height; i++) {
|
||||||
|
color = GET_COLOR(i);
|
||||||
|
for (j = 0; j < width; j++)
|
||||||
|
img32[i * width + j] = color;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WL_SHM_FORMAT_XRGB16161616:
|
||||||
|
case WL_SHM_FORMAT_ARGB16161616:
|
||||||
|
case WL_SHM_FORMAT_XBGR16161616:
|
||||||
|
case WL_SHM_FORMAT_ABGR16161616:
|
||||||
|
case WL_SHM_FORMAT_XRGB16161616F:
|
||||||
|
case WL_SHM_FORMAT_ARGB16161616F:
|
||||||
|
case WL_SHM_FORMAT_XBGR16161616F:
|
||||||
|
case WL_SHM_FORMAT_ABGR16161616F:
|
||||||
|
for (i = 0; i < height; i++) {
|
||||||
|
color = GET_COLOR(i);
|
||||||
|
for (j = 0; j < width; j++)
|
||||||
|
img64[i * width + j] = color;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef GET_COLOR
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wl_callback_listener frame_listener;
|
static const struct wl_callback_listener frame_listener;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -493,7 +698,12 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
paint_pixels(buffer->shm_data, 20, window->width, window->height, time);
|
if (window->display->paint_format)
|
||||||
|
paint_format(buffer->shm_data, window->display->format,
|
||||||
|
window->width, window->height);
|
||||||
|
else
|
||||||
|
paint_pixels(buffer->shm_data, 20, window->width,
|
||||||
|
window->height, time);
|
||||||
|
|
||||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||||
wl_surface_damage(window->surface,
|
wl_surface_damage(window->surface,
|
||||||
|
|
@ -517,8 +727,8 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
|
||||||
{
|
{
|
||||||
struct display *d = data;
|
struct display *d = data;
|
||||||
|
|
||||||
if (format == WL_SHM_FORMAT_XRGB8888)
|
if (format == d->format->code)
|
||||||
d->has_xrgb = true;
|
d->has_format = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wl_shm_listener shm_listener = {
|
struct wl_shm_listener shm_listener = {
|
||||||
|
|
@ -572,7 +782,7 @@ static const struct wl_registry_listener registry_listener = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct display *
|
static struct display *
|
||||||
create_display(void)
|
create_display(const struct format *format, bool paint_format)
|
||||||
{
|
{
|
||||||
struct display *display;
|
struct display *display;
|
||||||
|
|
||||||
|
|
@ -584,7 +794,9 @@ create_display(void)
|
||||||
display->display = wl_display_connect(NULL);
|
display->display = wl_display_connect(NULL);
|
||||||
assert(display->display);
|
assert(display->display);
|
||||||
|
|
||||||
display->has_xrgb = false;
|
display->format = format;
|
||||||
|
display->paint_format = paint_format;
|
||||||
|
display->has_format= false;
|
||||||
display->registry = wl_display_get_registry(display->display);
|
display->registry = wl_display_get_registry(display->display);
|
||||||
wl_registry_add_listener(display->registry,
|
wl_registry_add_listener(display->registry,
|
||||||
®istry_listener, display);
|
®istry_listener, display);
|
||||||
|
|
@ -636,8 +848,9 @@ create_display(void)
|
||||||
* technique.
|
* technique.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!display->has_xrgb) {
|
if (!display->has_format) {
|
||||||
fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
|
fprintf(stderr, "Format '%s' not supported by compositor.\n",
|
||||||
|
format->string);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -668,19 +881,86 @@ signal_int(int signum)
|
||||||
running = 0;
|
running = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(const char *program)
|
||||||
|
{
|
||||||
|
fprintf(stdout,
|
||||||
|
"Usage: %s [OPTIONS]\n"
|
||||||
|
"\n"
|
||||||
|
"Draw pixels into shared memory buffers using wl_shm\n"
|
||||||
|
"\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -h, --help Show this help\n"
|
||||||
|
" -F, --format <format> Test format (see list below)\n"
|
||||||
|
"\n"
|
||||||
|
"RGB formats:\n"
|
||||||
|
" - 8 bpp: r8.\n"
|
||||||
|
"\n"
|
||||||
|
" - 16 bpp: r16, gr88, rg88, rgb565, bgr565, xrgb4444, argb4444, xbgr4444,\n"
|
||||||
|
" abgr4444, rgbx4444, rgba4444, bgrx4444, bgra4444, xrgb1555,\n"
|
||||||
|
" argb1555, xbgr1555, abgr1555, rgbx5551, rgba5551, bgrx5551,\n"
|
||||||
|
" bgra5551.\n"
|
||||||
|
"\n"
|
||||||
|
" - 24 bpp: rgb888, bgr888.\n"
|
||||||
|
"\n"
|
||||||
|
" - 32 bpp: gr1616, rg1616, xrgb8888, argb8888, xbgr8888, abgr8888, rgbx8888,\n"
|
||||||
|
" rgba8888, bgrx8888, bgra8888, xrgb2101010, argb2101010, xbgr2101010,\n"
|
||||||
|
" abgr2101010, rgbx1010102, rgba1010102, bgrx1010102, bgra1010102.\n"
|
||||||
|
"\n"
|
||||||
|
" - 64 bpp: xrgb16161616, argb16161616, xbgr16161616, abgr16161616,\n"
|
||||||
|
" xrgb16161616f, argb16161616f, xbgr16161616f, abgr16161616f.\n",
|
||||||
|
program);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct sigaction sigint;
|
struct sigaction sigint;
|
||||||
struct display *display;
|
struct display *display;
|
||||||
struct window *window;
|
struct window *window;
|
||||||
int ret = 0;
|
const struct format *format = NULL;
|
||||||
|
bool paint_format = false;
|
||||||
|
const char *value;
|
||||||
|
int ret = 0, i, j;
|
||||||
|
|
||||||
display = create_display();
|
for (i = 1; i < argc; i++) {
|
||||||
window = create_window(display, 250, 250);
|
if (!strcmp(argv[i], "-h") ||
|
||||||
|
!strcmp(argv[i], "--help")) {
|
||||||
|
usage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
} else if (!strcmp(argv[i], "-F") ||
|
||||||
|
!strcmp(argv[i], "--format")) {
|
||||||
|
value = ++i == argc ? "" : argv[i];
|
||||||
|
for (j = 0; j < (int) ARRAY_SIZE(shm_formats); j++) {
|
||||||
|
if (!strcasecmp(shm_formats[j].string, value)) {
|
||||||
|
format = &shm_formats[j];
|
||||||
|
paint_format = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!format) {
|
||||||
|
fprintf(stderr, "Format '%s' not supported by "
|
||||||
|
"client.\n", value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!format)
|
||||||
|
for (i = 0; i < (int) ARRAY_SIZE(shm_formats); i++)
|
||||||
|
if (shm_formats[i].code == WL_SHM_FORMAT_XRGB8888)
|
||||||
|
format = &shm_formats[i];
|
||||||
|
assert(format);
|
||||||
|
|
||||||
|
display = create_display(format, paint_format);
|
||||||
|
window = create_window(display, 256, 256);
|
||||||
if (!window)
|
if (!window)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
display->window = window;
|
||||||
sigint.sa_handler = signal_int;
|
sigint.sa_handler = signal_int;
|
||||||
sigemptyset(&sigint.sa_mask);
|
sigemptyset(&sigint.sa_mask);
|
||||||
sigint.sa_flags = SA_RESETHAND;
|
sigint.sa_flags = SA_RESETHAND;
|
||||||
|
|
|
||||||
885
clients/simple-timing.c
Normal file
885
clients/simple-timing.c
Normal file
|
|
@ -0,0 +1,885 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2011 Benjamin Franzke
|
||||||
|
* Copyright © 2010 Intel Corporation
|
||||||
|
* Copyright © 2025 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include "shared/os-compatibility.h"
|
||||||
|
#include "shared/timespec-util.h"
|
||||||
|
#include "shared/xalloc.h"
|
||||||
|
#include <libweston/zalloc.h>
|
||||||
|
#include "xdg-shell-client-protocol.h"
|
||||||
|
|
||||||
|
#include "commit-timing-v1-client-protocol.h"
|
||||||
|
#include "fifo-v1-client-protocol.h"
|
||||||
|
#include "presentation-time-client-protocol.h"
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||||
|
|
||||||
|
#define MAX_BUFFER_ALLOC 1000
|
||||||
|
|
||||||
|
struct display {
|
||||||
|
struct wl_display *display;
|
||||||
|
struct wl_registry *registry;
|
||||||
|
struct wl_compositor *compositor;
|
||||||
|
struct xdg_wm_base *wm_base;
|
||||||
|
struct wl_seat *seat;
|
||||||
|
struct wl_keyboard *keyboard;
|
||||||
|
struct wl_shm *shm;
|
||||||
|
struct wp_commit_timing_manager_v1 *commit_timing_manager;
|
||||||
|
struct wp_fifo_manager_v1 *fifo_manager;
|
||||||
|
struct wp_presentation *presentation;
|
||||||
|
bool have_clock_id;
|
||||||
|
clockid_t presentation_clock_id;
|
||||||
|
int64_t first_frame_time;
|
||||||
|
int64_t refresh_nsec;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct buffer {
|
||||||
|
struct window *window;
|
||||||
|
struct wl_buffer *buffer;
|
||||||
|
void *shm_data;
|
||||||
|
int busy;
|
||||||
|
int width, height;
|
||||||
|
size_t size; /* width * 4 * height */
|
||||||
|
struct wl_list buffer_link; /** window::buffer_list */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct window {
|
||||||
|
struct display *display;
|
||||||
|
int width, height;
|
||||||
|
int init_width, init_height;
|
||||||
|
struct wl_surface *surface;
|
||||||
|
struct xdg_surface *xdg_surface;
|
||||||
|
struct xdg_toplevel *xdg_toplevel;
|
||||||
|
struct wl_list buffer_list;
|
||||||
|
struct wl_callback *callback;
|
||||||
|
struct wp_fifo_v1 *fifo;
|
||||||
|
struct wp_commit_timer_v1 *commit_timer;
|
||||||
|
bool wait_for_configure;
|
||||||
|
bool maximized;
|
||||||
|
bool fullscreen;
|
||||||
|
bool needs_update_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct feedback {
|
||||||
|
struct wp_presentation_feedback *fb;
|
||||||
|
struct window *window;
|
||||||
|
int64_t target_time;
|
||||||
|
bool final;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int running = 1;
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw_for_time(void *data, int64_t time, bool wait_fifo);
|
||||||
|
|
||||||
|
static void
|
||||||
|
finish_run(struct window *window);
|
||||||
|
|
||||||
|
static struct buffer *
|
||||||
|
alloc_buffer(struct window *window, int width, int height)
|
||||||
|
{
|
||||||
|
struct buffer *buffer = calloc(1, sizeof(*buffer));
|
||||||
|
|
||||||
|
buffer->width = width;
|
||||||
|
buffer->height = height;
|
||||||
|
wl_list_insert(&window->buffer_list, &buffer->buffer_link);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_buffer(struct buffer *buffer)
|
||||||
|
{
|
||||||
|
if (buffer->buffer)
|
||||||
|
wl_buffer_destroy(buffer->buffer);
|
||||||
|
|
||||||
|
munmap(buffer->shm_data, buffer->size);
|
||||||
|
wl_list_remove(&buffer->buffer_link);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buffer *
|
||||||
|
pick_free_buffer(struct window *window)
|
||||||
|
{
|
||||||
|
struct buffer *b;
|
||||||
|
struct buffer *buffer = NULL;
|
||||||
|
|
||||||
|
wl_list_for_each(b, &window->buffer_list, buffer_link) {
|
||||||
|
if (!b->busy) {
|
||||||
|
buffer = b;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
prune_old_released_buffers(struct window *window)
|
||||||
|
{
|
||||||
|
struct buffer *b, *b_next;
|
||||||
|
|
||||||
|
wl_list_for_each_safe(b, b_next,
|
||||||
|
&window->buffer_list, buffer_link) {
|
||||||
|
if (!b->busy && (b->width != window->width ||
|
||||||
|
b->height != window->height))
|
||||||
|
destroy_buffer(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_release(void *data, struct wl_buffer *buffer)
|
||||||
|
{
|
||||||
|
struct buffer *mybuf = data;
|
||||||
|
|
||||||
|
mybuf->busy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_buffer_listener buffer_listener = {
|
||||||
|
buffer_release
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
create_shm_buffer(struct window *window, struct buffer *buffer)
|
||||||
|
{
|
||||||
|
struct wl_shm_pool *pool;
|
||||||
|
int fd, size, stride;
|
||||||
|
void *data;
|
||||||
|
int width, height;
|
||||||
|
struct display *display;
|
||||||
|
|
||||||
|
width = window->width;
|
||||||
|
height = window->height;
|
||||||
|
stride = width * 4;
|
||||||
|
size = stride * height;
|
||||||
|
display = window->display;
|
||||||
|
|
||||||
|
fd = os_create_anonymous_file(size);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
|
||||||
|
size, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
if (data == MAP_FAILED) {
|
||||||
|
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool = wl_shm_create_pool(display->shm, fd, size);
|
||||||
|
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
|
||||||
|
width, height,
|
||||||
|
stride,
|
||||||
|
WL_SHM_FORMAT_XRGB8888);
|
||||||
|
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
|
||||||
|
wl_shm_pool_destroy(pool);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
buffer->size = size;
|
||||||
|
buffer->shm_data = data;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t format, int fd, uint32_t size)
|
||||||
|
{
|
||||||
|
/* Just so we don’t leak the keymap fd */
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, struct wl_surface *surface,
|
||||||
|
struct wl_array *keys)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, struct wl_surface *surface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, uint32_t time, uint32_t key,
|
||||||
|
uint32_t state)
|
||||||
|
{
|
||||||
|
if (key == KEY_ESC && state)
|
||||||
|
running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
|
||||||
|
uint32_t serial, uint32_t mods_depressed,
|
||||||
|
uint32_t mods_latched, uint32_t mods_locked,
|
||||||
|
uint32_t group)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_keyboard_listener keyboard_listener = {
|
||||||
|
keyboard_handle_keymap,
|
||||||
|
keyboard_handle_enter,
|
||||||
|
keyboard_handle_leave,
|
||||||
|
keyboard_handle_key,
|
||||||
|
keyboard_handle_modifiers,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
seat_handle_capabilities(void *data, struct wl_seat *seat,
|
||||||
|
enum wl_seat_capability caps)
|
||||||
|
{
|
||||||
|
struct display *d = data;
|
||||||
|
|
||||||
|
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
|
||||||
|
d->keyboard = wl_seat_get_keyboard(seat);
|
||||||
|
wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
|
||||||
|
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
|
||||||
|
wl_keyboard_destroy(d->keyboard);
|
||||||
|
d->keyboard = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_seat_listener seat_listener = {
|
||||||
|
seat_handle_capabilities,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
|
||||||
|
uint32_t serial)
|
||||||
|
{
|
||||||
|
struct window *window = data;
|
||||||
|
|
||||||
|
xdg_surface_ack_configure(surface, serial);
|
||||||
|
|
||||||
|
if (window->wait_for_configure) {
|
||||||
|
draw_for_time(window, 0, false);
|
||||||
|
window->wait_for_configure = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||||
|
handle_xdg_surface_configure,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
||||||
|
int32_t width, int32_t height,
|
||||||
|
struct wl_array *states)
|
||||||
|
{
|
||||||
|
struct window *window = data;
|
||||||
|
uint32_t *p;
|
||||||
|
|
||||||
|
window->fullscreen = false;
|
||||||
|
window->maximized = false;
|
||||||
|
|
||||||
|
wl_array_for_each(p, states) {
|
||||||
|
uint32_t state = *p;
|
||||||
|
switch (state) {
|
||||||
|
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
||||||
|
window->fullscreen = true;
|
||||||
|
break;
|
||||||
|
case XDG_TOPLEVEL_STATE_MAXIMIZED:
|
||||||
|
window->maximized = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width > 0 && height > 0) {
|
||||||
|
if (!window->fullscreen && !window->maximized) {
|
||||||
|
window->init_width = width;
|
||||||
|
window->init_height = height;
|
||||||
|
}
|
||||||
|
window->width = width;
|
||||||
|
window->height = height;
|
||||||
|
} else if (!window->fullscreen && !window->maximized) {
|
||||||
|
window->width = window->init_width;
|
||||||
|
window->height = window->init_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->needs_update_buffer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
|
||||||
|
{
|
||||||
|
running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
||||||
|
handle_xdg_toplevel_configure,
|
||||||
|
handle_xdg_toplevel_close,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct window *
|
||||||
|
create_window(struct display *display, int width, int height)
|
||||||
|
{
|
||||||
|
struct window *window;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
window = zalloc(sizeof *window);
|
||||||
|
if (!window)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
window->callback = NULL;
|
||||||
|
window->display = display;
|
||||||
|
window->width = width;
|
||||||
|
window->height = height;
|
||||||
|
window->init_width = width;
|
||||||
|
window->init_height = height;
|
||||||
|
window->surface = wl_compositor_create_surface(display->compositor);
|
||||||
|
window->fifo = wp_fifo_manager_v1_get_fifo(display->fifo_manager,
|
||||||
|
window->surface);
|
||||||
|
window->commit_timer = wp_commit_timing_manager_v1_get_timer(display->commit_timing_manager,
|
||||||
|
window->surface);
|
||||||
|
window->needs_update_buffer = false;
|
||||||
|
wl_list_init(&window->buffer_list);
|
||||||
|
|
||||||
|
assert(display->wm_base);
|
||||||
|
|
||||||
|
window->xdg_surface =
|
||||||
|
xdg_wm_base_get_xdg_surface(display->wm_base,
|
||||||
|
window->surface);
|
||||||
|
assert(window->xdg_surface);
|
||||||
|
xdg_surface_add_listener(window->xdg_surface,
|
||||||
|
&xdg_surface_listener, window);
|
||||||
|
|
||||||
|
window->xdg_toplevel =
|
||||||
|
xdg_surface_get_toplevel(window->xdg_surface);
|
||||||
|
assert(window->xdg_toplevel);
|
||||||
|
xdg_toplevel_add_listener(window->xdg_toplevel,
|
||||||
|
&xdg_toplevel_listener, window);
|
||||||
|
|
||||||
|
xdg_toplevel_set_title(window->xdg_toplevel, "simple-shm");
|
||||||
|
xdg_toplevel_set_app_id(window->xdg_toplevel,
|
||||||
|
"org.freedesktop.weston.simple-shm");
|
||||||
|
|
||||||
|
wl_surface_commit(window->surface);
|
||||||
|
window->wait_for_configure = true;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
|
||||||
|
alloc_buffer(window, window->width, window->height);
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_window(struct window *window)
|
||||||
|
{
|
||||||
|
struct buffer *buffer, *buffer_next;
|
||||||
|
|
||||||
|
if (window->callback)
|
||||||
|
wl_callback_destroy(window->callback);
|
||||||
|
|
||||||
|
wl_list_for_each_safe(buffer, buffer_next,
|
||||||
|
&window->buffer_list, buffer_link)
|
||||||
|
destroy_buffer(buffer);
|
||||||
|
|
||||||
|
if (window->xdg_toplevel)
|
||||||
|
xdg_toplevel_destroy(window->xdg_toplevel);
|
||||||
|
if (window->xdg_surface)
|
||||||
|
xdg_surface_destroy(window->xdg_surface);
|
||||||
|
wl_surface_destroy(window->surface);
|
||||||
|
|
||||||
|
if (window->fifo)
|
||||||
|
wp_fifo_v1_destroy(window->fifo);
|
||||||
|
|
||||||
|
if (window->commit_timer)
|
||||||
|
wp_commit_timer_v1_destroy(window->commit_timer);
|
||||||
|
|
||||||
|
free(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct buffer *
|
||||||
|
window_next_buffer(struct window *window)
|
||||||
|
{
|
||||||
|
struct buffer *buffer = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (window->needs_update_buffer) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
|
||||||
|
alloc_buffer(window, window->width, window->height);
|
||||||
|
|
||||||
|
window->needs_update_buffer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = pick_free_buffer(window);
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!buffer->buffer) {
|
||||||
|
ret = create_shm_buffer(window, buffer);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* paint the padding */
|
||||||
|
memset(buffer->shm_data, 0xff,
|
||||||
|
window->width * window->height * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paint_pixels(void *image, int width, int height, uint32_t time)
|
||||||
|
{
|
||||||
|
const int halfh = height / 2;
|
||||||
|
const int halfw = width / 2;
|
||||||
|
int ir, or;
|
||||||
|
uint32_t *pixel = image;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
/* squared radii thresholds */
|
||||||
|
or = (halfw < halfh ? halfw : halfh) - 8;
|
||||||
|
ir = or - 32;
|
||||||
|
or *= or;
|
||||||
|
ir *= ir;
|
||||||
|
|
||||||
|
for (y = 0; y < height; y++) {
|
||||||
|
int x;
|
||||||
|
int y2 = (y - halfh) * (y - halfh);
|
||||||
|
|
||||||
|
for (x = 0; x < width; x++) {
|
||||||
|
uint32_t v;
|
||||||
|
|
||||||
|
/* squared distance from center */
|
||||||
|
int r2 = (x - halfw) * (x - halfw) + y2;
|
||||||
|
|
||||||
|
if (r2 < ir)
|
||||||
|
v = (r2 / 32 + time / 64) * 0x0080401;
|
||||||
|
else if (r2 < or)
|
||||||
|
v = (y + time / 32) * 0x0080401;
|
||||||
|
else
|
||||||
|
v = (x + time / 16) * 0x0080401;
|
||||||
|
v &= 0x00ffffff;
|
||||||
|
|
||||||
|
/* cross if compositor uses X from XRGB as alpha */
|
||||||
|
if (abs(x - y) > 6 && abs(x + y - height) > 6)
|
||||||
|
v |= 0xff000000;
|
||||||
|
|
||||||
|
*pixel++ = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
queue_some_frames(struct window *window)
|
||||||
|
{
|
||||||
|
struct display *display = window->display;
|
||||||
|
int64_t target_nsec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(display->first_frame_time);
|
||||||
|
|
||||||
|
/* Round off error will cause us problems if we don't
|
||||||
|
* reduce this a bit, because we could end up rounding
|
||||||
|
* to either side of a refresh.
|
||||||
|
*/
|
||||||
|
target_nsec = display->first_frame_time - 100000;
|
||||||
|
|
||||||
|
for (i = 0; i < 60; i++) {
|
||||||
|
target_nsec += display->refresh_nsec * 2;
|
||||||
|
draw_for_time(window, target_nsec, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 30; i++) {
|
||||||
|
target_nsec += display->refresh_nsec * 4;
|
||||||
|
draw_for_time(window, target_nsec, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
target_nsec += display->refresh_nsec * 10;
|
||||||
|
draw_for_time(window, target_nsec, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
target_nsec += display->refresh_nsec * 100;
|
||||||
|
draw_for_time(window, target_nsec, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_run(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
feedback_sync_output(void *data,
|
||||||
|
struct wp_presentation_feedback *presentation_feedback,
|
||||||
|
struct wl_output *output)
|
||||||
|
{
|
||||||
|
/* Just don't care */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
feedback_presented(void *data,
|
||||||
|
struct wp_presentation_feedback *presentation_feedback,
|
||||||
|
uint32_t tv_sec_hi,
|
||||||
|
uint32_t tv_sec_lo,
|
||||||
|
uint32_t tv_nsec,
|
||||||
|
uint32_t refresh_nsec,
|
||||||
|
uint32_t seq_hi,
|
||||||
|
uint32_t seq_lo,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
struct feedback *feedback = data;
|
||||||
|
struct window *window = feedback->window;
|
||||||
|
struct display *display = window->display;
|
||||||
|
struct timespec pres_ts = {
|
||||||
|
.tv_sec = ((int64_t)tv_sec_hi << 32) + tv_sec_lo,
|
||||||
|
.tv_nsec = tv_nsec,
|
||||||
|
};
|
||||||
|
int64_t ntime = timespec_to_nsec(&pres_ts);
|
||||||
|
double delay;
|
||||||
|
|
||||||
|
if (feedback->final) {
|
||||||
|
running = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!feedback->target_time) {
|
||||||
|
display->first_frame_time = ntime;
|
||||||
|
display->refresh_nsec = refresh_nsec;
|
||||||
|
queue_some_frames(window);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay = (ntime - feedback->target_time) / 1000000.0;
|
||||||
|
|
||||||
|
printf("%fms away from intended time\n", delay);
|
||||||
|
if (fabs(delay) > display->refresh_nsec / 1000000)
|
||||||
|
printf("Warning: we missed the intended target display cycle.\n");
|
||||||
|
|
||||||
|
out:
|
||||||
|
wp_presentation_feedback_destroy(feedback->fb);
|
||||||
|
free(feedback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
feedback_discarded(void *data,
|
||||||
|
struct wp_presentation_feedback *presentation_feedback)
|
||||||
|
{
|
||||||
|
struct feedback *feedback = data;
|
||||||
|
|
||||||
|
printf("Warning: a frame was discarded\n");
|
||||||
|
|
||||||
|
if (feedback->final)
|
||||||
|
running = 0;
|
||||||
|
|
||||||
|
wp_presentation_feedback_destroy(feedback->fb);
|
||||||
|
free(feedback);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_presentation_feedback_listener feedback_listener = {
|
||||||
|
feedback_sync_output,
|
||||||
|
feedback_presented,
|
||||||
|
feedback_discarded,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
finish_run(struct window *window)
|
||||||
|
{
|
||||||
|
struct display *display = window->display;
|
||||||
|
struct feedback *feedback;
|
||||||
|
struct buffer *buffer;
|
||||||
|
|
||||||
|
feedback = xzalloc(sizeof *feedback);
|
||||||
|
feedback->window = window;
|
||||||
|
feedback->final = true;
|
||||||
|
feedback->target_time = 0;
|
||||||
|
|
||||||
|
buffer = window_next_buffer(window);
|
||||||
|
assert(buffer);
|
||||||
|
|
||||||
|
paint_pixels(buffer->shm_data, window->width,
|
||||||
|
window->height, 1);
|
||||||
|
|
||||||
|
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||||
|
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||||
|
|
||||||
|
feedback->fb = wp_presentation_feedback(display->presentation,
|
||||||
|
window->surface);
|
||||||
|
wp_presentation_feedback_add_listener(feedback->fb,
|
||||||
|
&feedback_listener, feedback);
|
||||||
|
|
||||||
|
wp_fifo_v1_wait_barrier(window->fifo);
|
||||||
|
wl_surface_commit(window->surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw_for_time(void *data, int64_t time, bool wait_fifo)
|
||||||
|
{
|
||||||
|
struct window *window = data;
|
||||||
|
struct display *display = window->display;
|
||||||
|
struct buffer *buffer;
|
||||||
|
struct feedback *feedback;
|
||||||
|
|
||||||
|
assert(display->have_clock_id);
|
||||||
|
|
||||||
|
prune_old_released_buffers(window);
|
||||||
|
|
||||||
|
buffer = window_next_buffer(window);
|
||||||
|
assert(buffer);
|
||||||
|
|
||||||
|
paint_pixels(buffer->shm_data, window->width,
|
||||||
|
window->height, time / 1000000);
|
||||||
|
|
||||||
|
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||||
|
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||||
|
|
||||||
|
feedback = xzalloc(sizeof *feedback);
|
||||||
|
feedback->window = window;
|
||||||
|
|
||||||
|
feedback->fb = wp_presentation_feedback(display->presentation,
|
||||||
|
window->surface);
|
||||||
|
wp_presentation_feedback_add_listener(feedback->fb,
|
||||||
|
&feedback_listener, feedback);
|
||||||
|
|
||||||
|
feedback->target_time = time;
|
||||||
|
if (time) {
|
||||||
|
struct timespec target;
|
||||||
|
|
||||||
|
timespec_from_nsec(&target, time);
|
||||||
|
wp_commit_timer_v1_set_timestamp(window->commit_timer,
|
||||||
|
(int64_t)target.tv_sec >> 32,
|
||||||
|
target.tv_sec,
|
||||||
|
target.tv_nsec);
|
||||||
|
}
|
||||||
|
wp_fifo_v1_set_barrier(window->fifo);
|
||||||
|
wl_surface_commit(window->surface);
|
||||||
|
buffer->busy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
|
||||||
|
{
|
||||||
|
xdg_wm_base_pong(shell, serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
||||||
|
xdg_wm_base_ping,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
presentation_handle_clock_id(void *data,
|
||||||
|
struct wp_presentation *wp_presentation,
|
||||||
|
uint32_t clock_id)
|
||||||
|
{
|
||||||
|
struct display *display = data;
|
||||||
|
|
||||||
|
display->presentation_clock_id = clock_id;
|
||||||
|
display->have_clock_id = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_presentation_listener presentation_listener = {
|
||||||
|
presentation_handle_clock_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
registry_handle_global(void *data, struct wl_registry *registry,
|
||||||
|
uint32_t id, const char *interface, uint32_t version)
|
||||||
|
{
|
||||||
|
struct display *d = data;
|
||||||
|
|
||||||
|
if (strcmp(interface, "wl_compositor") == 0) {
|
||||||
|
d->compositor =
|
||||||
|
wl_registry_bind(registry,
|
||||||
|
id, &wl_compositor_interface, 1);
|
||||||
|
} else if (strcmp(interface, "xdg_wm_base") == 0) {
|
||||||
|
d->wm_base = wl_registry_bind(registry,
|
||||||
|
id, &xdg_wm_base_interface, 1);
|
||||||
|
xdg_wm_base_add_listener(d->wm_base, &xdg_wm_base_listener, d);
|
||||||
|
} else if (strcmp(interface, "wl_seat") == 0) {
|
||||||
|
d->seat = wl_registry_bind(registry, id,
|
||||||
|
&wl_seat_interface, 1);
|
||||||
|
wl_seat_add_listener(d->seat, &seat_listener, d);
|
||||||
|
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||||
|
d->shm = wl_registry_bind(registry,
|
||||||
|
id, &wl_shm_interface, 1);
|
||||||
|
} else if (strcmp(interface, wp_commit_timing_manager_v1_interface.name) == 0) {
|
||||||
|
d->commit_timing_manager = wl_registry_bind(registry, id,
|
||||||
|
&wp_commit_timing_manager_v1_interface,
|
||||||
|
1);
|
||||||
|
} else if (strcmp(interface, wp_fifo_manager_v1_interface.name) == 0) {
|
||||||
|
d->fifo_manager = wl_registry_bind(registry, id,
|
||||||
|
&wp_fifo_manager_v1_interface,
|
||||||
|
1);
|
||||||
|
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
|
||||||
|
d->presentation = wl_registry_bind(registry, id,
|
||||||
|
&wp_presentation_interface,
|
||||||
|
2);
|
||||||
|
wp_presentation_add_listener(d->presentation,
|
||||||
|
&presentation_listener, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
registry_handle_global_remove(void *data, struct wl_registry *registry,
|
||||||
|
uint32_t name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_registry_listener registry_listener = {
|
||||||
|
registry_handle_global,
|
||||||
|
registry_handle_global_remove
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct display *
|
||||||
|
create_display(void)
|
||||||
|
{
|
||||||
|
struct display *display;
|
||||||
|
|
||||||
|
display = xzalloc(sizeof *display);
|
||||||
|
|
||||||
|
display->display = wl_display_connect(NULL);
|
||||||
|
assert(display->display);
|
||||||
|
|
||||||
|
display->registry = wl_display_get_registry(display->display);
|
||||||
|
wl_registry_add_listener(display->registry,
|
||||||
|
®istry_listener, display);
|
||||||
|
wl_display_roundtrip(display->display);
|
||||||
|
if (display->shm == NULL) {
|
||||||
|
fprintf(stderr, "No wl_shm global\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_display_roundtrip(display->display);
|
||||||
|
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_display(struct display *display)
|
||||||
|
{
|
||||||
|
if (display->shm)
|
||||||
|
wl_shm_destroy(display->shm);
|
||||||
|
|
||||||
|
if (display->wm_base)
|
||||||
|
xdg_wm_base_destroy(display->wm_base);
|
||||||
|
|
||||||
|
if (display->compositor)
|
||||||
|
wl_compositor_destroy(display->compositor);
|
||||||
|
|
||||||
|
if (display->presentation)
|
||||||
|
wp_presentation_destroy(display->presentation);
|
||||||
|
|
||||||
|
if (display->fifo_manager)
|
||||||
|
wp_fifo_manager_v1_destroy(display->fifo_manager);
|
||||||
|
|
||||||
|
if (display->commit_timing_manager)
|
||||||
|
wp_commit_timing_manager_v1_destroy(display->commit_timing_manager);
|
||||||
|
|
||||||
|
if (display->keyboard)
|
||||||
|
wl_keyboard_destroy(display->keyboard);
|
||||||
|
|
||||||
|
if (display->seat)
|
||||||
|
wl_seat_destroy(display->seat);
|
||||||
|
|
||||||
|
wl_registry_destroy(display->registry);
|
||||||
|
wl_display_flush(display->display);
|
||||||
|
wl_display_disconnect(display->display);
|
||||||
|
free(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
signal_int(int signum)
|
||||||
|
{
|
||||||
|
running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(const char *program)
|
||||||
|
{
|
||||||
|
fprintf(stdout,
|
||||||
|
"Usage: %s [OPTIONS]\n"
|
||||||
|
"\n"
|
||||||
|
"Schedule frames in the future with commit-timing\n"
|
||||||
|
"\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -h, --help Show this help\n"
|
||||||
|
"\n",
|
||||||
|
program);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sigaction sigint;
|
||||||
|
struct display *display;
|
||||||
|
struct window *window;
|
||||||
|
int ret = 0, i;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
if (!strcmp(argv[i], "-h") ||
|
||||||
|
!strcmp(argv[i], "--help")) {
|
||||||
|
usage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
display = create_display();
|
||||||
|
window = create_window(display, 256, 256);
|
||||||
|
if (!window)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sigint.sa_handler = signal_int;
|
||||||
|
sigemptyset(&sigint.sa_mask);
|
||||||
|
sigint.sa_flags = SA_RESETHAND;
|
||||||
|
sigaction(SIGINT, &sigint, NULL);
|
||||||
|
|
||||||
|
while (running && ret != -1)
|
||||||
|
ret = wl_display_dispatch(display->display);
|
||||||
|
|
||||||
|
fprintf(stderr, "simple-timing exiting\n");
|
||||||
|
|
||||||
|
destroy_window(window);
|
||||||
|
destroy_display(display);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
2171
clients/simple-vulkan.c
Normal file
2171
clients/simple-vulkan.c
Normal file
File diff suppressed because it is too large
Load diff
9
clients/simple_dmabuf_vulkan_fragment_shader.frag
Normal file
9
clients/simple_dmabuf_vulkan_fragment_shader.frag
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 v_color;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 f_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
f_color = v_color;
|
||||||
|
}
|
||||||
17
clients/simple_dmabuf_vulkan_vertex_shader.vert
Normal file
17
clients/simple_dmabuf_vulkan_vertex_shader.vert
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(std140, set = 0, binding = 0) uniform block {
|
||||||
|
uniform mat4 reflection;
|
||||||
|
uniform float offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 pos;
|
||||||
|
layout(location = 1) in vec4 color;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 v_color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = reflection * (pos + vec4(offset, offset, 0.0, 0.0));
|
||||||
|
v_color = color;
|
||||||
|
}
|
||||||
9
clients/simple_vulkan_fragment_shader.frag
Normal file
9
clients/simple_vulkan_fragment_shader.frag
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 vVaryingColor;
|
||||||
|
layout(location = 0) out vec4 f_color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
f_color = vVaryingColor;
|
||||||
|
}
|
||||||
16
clients/simple_vulkan_vertex_shader.vert
Normal file
16
clients/simple_vulkan_vertex_shader.vert
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
layout(std140, set = 0, binding = 0) uniform block {
|
||||||
|
uniform mat4 rotation;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 in_position;
|
||||||
|
layout(location = 1) in vec4 in_color;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 vVaryingColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = rotation * in_position;
|
||||||
|
vVaryingColor = vec4(in_color.rgba);
|
||||||
|
}
|
||||||
|
|
@ -58,6 +58,7 @@ static char *option_term;
|
||||||
static char *option_shell;
|
static char *option_shell;
|
||||||
|
|
||||||
static struct wl_list terminal_list;
|
static struct wl_list terminal_list;
|
||||||
|
struct sigaction oldact;
|
||||||
|
|
||||||
static struct terminal *
|
static struct terminal *
|
||||||
terminal_create(struct display *display);
|
terminal_create(struct display *display);
|
||||||
|
|
@ -3100,6 +3101,9 @@ terminal_run(struct terminal *terminal, const char *path)
|
||||||
close(pipes[0]);
|
close(pipes[0]);
|
||||||
setenv("TERM", option_term, 1);
|
setenv("TERM", option_term, 1);
|
||||||
setenv("COLORTERM", option_term, 1);
|
setenv("COLORTERM", option_term, 1);
|
||||||
|
|
||||||
|
sigaction(SIGPIPE, &oldact, NULL);
|
||||||
|
|
||||||
if (execl(path, path, NULL)) {
|
if (execl(path, path, NULL)) {
|
||||||
printf("exec failed: %s\n", strerror(errno));
|
printf("exec failed: %s\n", strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
@ -3177,8 +3181,10 @@ int main(int argc, char *argv[])
|
||||||
* socket whose reading end has been closed */
|
* socket whose reading end has been closed */
|
||||||
sigpipe.sa_handler = SIG_IGN;
|
sigpipe.sa_handler = SIG_IGN;
|
||||||
sigemptyset(&sigpipe.sa_mask);
|
sigemptyset(&sigpipe.sa_mask);
|
||||||
|
sigemptyset(&oldact.sa_mask);
|
||||||
|
|
||||||
sigpipe.sa_flags = 0;
|
sigpipe.sa_flags = 0;
|
||||||
sigaction(SIGPIPE, &sigpipe, NULL);
|
sigaction(SIGPIPE, &sigpipe, &oldact);
|
||||||
|
|
||||||
d = display_create(&argc, argv);
|
d = display_create(&argc, argv);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
|
|
|
||||||
|
|
@ -330,9 +330,9 @@ compute_calibration(struct calibrator *cal, float *result)
|
||||||
*/
|
*/
|
||||||
weston_matrix_init(&m);
|
weston_matrix_init(&m);
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
m.d[i + 0] = cal->samples[i].touched.x;
|
m.M.col[0].el[i] = cal->samples[i].touched.x;
|
||||||
m.d[i + 4] = cal->samples[i].touched.y;
|
m.M.col[1].el[i] = cal->samples[i].touched.y;
|
||||||
m.d[i + 8] = 1.0f;
|
m.M.col[2].el[i] = 1.0f;
|
||||||
}
|
}
|
||||||
m.type = WESTON_MATRIX_TRANSFORM_OTHER;
|
m.type = WESTON_MATRIX_TRANSFORM_OTHER;
|
||||||
|
|
||||||
|
|
@ -342,20 +342,20 @@ compute_calibration(struct calibrator *cal, float *result)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
x_calib.f[i] = cal->samples[i].drawn_cal.x;
|
x_calib.v.el[i] = cal->samples[i].drawn_cal.x;
|
||||||
y_calib.f[i] = cal->samples[i].drawn_cal.y;
|
y_calib.v.el[i] = cal->samples[i].drawn_cal.y;
|
||||||
}
|
}
|
||||||
x_calib.f[3] = 0.0f;
|
x_calib.v.el[3] = 0.0f;
|
||||||
y_calib.f[3] = 0.0f;
|
y_calib.v.el[3] = 0.0f;
|
||||||
|
|
||||||
/* Multiples into the vector */
|
/* Multiples into the vector */
|
||||||
weston_matrix_transform(&inverse, &x_calib);
|
weston_matrix_transform(&inverse, &x_calib);
|
||||||
weston_matrix_transform(&inverse, &y_calib);
|
weston_matrix_transform(&inverse, &y_calib);
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
result[i] = x_calib.f[i];
|
result[i] = x_calib.v.el[i];
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
result[i + 3] = y_calib.f[i];
|
result[i + 3] = y_calib.v.el[i];
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
178
clients/window.c
178
clients/window.c
|
|
@ -44,9 +44,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE
|
|
||||||
#include <xkbcommon/xkbcommon-compose.h>
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
#endif
|
|
||||||
#include <wayland-cursor.h>
|
#include <wayland-cursor.h>
|
||||||
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
@ -57,6 +55,7 @@
|
||||||
#include <libweston/zalloc.h>
|
#include <libweston/zalloc.h>
|
||||||
#include "xdg-shell-client-protocol.h"
|
#include "xdg-shell-client-protocol.h"
|
||||||
#include "color-management-v1-client-protocol.h"
|
#include "color-management-v1-client-protocol.h"
|
||||||
|
#include "single-pixel-buffer-v1-client-protocol.h"
|
||||||
#include "text-cursor-position-client-protocol.h"
|
#include "text-cursor-position-client-protocol.h"
|
||||||
#include "pointer-constraints-unstable-v1-client-protocol.h"
|
#include "pointer-constraints-unstable-v1-client-protocol.h"
|
||||||
#include "relative-pointer-unstable-v1-client-protocol.h"
|
#include "relative-pointer-unstable-v1-client-protocol.h"
|
||||||
|
|
@ -91,10 +90,11 @@ struct display {
|
||||||
struct wl_data_device_manager *data_device_manager;
|
struct wl_data_device_manager *data_device_manager;
|
||||||
struct text_cursor_position *text_cursor_position;
|
struct text_cursor_position *text_cursor_position;
|
||||||
struct xdg_wm_base *xdg_shell;
|
struct xdg_wm_base *xdg_shell;
|
||||||
struct xx_color_manager_v4 *color_manager;
|
struct wp_color_manager_v1 *color_manager;
|
||||||
struct zwp_tablet_manager_v2 *tablet_manager;
|
struct zwp_tablet_manager_v2 *tablet_manager;
|
||||||
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
|
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
|
||||||
struct zwp_pointer_constraints_v1 *pointer_constraints;
|
struct zwp_pointer_constraints_v1 *pointer_constraints;
|
||||||
|
struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer_manager;
|
||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
|
|
||||||
uint32_t color_manager_features;
|
uint32_t color_manager_features;
|
||||||
|
|
@ -217,7 +217,7 @@ struct surface {
|
||||||
struct wl_callback *frame_cb;
|
struct wl_callback *frame_cb;
|
||||||
uint32_t last_time;
|
uint32_t last_time;
|
||||||
|
|
||||||
struct xx_color_management_surface_v4 *cm_surface;
|
struct wp_color_management_surface_v1 *cm_surface;
|
||||||
|
|
||||||
struct rectangle allocation;
|
struct rectangle allocation;
|
||||||
struct rectangle server_allocation;
|
struct rectangle server_allocation;
|
||||||
|
|
@ -400,10 +400,8 @@ struct input {
|
||||||
struct {
|
struct {
|
||||||
struct xkb_keymap *keymap;
|
struct xkb_keymap *keymap;
|
||||||
struct xkb_state *state;
|
struct xkb_state *state;
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE
|
|
||||||
struct xkb_compose_table *compose_table;
|
struct xkb_compose_table *compose_table;
|
||||||
struct xkb_compose_state *compose_state;
|
struct xkb_compose_state *compose_state;
|
||||||
#endif
|
|
||||||
xkb_mod_mask_t control_mask;
|
xkb_mod_mask_t control_mask;
|
||||||
xkb_mod_mask_t alt_mask;
|
xkb_mod_mask_t alt_mask;
|
||||||
xkb_mod_mask_t shift_mask;
|
xkb_mod_mask_t shift_mask;
|
||||||
|
|
@ -480,7 +478,7 @@ struct shm_pool {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cm_image_description {
|
struct cm_image_description {
|
||||||
struct xx_image_description_v4 *image_desc;
|
struct wp_image_description_v1 *image_desc;
|
||||||
enum cm_image_desc_status {
|
enum cm_image_desc_status {
|
||||||
CM_IMAGE_DESC_NOT_CREATED = 0,
|
CM_IMAGE_DESC_NOT_CREATED = 0,
|
||||||
CM_IMAGE_DESC_READY,
|
CM_IMAGE_DESC_READY,
|
||||||
|
|
@ -493,27 +491,27 @@ render_intent_info_table[] = {
|
||||||
{
|
{
|
||||||
.intent = RENDER_INTENT_PERCEPTUAL,
|
.intent = RENDER_INTENT_PERCEPTUAL,
|
||||||
.desc = "Perceptual",
|
.desc = "Perceptual",
|
||||||
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL,
|
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.intent = RENDER_INTENT_RELATIVE,
|
.intent = RENDER_INTENT_RELATIVE,
|
||||||
.desc = "Media-relative colorimetric",
|
.desc = "Media-relative colorimetric",
|
||||||
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE,
|
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.intent = RENDER_INTENT_RELATIVE_BPC,
|
.intent = RENDER_INTENT_RELATIVE_BPC,
|
||||||
.desc = "Media-relative colorimetric + black point compensation",
|
.desc = "Media-relative colorimetric + black point compensation",
|
||||||
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE_BPC,
|
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE_BPC,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.intent = RENDER_INTENT_SATURATION,
|
.intent = RENDER_INTENT_SATURATION,
|
||||||
.desc = "Saturation",
|
.desc = "Saturation",
|
||||||
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_SATURATION,
|
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_SATURATION,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.intent = RENDER_INTENT_ABSOLUTE,
|
.intent = RENDER_INTENT_ABSOLUTE,
|
||||||
.desc = "ICC-absolute colorimetric",
|
.desc = "ICC-absolute colorimetric",
|
||||||
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_ABSOLUTE,
|
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_ABSOLUTE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -568,7 +566,7 @@ debug_print(void *proxy, int line, const char *func, const char *fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cm_image_desc_ready(void *data, struct xx_image_description_v4 *xx_image_description_v4,
|
cm_image_desc_ready(void *data, struct wp_image_description_v1 *wp_image_description_v1,
|
||||||
uint32_t identity)
|
uint32_t identity)
|
||||||
{
|
{
|
||||||
struct cm_image_description *cm_image_desc = data;
|
struct cm_image_description *cm_image_desc = data;
|
||||||
|
|
@ -577,7 +575,7 @@ cm_image_desc_ready(void *data, struct xx_image_description_v4 *xx_image_descrip
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cm_image_desc_failed(void *data, struct xx_image_description_v4 *xx_image_description_v4,
|
cm_image_desc_failed(void *data, struct wp_image_description_v1 *wp_image_description_v1,
|
||||||
uint32_t cause, const char *msg)
|
uint32_t cause, const char *msg)
|
||||||
{
|
{
|
||||||
struct cm_image_description *cm_image_desc = data;
|
struct cm_image_description *cm_image_desc = data;
|
||||||
|
|
@ -588,7 +586,7 @@ cm_image_desc_failed(void *data, struct xx_image_description_v4 *xx_image_descri
|
||||||
cm_image_desc->status = CM_IMAGE_DESC_FAILED;
|
cm_image_desc->status = CM_IMAGE_DESC_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xx_image_description_v4_listener cm_image_desc_listener = {
|
static const struct wp_image_description_v1_listener cm_image_desc_listener = {
|
||||||
.ready = cm_image_desc_ready,
|
.ready = cm_image_desc_ready,
|
||||||
.failed = cm_image_desc_failed,
|
.failed = cm_image_desc_failed,
|
||||||
};
|
};
|
||||||
|
|
@ -610,10 +608,10 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
|
||||||
uint32_t length, uint32_t offset,
|
uint32_t length, uint32_t offset,
|
||||||
enum render_intent intent, char **err_msg)
|
enum render_intent intent, char **err_msg)
|
||||||
{
|
{
|
||||||
struct xx_image_description_creator_icc_v4 *icc_creator;
|
struct wp_image_description_creator_icc_v1 *icc_creator;
|
||||||
struct display *display = widget->window->display;
|
struct display *display = widget->window->display;
|
||||||
struct surface *surface = widget->surface;
|
struct surface *surface = widget->surface;
|
||||||
struct xx_color_manager_v4 *color_manager_wrapper;
|
struct wp_color_manager_v1 *color_manager_wrapper;
|
||||||
struct wl_event_queue *queue;
|
struct wl_event_queue *queue;
|
||||||
struct cm_image_description cm_image_desc;
|
struct cm_image_description cm_image_desc;
|
||||||
const struct render_intent_info *intent_info;
|
const struct render_intent_info *intent_info;
|
||||||
|
|
@ -623,11 +621,11 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
|
||||||
str_printf(err_msg,
|
str_printf(err_msg,
|
||||||
"%s extension not supported by the Wayland " \
|
"%s extension not supported by the Wayland " \
|
||||||
"compositor, ignoring image color profile.",
|
"compositor, ignoring image color profile.",
|
||||||
xx_color_manager_v4_interface.name);
|
wp_color_manager_v1_interface.name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!((display->color_manager_features >> XX_COLOR_MANAGER_V4_FEATURE_ICC_V2_V4) & 1)) {
|
if (!((display->color_manager_features >> WP_COLOR_MANAGER_V1_FEATURE_ICC_V2_V4) & 1)) {
|
||||||
str_printf(err_msg,
|
str_printf(err_msg,
|
||||||
"Wayland compositor does not support creating image " \
|
"Wayland compositor does not support creating image " \
|
||||||
"descriptions from ICC files, ignoring color profile.");
|
"descriptions from ICC files, ignoring color profile.");
|
||||||
|
|
@ -650,15 +648,15 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
|
||||||
wl_proxy_set_queue((struct wl_proxy *)color_manager_wrapper, queue);
|
wl_proxy_set_queue((struct wl_proxy *)color_manager_wrapper, queue);
|
||||||
|
|
||||||
/* Create ICC image description creator and set the ICC file. */
|
/* Create ICC image description creator and set the ICC file. */
|
||||||
icc_creator = xx_color_manager_v4_new_icc_creator(color_manager_wrapper);
|
icc_creator = wp_color_manager_v1_create_icc_creator(color_manager_wrapper);
|
||||||
wl_proxy_wrapper_destroy(color_manager_wrapper);
|
wl_proxy_wrapper_destroy(color_manager_wrapper);
|
||||||
xx_image_description_creator_icc_v4_set_icc_file(icc_creator,
|
wp_image_description_creator_icc_v1_set_icc_file(icc_creator,
|
||||||
icc_fd, offset, length);
|
icc_fd, offset, length);
|
||||||
|
|
||||||
/* Create the image description. It will also destroy the ICC creator. */
|
/* Create the image description. It will also destroy the ICC creator. */
|
||||||
cm_image_desc.status = CM_IMAGE_DESC_NOT_CREATED;
|
cm_image_desc.status = CM_IMAGE_DESC_NOT_CREATED;
|
||||||
cm_image_desc.image_desc = xx_image_description_creator_icc_v4_create(icc_creator);
|
cm_image_desc.image_desc = wp_image_description_creator_icc_v1_create(icc_creator);
|
||||||
xx_image_description_v4_add_listener(cm_image_desc.image_desc,
|
wp_image_description_v1_add_listener(cm_image_desc.image_desc,
|
||||||
&cm_image_desc_listener, &cm_image_desc);
|
&cm_image_desc_listener, &cm_image_desc);
|
||||||
|
|
||||||
/* Wait until compositor creates the image description or gracefully
|
/* Wait until compositor creates the image description or gracefully
|
||||||
|
|
@ -666,7 +664,7 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
|
||||||
while (ret != -1 && cm_image_desc.status == CM_IMAGE_DESC_NOT_CREATED)
|
while (ret != -1 && cm_image_desc.status == CM_IMAGE_DESC_NOT_CREATED)
|
||||||
ret = wl_display_dispatch_queue(display->display, queue);
|
ret = wl_display_dispatch_queue(display->display, queue);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
xx_image_description_v4_destroy(cm_image_desc.image_desc);
|
wp_image_description_v1_destroy(cm_image_desc.image_desc);
|
||||||
wl_event_queue_destroy(queue);
|
wl_event_queue_destroy(queue);
|
||||||
str_printf(err_msg,
|
str_printf(err_msg,
|
||||||
"Disconnected from the Wayland compositor, " \
|
"Disconnected from the Wayland compositor, " \
|
||||||
|
|
@ -677,7 +675,7 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
|
||||||
/* Gracefully failed to create image description. Error already printed
|
/* Gracefully failed to create image description. Error already printed
|
||||||
* in the handler. */
|
* in the handler. */
|
||||||
if (cm_image_desc.status == CM_IMAGE_DESC_FAILED) {
|
if (cm_image_desc.status == CM_IMAGE_DESC_FAILED) {
|
||||||
xx_image_description_v4_destroy(cm_image_desc.image_desc);
|
wp_image_description_v1_destroy(cm_image_desc.image_desc);
|
||||||
wl_event_queue_destroy(queue);
|
wl_event_queue_destroy(queue);
|
||||||
str_printf(err_msg,
|
str_printf(err_msg,
|
||||||
"Image description creation gracefully failed.");
|
"Image description creation gracefully failed.");
|
||||||
|
|
@ -687,14 +685,14 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
|
||||||
|
|
||||||
if (!surface->cm_surface)
|
if (!surface->cm_surface)
|
||||||
surface->cm_surface =
|
surface->cm_surface =
|
||||||
xx_color_manager_v4_get_surface(display->color_manager,
|
wp_color_manager_v1_get_surface(display->color_manager,
|
||||||
surface->surface);
|
surface->surface);
|
||||||
|
|
||||||
xx_color_management_surface_v4_set_image_description(surface->cm_surface,
|
wp_color_management_surface_v1_set_image_description(surface->cm_surface,
|
||||||
cm_image_desc.image_desc,
|
cm_image_desc.image_desc,
|
||||||
intent_info->protocol_intent);
|
intent_info->protocol_intent);
|
||||||
|
|
||||||
xx_image_description_v4_destroy(cm_image_desc.image_desc);
|
wp_image_description_v1_destroy(cm_image_desc.image_desc);
|
||||||
wl_event_queue_destroy(queue);
|
wl_event_queue_destroy(queue);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1451,6 +1449,35 @@ surface_flush(struct surface *surface)
|
||||||
surface->cairo_surface = NULL;
|
surface->cairo_surface = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
widget_surface_flush(struct widget *widget)
|
||||||
|
{
|
||||||
|
struct surface *surface = widget->surface;
|
||||||
|
|
||||||
|
if (surface->opaque_region) {
|
||||||
|
wl_surface_set_opaque_region(surface->surface,
|
||||||
|
surface->opaque_region);
|
||||||
|
wl_region_destroy(surface->opaque_region);
|
||||||
|
surface->opaque_region = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surface->input_region) {
|
||||||
|
wl_surface_set_input_region(surface->surface,
|
||||||
|
surface->input_region);
|
||||||
|
wl_region_destroy(surface->input_region);
|
||||||
|
surface->input_region = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surface->viewport) {
|
||||||
|
wp_viewport_set_destination(surface->viewport,
|
||||||
|
widget->viewport_dest_width,
|
||||||
|
widget->viewport_dest_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_surface_damage(surface->surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||||
|
wl_surface_commit(surface->surface);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
window_has_focus(struct window *window)
|
window_has_focus(struct window *window)
|
||||||
{
|
{
|
||||||
|
|
@ -1578,7 +1605,7 @@ surface_destroy(struct surface *surface)
|
||||||
wp_viewport_destroy(surface->viewport);
|
wp_viewport_destroy(surface->viewport);
|
||||||
|
|
||||||
if (surface->cm_surface)
|
if (surface->cm_surface)
|
||||||
xx_color_management_surface_v4_destroy(surface->cm_surface);
|
wp_color_management_surface_v1_destroy(surface->cm_surface);
|
||||||
|
|
||||||
wl_surface_destroy(surface->surface);
|
wl_surface_destroy(surface->surface);
|
||||||
|
|
||||||
|
|
@ -1846,8 +1873,9 @@ widget_cairo_update_transform(struct widget *widget, cairo_t *cr)
|
||||||
surface->allocation.width,
|
surface->allocation.width,
|
||||||
surface->allocation.height,
|
surface->allocation.height,
|
||||||
surface->buffer_scale);
|
surface->buffer_scale);
|
||||||
cairo_matrix_init(&m, matrix.d[0], matrix.d[1], matrix.d[4],
|
cairo_matrix_init(&m, matrix.M.col[0].x, matrix.M.col[0].y,
|
||||||
matrix.d[5], matrix.d[12], matrix.d[13]);
|
matrix.M.col[1].x, matrix.M.col[1].y,
|
||||||
|
matrix.M.col[3].x, matrix.M.col[3].y);
|
||||||
cairo_transform(cr, &m);
|
cairo_transform(cr, &m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3102,10 +3130,8 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||||
struct input *input = data;
|
struct input *input = data;
|
||||||
struct xkb_keymap *keymap;
|
struct xkb_keymap *keymap;
|
||||||
struct xkb_state *state;
|
struct xkb_state *state;
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE
|
|
||||||
struct xkb_compose_table *compose_table;
|
struct xkb_compose_table *compose_table;
|
||||||
struct xkb_compose_state *compose_state;
|
struct xkb_compose_state *compose_state;
|
||||||
#endif
|
|
||||||
char *locale;
|
char *locale;
|
||||||
char *map_str;
|
char *map_str;
|
||||||
|
|
||||||
|
|
@ -3153,7 +3179,6 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||||
locale = "C";
|
locale = "C";
|
||||||
|
|
||||||
/* Set up XKB compose table */
|
/* Set up XKB compose table */
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE
|
|
||||||
compose_table =
|
compose_table =
|
||||||
xkb_compose_table_new_from_locale(input->display->xkb_context,
|
xkb_compose_table_new_from_locale(input->display->xkb_context,
|
||||||
locale,
|
locale,
|
||||||
|
|
@ -3177,7 +3202,6 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||||
fprintf(stderr, "could not create XKB compose table for locale '%s'. "
|
fprintf(stderr, "could not create XKB compose table for locale '%s'. "
|
||||||
"Disabiling compose\n", locale);
|
"Disabiling compose\n", locale);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
xkb_keymap_unref(input->xkb.keymap);
|
xkb_keymap_unref(input->xkb.keymap);
|
||||||
xkb_state_unref(input->xkb.state);
|
xkb_state_unref(input->xkb.state);
|
||||||
|
|
@ -3228,7 +3252,6 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
||||||
static xkb_keysym_t
|
static xkb_keysym_t
|
||||||
process_key_press(xkb_keysym_t sym, struct input *input)
|
process_key_press(xkb_keysym_t sym, struct input *input)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE
|
|
||||||
if (!input->xkb.compose_state)
|
if (!input->xkb.compose_state)
|
||||||
return sym;
|
return sym;
|
||||||
if (sym == XKB_KEY_NoSymbol)
|
if (sym == XKB_KEY_NoSymbol)
|
||||||
|
|
@ -3249,9 +3272,6 @@ process_key_press(xkb_keysym_t sym, struct input *input)
|
||||||
default:
|
default:
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
return sym;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -4372,8 +4392,8 @@ undo_resize(struct window *window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
window_schedule_resize(struct window *window, int width, int height)
|
window_configure_resize(struct window *window, int width, int height)
|
||||||
{
|
{
|
||||||
/* We should probably get these numbers from the theme. */
|
/* We should probably get these numbers from the theme. */
|
||||||
const int min_width = 200, min_height = 200;
|
const int min_width = 200, min_height = 200;
|
||||||
|
|
@ -4400,6 +4420,12 @@ window_schedule_resize(struct window *window, int width, int height)
|
||||||
window->pending_allocation.height = window->min_allocation.height;
|
window->pending_allocation.height = window->min_allocation.height;
|
||||||
|
|
||||||
window->resize_needed = 1;
|
window->resize_needed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_schedule_resize(struct window *window, int width, int height)
|
||||||
|
{
|
||||||
|
window_configure_resize(window, width, height);
|
||||||
window_schedule_redraw(window);
|
window_schedule_redraw(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4488,6 +4514,14 @@ xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the window is being mapped fullscreen,
|
||||||
|
* save the last pending allocation */
|
||||||
|
if (window->fullscreen &&
|
||||||
|
(window->saved_allocation.width == 0 ||
|
||||||
|
window->saved_allocation.height == 0)) {
|
||||||
|
window->saved_allocation = window->pending_allocation;
|
||||||
|
}
|
||||||
|
|
||||||
if (window->frame) {
|
if (window->frame) {
|
||||||
if (window->maximized) {
|
if (window->maximized) {
|
||||||
frame_set_flag(window->frame->frame, FRAME_FLAG_MAXIMIZED);
|
frame_set_flag(window->frame->frame, FRAME_FLAG_MAXIMIZED);
|
||||||
|
|
@ -4508,14 +4542,14 @@ xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
||||||
* on the shadow margin to get the difference. */
|
* on the shadow margin to get the difference. */
|
||||||
int margin = window_get_shadow_margin(window);
|
int margin = window_get_shadow_margin(window);
|
||||||
|
|
||||||
window_schedule_resize(window,
|
window_configure_resize(window,
|
||||||
width + margin * 2,
|
width + margin * 2,
|
||||||
height + margin * 2);
|
height + margin * 2);
|
||||||
} else if (window->saved_allocation.width > 0 &&
|
} else if (window->saved_allocation.width > 0 &&
|
||||||
window->saved_allocation.height > 0) {
|
window->saved_allocation.height > 0) {
|
||||||
window_schedule_resize(window,
|
window_configure_resize(window,
|
||||||
window->saved_allocation.width,
|
window->saved_allocation.width,
|
||||||
window->saved_allocation.height);
|
window->saved_allocation.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4937,6 +4971,20 @@ window_set_locked_pointer_motion_handler(struct window *window,
|
||||||
window->locked_pointer_motion_handler = handler;
|
window->locked_pointer_motion_handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_set_shadow(struct window *window)
|
||||||
|
{
|
||||||
|
if (window->frame)
|
||||||
|
frame_unset_flag(window->frame->frame, FRAME_FLAG_NO_SHADOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_unset_shadow(struct window *window)
|
||||||
|
{
|
||||||
|
if (window->frame)
|
||||||
|
frame_set_flag(window->frame->frame, FRAME_FLAG_NO_SHADOW);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_set_title(struct window *window, const char *title)
|
window_set_title(struct window *window, const char *title)
|
||||||
{
|
{
|
||||||
|
|
@ -6671,7 +6719,7 @@ display_bind_tablets(struct display *d, uint32_t id)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cm_supported_intent(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
cm_supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||||
uint32_t render_intent)
|
uint32_t render_intent)
|
||||||
{
|
{
|
||||||
struct display *d = data;
|
struct display *d = data;
|
||||||
|
|
@ -6680,7 +6728,7 @@ cm_supported_intent(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cm_supported_feature(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
cm_supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||||
uint32_t feature)
|
uint32_t feature)
|
||||||
{
|
{
|
||||||
struct display *d = data;
|
struct display *d = data;
|
||||||
|
|
@ -6689,24 +6737,31 @@ cm_supported_feature(void *data, struct xx_color_manager_v4 *xx_color_manager_v4
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cm_supported_tf_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
cm_supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||||
uint32_t tf_code)
|
uint32_t tf_code)
|
||||||
{
|
{
|
||||||
/* unused in this file */
|
/* unused in this file */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cm_supported_primaries_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
cm_supported_primaries_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||||
uint32_t primaries_code)
|
uint32_t primaries_code)
|
||||||
{
|
{
|
||||||
/* unused in this file */
|
/* unused in this file */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xx_color_manager_v4_listener cm_listener = {
|
static void
|
||||||
|
cm_done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
|
||||||
|
{
|
||||||
|
/* unused in this file */
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_color_manager_v1_listener cm_listener = {
|
||||||
.supported_intent = cm_supported_intent,
|
.supported_intent = cm_supported_intent,
|
||||||
.supported_feature = cm_supported_feature,
|
.supported_feature = cm_supported_feature,
|
||||||
.supported_tf_named = cm_supported_tf_named,
|
.supported_tf_named = cm_supported_tf_named,
|
||||||
.supported_primaries_named = cm_supported_primaries_named,
|
.supported_primaries_named = cm_supported_primaries_named,
|
||||||
|
.done = cm_done,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -6777,12 +6832,17 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
|
||||||
&wp_viewporter_interface, 1);
|
&wp_viewporter_interface, 1);
|
||||||
} else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
|
} else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
|
||||||
display_bind_tablets(d, id);
|
display_bind_tablets(d, id);
|
||||||
} else if (strcmp(interface, "xx_color_manager_v4") == 0) {
|
} else if (strcmp(interface, "wp_color_manager_v1") == 0) {
|
||||||
d->color_manager =
|
d->color_manager =
|
||||||
wl_registry_bind(registry, id,
|
wl_registry_bind(registry, id,
|
||||||
&xx_color_manager_v4_interface, 1);
|
&wp_color_manager_v1_interface, 1);
|
||||||
xx_color_manager_v4_add_listener(d->color_manager,
|
wp_color_manager_v1_add_listener(d->color_manager,
|
||||||
&cm_listener, d);
|
&cm_listener, d);
|
||||||
|
} else if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
|
||||||
|
d->single_pixel_buffer_manager =
|
||||||
|
wl_registry_bind(registry, id,
|
||||||
|
&wp_single_pixel_buffer_manager_v1_interface,
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->global_handler)
|
if (d->global_handler)
|
||||||
|
|
@ -7005,7 +7065,7 @@ display_destroy(struct display *display)
|
||||||
xdg_wm_base_destroy(display->xdg_shell);
|
xdg_wm_base_destroy(display->xdg_shell);
|
||||||
|
|
||||||
if (display->color_manager)
|
if (display->color_manager)
|
||||||
xx_color_manager_v4_destroy(display->color_manager);
|
wp_color_manager_v1_destroy(display->color_manager);
|
||||||
|
|
||||||
if (display->shm)
|
if (display->shm)
|
||||||
wl_shm_destroy(display->shm);
|
wl_shm_destroy(display->shm);
|
||||||
|
|
@ -7071,6 +7131,12 @@ display_get_compositor(struct display *display)
|
||||||
return display->compositor;
|
return display->compositor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wp_single_pixel_buffer_manager_v1 *
|
||||||
|
display_get_single_pixel_buffer_manager(struct display *display)
|
||||||
|
{
|
||||||
|
return display->single_pixel_buffer_manager;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
display_get_serial(struct display *display)
|
display_get_serial(struct display *display)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,9 @@ display_has_subcompositor(struct display *display);
|
||||||
struct wl_compositor *
|
struct wl_compositor *
|
||||||
display_get_compositor(struct display *display);
|
display_get_compositor(struct display *display);
|
||||||
|
|
||||||
|
struct wp_single_pixel_buffer_manager_v1 *
|
||||||
|
display_get_single_pixel_buffer_manager(struct display *display);
|
||||||
|
|
||||||
struct output *
|
struct output *
|
||||||
display_get_output(struct display *display);
|
display_get_output(struct display *display);
|
||||||
|
|
||||||
|
|
@ -530,6 +533,12 @@ void
|
||||||
window_set_locked_pointer_motion_handler(
|
window_set_locked_pointer_motion_handler(
|
||||||
struct window *window, window_locked_pointer_motion_handler_t handler);
|
struct window *window, window_locked_pointer_motion_handler_t handler);
|
||||||
|
|
||||||
|
void
|
||||||
|
window_set_shadow(struct window *window);
|
||||||
|
|
||||||
|
void
|
||||||
|
window_unset_shadow(struct window *window);
|
||||||
|
|
||||||
void
|
void
|
||||||
window_set_title(struct window *window, const char *title);
|
window_set_title(struct window *window, const char *title);
|
||||||
|
|
||||||
|
|
@ -604,6 +613,9 @@ widget_cairo_create(struct widget *widget);
|
||||||
struct wl_surface *
|
struct wl_surface *
|
||||||
widget_get_wl_surface(struct widget *widget);
|
widget_get_wl_surface(struct widget *widget);
|
||||||
|
|
||||||
|
void
|
||||||
|
widget_surface_flush(struct widget *widget);
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
widget_get_last_time(struct widget *widget);
|
widget_get_last_time(struct widget *widget);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ home.png
|
||||||
icon_ivi_clickdot.png
|
icon_ivi_clickdot.png
|
||||||
icon_ivi_flower.png
|
icon_ivi_flower.png
|
||||||
icon_ivi_simple-egl.png
|
icon_ivi_simple-egl.png
|
||||||
|
icon_ivi_simple-egl-vertical.png
|
||||||
icon_ivi_simple-shm.png
|
icon_ivi_simple-shm.png
|
||||||
icon_ivi_smoke.png
|
icon_ivi_smoke.png
|
||||||
|
|
||||||
|
|
|
||||||
BIN
data/icon_ivi_simple-egl-vertical.png
Normal file
BIN
data/icon_ivi_simple-egl-vertical.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
|
|
@ -9,6 +9,7 @@ install_data(
|
||||||
'icon_ivi_clickdot.png',
|
'icon_ivi_clickdot.png',
|
||||||
'icon_ivi_flower.png',
|
'icon_ivi_flower.png',
|
||||||
'icon_ivi_simple-egl.png',
|
'icon_ivi_simple-egl.png',
|
||||||
|
'icon_ivi_simple-egl-vertical.png',
|
||||||
'icon_ivi_simple-shm.png',
|
'icon_ivi_simple-shm.png',
|
||||||
'icon_ivi_smoke.png',
|
'icon_ivi_smoke.png',
|
||||||
'icon_terminal.png',
|
'icon_terminal.png',
|
||||||
|
|
|
||||||
|
|
@ -48,168 +48,6 @@
|
||||||
#define DEFAULT_NUM_WORKSPACES 1
|
#define DEFAULT_NUM_WORKSPACES 1
|
||||||
#define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
|
#define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
|
||||||
|
|
||||||
struct focus_state {
|
|
||||||
struct desktop_shell *shell;
|
|
||||||
struct weston_seat *seat;
|
|
||||||
struct workspace *ws;
|
|
||||||
struct weston_surface *keyboard_focus;
|
|
||||||
struct wl_list link;
|
|
||||||
struct wl_listener seat_destroy_listener;
|
|
||||||
struct wl_listener surface_destroy_listener;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Surface stacking and ordering.
|
|
||||||
*
|
|
||||||
* This is handled using several linked lists of surfaces, organised into
|
|
||||||
* ‘layers’. The layers are ordered, and each of the surfaces in one layer are
|
|
||||||
* above all of the surfaces in the layer below. The set of layers is static and
|
|
||||||
* in the following order (top-most first):
|
|
||||||
* • Lock layer (only ever displayed on its own)
|
|
||||||
* • Cursor layer
|
|
||||||
* • Input panel layer
|
|
||||||
* • Fullscreen layer
|
|
||||||
* • Panel layer
|
|
||||||
* • Workspace layers
|
|
||||||
* • Background layer
|
|
||||||
*
|
|
||||||
* The list of layers may be manipulated to remove whole layers of surfaces from
|
|
||||||
* display. For example, when locking the screen, all layers except the lock
|
|
||||||
* layer are removed.
|
|
||||||
*
|
|
||||||
* A surface’s layer is modified on configuring the surface, in
|
|
||||||
* set_surface_type() (which is only called when the surface’s type change is
|
|
||||||
* _committed_). If a surface’s type changes (e.g. when making a window
|
|
||||||
* fullscreen) its layer changes too.
|
|
||||||
*
|
|
||||||
* In order to allow popup and transient surfaces to be correctly stacked above
|
|
||||||
* their parent surfaces, each surface tracks both its parent surface, and a
|
|
||||||
* linked list of its children. When a surface’s layer is updated, so are the
|
|
||||||
* layers of its children. Note that child surfaces are *not* the same as
|
|
||||||
* subsurfaces — child/parent surfaces are purely for maintaining stacking
|
|
||||||
* order.
|
|
||||||
*
|
|
||||||
* The children_link list of siblings of a surface (i.e. those surfaces which
|
|
||||||
* have the same parent) only contains weston_surfaces which have a
|
|
||||||
* shell_surface. Stacking is not implemented for non-shell_surface
|
|
||||||
* weston_surfaces. This means that the following implication does *not* hold:
|
|
||||||
* (shsurf->parent != NULL) ⇒ !wl_list_is_empty(shsurf->children_link)
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct shell_surface {
|
|
||||||
struct wl_signal destroy_signal;
|
|
||||||
|
|
||||||
struct weston_desktop_surface *desktop_surface;
|
|
||||||
struct weston_view *view;
|
|
||||||
struct weston_surface *wsurface_anim_fade;
|
|
||||||
struct weston_view *wview_anim_fade;
|
|
||||||
int32_t last_width, last_height;
|
|
||||||
|
|
||||||
struct desktop_shell *shell;
|
|
||||||
|
|
||||||
struct wl_list children_list;
|
|
||||||
struct wl_list children_link;
|
|
||||||
|
|
||||||
struct weston_coord_global saved_pos;
|
|
||||||
bool saved_position_valid;
|
|
||||||
bool saved_rotation_valid;
|
|
||||||
int unresponsive, grabbed;
|
|
||||||
uint32_t resize_edges;
|
|
||||||
uint32_t orientation;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct weston_transform transform;
|
|
||||||
struct weston_matrix rotation;
|
|
||||||
} rotation;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct weston_curtain *black_view;
|
|
||||||
} fullscreen;
|
|
||||||
|
|
||||||
struct weston_output *fullscreen_output;
|
|
||||||
struct weston_output *output;
|
|
||||||
struct wl_listener output_destroy_listener;
|
|
||||||
|
|
||||||
struct surface_state {
|
|
||||||
bool fullscreen;
|
|
||||||
bool maximized;
|
|
||||||
bool lowered;
|
|
||||||
} state;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
bool is_set;
|
|
||||||
struct weston_coord_global pos;
|
|
||||||
} xwayland;
|
|
||||||
|
|
||||||
int focus_count;
|
|
||||||
|
|
||||||
bool destroying;
|
|
||||||
struct wl_list link; /** desktop_shell::shsurf_list */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct shell_grab {
|
|
||||||
struct weston_pointer_grab grab;
|
|
||||||
struct shell_surface *shsurf;
|
|
||||||
struct wl_listener shsurf_destroy_listener;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct shell_touch_grab {
|
|
||||||
struct weston_touch_grab grab;
|
|
||||||
struct shell_surface *shsurf;
|
|
||||||
struct wl_listener shsurf_destroy_listener;
|
|
||||||
struct weston_touch *touch;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct shell_tablet_tool_grab {
|
|
||||||
struct weston_tablet_tool_grab grab;
|
|
||||||
struct shell_surface *shsurf;
|
|
||||||
struct wl_listener shsurf_destroy_listener;
|
|
||||||
struct weston_tablet_tool *tool;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_move_grab {
|
|
||||||
struct shell_grab base;
|
|
||||||
struct weston_coord_global delta;
|
|
||||||
bool client_initiated;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_touch_move_grab {
|
|
||||||
struct shell_touch_grab base;
|
|
||||||
int active;
|
|
||||||
struct weston_coord_global delta;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_tablet_tool_move_grab {
|
|
||||||
struct shell_tablet_tool_grab base;
|
|
||||||
wl_fixed_t dx, dy;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct rotate_grab {
|
|
||||||
struct shell_grab base;
|
|
||||||
struct weston_matrix rotation;
|
|
||||||
struct {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
} center;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct shell_seat {
|
|
||||||
struct weston_seat *seat;
|
|
||||||
struct wl_listener seat_destroy_listener;
|
|
||||||
struct weston_surface *focused_surface;
|
|
||||||
|
|
||||||
struct wl_listener caps_changed_listener;
|
|
||||||
struct wl_listener pointer_focus_listener;
|
|
||||||
struct wl_listener keyboard_focus_listener;
|
|
||||||
struct wl_listener tablet_tool_added_listener;
|
|
||||||
|
|
||||||
struct wl_list link; /** shell::seat_list */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct tablet_tool_listener {
|
|
||||||
struct wl_listener base;
|
|
||||||
struct wl_listener removed_listener;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct desktop_shell *
|
static struct desktop_shell *
|
||||||
shell_surface_get_shell(struct shell_surface *shsurf);
|
shell_surface_get_shell(struct shell_surface *shsurf);
|
||||||
|
|
@ -235,20 +73,6 @@ shell_surface_update_child_surface_layers(struct shell_surface *shsurf);
|
||||||
static void
|
static void
|
||||||
get_maximized_size(struct shell_surface *shsurf, int32_t *width, int32_t *height);
|
get_maximized_size(struct shell_surface *shsurf, int32_t *width, int32_t *height);
|
||||||
|
|
||||||
static struct shell_output *
|
|
||||||
find_shell_output_from_weston_output(struct desktop_shell *shell,
|
|
||||||
struct weston_output *output)
|
|
||||||
{
|
|
||||||
struct shell_output *shell_output;
|
|
||||||
|
|
||||||
wl_list_for_each(shell_output, &shell->output_list, link) {
|
|
||||||
if (shell_output->output == output)
|
|
||||||
return shell_output;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
shsurf_is_max_or_fullscreen(struct shell_surface *shsurf)
|
shsurf_is_max_or_fullscreen(struct shell_surface *shsurf)
|
||||||
{
|
{
|
||||||
|
|
@ -269,8 +93,8 @@ set_shsurf_size_maximized_or_fullscreen(struct shell_surface *shsurf,
|
||||||
|
|
||||||
if (fullscreen_requested) {
|
if (fullscreen_requested) {
|
||||||
if (shsurf->output) {
|
if (shsurf->output) {
|
||||||
width = shsurf->output->width;
|
width = shsurf->output->output->width;
|
||||||
height = shsurf->output->height;
|
height = shsurf->output->output->height;
|
||||||
}
|
}
|
||||||
} else if (max_requested) {
|
} else if (max_requested) {
|
||||||
/* take the panels into considerations */
|
/* take the panels into considerations */
|
||||||
|
|
@ -369,21 +193,18 @@ shell_grab_start(struct shell_grab *grab,
|
||||||
|
|
||||||
void
|
void
|
||||||
get_output_work_area(struct desktop_shell *shell,
|
get_output_work_area(struct desktop_shell *shell,
|
||||||
struct weston_output *output,
|
struct shell_output *sh_output,
|
||||||
pixman_rectangle32_t *area)
|
pixman_rectangle32_t *area)
|
||||||
{
|
{
|
||||||
struct shell_output *sh_output;
|
struct weston_output *output;
|
||||||
|
|
||||||
area->x = 0;
|
area->x = 0;
|
||||||
area->y = 0;
|
area->y = 0;
|
||||||
area->width = 0;
|
area->width = 0;
|
||||||
area->height = 0;
|
area->height = 0;
|
||||||
|
|
||||||
if (!output)
|
if (!sh_output)
|
||||||
return;
|
return;
|
||||||
|
output = sh_output->output;
|
||||||
sh_output = find_shell_output_from_weston_output(shell, output);
|
|
||||||
assert(sh_output);
|
|
||||||
|
|
||||||
area->x = output->pos.c.x;
|
area->x = output->pos.c.x;
|
||||||
area->y = output->pos.c.y;
|
area->y = output->pos.c.y;
|
||||||
|
|
@ -523,6 +344,7 @@ shell_configuration(struct desktop_shell *shell)
|
||||||
struct weston_config *config;
|
struct weston_config *config;
|
||||||
char *s, *client;
|
char *s, *client;
|
||||||
bool allow_zap;
|
bool allow_zap;
|
||||||
|
bool disallow_output_changed_move;
|
||||||
|
|
||||||
config = wet_get_config(shell->compositor);
|
config = wet_get_config(shell->compositor);
|
||||||
section = weston_config_get_section(config, "shell", NULL, NULL);
|
section = weston_config_get_section(config, "shell", NULL, NULL);
|
||||||
|
|
@ -535,6 +357,11 @@ shell_configuration(struct desktop_shell *shell)
|
||||||
"allow-zap", &allow_zap, true);
|
"allow-zap", &allow_zap, true);
|
||||||
shell->allow_zap = allow_zap;
|
shell->allow_zap = allow_zap;
|
||||||
|
|
||||||
|
weston_config_section_get_bool(section,
|
||||||
|
"disallow-output-changed-move",
|
||||||
|
&disallow_output_changed_move, false);
|
||||||
|
shell->disallow_output_changed_move = disallow_output_changed_move;
|
||||||
|
|
||||||
shell->binding_modifier = weston_config_get_binding_modifier(config, MODIFIER_SUPER);
|
shell->binding_modifier = weston_config_get_binding_modifier(config, MODIFIER_SUPER);
|
||||||
|
|
||||||
weston_config_section_get_string(section, "animation", &s, "none");
|
weston_config_section_get_string(section, "animation", &s, "none");
|
||||||
|
|
@ -1061,7 +888,12 @@ constrain_position(struct weston_move_grab *move)
|
||||||
|
|
||||||
if (shsurf->shell->panel_position ==
|
if (shsurf->shell->panel_position ==
|
||||||
WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP) {
|
WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP) {
|
||||||
get_output_work_area(shsurf->shell, surface->output, &area);
|
struct shell_output *shoutput = NULL;
|
||||||
|
|
||||||
|
if (surface->output)
|
||||||
|
shoutput = weston_output_get_shell_private(surface->output);
|
||||||
|
|
||||||
|
get_output_work_area(shsurf->shell, shoutput, &area);
|
||||||
geometry =
|
geometry =
|
||||||
weston_desktop_surface_get_geometry(shsurf->desktop_surface);
|
weston_desktop_surface_get_geometry(shsurf->desktop_surface);
|
||||||
|
|
||||||
|
|
@ -1702,15 +1534,26 @@ shell_surface_set_output(struct shell_surface *shsurf,
|
||||||
{
|
{
|
||||||
struct weston_surface *es =
|
struct weston_surface *es =
|
||||||
weston_desktop_surface_get_surface(shsurf->desktop_surface);
|
weston_desktop_surface_get_surface(shsurf->desktop_surface);
|
||||||
|
struct shell_output *shoutput = NULL;
|
||||||
|
|
||||||
|
if (output)
|
||||||
|
shoutput = weston_output_get_shell_private(output);
|
||||||
|
|
||||||
/* get the default output, if the client set it as NULL
|
/* get the default output, if the client set it as NULL
|
||||||
check whether the output is available */
|
check whether the output is available */
|
||||||
if (output)
|
if (shoutput)
|
||||||
shsurf->output = output;
|
shsurf->output = shoutput;
|
||||||
else if (es->output)
|
else if (es->output)
|
||||||
shsurf->output = es->output;
|
shsurf->output = weston_output_get_shell_private(es->output);
|
||||||
else
|
else {
|
||||||
shsurf->output = weston_shell_utils_get_default_output(es->compositor);
|
struct shell_output *shoutput = NULL;
|
||||||
|
struct weston_output *w_output;
|
||||||
|
|
||||||
|
w_output = weston_shell_utils_get_default_output(es->compositor);
|
||||||
|
if (w_output)
|
||||||
|
shoutput = weston_output_get_shell_private(w_output);
|
||||||
|
shsurf->output = shoutput;
|
||||||
|
}
|
||||||
|
|
||||||
if (shsurf->output_destroy_listener.notify) {
|
if (shsurf->output_destroy_listener.notify) {
|
||||||
wl_list_remove(&shsurf->output_destroy_listener.link);
|
wl_list_remove(&shsurf->output_destroy_listener.link);
|
||||||
|
|
@ -1721,7 +1564,7 @@ shell_surface_set_output(struct shell_surface *shsurf,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
shsurf->output_destroy_listener.notify = notify_output_destroy;
|
shsurf->output_destroy_listener.notify = notify_output_destroy;
|
||||||
wl_signal_add(&shsurf->output->destroy_signal,
|
wl_signal_add(&shsurf->output->output->destroy_signal,
|
||||||
&shsurf->output_destroy_listener);
|
&shsurf->output_destroy_listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1867,7 +1710,13 @@ shell_set_view_fullscreen(struct shell_surface *shsurf)
|
||||||
struct weston_surface *surface =
|
struct weston_surface *surface =
|
||||||
weston_desktop_surface_get_surface(shsurf->desktop_surface);
|
weston_desktop_surface_get_surface(shsurf->desktop_surface);
|
||||||
struct weston_compositor *ec = surface->compositor;
|
struct weston_compositor *ec = surface->compositor;
|
||||||
struct weston_output *output = shsurf->fullscreen_output;
|
struct weston_output *output = NULL;
|
||||||
|
|
||||||
|
if (!shsurf->fullscreen_output)
|
||||||
|
return;
|
||||||
|
|
||||||
|
output = shsurf->fullscreen_output->output;
|
||||||
|
|
||||||
struct weston_curtain_params curtain_params = {
|
struct weston_curtain_params curtain_params = {
|
||||||
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0,
|
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0,
|
||||||
.pos = output->pos,
|
.pos = output->pos,
|
||||||
|
|
@ -1882,14 +1731,14 @@ shell_set_view_fullscreen(struct shell_surface *shsurf)
|
||||||
|
|
||||||
weston_view_move_to_layer(shsurf->view,
|
weston_view_move_to_layer(shsurf->view,
|
||||||
&shsurf->shell->fullscreen_layer.view_list);
|
&shsurf->shell->fullscreen_layer.view_list);
|
||||||
weston_shell_utils_center_on_output(shsurf->view, shsurf->fullscreen_output);
|
weston_shell_utils_center_on_output(shsurf->view, output);
|
||||||
|
|
||||||
if (!shsurf->fullscreen.black_view) {
|
if (!shsurf->fullscreen.black_view) {
|
||||||
shsurf->fullscreen.black_view =
|
shsurf->fullscreen.black_view =
|
||||||
weston_shell_utils_curtain_create(ec, &curtain_params);
|
weston_shell_utils_curtain_create(ec, &curtain_params);
|
||||||
}
|
}
|
||||||
weston_view_set_output(shsurf->fullscreen.black_view->view,
|
weston_view_set_output(shsurf->fullscreen.black_view->view,
|
||||||
shsurf->fullscreen_output);
|
output);
|
||||||
weston_view_move_to_layer(shsurf->fullscreen.black_view->view,
|
weston_view_move_to_layer(shsurf->fullscreen.black_view->view,
|
||||||
&shsurf->view->layer_link);
|
&shsurf->view->layer_link);
|
||||||
|
|
||||||
|
|
@ -2055,8 +1904,8 @@ fade_out_done(struct weston_view_animation *animation, void *data)
|
||||||
|
|
||||||
if (weston_view_is_mapped(shsurf->wview_anim_fade)) {
|
if (weston_view_is_mapped(shsurf->wview_anim_fade)) {
|
||||||
weston_view_move_to_layer(shsurf->wview_anim_fade, NULL);
|
weston_view_move_to_layer(shsurf->wview_anim_fade, NULL);
|
||||||
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
|
|
||||||
}
|
}
|
||||||
|
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct shell_surface *
|
struct shell_surface *
|
||||||
|
|
@ -2269,8 +2118,13 @@ map(struct desktop_shell *shell, struct shell_surface *shsurf)
|
||||||
shell_surface_update_layer(shsurf);
|
shell_surface_update_layer(shsurf);
|
||||||
|
|
||||||
if (shsurf->state.maximized) {
|
if (shsurf->state.maximized) {
|
||||||
surface->output = shsurf->output;
|
struct weston_output *w_output = NULL;
|
||||||
weston_view_set_output(shsurf->view, shsurf->output);
|
|
||||||
|
if (shsurf->output)
|
||||||
|
w_output = shsurf->output->output;
|
||||||
|
|
||||||
|
surface->output = w_output;
|
||||||
|
weston_view_set_output(shsurf->view, w_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shell->locked) {
|
if (!shell->locked) {
|
||||||
|
|
@ -2376,8 +2230,12 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
||||||
WESTON_ACTIVATE_FLAG_FULLSCREEN);
|
WESTON_ACTIVATE_FLAG_FULLSCREEN);
|
||||||
}
|
}
|
||||||
} else if (shsurf->state.maximized) {
|
} else if (shsurf->state.maximized) {
|
||||||
|
struct weston_output *w_output = NULL;
|
||||||
|
|
||||||
set_maximized_position(shell, shsurf);
|
set_maximized_position(shell, shsurf);
|
||||||
surface->output = shsurf->output;
|
if (surface->output)
|
||||||
|
w_output = shsurf->output->output;
|
||||||
|
surface->output = w_output;
|
||||||
} else {
|
} else {
|
||||||
struct weston_coord_surface offset = buf_offset;
|
struct weston_coord_surface offset = buf_offset;
|
||||||
struct weston_coord_global pos;
|
struct weston_coord_global pos;
|
||||||
|
|
@ -2777,7 +2635,13 @@ background_committed(struct weston_surface *es,
|
||||||
struct weston_coord_surface new_origin)
|
struct weston_coord_surface new_origin)
|
||||||
{
|
{
|
||||||
struct shell_output *sh_output = es->committed_private;
|
struct shell_output *sh_output = es->committed_private;
|
||||||
struct desktop_shell *shell = sh_output->shell;
|
struct desktop_shell *shell;
|
||||||
|
|
||||||
|
/* The output was destroyed before the background was committed */
|
||||||
|
if (!sh_output)
|
||||||
|
return;
|
||||||
|
|
||||||
|
shell = sh_output->shell;
|
||||||
|
|
||||||
if (!weston_surface_has_content(es))
|
if (!weston_surface_has_content(es))
|
||||||
return;
|
return;
|
||||||
|
|
@ -2793,6 +2657,7 @@ background_committed(struct weston_surface *es,
|
||||||
sh_output->output->pos);
|
sh_output->output->pos);
|
||||||
weston_view_move_to_layer(sh_output->background_view,
|
weston_view_move_to_layer(sh_output->background_view,
|
||||||
&shell->background_layer.view_list);
|
&shell->background_layer.view_list);
|
||||||
|
weston_output_set_ready(sh_output->output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -2812,7 +2677,6 @@ desktop_shell_set_background(struct wl_client *client,
|
||||||
struct wl_resource *output_resource,
|
struct wl_resource *output_resource,
|
||||||
struct wl_resource *surface_resource)
|
struct wl_resource *surface_resource)
|
||||||
{
|
{
|
||||||
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
|
||||||
struct weston_surface *surface =
|
struct weston_surface *surface =
|
||||||
wl_resource_get_user_data(surface_resource);
|
wl_resource_get_user_data(surface_resource);
|
||||||
struct shell_output *sh_output;
|
struct shell_output *sh_output;
|
||||||
|
|
@ -2829,7 +2693,7 @@ desktop_shell_set_background(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
surface->output = head->output;
|
surface->output = head->output;
|
||||||
sh_output = find_shell_output_from_weston_output(shell, surface->output);
|
sh_output = weston_output_get_shell_private(surface->output);
|
||||||
if (sh_output->background_surface) {
|
if (sh_output->background_surface) {
|
||||||
wl_resource_post_error(surface_resource,
|
wl_resource_post_error(surface_resource,
|
||||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||||
|
|
@ -2866,9 +2730,17 @@ panel_committed(struct weston_surface *es,
|
||||||
struct weston_coord_surface new_origin)
|
struct weston_coord_surface new_origin)
|
||||||
{
|
{
|
||||||
struct shell_output *sh_output = es->committed_private;
|
struct shell_output *sh_output = es->committed_private;
|
||||||
struct weston_output *output = sh_output->output;
|
struct weston_output *output;
|
||||||
struct weston_coord_global pos = output->pos;
|
struct weston_coord_global pos;
|
||||||
struct desktop_shell *shell = sh_output->shell;
|
struct desktop_shell *shell;
|
||||||
|
|
||||||
|
/* The output was destroyed before the panel was committed */
|
||||||
|
if (!sh_output)
|
||||||
|
return;
|
||||||
|
|
||||||
|
output = sh_output->output;
|
||||||
|
pos = output->pos;
|
||||||
|
shell = sh_output->shell;
|
||||||
|
|
||||||
if (!weston_surface_has_content(es))
|
if (!weston_surface_has_content(es))
|
||||||
return;
|
return;
|
||||||
|
|
@ -2895,13 +2767,14 @@ panel_committed(struct weston_surface *es,
|
||||||
weston_surface_map(es);
|
weston_surface_map(es);
|
||||||
assert(wl_list_empty(&es->views));
|
assert(wl_list_empty(&es->views));
|
||||||
sh_output->panel_view = weston_view_create(es);
|
sh_output->panel_view = weston_view_create(es);
|
||||||
|
|
||||||
|
weston_view_move_to_layer(sh_output->panel_view,
|
||||||
|
&shell->panel_layer.view_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(sh_output->panel_view);
|
assert(sh_output->panel_view);
|
||||||
pos = weston_coord_global_add(output->pos, sh_output->panel_offset);
|
pos = weston_coord_global_add(output->pos, sh_output->panel_offset);
|
||||||
weston_view_set_position(sh_output->panel_view, pos);
|
weston_view_set_position(sh_output->panel_view, pos);
|
||||||
weston_view_move_to_layer(sh_output->panel_view,
|
|
||||||
&shell->panel_layer.view_list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -2922,7 +2795,6 @@ desktop_shell_set_panel(struct wl_client *client,
|
||||||
struct wl_resource *output_resource,
|
struct wl_resource *output_resource,
|
||||||
struct wl_resource *surface_resource)
|
struct wl_resource *surface_resource)
|
||||||
{
|
{
|
||||||
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
|
||||||
struct weston_surface *surface =
|
struct weston_surface *surface =
|
||||||
wl_resource_get_user_data(surface_resource);
|
wl_resource_get_user_data(surface_resource);
|
||||||
struct shell_output *sh_output;
|
struct shell_output *sh_output;
|
||||||
|
|
@ -2939,7 +2811,7 @@ desktop_shell_set_panel(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
surface->output = head->output;
|
surface->output = head->output;
|
||||||
sh_output = find_shell_output_from_weston_output(shell, surface->output);
|
sh_output = weston_output_get_shell_private(surface->output);
|
||||||
|
|
||||||
if (sh_output->panel_surface) {
|
if (sh_output->panel_surface) {
|
||||||
wl_resource_post_error(surface_resource,
|
wl_resource_post_error(surface_resource,
|
||||||
|
|
@ -3431,7 +3303,6 @@ rotate_grab_motion(struct weston_pointer_grab *grab,
|
||||||
}
|
}
|
||||||
|
|
||||||
weston_view_update_transform(shsurf->view);
|
weston_view_update_transform(shsurf->view);
|
||||||
weston_surface_damage(shsurf->view->surface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -3555,7 +3426,7 @@ rotate_binding(struct weston_pointer *pointer, const struct timespec *time,
|
||||||
* the alt-tab switcher, which need to de-promote fullscreen layers. */
|
* the alt-tab switcher, which need to de-promote fullscreen layers. */
|
||||||
void
|
void
|
||||||
lower_fullscreen_layer(struct desktop_shell *shell,
|
lower_fullscreen_layer(struct desktop_shell *shell,
|
||||||
struct weston_output *lowering_output)
|
struct shell_output *lowering_output)
|
||||||
{
|
{
|
||||||
struct workspace *ws;
|
struct workspace *ws;
|
||||||
struct weston_view *view, *prev;
|
struct weston_view *view, *prev;
|
||||||
|
|
@ -3975,9 +3846,6 @@ shell_fade_init(struct desktop_shell *shell)
|
||||||
if (!shell->fade.curtain)
|
if (!shell->fade.curtain)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
weston_view_update_transform(shell->fade.curtain->view);
|
|
||||||
weston_surface_damage(shell->fade.curtain->view->surface);
|
|
||||||
|
|
||||||
loop = wl_display_get_event_loop(shell->compositor->wl_display);
|
loop = wl_display_get_event_loop(shell->compositor->wl_display);
|
||||||
shell->fade.startup_timer =
|
shell->fade.startup_timer =
|
||||||
wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
|
wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
|
||||||
|
|
@ -4047,6 +3915,7 @@ weston_view_set_initial_position(struct weston_view *view,
|
||||||
int32_t range_x, range_y;
|
int32_t range_x, range_y;
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
struct weston_output *output, *target_output = NULL;
|
struct weston_output *output, *target_output = NULL;
|
||||||
|
struct shell_output *shoutput;
|
||||||
struct weston_seat *seat;
|
struct weston_seat *seat;
|
||||||
pixman_rectangle32_t area;
|
pixman_rectangle32_t area;
|
||||||
struct weston_coord_global pos;
|
struct weston_coord_global pos;
|
||||||
|
|
@ -4084,7 +3953,9 @@ weston_view_set_initial_position(struct weston_view *view,
|
||||||
* If this is negative it means that the surface is bigger than
|
* If this is negative it means that the surface is bigger than
|
||||||
* output.
|
* output.
|
||||||
*/
|
*/
|
||||||
get_output_work_area(shell, target_output, &area);
|
assert(target_output);
|
||||||
|
shoutput = weston_output_get_shell_private(target_output);
|
||||||
|
get_output_work_area(shell, shoutput, &area);
|
||||||
|
|
||||||
x = area.x;
|
x = area.x;
|
||||||
y = area.y;
|
y = area.y;
|
||||||
|
|
@ -4466,6 +4337,12 @@ shell_reposition_view_on_output_change(struct weston_view *view)
|
||||||
struct shell_surface *shsurf;
|
struct shell_surface *shsurf;
|
||||||
int visible;
|
int visible;
|
||||||
|
|
||||||
|
/* We can't simply reposition popups and such, they must move with
|
||||||
|
* the parent.
|
||||||
|
*/
|
||||||
|
if (view->geometry.parent)
|
||||||
|
return;
|
||||||
|
|
||||||
if (wl_list_empty(&ec->output_list))
|
if (wl_list_empty(&ec->output_list))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -4541,12 +4418,18 @@ shell_output_destroy(struct shell_output *shell_output)
|
||||||
{
|
{
|
||||||
struct desktop_shell *shell = shell_output->shell;
|
struct desktop_shell *shell = shell_output->shell;
|
||||||
|
|
||||||
shell_for_each_layer(shell, shell_output_changed_move_layer, NULL);
|
if (!shell->disallow_output_changed_move) {
|
||||||
|
shell_for_each_layer(shell, shell_output_changed_move_layer, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (shell_output->panel_surface)
|
if (shell_output->panel_surface) {
|
||||||
wl_list_remove(&shell_output->panel_surface_listener.link);
|
wl_list_remove(&shell_output->panel_surface_listener.link);
|
||||||
if (shell_output->background_surface)
|
shell_output->panel_surface->committed_private = NULL;
|
||||||
|
}
|
||||||
|
if (shell_output->background_surface) {
|
||||||
wl_list_remove(&shell_output->background_surface_listener.link);
|
wl_list_remove(&shell_output->background_surface_listener.link);
|
||||||
|
shell_output->background_surface->committed_private = NULL;
|
||||||
|
}
|
||||||
wl_list_remove(&shell_output->destroy_listener.link);
|
wl_list_remove(&shell_output->destroy_listener.link);
|
||||||
wl_list_remove(&shell_output->link);
|
wl_list_remove(&shell_output->link);
|
||||||
free(shell_output);
|
free(shell_output);
|
||||||
|
|
@ -4606,7 +4489,7 @@ handle_output_resized(struct wl_listener *listener, void *data)
|
||||||
struct desktop_shell *shell =
|
struct desktop_shell *shell =
|
||||||
container_of(listener, struct desktop_shell, resized_listener);
|
container_of(listener, struct desktop_shell, resized_listener);
|
||||||
struct weston_output *output = (struct weston_output *)data;
|
struct weston_output *output = (struct weston_output *)data;
|
||||||
struct shell_output *sh_output = find_shell_output_from_weston_output(shell, output);
|
struct shell_output *sh_output = weston_output_get_shell_private(output);
|
||||||
|
|
||||||
handle_output_resized_shsurfs(shell);
|
handle_output_resized_shsurfs(shell);
|
||||||
|
|
||||||
|
|
@ -4624,6 +4507,8 @@ create_shell_output(struct desktop_shell *shell,
|
||||||
if (shell_output == NULL)
|
if (shell_output == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
weston_output_set_shell_private(output, shell_output);
|
||||||
|
|
||||||
shell_output->output = output;
|
shell_output->output = output;
|
||||||
shell_output->shell = shell;
|
shell_output->shell = shell;
|
||||||
shell_output->destroy_listener.notify = handle_output_destroy;
|
shell_output->destroy_listener.notify = handle_output_destroy;
|
||||||
|
|
@ -4631,7 +4516,7 @@ create_shell_output(struct desktop_shell *shell,
|
||||||
&shell_output->destroy_listener);
|
&shell_output->destroy_listener);
|
||||||
wl_list_insert(shell->output_list.prev, &shell_output->link);
|
wl_list_insert(shell->output_list.prev, &shell_output->link);
|
||||||
|
|
||||||
if (wl_list_length(&shell->output_list) == 1)
|
if (!shell->disallow_output_changed_move && wl_list_length(&shell->output_list) == 1)
|
||||||
shell_for_each_layer(shell,
|
shell_for_each_layer(shell,
|
||||||
shell_output_changed_move_layer, NULL);
|
shell_output_changed_move_layer, NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -4658,6 +4543,12 @@ handle_output_move_layer(struct desktop_shell *shell,
|
||||||
if (view->output != output)
|
if (view->output != output)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* We can't simply reposition popups and such, they must move with
|
||||||
|
* the parent.
|
||||||
|
*/
|
||||||
|
if (view->geometry.parent)
|
||||||
|
continue;
|
||||||
|
|
||||||
pos = weston_coord_global_add(
|
pos = weston_coord_global_add(
|
||||||
weston_view_get_pos_offset_global(view),
|
weston_view_get_pos_offset_global(view),
|
||||||
output->move);
|
output->move);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef WESTON_DESKTOP_SHELL_H
|
||||||
|
#define WESTON_DESKTOP_SHELL_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
@ -32,6 +35,169 @@
|
||||||
|
|
||||||
#include "weston-desktop-shell-server-protocol.h"
|
#include "weston-desktop-shell-server-protocol.h"
|
||||||
|
|
||||||
|
struct focus_state {
|
||||||
|
struct desktop_shell *shell;
|
||||||
|
struct weston_seat *seat;
|
||||||
|
struct workspace *ws;
|
||||||
|
struct weston_surface *keyboard_focus;
|
||||||
|
struct wl_list link;
|
||||||
|
struct wl_listener seat_destroy_listener;
|
||||||
|
struct wl_listener surface_destroy_listener;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Surface stacking and ordering.
|
||||||
|
*
|
||||||
|
* This is handled using several linked lists of surfaces, organised into
|
||||||
|
* ‘layers’. The layers are ordered, and each of the surfaces in one layer are
|
||||||
|
* above all of the surfaces in the layer below. The set of layers is static and
|
||||||
|
* in the following order (top-most first):
|
||||||
|
* • Lock layer (only ever displayed on its own)
|
||||||
|
* • Cursor layer
|
||||||
|
* • Input panel layer
|
||||||
|
* • Fullscreen layer
|
||||||
|
* • Panel layer
|
||||||
|
* • Workspace layers
|
||||||
|
* • Background layer
|
||||||
|
*
|
||||||
|
* The list of layers may be manipulated to remove whole layers of surfaces from
|
||||||
|
* display. For example, when locking the screen, all layers except the lock
|
||||||
|
* layer are removed.
|
||||||
|
*
|
||||||
|
* A surface’s layer is modified on configuring the surface, in
|
||||||
|
* set_surface_type() (which is only called when the surface’s type change is
|
||||||
|
* _committed_). If a surface’s type changes (e.g. when making a window
|
||||||
|
* fullscreen) its layer changes too.
|
||||||
|
*
|
||||||
|
* In order to allow popup and transient surfaces to be correctly stacked above
|
||||||
|
* their parent surfaces, each surface tracks both its parent surface, and a
|
||||||
|
* linked list of its children. When a surface’s layer is updated, so are the
|
||||||
|
* layers of its children. Note that child surfaces are *not* the same as
|
||||||
|
* subsurfaces — child/parent surfaces are purely for maintaining stacking
|
||||||
|
* order.
|
||||||
|
*
|
||||||
|
* The children_link list of siblings of a surface (i.e. those surfaces which
|
||||||
|
* have the same parent) only contains weston_surfaces which have a
|
||||||
|
* shell_surface. Stacking is not implemented for non-shell_surface
|
||||||
|
* weston_surfaces. This means that the following implication does *not* hold:
|
||||||
|
* (shsurf->parent != NULL) ⇒ !wl_list_is_empty(shsurf->children_link)
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct shell_surface {
|
||||||
|
struct wl_signal destroy_signal;
|
||||||
|
|
||||||
|
struct weston_desktop_surface *desktop_surface;
|
||||||
|
struct weston_view *view;
|
||||||
|
struct weston_surface *wsurface_anim_fade;
|
||||||
|
struct weston_view *wview_anim_fade;
|
||||||
|
int32_t last_width, last_height;
|
||||||
|
|
||||||
|
struct desktop_shell *shell;
|
||||||
|
|
||||||
|
struct wl_list children_list;
|
||||||
|
struct wl_list children_link;
|
||||||
|
|
||||||
|
struct weston_coord_global saved_pos;
|
||||||
|
bool saved_position_valid;
|
||||||
|
bool saved_rotation_valid;
|
||||||
|
int unresponsive, grabbed;
|
||||||
|
uint32_t resize_edges;
|
||||||
|
uint32_t orientation;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct weston_transform transform;
|
||||||
|
struct weston_matrix rotation;
|
||||||
|
} rotation;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct weston_curtain *black_view;
|
||||||
|
} fullscreen;
|
||||||
|
|
||||||
|
struct shell_output *fullscreen_output;
|
||||||
|
struct shell_output *output;
|
||||||
|
struct wl_listener output_destroy_listener;
|
||||||
|
|
||||||
|
struct surface_state {
|
||||||
|
bool fullscreen;
|
||||||
|
bool maximized;
|
||||||
|
bool lowered;
|
||||||
|
} state;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool is_set;
|
||||||
|
struct weston_coord_global pos;
|
||||||
|
} xwayland;
|
||||||
|
|
||||||
|
int focus_count;
|
||||||
|
|
||||||
|
bool destroying;
|
||||||
|
struct wl_list link; /** desktop_shell::shsurf_list */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shell_grab {
|
||||||
|
struct weston_pointer_grab grab;
|
||||||
|
struct shell_surface *shsurf;
|
||||||
|
struct wl_listener shsurf_destroy_listener;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shell_touch_grab {
|
||||||
|
struct weston_touch_grab grab;
|
||||||
|
struct shell_surface *shsurf;
|
||||||
|
struct wl_listener shsurf_destroy_listener;
|
||||||
|
struct weston_touch *touch;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shell_tablet_tool_grab {
|
||||||
|
struct weston_tablet_tool_grab grab;
|
||||||
|
struct shell_surface *shsurf;
|
||||||
|
struct wl_listener shsurf_destroy_listener;
|
||||||
|
struct weston_tablet_tool *tool;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct weston_move_grab {
|
||||||
|
struct shell_grab base;
|
||||||
|
struct weston_coord_global delta;
|
||||||
|
bool client_initiated;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct weston_touch_move_grab {
|
||||||
|
struct shell_touch_grab base;
|
||||||
|
int active;
|
||||||
|
struct weston_coord_global delta;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct weston_tablet_tool_move_grab {
|
||||||
|
struct shell_tablet_tool_grab base;
|
||||||
|
wl_fixed_t dx, dy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rotate_grab {
|
||||||
|
struct shell_grab base;
|
||||||
|
struct weston_matrix rotation;
|
||||||
|
struct {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} center;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shell_seat {
|
||||||
|
struct weston_seat *seat;
|
||||||
|
struct wl_listener seat_destroy_listener;
|
||||||
|
struct weston_surface *focused_surface;
|
||||||
|
|
||||||
|
struct wl_listener caps_changed_listener;
|
||||||
|
struct wl_listener pointer_focus_listener;
|
||||||
|
struct wl_listener keyboard_focus_listener;
|
||||||
|
struct wl_listener tablet_tool_added_listener;
|
||||||
|
|
||||||
|
struct wl_list link; /** shell::seat_list */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tablet_tool_listener {
|
||||||
|
struct wl_listener base;
|
||||||
|
struct wl_listener removed_listener;
|
||||||
|
};
|
||||||
|
|
||||||
enum animation_type {
|
enum animation_type {
|
||||||
ANIMATION_NONE,
|
ANIMATION_NONE,
|
||||||
|
|
||||||
|
|
@ -140,6 +306,7 @@ struct desktop_shell {
|
||||||
} fade;
|
} fade;
|
||||||
|
|
||||||
bool allow_zap;
|
bool allow_zap;
|
||||||
|
bool disallow_output_changed_move;
|
||||||
uint32_t binding_modifier;
|
uint32_t binding_modifier;
|
||||||
enum animation_type win_animation_type;
|
enum animation_type win_animation_type;
|
||||||
enum animation_type win_close_animation_type;
|
enum animation_type win_close_animation_type;
|
||||||
|
|
@ -176,12 +343,12 @@ get_current_workspace(struct desktop_shell *shell);
|
||||||
|
|
||||||
void
|
void
|
||||||
get_output_work_area(struct desktop_shell *shell,
|
get_output_work_area(struct desktop_shell *shell,
|
||||||
struct weston_output *output,
|
struct shell_output *output,
|
||||||
pixman_rectangle32_t *area);
|
pixman_rectangle32_t *area);
|
||||||
|
|
||||||
void
|
void
|
||||||
lower_fullscreen_layer(struct desktop_shell *shell,
|
lower_fullscreen_layer(struct desktop_shell *shell,
|
||||||
struct weston_output *lowering_output);
|
struct shell_output *lowering_output);
|
||||||
|
|
||||||
void
|
void
|
||||||
activate(struct desktop_shell *shell, struct weston_view *view,
|
activate(struct desktop_shell *shell, struct weston_view *view,
|
||||||
|
|
@ -199,3 +366,5 @@ void
|
||||||
shell_for_each_layer(struct desktop_shell *shell,
|
shell_for_each_layer(struct desktop_shell *shell,
|
||||||
shell_for_each_layer_func_t func,
|
shell_for_each_layer_func_t func,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
|
#endif /* WESTON_DESKTOP_SHELL_H */
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,8 @@ epub_exclude_files = ['search.html']
|
||||||
# -- Options for intersphinx extension ---------------------------------------
|
# -- Options for intersphinx extension ---------------------------------------
|
||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
intersphinx_mapping = {'https://docs.python.org/3': None}
|
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
|
||||||
|
|
||||||
|
|
||||||
# -- Options for todo extension ----------------------------------------------
|
# -- Options for todo extension ----------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1208,15 +1208,6 @@ HTML_COLORSTYLE_SAT = 100
|
||||||
|
|
||||||
HTML_COLORSTYLE_GAMMA = 80
|
HTML_COLORSTYLE_GAMMA = 80
|
||||||
|
|
||||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
|
||||||
# page will contain the date and time when the page was generated. Setting this
|
|
||||||
# to YES can help to show when doxygen was last run and thus if the
|
|
||||||
# documentation is up to date.
|
|
||||||
# The default value is: NO.
|
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
|
||||||
|
|
||||||
HTML_TIMESTAMP = NO
|
|
||||||
|
|
||||||
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
|
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
|
||||||
# documentation will contain sections that can be hidden and shown after the
|
# documentation will contain sections that can be hidden and shown after the
|
||||||
# page has loaded.
|
# page has loaded.
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ doxygen_conf_weston = configure_file(
|
||||||
|
|
||||||
script_data = configuration_data()
|
script_data = configuration_data()
|
||||||
script_data.set('SRCDIR', meson.current_build_dir())
|
script_data.set('SRCDIR', meson.current_build_dir())
|
||||||
script_data.set('OUTDIR', meson.current_build_dir() + '/doc')
|
script_data.set('OUTDIR', meson.current_build_dir() / 'weston')
|
||||||
|
|
||||||
# Set a different directory for doctrees to avoid installing them
|
# Set a different directory for doctrees to avoid installing them
|
||||||
script_data.set('DOCTREES_DIR', meson.current_build_dir() + '/doctrees')
|
script_data.set('DOCTREES_DIR', meson.current_build_dir() + '/doctrees')
|
||||||
|
|
@ -82,9 +82,11 @@ endif
|
||||||
sphinx_doc = custom_target(
|
sphinx_doc = custom_target(
|
||||||
'weston-doc-breathe',
|
'weston-doc-breathe',
|
||||||
command: script_doxy_sphinx,
|
command: script_doxy_sphinx,
|
||||||
output: 'doc',
|
output: 'weston',
|
||||||
build_by_default: true,
|
build_by_default: true,
|
||||||
env: sphinx_env,
|
env: sphinx_env,
|
||||||
|
install: true,
|
||||||
|
install_dir: dir_data / 'doc',
|
||||||
)
|
)
|
||||||
|
|
||||||
# we need this because we will have a stale 'doc' directory
|
# we need this because we will have a stale 'doc' directory
|
||||||
|
|
@ -93,10 +95,3 @@ docs = run_target(
|
||||||
'docs',
|
'docs',
|
||||||
command: script_doxy_sphinx,
|
command: script_doxy_sphinx,
|
||||||
)
|
)
|
||||||
|
|
||||||
install_subdir(
|
|
||||||
sphinx_doc.full_path(),
|
|
||||||
install_dir: dir_data / 'doc' / 'weston',
|
|
||||||
exclude_files: '.buildinfo',
|
|
||||||
strip_directory: true,
|
|
||||||
)
|
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,15 @@ else
|
||||||
SPHINX_WERROR=""
|
SPHINX_WERROR=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@DOXYGEN_CMD@ @DOXYGEN_CONF@ && @SPHINX_CMD@ $SPHINX_WERROR -E -q -j auto -d @DOCTREES_DIR@ @SRCDIR@ @OUTDIR@
|
set -e
|
||||||
|
|
||||||
|
BUILDINFO_ORIG="@OUTDIR@/.buildinfo"
|
||||||
|
BUILDINFO_SAVE="@SRCDIR@/buildinfo.save"
|
||||||
|
|
||||||
|
[ -f "$BUILDINFO_SAVE" ] && mv -f "$BUILDINFO_SAVE" "$BUILDINFO_ORIG"
|
||||||
|
|
||||||
|
@DOXYGEN_CMD@ @DOXYGEN_CONF@
|
||||||
|
|
||||||
|
@SPHINX_CMD@ $SPHINX_WERROR -E -q -j auto -d @DOCTREES_DIR@ @SRCDIR@ @OUTDIR@
|
||||||
|
|
||||||
|
mv -f "$BUILDINFO_ORIG" "$BUILDINFO_SAVE"
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,8 @@ the surface was added to. However, the views are not provided to the IVI
|
||||||
controller.
|
controller.
|
||||||
|
|
||||||
After configuring all expected changes, the controller must call the
|
After configuring all expected changes, the controller must call the
|
||||||
``commit_changes`` to atomically update the display layout.
|
``commit_changes`` to atomically update the display layout and call
|
||||||
|
``screen_ready`` to inform the compositor that it can start issueing repaints.
|
||||||
|
|
||||||
IVI-shell example implementation
|
IVI-shell example implementation
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ Libweston
|
||||||
libweston/shell-utils.rst
|
libweston/shell-utils.rst
|
||||||
libweston/output-management.rst
|
libweston/output-management.rst
|
||||||
libweston/log.rst
|
libweston/log.rst
|
||||||
|
libweston/debug-flight-recorder.rst
|
||||||
|
|
||||||
`Libweston` is an effort to separate the re-usable parts of Weston into a
|
`Libweston` is an effort to separate the re-usable parts of Weston into a
|
||||||
library. `Libweston` provides most of the boring and tedious bits of correctly
|
library. `Libweston` provides most of the boring and tedious bits of correctly
|
||||||
|
|
|
||||||
51
doc/sphinx/toc/libweston/debug-flight-recorder.rst
Normal file
51
doc/sphinx/toc/libweston/debug-flight-recorder.rst
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
.. _debugging flight recorder:
|
||||||
|
|
||||||
|
|
||||||
|
Debugging with Flight Recorder
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Weston can write debug scopes data to a circular ring buffer. This ring
|
||||||
|
buffer can be accessed through a debug key, assuming you have a keyboard
|
||||||
|
attached, or in case Weston dies, through a coredump. This document describes
|
||||||
|
how to access that data in the later case.
|
||||||
|
|
||||||
|
The ring buffer data can be accessed with a gdb python script that searches
|
||||||
|
the coredump file for the that ring buffer address in order to retrieve
|
||||||
|
data from it.
|
||||||
|
|
||||||
|
Prior to setting this up make sure that flight recorder is configured
|
||||||
|
accordingly. Make sure that Weston is started with the debug scopes that
|
||||||
|
you're interested into. For instance if you'd like to get the :samp:`drm-backend` one
|
||||||
|
Weston should show when starting up:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Flight recorder: enabled, scopes subscribed: drm-backend
|
||||||
|
|
||||||
|
For that Weston needs to be started with :samp:`--debug -f drm-backend`.
|
||||||
|
|
||||||
|
Also, make sure that the system is configured to generate a core dump. Refer
|
||||||
|
to :samp:`man core(5)` for how to do that.
|
||||||
|
|
||||||
|
Next you'll need the `gdb python
|
||||||
|
script <https://gitlab.freedesktop.org/wayland/weston/-/blob/main/doc/scripts/gdb/flight_rec.py>`_,
|
||||||
|
as that will be needed to search for the ring buffer within the coredump.
|
||||||
|
|
||||||
|
Finally, to make this easier and push everything from the ring buffer to a
|
||||||
|
file, we would need to create a batch gdb file script to invoke the commands
|
||||||
|
for us.
|
||||||
|
|
||||||
|
As an example name that file :file:`test.gdb` and add the following to entries
|
||||||
|
to it, making sure to adjust the path for the python script.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
source /path/to/flight_rec.py
|
||||||
|
display_flight_rec
|
||||||
|
|
||||||
|
Then run the following commands to dump the contents of the ring buffer
|
||||||
|
straight to a file:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
$ gdb --batch --command=/path/to/test.gdb -q /path/to/test/weston/binary --core /path/to/coredump &> dump.log.txt
|
||||||
|
|
@ -141,8 +141,9 @@ force the contents to be printed on :samp:`stdout` file-descriptor.
|
||||||
The user has first to specify which log scope to subscribe to.
|
The user has first to specify which log scope to subscribe to.
|
||||||
|
|
||||||
Specifying which scopes to subscribe for the flight-recorder can be done using
|
Specifying which scopes to subscribe for the flight-recorder can be done using
|
||||||
:samp:`--flight-rec-scopes`. By default, the 'log' scope and 'drm-backend' are
|
:samp:`-f|--flight-rec-scopes`. By default, only the 'log' scope is subscribed
|
||||||
the scopes subscribed to.
|
to. See :ref:`debugging flight recorder` on how retrieve the contents of the
|
||||||
|
flight recorder in case Weston dies/crashes unexpectedly.
|
||||||
|
|
||||||
weston-debug protocol
|
weston-debug protocol
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
@ -178,6 +179,13 @@ The following illustrates how to use it:
|
||||||
./weston-debug timeline > log.json
|
./weston-debug timeline > log.json
|
||||||
./wesgr -i log.json -o log.svg
|
./wesgr -i log.json -o log.svg
|
||||||
|
|
||||||
|
Weston has experimental support for `Perfetto <https://perfetto.dev>`_ for
|
||||||
|
performance profiling. It can be enabled by using `-Dperfetto=true` during
|
||||||
|
the meson invocation to configure the build.
|
||||||
|
|
||||||
|
If Perfetto support is built in, timeline points are added to Perfetto tracks
|
||||||
|
when Perfetto is running, even when the 'timeline' scope is not enabled.
|
||||||
|
|
||||||
Inserting timeline points
|
Inserting timeline points
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
@ -186,6 +194,13 @@ take the :type:`weston_compositor` instance, followed by the name of the
|
||||||
timeline point. What follows next is a variable number of arguments, which
|
timeline point. What follows next is a variable number of arguments, which
|
||||||
**must** end with the macro :c:macro:`TLP_END`.
|
**must** end with the macro :c:macro:`TLP_END`.
|
||||||
|
|
||||||
|
Adding Perfetto trace points
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
In addition to timeline points, Perfetto can also display timing information
|
||||||
|
for individual functions. The easiest way to add profiling data for a function
|
||||||
|
is to insert the :c:macro:`WESTON_TRACE_FUNC` at the top of the function.
|
||||||
|
|
||||||
Debug protocol API
|
Debug protocol API
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
files = [
|
files = [
|
||||||
'compositor.rst',
|
'compositor.rst',
|
||||||
'head.rst',
|
'head.rst',
|
||||||
|
'debug-flight-recorder.rst',
|
||||||
'log.rst',
|
'log.rst',
|
||||||
'output.rst',
|
'output.rst',
|
||||||
'output-management.rst',
|
'output-management.rst',
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,15 @@ stitching them together is performed by a *renderer*. By doing so, it is
|
||||||
compositing all surfaces into a single image, which is being handed out to a
|
compositing all surfaces into a single image, which is being handed out to a
|
||||||
back-end, and finally, displayed on the screen.
|
back-end, and finally, displayed on the screen.
|
||||||
|
|
||||||
libweston provides two useful renderers. One uses
|
libweston provides multiple useful renderers. There are
|
||||||
`OpenGL ES <https://www.khronos.org/opengles/>`_, which will often be accelerated
|
`OpenGL ES <https://www.khronos.org/opengles/>`_ and
|
||||||
by your GPU when suitable drivers are installed. The other uses the
|
`Vulkan <https://www.vulkan.org/>`_ renderers, which will often be accelerated
|
||||||
`Pixman <http://www.pixman.org>`_ library which is entirely CPU (software)
|
by your GPU when suitable drivers are installed.
|
||||||
rendered. You can select between these with the ``--renderer=gl`` and
|
Another uses the `Pixman <http://www.pixman.org>`_ library which is entirely
|
||||||
``--renderer=pixman`` arguments when starting Weston.
|
CPU (software) rendered.
|
||||||
|
|
||||||
|
You can select between these with the ``--renderer=gl``, ``--renderer=vulkan``
|
||||||
|
and ``--renderer=pixman`` arguments when starting Weston.
|
||||||
|
|
||||||
Multi-back-end support
|
Multi-back-end support
|
||||||
----------------------
|
----------------------
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,8 @@ Standalone tests
|
||||||
Standalone tests do not have a fixture setup function defined in the test
|
Standalone tests do not have a fixture setup function defined in the test
|
||||||
program or the fixture setup function calls
|
program or the fixture setup function calls
|
||||||
:func:`weston_test_harness_execute_standalone` explicitly. All test cases must
|
:func:`weston_test_harness_execute_standalone` explicitly. All test cases must
|
||||||
be defined with :c:func:`TEST` or :c:func:`TEST_P`.
|
be defined with :c:func:`TEST` or :c:func:`TEST_P`, and each such function must
|
||||||
|
return a value from :type:`test_result_code`.
|
||||||
|
|
||||||
This is the simplest possible test example:
|
This is the simplest possible test example:
|
||||||
|
|
||||||
|
|
@ -98,7 +99,7 @@ This is the simplest possible test example:
|
||||||
|
|
||||||
TEST(always_success)
|
TEST(always_success)
|
||||||
{
|
{
|
||||||
/* true */
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -110,7 +111,8 @@ Plugin tests
|
||||||
Plugin tests must have a fixture setup function that calls
|
Plugin tests must have a fixture setup function that calls
|
||||||
:func:`weston_test_harness_execute_as_plugin`. All test cases must be defined
|
:func:`weston_test_harness_execute_as_plugin`. All test cases must be defined
|
||||||
with :c:func:`PLUGIN_TEST` which declares an implicit function argument
|
with :c:func:`PLUGIN_TEST` which declares an implicit function argument
|
||||||
:type:`weston_compositor` ``*compositor``.
|
:type:`weston_compositor` ``*compositor``. Each such function must
|
||||||
|
return a value from :type:`test_result_code`.
|
||||||
|
|
||||||
The compositor fixture manufactures the necessary environment variables and the
|
The compositor fixture manufactures the necessary environment variables and the
|
||||||
command line argument array to launch Weston, and calls :func:`wet_main`
|
command line argument array to launch Weston, and calls :func:`wet_main`
|
||||||
|
|
@ -137,6 +139,7 @@ This is an example of a plugin test that just logs a line:
|
||||||
{
|
{
|
||||||
/* struct weston_compositor *compositor; */
|
/* struct weston_compositor *compositor; */
|
||||||
testlog("Got compositor %p\n", compositor);
|
testlog("Got compositor %p\n", compositor);
|
||||||
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -147,7 +150,8 @@ Client tests
|
||||||
|
|
||||||
Plugin tests must have a fixture setup function that calls
|
Plugin tests must have a fixture setup function that calls
|
||||||
:func:`weston_test_harness_execute_as_client`. All test cases must be
|
:func:`weston_test_harness_execute_as_client`. All test cases must be
|
||||||
defined with :c:func:`TEST` or :c:func:`TEST_P`.
|
defined with :c:func:`TEST` or :c:func:`TEST_P`, and each such function must
|
||||||
|
return a value from :type:`test_result_code`.
|
||||||
|
|
||||||
The compositor fixture manufactures the necessary environment variables and the
|
The compositor fixture manufactures the necessary environment variables and the
|
||||||
command line argument array to launch Weston, and calls :func:`wet_main`
|
command line argument array to launch Weston, and calls :func:`wet_main`
|
||||||
|
|
@ -202,6 +206,7 @@ clients:
|
||||||
|
|
||||||
expect_protocol_error(client, &wp_viewport_interface,
|
expect_protocol_error(client, &wp_viewport_interface,
|
||||||
WP_VIEWPORT_ERROR_BAD_VALUE);
|
WP_VIEWPORT_ERROR_BAD_VALUE);
|
||||||
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(test_roundtrip)
|
TEST(test_roundtrip)
|
||||||
|
|
@ -210,6 +215,7 @@ clients:
|
||||||
|
|
||||||
client = create_client_and_test_surface(100, 50, 123, 77);
|
client = create_client_and_test_surface(100, 50, 123, 77);
|
||||||
client_roundtrip(client);
|
client_roundtrip(client);
|
||||||
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -257,15 +263,6 @@ type of tests to keep the fixture setup simple. See
|
||||||
:ref:`test-suite-standalone`, :ref:`test-suite-plugin` and
|
:ref:`test-suite-standalone`, :ref:`test-suite-plugin` and
|
||||||
:ref:`test-suite-client` how to set up each type in a test program.
|
:ref:`test-suite-client` how to set up each type in a test program.
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
**TODO:** Currently it is not possible to gracefully skip or fail a test.
|
|
||||||
You can skip with ``exit(RESULT_SKIP)`` but that will quit the whole test
|
|
||||||
program and all defined tests that were not ran yet will be counted as
|
|
||||||
failed. You can fail a test by any means, e.g. ``exit(RESULT_FAIL)``, but
|
|
||||||
the same caveat applies. Succeeded tests must simply return and not call any
|
|
||||||
exit function.
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:hidden:
|
:hidden:
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include <libweston/config-parser.h>
|
#include <libweston/config-parser.h>
|
||||||
|
|
||||||
#include "shared/helpers.h"
|
#include "shared/helpers.h"
|
||||||
|
#include "shared/string-helpers.h"
|
||||||
#include "weston-private.h"
|
#include "weston-private.h"
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -64,12 +65,10 @@ get_backend_from_string(const char *name,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct {
|
static const struct weston_enum_map renderer_name_map[] = {
|
||||||
char *name;
|
|
||||||
enum weston_renderer_type renderer;
|
|
||||||
} renderer_name_map[] = {
|
|
||||||
{ "auto", WESTON_RENDERER_AUTO },
|
{ "auto", WESTON_RENDERER_AUTO },
|
||||||
{ "gl", WESTON_RENDERER_GL },
|
{ "gl", WESTON_RENDERER_GL },
|
||||||
|
{ "vulkan", WESTON_RENDERER_VULKAN },
|
||||||
{ "noop", WESTON_RENDERER_NOOP },
|
{ "noop", WESTON_RENDERER_NOOP },
|
||||||
{ "pixman", WESTON_RENDERER_PIXMAN },
|
{ "pixman", WESTON_RENDERER_PIXMAN },
|
||||||
};
|
};
|
||||||
|
|
@ -78,16 +77,15 @@ bool
|
||||||
get_renderer_from_string(const char *name,
|
get_renderer_from_string(const char *name,
|
||||||
enum weston_renderer_type *renderer)
|
enum weston_renderer_type *renderer)
|
||||||
{
|
{
|
||||||
size_t i;
|
const struct weston_enum_map *entry;
|
||||||
|
|
||||||
if (!name)
|
if (!name)
|
||||||
name = "auto";
|
name = "auto";
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(renderer_name_map); i++) {
|
entry = weston_enum_map_find_name(renderer_name_map, name);
|
||||||
if (strcmp(name, renderer_name_map[i].name) == 0) {
|
if (entry) {
|
||||||
*renderer = renderer_name_map[i].renderer;
|
*renderer = entry->value;
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
1103
frontend/main.c
1103
frontend/main.c
File diff suppressed because it is too large
Load diff
|
|
@ -16,6 +16,7 @@ deps_weston = [
|
||||||
dep_libevdev,
|
dep_libevdev,
|
||||||
dep_libdl,
|
dep_libdl,
|
||||||
dep_threads,
|
dep_threads,
|
||||||
|
dep_libdisplay_info,
|
||||||
]
|
]
|
||||||
|
|
||||||
if get_option('xwayland')
|
if get_option('xwayland')
|
||||||
|
|
@ -67,7 +68,8 @@ install_data(
|
||||||
install_dir: dir_data / 'wayland-sessions'
|
install_dir: dir_data / 'wayland-sessions'
|
||||||
)
|
)
|
||||||
|
|
||||||
if get_option('screenshare')
|
if get_option('deprecated-screenshare') and get_option('deprecated-shell-fullscreen')
|
||||||
|
warning('deprecated-screenshare. This will go away, see https://gitlab.freedesktop.org/wayland/weston/-/issues/848. Consider using mirroring (see man page) for same functionality and better performance.')
|
||||||
srcs_screenshare = [
|
srcs_screenshare = [
|
||||||
'screen-share.c',
|
'screen-share.c',
|
||||||
fullscreen_shell_unstable_v1_client_protocol_h,
|
fullscreen_shell_unstable_v1_client_protocol_h,
|
||||||
|
|
|
||||||
|
|
@ -371,7 +371,13 @@ ss_seat_create(struct shared_output *so, uint32_t id)
|
||||||
if (seat == NULL)
|
if (seat == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
weston_seat_init(&seat->base, so->output->compositor, "screen-share");
|
if (so->output) {
|
||||||
|
weston_seat_init(&seat->base, so->output->compositor, "screen-share");
|
||||||
|
} else {
|
||||||
|
weston_log("Skip seat creation the screen share output has not an output compositor\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
seat->output = so;
|
seat->output = so;
|
||||||
seat->id = id;
|
seat->id = id;
|
||||||
seat->parent.seat = wl_registry_bind(so->parent.registry, id,
|
seat->parent.seat = wl_registry_bind(so->parent.registry, id,
|
||||||
|
|
@ -970,6 +976,8 @@ shared_output_create(struct weston_output *output, struct screen_share *ss, int
|
||||||
if (!so->parent.display)
|
if (!so->parent.display)
|
||||||
goto err_alloc;
|
goto err_alloc;
|
||||||
|
|
||||||
|
/* Set Weston output reference in the shared output before registry */
|
||||||
|
so->output = output;
|
||||||
so->parent.registry = wl_display_get_registry(so->parent.display);
|
so->parent.registry = wl_display_get_registry(so->parent.display);
|
||||||
if (!so->parent.registry)
|
if (!so->parent.registry)
|
||||||
goto err_display;
|
goto err_display;
|
||||||
|
|
@ -1033,7 +1041,6 @@ shared_output_create(struct weston_output *output, struct screen_share *ss, int
|
||||||
wl_list_init(&so->shm.buffers);
|
wl_list_init(&so->shm.buffers);
|
||||||
wl_list_init(&so->shm.free_buffers);
|
wl_list_init(&so->shm.free_buffers);
|
||||||
|
|
||||||
so->output = output;
|
|
||||||
so->output_destroyed.notify = output_destroyed;
|
so->output_destroyed.notify = output_destroyed;
|
||||||
wl_signal_add(&so->output->destroy_signal, &so->output_destroyed);
|
wl_signal_add(&so->output->destroy_signal, &so->output_destroyed);
|
||||||
|
|
||||||
|
|
@ -1079,7 +1086,8 @@ shared_output_destroy(struct shared_output *so)
|
||||||
wl_list_remove(&so->output_destroyed.link);
|
wl_list_remove(&so->output_destroyed.link);
|
||||||
wl_list_remove(&so->frame_listener.link);
|
wl_list_remove(&so->frame_listener.link);
|
||||||
|
|
||||||
pixman_image_unref(so->cache_image);
|
if (so->cache_image)
|
||||||
|
pixman_image_unref(so->cache_image);
|
||||||
free(so->tmp_data);
|
free(so->tmp_data);
|
||||||
|
|
||||||
free(so);
|
free(so);
|
||||||
|
|
|
||||||
|
|
@ -53,3 +53,8 @@ wet_output_set_colorimetry_mode(struct weston_output *output,
|
||||||
|
|
||||||
typedef void (*wet_head_additional_setup)(struct weston_head *head,
|
typedef void (*wet_head_additional_setup)(struct weston_head *head,
|
||||||
struct weston_head *head_to_mirror);
|
struct weston_head *head_to_mirror);
|
||||||
|
|
||||||
|
struct weston_color_profile *
|
||||||
|
wet_create_output_color_profile(struct weston_output *output,
|
||||||
|
struct weston_config *wc,
|
||||||
|
const char *prof_name);
|
||||||
|
|
|
||||||
|
|
@ -260,8 +260,10 @@ wet_load_xwayland(struct weston_compositor *comp)
|
||||||
wxw->compositor = comp;
|
wxw->compositor = comp;
|
||||||
wxw->api = api;
|
wxw->api = api;
|
||||||
wxw->xwayland = xwayland;
|
wxw->xwayland = xwayland;
|
||||||
if (api->listen(xwayland, wxw, spawn_xserver) < 0)
|
if (api->listen(xwayland, wxw, spawn_xserver) < 0) {
|
||||||
|
free(wxw);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return wxw;
|
return wxw;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -353,6 +353,8 @@ fs_output_create(struct fullscreen_shell *shell, struct weston_output *output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
weston_output_set_ready(output);
|
||||||
|
|
||||||
return fsout;
|
return fsout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
if get_option('shell-fullscreen')
|
if get_option('deprecated-shell-fullscreen')
|
||||||
|
warning('deprecated-shell-fullscreen enabled. This will go away, see https://gitlab.freedesktop.org/wayland/weston/-/issues/848')
|
||||||
|
|
||||||
srcs_shell_fullscreen = [
|
srcs_shell_fullscreen = [
|
||||||
'fullscreen-shell.c',
|
'fullscreen-shell.c',
|
||||||
fullscreen_shell_unstable_v1_server_protocol_h,
|
fullscreen_shell_unstable_v1_server_protocol_h,
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,14 @@ struct weston_drm_backend_config {
|
||||||
* rendering device.
|
* rendering device.
|
||||||
*/
|
*/
|
||||||
char *additional_devices;
|
char *additional_devices;
|
||||||
|
|
||||||
|
/** Try to offload blend-to-output color transformation
|
||||||
|
*
|
||||||
|
* As KMS currently only supports to offload the transformation in a
|
||||||
|
* LUT, this may result in precision issues. Also, this requires
|
||||||
|
* "color-management" to be enabled.
|
||||||
|
*/
|
||||||
|
bool offload_blend_to_output;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,11 @@ struct weston_headless_backend_config {
|
||||||
* mHz to 1,000,000 mHz. 0 is a special value that triggers repaints
|
* mHz to 1,000,000 mHz. 0 is a special value that triggers repaints
|
||||||
* only on capture requests, not on damages. */
|
* only on capture requests, not on damages. */
|
||||||
int refresh;
|
int refresh;
|
||||||
|
|
||||||
|
/** Create a fake seat, some clients may complain without a wl_seat.
|
||||||
|
* The default is not to create a wl_seat.
|
||||||
|
*/
|
||||||
|
bool fake_seat;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -54,19 +54,20 @@ struct weston_pipewire_output_api {
|
||||||
const char *name,
|
const char *name,
|
||||||
const struct pipewire_config *config);
|
const struct pipewire_config *config);
|
||||||
|
|
||||||
/** Set the size of a PipeWire output to the specified width and height.
|
/** Set the size and frame rate of a PipeWire output to the specified value.
|
||||||
*
|
*
|
||||||
* If the width or height are set to -1, the size of the underlying
|
* If the width or height or framerate are set to -1, the size or frame rate
|
||||||
* PipeWire head will be used.
|
* of the underlying PipeWire head will be used.
|
||||||
*
|
*
|
||||||
* \param output The weston output for which the size shall be set
|
* \param output The weston output for which the size shall be set
|
||||||
* \param width Desired width of the output
|
* \param width Desired width of the output
|
||||||
* \param height Desired height of the output
|
* \param height Desired height of the output
|
||||||
|
* \param framerate Desired frame rate of the output
|
||||||
*
|
*
|
||||||
* Returns 0 on success, -1 on failure.
|
* Returns 0 on success, -1 on failure.
|
||||||
*/
|
*/
|
||||||
int (*output_set_size)(struct weston_output *output,
|
int (*output_set_size)(struct weston_output *output,
|
||||||
int width, int height);
|
int width, int height, int framerate);
|
||||||
|
|
||||||
/** The pixel format to be used by the output.
|
/** The pixel format to be used by the output.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
358
include/libweston/colorimetry.h
Normal file
358
include/libweston/colorimetry.h
Normal file
|
|
@ -0,0 +1,358 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2008-2011 Kristian Høgsberg
|
||||||
|
* Copyright © 2012-2025 Collabora, Ltd.
|
||||||
|
* Copyright © 2017, 2018 General Electric Company
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial
|
||||||
|
* portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <libweston/linalg-3.h>
|
||||||
|
|
||||||
|
struct weston_compositor;
|
||||||
|
struct weston_color_profile_param_builder;
|
||||||
|
struct weston_color_profile;
|
||||||
|
struct weston_color_transform;
|
||||||
|
|
||||||
|
/** Colorimetry mode for outputs and heads
|
||||||
|
*
|
||||||
|
* A list of colorimetry modes for driving displays, defined by ANSI/CTA-861-H.
|
||||||
|
*
|
||||||
|
* On heads, a bitmask of one or more entries shows which modes are claimed
|
||||||
|
* supported.
|
||||||
|
*
|
||||||
|
* On outputs, the mode to be used for driving the video sink.
|
||||||
|
*
|
||||||
|
* Default (RGB) colorimetry differs from all the others in that the signal
|
||||||
|
* colorimetry is not defined here. It is defined by the video sink, and it
|
||||||
|
* may be described in e.g. EDID.
|
||||||
|
*/
|
||||||
|
enum weston_colorimetry_mode {
|
||||||
|
/** Invalid colorimetry mode, or none supported. */
|
||||||
|
WESTON_COLORIMETRY_MODE_NONE = 0,
|
||||||
|
|
||||||
|
/** Default (RGB) colorimetry, video sink dependant */
|
||||||
|
WESTON_COLORIMETRY_MODE_DEFAULT = 0x01,
|
||||||
|
|
||||||
|
/** Rec. ITU-R BT.2020 constant luminance YCbCr */
|
||||||
|
WESTON_COLORIMETRY_MODE_BT2020_CYCC = 0x02,
|
||||||
|
|
||||||
|
/** Rec. ITU-R BT.2020 non-constant luminance YCbCr */
|
||||||
|
WESTON_COLORIMETRY_MODE_BT2020_YCC = 0x04,
|
||||||
|
|
||||||
|
/** Rec. ITU-R BT.2020 RGB */
|
||||||
|
WESTON_COLORIMETRY_MODE_BT2020_RGB = 0x08,
|
||||||
|
|
||||||
|
/** SMPTE ST 2113 DCI-P3 RGB D65 */
|
||||||
|
WESTON_COLORIMETRY_MODE_P3D65 = 0x10,
|
||||||
|
|
||||||
|
/** SMPTE ST 2113 DCI-P3 RGB Theater */
|
||||||
|
WESTON_COLORIMETRY_MODE_P3DCI = 0x20,
|
||||||
|
|
||||||
|
/** Rec. ITU-R BT.2100 ICtCp HDR (with PQ and/or HLG)*/
|
||||||
|
WESTON_COLORIMETRY_MODE_ICTCP = 0x40,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Bitmask of all defined colorimetry modes */
|
||||||
|
#define WESTON_COLORIMETRY_MODE_ALL_MASK \
|
||||||
|
((uint32_t)(WESTON_COLORIMETRY_MODE_DEFAULT | \
|
||||||
|
WESTON_COLORIMETRY_MODE_BT2020_CYCC | \
|
||||||
|
WESTON_COLORIMETRY_MODE_BT2020_YCC | \
|
||||||
|
WESTON_COLORIMETRY_MODE_BT2020_RGB | \
|
||||||
|
WESTON_COLORIMETRY_MODE_P3D65 | \
|
||||||
|
WESTON_COLORIMETRY_MODE_P3DCI | \
|
||||||
|
WESTON_COLORIMETRY_MODE_ICTCP))
|
||||||
|
|
||||||
|
const char *
|
||||||
|
weston_colorimetry_mode_to_str(enum weston_colorimetry_mode c);
|
||||||
|
|
||||||
|
/** EOTF mode for outputs and heads
|
||||||
|
*
|
||||||
|
* A list of EOTF modes for driving displays, defined by CTA-861-G for
|
||||||
|
* Dynamic Range and Mastering InfoFrame.
|
||||||
|
*
|
||||||
|
* On heads, a bitmask of one or more entries shows which modes are claimed
|
||||||
|
* supported.
|
||||||
|
*
|
||||||
|
* On outputs, the mode to be used for driving the video sink.
|
||||||
|
*
|
||||||
|
* For traditional non-HDR sRGB, use WESTON_EOTF_MODE_SDR.
|
||||||
|
*/
|
||||||
|
enum weston_eotf_mode {
|
||||||
|
/** Invalid EOTF mode, or none supported. */
|
||||||
|
WESTON_EOTF_MODE_NONE = 0,
|
||||||
|
|
||||||
|
/** Traditional gamma, SDR luminance range */
|
||||||
|
WESTON_EOTF_MODE_SDR = 0x01,
|
||||||
|
|
||||||
|
/** Traditional gamma, HDR luminance range */
|
||||||
|
WESTON_EOTF_MODE_TRADITIONAL_HDR = 0x02,
|
||||||
|
|
||||||
|
/** Preceptual quantizer, SMPTE ST 2084 */
|
||||||
|
WESTON_EOTF_MODE_ST2084 = 0x04,
|
||||||
|
|
||||||
|
/** Hybrid log-gamma, ITU-R BT.2100 */
|
||||||
|
WESTON_EOTF_MODE_HLG = 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Bitmask of all defined EOTF modes */
|
||||||
|
#define WESTON_EOTF_MODE_ALL_MASK \
|
||||||
|
((uint32_t)(WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | \
|
||||||
|
WESTON_EOTF_MODE_ST2084 | WESTON_EOTF_MODE_HLG))
|
||||||
|
|
||||||
|
const char *
|
||||||
|
weston_eotf_mode_to_str(enum weston_eotf_mode e);
|
||||||
|
|
||||||
|
/** CIE 1931 xy chromaticity coordinates */
|
||||||
|
struct weston_CIExy {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Chromaticity coordinates and white point that defines the color gamut */
|
||||||
|
struct weston_color_gamut {
|
||||||
|
struct weston_CIExy primary[3]; /* RGB order */
|
||||||
|
struct weston_CIExy white_point;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum weston_npm_direction {
|
||||||
|
WESTON_NPM_FORWARD,
|
||||||
|
WESTON_NPM_INVERSE
|
||||||
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_normalized_primary_matrix_init(struct weston_mat3f *npm,
|
||||||
|
const struct weston_color_gamut *gamut,
|
||||||
|
enum weston_npm_direction dir);
|
||||||
|
|
||||||
|
struct weston_mat3f
|
||||||
|
weston_bradford_adaptation(struct weston_CIExy from, struct weston_CIExy to);
|
||||||
|
|
||||||
|
/** Color primaries known by libweston */
|
||||||
|
enum weston_color_primaries {
|
||||||
|
WESTON_PRIMARIES_CICP_SRGB = 0,
|
||||||
|
WESTON_PRIMARIES_CICP_PAL_M,
|
||||||
|
WESTON_PRIMARIES_CICP_PAL,
|
||||||
|
WESTON_PRIMARIES_CICP_NTSC,
|
||||||
|
WESTON_PRIMARIES_CICP_GENERIC_FILM,
|
||||||
|
WESTON_PRIMARIES_CICP_BT2020,
|
||||||
|
WESTON_PRIMARIES_CICP_CIE1931_XYZ,
|
||||||
|
WESTON_PRIMARIES_CICP_DCI_P3,
|
||||||
|
WESTON_PRIMARIES_CICP_DISPLAY_P3,
|
||||||
|
WESTON_PRIMARIES_ADOBE_RGB,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Transfer functions known by libweston */
|
||||||
|
enum weston_transfer_function {
|
||||||
|
WESTON_TF_BT1886 = 0,
|
||||||
|
WESTON_TF_GAMMA22,
|
||||||
|
WESTON_TF_GAMMA28,
|
||||||
|
WESTON_TF_SRGB,
|
||||||
|
WESTON_TF_EXT_SRGB,
|
||||||
|
WESTON_TF_ST240,
|
||||||
|
WESTON_TF_ST428,
|
||||||
|
WESTON_TF_ST2084_PQ,
|
||||||
|
WESTON_TF_EXT_LINEAR,
|
||||||
|
WESTON_TF_LOG_100,
|
||||||
|
WESTON_TF_LOG_316,
|
||||||
|
WESTON_TF_XVYCC,
|
||||||
|
WESTON_TF_HLG,
|
||||||
|
WESTON_TF_POWER,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum weston_alpha_mode {
|
||||||
|
WESTON_ALPHA_MODE_PREMULTIPLIED_ELECTRICAL = 0,
|
||||||
|
WESTON_ALPHA_MODE_PREMULTIPLIED_OPTICAL,
|
||||||
|
WESTON_ALPHA_MODE_STRAIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum weston_color_matrix_coef {
|
||||||
|
WESTON_COLOR_MATRIX_COEF_UNSET = 0,
|
||||||
|
WESTON_COLOR_MATRIX_COEF_IDENTITY,
|
||||||
|
WESTON_COLOR_MATRIX_COEF_BT601,
|
||||||
|
WESTON_COLOR_MATRIX_COEF_BT709,
|
||||||
|
WESTON_COLOR_MATRIX_COEF_BT2020,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum weston_color_quant_range {
|
||||||
|
WESTON_COLOR_QUANT_RANGE_UNSET = 0,
|
||||||
|
WESTON_COLOR_QUANT_RANGE_FULL,
|
||||||
|
WESTON_COLOR_QUANT_RANGE_LIMITED,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum weston_ycbcr_chroma_location {
|
||||||
|
WESTON_YCBCR_CHROMA_LOCATION_UNSET = 0,
|
||||||
|
WESTON_YCBCR_CHROMA_LOCATION_TYPE_0,
|
||||||
|
WESTON_YCBCR_CHROMA_LOCATION_TYPE_1,
|
||||||
|
WESTON_YCBCR_CHROMA_LOCATION_TYPE_2,
|
||||||
|
WESTON_YCBCR_CHROMA_LOCATION_TYPE_3,
|
||||||
|
WESTON_YCBCR_CHROMA_LOCATION_TYPE_4,
|
||||||
|
WESTON_YCBCR_CHROMA_LOCATION_TYPE_5,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Error codes that the color profile parameters functions may return. */
|
||||||
|
enum weston_color_profile_param_builder_error {
|
||||||
|
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF = 0,
|
||||||
|
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES_NAMED,
|
||||||
|
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
|
||||||
|
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CREATE_FAILED,
|
||||||
|
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
|
||||||
|
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
|
||||||
|
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
|
||||||
|
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct weston_color_profile_param_builder *
|
||||||
|
weston_color_profile_param_builder_create(struct weston_compositor *compositor);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_get_error(struct weston_color_profile_param_builder *builder,
|
||||||
|
enum weston_color_profile_param_builder_error *err,
|
||||||
|
char **err_msg);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
|
||||||
|
const struct weston_color_gamut *primaries);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
|
||||||
|
enum weston_color_primaries primaries);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
|
||||||
|
enum weston_transfer_function tf);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
|
||||||
|
float power_exponent);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_set_primary_luminance(struct weston_color_profile_param_builder *builder,
|
||||||
|
float ref_lum, float min_lum, float max_lum);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
|
||||||
|
const struct weston_color_gamut *target_primaries);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_set_target_primaries_named(struct weston_color_profile_param_builder *builder,
|
||||||
|
enum weston_color_primaries target_primaries);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
|
||||||
|
float min_lum, float max_lum);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
|
||||||
|
float maxFALL);
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
|
||||||
|
float maxCLL);
|
||||||
|
|
||||||
|
struct weston_color_profile *
|
||||||
|
weston_color_profile_param_builder_create_color_profile(struct weston_color_profile_param_builder *builder,
|
||||||
|
const char *name_part,
|
||||||
|
enum weston_color_profile_param_builder_error *err,
|
||||||
|
char **err_msg);
|
||||||
|
|
||||||
|
enum weston_color_characteristics_groups {
|
||||||
|
/** weston_color_characteristics::primary is set */
|
||||||
|
WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01,
|
||||||
|
|
||||||
|
/** weston_color_characteristics::white is set */
|
||||||
|
WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE = 0x02,
|
||||||
|
|
||||||
|
/** weston_color_characteristics::max_luminance is set */
|
||||||
|
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL = 0x04,
|
||||||
|
|
||||||
|
/** weston_color_characteristics::min_luminance is set */
|
||||||
|
WESTON_COLOR_CHARACTERISTICS_GROUP_MINL = 0x08,
|
||||||
|
|
||||||
|
/** weston_color_characteristics::maxFALL is set */
|
||||||
|
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL = 0x10,
|
||||||
|
|
||||||
|
/** all valid bits */
|
||||||
|
WESTON_COLOR_CHARACTERISTICS_GROUP_ALL_MASK = 0x1f
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Basic display color characteristics
|
||||||
|
*
|
||||||
|
* This is a simple description of a display or output (monitor) color
|
||||||
|
* characteristics. The parameters can be found in EDID, with caveats. They
|
||||||
|
* are particularly useful with HDR monitors.
|
||||||
|
*/
|
||||||
|
struct weston_color_characteristics {
|
||||||
|
/** Which fields are valid
|
||||||
|
*
|
||||||
|
* A bitmask of values from enum weston_color_characteristics_groups.
|
||||||
|
*/
|
||||||
|
uint32_t group_mask;
|
||||||
|
|
||||||
|
/* EOTF is tracked externally with enum weston_eotf_mode */
|
||||||
|
|
||||||
|
/** Chromaticities of the primaries */
|
||||||
|
struct weston_CIExy primary[3];
|
||||||
|
|
||||||
|
/** White point chromaticity */
|
||||||
|
struct weston_CIExy white;
|
||||||
|
|
||||||
|
/** Display's desired maximum content peak luminance, cd/m² */
|
||||||
|
float max_luminance;
|
||||||
|
|
||||||
|
/** Display's desired minimum content luminance, cd/m² */
|
||||||
|
float min_luminance;
|
||||||
|
|
||||||
|
/** Display's desired maximum frame-average light level, cd/m² */
|
||||||
|
float maxFALL;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct weston_color_profile *
|
||||||
|
weston_color_profile_ref(struct weston_color_profile *cprof);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_color_profile_unref(struct weston_color_profile *cprof);
|
||||||
|
|
||||||
|
const char *
|
||||||
|
weston_color_profile_get_description(struct weston_color_profile *cprof);
|
||||||
|
|
||||||
|
char *
|
||||||
|
weston_color_profile_get_details(struct weston_color_profile *cprof);
|
||||||
|
|
||||||
|
struct weston_color_profile *
|
||||||
|
weston_compositor_load_icc_file(struct weston_compositor *compositor,
|
||||||
|
const char *path);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -32,6 +32,7 @@ extern "C" {
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#define WESTON_CONFIG_FILE_ENV_VAR "WESTON_CONFIG_FILE"
|
#define WESTON_CONFIG_FILE_ENV_VAR "WESTON_CONFIG_FILE"
|
||||||
|
|
||||||
|
|
@ -107,6 +108,20 @@ int weston_config_next_section(struct weston_config *config,
|
||||||
uint32_t
|
uint32_t
|
||||||
weston_config_get_binding_modifier(struct weston_config *config, uint32_t default_mod);
|
weston_config_get_binding_modifier(struct weston_config *config, uint32_t default_mod);
|
||||||
|
|
||||||
|
/** Container for an array of strings. */
|
||||||
|
struct weston_string_array {
|
||||||
|
/** Length of \c array. */
|
||||||
|
size_t len;
|
||||||
|
/** Pointer to an array of strings. */
|
||||||
|
char **array;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_string_array_fini(struct weston_string_array *strarr);
|
||||||
|
|
||||||
|
struct weston_string_array
|
||||||
|
weston_parse_space_separated_list(const char *str);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ extern "C" {
|
||||||
|
|
||||||
#include <libweston/matrix.h>
|
#include <libweston/matrix.h>
|
||||||
#include <libweston/zalloc.h>
|
#include <libweston/zalloc.h>
|
||||||
|
#include <libweston/colorimetry.h>
|
||||||
|
|
||||||
struct weston_log_pacer {
|
struct weston_log_pacer {
|
||||||
/** This must be set to zero before first use */
|
/** This must be set to zero before first use */
|
||||||
|
|
@ -73,6 +74,12 @@ struct weston_point2d_device_normalized {
|
||||||
double y;
|
double y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct weston_commit_timing_target {
|
||||||
|
bool valid;
|
||||||
|
bool satisfied;
|
||||||
|
struct timespec time;
|
||||||
|
};
|
||||||
|
|
||||||
struct weston_compositor;
|
struct weston_compositor;
|
||||||
struct weston_surface;
|
struct weston_surface;
|
||||||
struct weston_buffer;
|
struct weston_buffer;
|
||||||
|
|
@ -85,9 +92,6 @@ struct linux_dmabuf_buffer;
|
||||||
struct weston_recorder;
|
struct weston_recorder;
|
||||||
struct weston_pointer_constraint;
|
struct weston_pointer_constraint;
|
||||||
struct ro_anonymous_file;
|
struct ro_anonymous_file;
|
||||||
struct weston_color_profile_param_builder;
|
|
||||||
struct weston_color_profile;
|
|
||||||
struct weston_color_transform;
|
|
||||||
struct pixel_format_info;
|
struct pixel_format_info;
|
||||||
struct weston_output_capture_info;
|
struct weston_output_capture_info;
|
||||||
struct weston_output_color_outcome;
|
struct weston_output_color_outcome;
|
||||||
|
|
@ -107,9 +111,13 @@ enum weston_keyboard_locks {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum weston_led {
|
enum weston_led {
|
||||||
LED_NUM_LOCK = (1 << 0),
|
WESTON_LED_NUM_LOCK = (1 << 0),
|
||||||
LED_CAPS_LOCK = (1 << 1),
|
WESTON_LED_CAPS_LOCK = (1 << 1),
|
||||||
LED_SCROLL_LOCK = (1 << 2),
|
WESTON_LED_SCROLL_LOCK = (1 << 2),
|
||||||
|
#ifdef HAVE_COMPOSE_AND_KANA
|
||||||
|
WESTON_LED_COMPOSE = (1 << 3),
|
||||||
|
WESTON_LED_KANA = (1 << 4),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum weston_mode_aspect_ratio {
|
enum weston_mode_aspect_ratio {
|
||||||
|
|
@ -129,6 +137,17 @@ enum weston_surface_protection_mode {
|
||||||
WESTON_SURFACE_PROTECTION_MODE_ENFORCED
|
WESTON_SURFACE_PROTECTION_MODE_ENFORCED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum weston_output_color_effect_type {
|
||||||
|
WESTON_OUTPUT_COLOR_EFFECT_TYPE_INVERSION = 0,
|
||||||
|
WESTON_OUTPUT_COLOR_EFFECT_TYPE_CVD_CORRECTION,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum weston_cvd_correction_type {
|
||||||
|
WESTON_CVD_CORRECTION_TYPE_DEUTERANOPIA = 0,
|
||||||
|
WESTON_CVD_CORRECTION_TYPE_PROTANOPIA,
|
||||||
|
WESTON_CVD_CORRECTION_TYPE_TRITANOPIA,
|
||||||
|
};
|
||||||
|
|
||||||
/** Possible mode of an output
|
/** Possible mode of an output
|
||||||
*
|
*
|
||||||
* \ingroup output
|
* \ingroup output
|
||||||
|
|
@ -147,7 +166,6 @@ struct weston_animation {
|
||||||
void (*frame)(struct weston_animation *animation,
|
void (*frame)(struct weston_animation *animation,
|
||||||
struct weston_output *output,
|
struct weston_output *output,
|
||||||
const struct timespec *time);
|
const struct timespec *time);
|
||||||
int frame_counter;
|
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -199,10 +217,12 @@ enum weston_hdcp_protection {
|
||||||
* \ingroup testharness
|
* \ingroup testharness
|
||||||
*/
|
*/
|
||||||
struct weston_testsuite_quirks {
|
struct weston_testsuite_quirks {
|
||||||
/** Force GL-renderer to do a full upload of wl_shm buffers. */
|
/** Force GL/Vulkan-renderer to do a full upload of wl_shm buffers. */
|
||||||
bool gl_force_full_upload;
|
bool force_full_upload;
|
||||||
/** Ensure GL shadow fb is used, and always repaint it fully. */
|
/** Ensure GL shadow fb is used, and always repaint it fully. */
|
||||||
bool gl_force_full_redraw_of_shadow_fb;
|
bool gl_force_full_redraw_of_shadow_fb;
|
||||||
|
/** Force GL-renderer to use the internal YUV->RGB shader */
|
||||||
|
bool gl_force_import_yuv_fallback;
|
||||||
/** Required enum weston_capability bit mask, otherwise skip run. */
|
/** Required enum weston_capability bit mask, otherwise skip run. */
|
||||||
uint32_t required_capabilities;
|
uint32_t required_capabilities;
|
||||||
};
|
};
|
||||||
|
|
@ -225,248 +245,6 @@ struct weston_testsuite_data {
|
||||||
void *test_private_data;
|
void *test_private_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Colorimetry mode for outputs and heads
|
|
||||||
*
|
|
||||||
* A list of colorimetry modes for driving displays, defined by ANSI/CTA-861-H.
|
|
||||||
*
|
|
||||||
* On heads, a bitmask of one or more entries shows which modes are claimed
|
|
||||||
* supported.
|
|
||||||
*
|
|
||||||
* On outputs, the mode to be used for driving the video sink.
|
|
||||||
*
|
|
||||||
* Default (RGB) colorimetry differs from all the others in that the signal
|
|
||||||
* colorimetry is not defined here. It is defined by the video sink, and it
|
|
||||||
* may be described in e.g. EDID.
|
|
||||||
*/
|
|
||||||
enum weston_colorimetry_mode {
|
|
||||||
/** Invalid colorimetry mode, or none supported. */
|
|
||||||
WESTON_COLORIMETRY_MODE_NONE = 0,
|
|
||||||
|
|
||||||
/** Default (RGB) colorimetry, video sink dependant */
|
|
||||||
WESTON_COLORIMETRY_MODE_DEFAULT = 0x01,
|
|
||||||
|
|
||||||
/** Rec. ITU-R BT.2020 constant luminance YCbCr */
|
|
||||||
WESTON_COLORIMETRY_MODE_BT2020_CYCC = 0x02,
|
|
||||||
|
|
||||||
/** Rec. ITU-R BT.2020 non-constant luminance YCbCr */
|
|
||||||
WESTON_COLORIMETRY_MODE_BT2020_YCC = 0x04,
|
|
||||||
|
|
||||||
/** Rec. ITU-R BT.2020 RGB */
|
|
||||||
WESTON_COLORIMETRY_MODE_BT2020_RGB = 0x08,
|
|
||||||
|
|
||||||
/** SMPTE ST 2113 DCI-P3 RGB D65 */
|
|
||||||
WESTON_COLORIMETRY_MODE_P3D65 = 0x10,
|
|
||||||
|
|
||||||
/** SMPTE ST 2113 DCI-P3 RGB Theater */
|
|
||||||
WESTON_COLORIMETRY_MODE_P3DCI = 0x20,
|
|
||||||
|
|
||||||
/** Rec. ITU-R BT.2100 ICtCp HDR (with PQ and/or HLG)*/
|
|
||||||
WESTON_COLORIMETRY_MODE_ICTCP = 0x40,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Bitmask of all defined colorimetry modes */
|
|
||||||
#define WESTON_COLORIMETRY_MODE_ALL_MASK \
|
|
||||||
((uint32_t)(WESTON_COLORIMETRY_MODE_DEFAULT | \
|
|
||||||
WESTON_COLORIMETRY_MODE_BT2020_CYCC | \
|
|
||||||
WESTON_COLORIMETRY_MODE_BT2020_YCC | \
|
|
||||||
WESTON_COLORIMETRY_MODE_BT2020_RGB | \
|
|
||||||
WESTON_COLORIMETRY_MODE_P3D65 | \
|
|
||||||
WESTON_COLORIMETRY_MODE_P3DCI | \
|
|
||||||
WESTON_COLORIMETRY_MODE_ICTCP))
|
|
||||||
|
|
||||||
/** EOTF mode for outputs and heads
|
|
||||||
*
|
|
||||||
* A list of EOTF modes for driving displays, defined by CTA-861-G for
|
|
||||||
* Dynamic Range and Mastering InfoFrame.
|
|
||||||
*
|
|
||||||
* On heads, a bitmask of one or more entries shows which modes are claimed
|
|
||||||
* supported.
|
|
||||||
*
|
|
||||||
* On outputs, the mode to be used for driving the video sink.
|
|
||||||
*
|
|
||||||
* For traditional non-HDR sRGB, use WESTON_EOTF_MODE_SDR.
|
|
||||||
*/
|
|
||||||
enum weston_eotf_mode {
|
|
||||||
/** Invalid EOTF mode, or none supported. */
|
|
||||||
WESTON_EOTF_MODE_NONE = 0,
|
|
||||||
|
|
||||||
/** Traditional gamma, SDR luminance range */
|
|
||||||
WESTON_EOTF_MODE_SDR = 0x01,
|
|
||||||
|
|
||||||
/** Traditional gamma, HDR luminance range */
|
|
||||||
WESTON_EOTF_MODE_TRADITIONAL_HDR = 0x02,
|
|
||||||
|
|
||||||
/** Preceptual quantizer, SMPTE ST 2084 */
|
|
||||||
WESTON_EOTF_MODE_ST2084 = 0x04,
|
|
||||||
|
|
||||||
/** Hybrid log-gamma, ITU-R BT.2100 */
|
|
||||||
WESTON_EOTF_MODE_HLG = 0x08,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Bitmask of all defined EOTF modes */
|
|
||||||
#define WESTON_EOTF_MODE_ALL_MASK \
|
|
||||||
((uint32_t)(WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | \
|
|
||||||
WESTON_EOTF_MODE_ST2084 | WESTON_EOTF_MODE_HLG))
|
|
||||||
|
|
||||||
/** CIE 1931 xy chromaticity coordinates */
|
|
||||||
struct weston_CIExy {
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Chromaticity coordinates and white point that defines the color gamut */
|
|
||||||
struct weston_color_gamut {
|
|
||||||
struct weston_CIExy primary[3]; /* RGB order */
|
|
||||||
struct weston_CIExy white_point;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Color primaries known by libweston */
|
|
||||||
enum weston_color_primaries {
|
|
||||||
WESTON_PRIMARIES_CICP_SRGB = 0,
|
|
||||||
WESTON_PRIMARIES_CICP_PAL_M,
|
|
||||||
WESTON_PRIMARIES_CICP_PAL,
|
|
||||||
WESTON_PRIMARIES_CICP_NTSC,
|
|
||||||
WESTON_PRIMARIES_CICP_GENERIC_FILM,
|
|
||||||
WESTON_PRIMARIES_CICP_BT2020,
|
|
||||||
WESTON_PRIMARIES_CICP_CIE1931_XYZ,
|
|
||||||
WESTON_PRIMARIES_CICP_DCI_P3,
|
|
||||||
WESTON_PRIMARIES_CICP_DISPLAY_P3,
|
|
||||||
WESTON_PRIMARIES_ADOBE_RGB,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Transfer functions known by libweston */
|
|
||||||
enum weston_transfer_function {
|
|
||||||
WESTON_TF_LINEAR = 0,
|
|
||||||
WESTON_TF_GAMMA22,
|
|
||||||
WESTON_TF_GAMMA28,
|
|
||||||
WESTON_TF_SRGB,
|
|
||||||
WESTON_TF_EXT_SRGB,
|
|
||||||
WESTON_TF_BT709,
|
|
||||||
WESTON_TF_BT1361,
|
|
||||||
WESTON_TF_ST240,
|
|
||||||
WESTON_TF_ST428,
|
|
||||||
WESTON_TF_ST2084_PQ,
|
|
||||||
WESTON_TF_LOG_100,
|
|
||||||
WESTON_TF_LOG_316,
|
|
||||||
WESTON_TF_XVYCC,
|
|
||||||
WESTON_TF_HLG,
|
|
||||||
WESTON_TF_POWER,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Error codes that the color profile parameters functions may return. */
|
|
||||||
enum weston_color_profile_param_builder_error {
|
|
||||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF = 0,
|
|
||||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES,
|
|
||||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TARGET_PRIMARIES,
|
|
||||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
|
|
||||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
|
|
||||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_LUMINANCES,
|
|
||||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_SET,
|
|
||||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
|
|
||||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
|
|
||||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_color_profile_param_builder *
|
|
||||||
weston_color_profile_param_builder_create(struct weston_compositor *compositor);
|
|
||||||
|
|
||||||
void
|
|
||||||
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder);
|
|
||||||
|
|
||||||
bool
|
|
||||||
weston_color_profile_param_builder_get_error(struct weston_color_profile_param_builder *builder,
|
|
||||||
enum weston_color_profile_param_builder_error *err,
|
|
||||||
char **err_msg);
|
|
||||||
|
|
||||||
bool
|
|
||||||
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
|
|
||||||
const struct weston_color_gamut *primaries);
|
|
||||||
|
|
||||||
bool
|
|
||||||
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
|
|
||||||
enum weston_color_primaries primaries);
|
|
||||||
|
|
||||||
bool
|
|
||||||
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
|
|
||||||
enum weston_transfer_function tf);
|
|
||||||
|
|
||||||
bool
|
|
||||||
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
|
|
||||||
float power_exponent);
|
|
||||||
|
|
||||||
bool
|
|
||||||
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
|
|
||||||
const struct weston_color_gamut *target_primaries);
|
|
||||||
|
|
||||||
bool
|
|
||||||
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
|
|
||||||
float min_luminance, float max_luminance);
|
|
||||||
|
|
||||||
bool
|
|
||||||
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
|
|
||||||
float maxFALL);
|
|
||||||
|
|
||||||
bool
|
|
||||||
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
|
|
||||||
float maxCLL);
|
|
||||||
|
|
||||||
struct weston_color_profile *
|
|
||||||
weston_color_profile_param_builder_create_color_profile(struct weston_color_profile_param_builder *builder,
|
|
||||||
const char *name_part,
|
|
||||||
enum weston_color_profile_param_builder_error *err,
|
|
||||||
char **err_msg);
|
|
||||||
|
|
||||||
enum weston_color_characteristics_groups {
|
|
||||||
/** weston_color_characteristics::primary is set */
|
|
||||||
WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01,
|
|
||||||
|
|
||||||
/** weston_color_characteristics::white is set */
|
|
||||||
WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE = 0x02,
|
|
||||||
|
|
||||||
/** weston_color_characteristics::max_luminance is set */
|
|
||||||
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL = 0x04,
|
|
||||||
|
|
||||||
/** weston_color_characteristics::min_luminance is set */
|
|
||||||
WESTON_COLOR_CHARACTERISTICS_GROUP_MINL = 0x08,
|
|
||||||
|
|
||||||
/** weston_color_characteristics::maxFALL is set */
|
|
||||||
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL = 0x10,
|
|
||||||
|
|
||||||
/** all valid bits */
|
|
||||||
WESTON_COLOR_CHARACTERISTICS_GROUP_ALL_MASK = 0x1f
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Basic display color characteristics
|
|
||||||
*
|
|
||||||
* This is a simple description of a display or output (monitor) color
|
|
||||||
* characteristics. The parameters can be found in EDID, with caveats. They
|
|
||||||
* are particularly useful with HDR monitors.
|
|
||||||
*/
|
|
||||||
struct weston_color_characteristics {
|
|
||||||
/** Which fields are valid
|
|
||||||
*
|
|
||||||
* A bitmask of values from enum weston_color_characteristics_groups.
|
|
||||||
*/
|
|
||||||
uint32_t group_mask;
|
|
||||||
|
|
||||||
/* EOTF is tracked externally with enum weston_eotf_mode */
|
|
||||||
|
|
||||||
/** Chromaticities of the primaries */
|
|
||||||
struct weston_CIExy primary[3];
|
|
||||||
|
|
||||||
/** White point chromaticity */
|
|
||||||
struct weston_CIExy white;
|
|
||||||
|
|
||||||
/** Display's desired maximum content peak luminance, cd/m² */
|
|
||||||
float max_luminance;
|
|
||||||
|
|
||||||
/** Display's desired minimum content luminance, cd/m² */
|
|
||||||
float min_luminance;
|
|
||||||
|
|
||||||
/** Display's desired maximum frame-average light level, cd/m² */
|
|
||||||
float maxFALL;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Represents a head, usually a display connector
|
/** Represents a head, usually a display connector
|
||||||
*
|
*
|
||||||
* \rst
|
* \rst
|
||||||
|
|
@ -516,6 +294,10 @@ struct weston_head {
|
||||||
* When a client uses this request, we add the wl_resource we create to
|
* When a client uses this request, we add the wl_resource we create to
|
||||||
* this list. */
|
* this list. */
|
||||||
struct wl_list cm_output_resource_list;
|
struct wl_list cm_output_resource_list;
|
||||||
|
|
||||||
|
uint32_t supported_vrr_mode_mask;
|
||||||
|
|
||||||
|
uint32_t supported_color_format_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum weston_output_power_state {
|
enum weston_output_power_state {
|
||||||
|
|
@ -525,12 +307,63 @@ enum weston_output_power_state {
|
||||||
WESTON_OUTPUT_POWER_NORMAL
|
WESTON_OUTPUT_POWER_NORMAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum weston_paint_node_status {
|
||||||
|
WESTON_PAINT_NODE_CLEAN = 0,
|
||||||
|
WESTON_PAINT_NODE_OUTPUT_DIRTY = 1 << 0,
|
||||||
|
WESTON_PAINT_NODE_VIEW_DIRTY = 1 << 1,
|
||||||
|
WESTON_PAINT_NODE_VISIBILITY_DIRTY = 1 << 2,
|
||||||
|
WESTON_PAINT_NODE_PLANE_DIRTY = 1 << 3,
|
||||||
|
WESTON_PAINT_NODE_BUFFER_DIRTY = 1 << 4,
|
||||||
|
WESTON_PAINT_NODE_BUFFER_PARAMS_DIRTY = 1 << 5,
|
||||||
|
WESTON_PAINT_NODE_ALL_DIRTY = (1 << 6) - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum weston_vrr_mode {
|
||||||
|
/** No VRR */
|
||||||
|
WESTON_VRR_MODE_NONE = 0,
|
||||||
|
/** Game mode VRR */
|
||||||
|
WESTON_VRR_MODE_GAME = 1 << 0,
|
||||||
|
};
|
||||||
|
#define WESTON_VRR_MODE_ALL_MASK \
|
||||||
|
((uint32_t)(WESTON_VRR_MODE_GAME))
|
||||||
|
|
||||||
|
enum weston_color_format {
|
||||||
|
/** Driver assigned color format automatically */
|
||||||
|
WESTON_COLOR_FORMAT_AUTO = (1 << 0),
|
||||||
|
/** Force RGB color format */
|
||||||
|
WESTON_COLOR_FORMAT_RGB = (1 << 1),
|
||||||
|
/** Force YUV color format with 4:2:2 susampling */
|
||||||
|
WESTON_COLOR_FORMAT_YUV422 = (1 << 2),
|
||||||
|
/** Force YUV color format with no subsampling */
|
||||||
|
WESTON_COLOR_FORMAT_YUV444 = (1 << 3),
|
||||||
|
/** Force YUV color format with 4:2:0 subsampling */
|
||||||
|
WESTON_COLOR_FORMAT_YUV420 = (1 << 4),
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Bitmask of all defined color formats */
|
||||||
|
#define WESTON_COLOR_FORMAT_ALL_MASK \
|
||||||
|
((uint32_t)(WESTON_COLOR_FORMAT_AUTO | WESTON_COLOR_FORMAT_RGB | \
|
||||||
|
WESTON_COLOR_FORMAT_YUV444 | WESTON_COLOR_FORMAT_YUV422 | \
|
||||||
|
WESTON_COLOR_FORMAT_YUV420))
|
||||||
|
|
||||||
struct weston_plane {
|
struct weston_plane {
|
||||||
struct weston_compositor *compositor;
|
struct weston_compositor *compositor;
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** State of the repaint loop
|
||||||
|
*
|
||||||
|
* \ingroup output
|
||||||
|
*/
|
||||||
|
enum weston_repaint_status {
|
||||||
|
REPAINT_NOT_SCHEDULED = 0, /**< idle; no repaint will occur */
|
||||||
|
REPAINT_BEGIN_FROM_IDLE, /**< start_repaint_loop scheduled */
|
||||||
|
REPAINT_SCHEDULED, /**< repaint is scheduled to occur */
|
||||||
|
REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
|
||||||
|
};
|
||||||
|
|
||||||
/** Content producer for heads
|
/** Content producer for heads
|
||||||
*
|
*
|
||||||
* \rst
|
* \rst
|
||||||
|
|
@ -542,6 +375,8 @@ struct weston_output {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
|
void *shell_private;
|
||||||
|
|
||||||
struct weston_backend *backend;
|
struct weston_backend *backend;
|
||||||
|
|
||||||
/** Matches the lifetime from the user perspective */
|
/** Matches the lifetime from the user perspective */
|
||||||
|
|
@ -556,6 +391,9 @@ struct weston_output {
|
||||||
/* struct weston_paint_node::output_link */
|
/* struct weston_paint_node::output_link */
|
||||||
struct wl_list paint_node_list;
|
struct wl_list paint_node_list;
|
||||||
|
|
||||||
|
/** Only valid during repaint: changes for this repaint */
|
||||||
|
enum weston_paint_node_status paint_node_changes;
|
||||||
|
|
||||||
/** From global to output buffer coordinates. */
|
/** From global to output buffer coordinates. */
|
||||||
struct weston_matrix matrix;
|
struct weston_matrix matrix;
|
||||||
/** From output buffer to global coordinates. */
|
/** From output buffer to global coordinates. */
|
||||||
|
|
@ -565,6 +403,10 @@ struct weston_output {
|
||||||
struct weston_coord_global pos;
|
struct weston_coord_global pos;
|
||||||
int32_t width, height;
|
int32_t width, height;
|
||||||
|
|
||||||
|
uint64_t gpu_track_id;
|
||||||
|
uint64_t paint_track_id;
|
||||||
|
uint64_t presentation_track_id;
|
||||||
|
|
||||||
/** List of paint nodes in z-order, from top to bottom, maybe pruned
|
/** List of paint nodes in z-order, from top to bottom, maybe pruned
|
||||||
*
|
*
|
||||||
* struct weston_paint_node::z_order_link
|
* struct weston_paint_node::z_order_link
|
||||||
|
|
@ -592,24 +434,34 @@ struct weston_output {
|
||||||
bool repaint_only_on_capture;
|
bool repaint_only_on_capture;
|
||||||
|
|
||||||
/** State of the repaint loop */
|
/** State of the repaint loop */
|
||||||
enum {
|
enum weston_repaint_status repaint_status;
|
||||||
REPAINT_NOT_SCHEDULED = 0, /**< idle; no repaint will occur */
|
|
||||||
REPAINT_BEGIN_FROM_IDLE, /**< start_repaint_loop scheduled */
|
|
||||||
REPAINT_SCHEDULED, /**< repaint is scheduled to occur */
|
|
||||||
REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
|
|
||||||
} repaint_status;
|
|
||||||
|
|
||||||
/** If repaint_status is REPAINT_SCHEDULED, contains the time the
|
/** If repaint_status is REPAINT_SCHEDULED, contains the time the
|
||||||
* next repaint should be run */
|
* next repaint should be run */
|
||||||
struct timespec next_repaint;
|
struct timespec next_repaint;
|
||||||
|
/** If repaint_statue is REPAINT_SCHEDULED, contains the time the
|
||||||
|
* next repaint should be displayed */
|
||||||
|
struct timespec next_present;
|
||||||
|
|
||||||
|
/** commit-timing protocol will set this for the closest requested
|
||||||
|
* presentation time from a surface on this output. It's only
|
||||||
|
* valid during weston_repaint_timer_arm. */
|
||||||
|
struct weston_commit_timing_target requested_present;
|
||||||
|
/** commit-timing protocol will set this when state containing
|
||||||
|
* a target time is applied. Weston will try to hit this time if
|
||||||
|
* VRR is in use.
|
||||||
|
*/
|
||||||
|
struct weston_commit_timing_target forced_present;
|
||||||
|
|
||||||
/** For cancelling the idle_repaint callback on output destruction. */
|
/** For cancelling the idle_repaint callback on output destruction. */
|
||||||
struct wl_event_source *idle_repaint_source;
|
struct wl_event_source *idle_repaint_source;
|
||||||
|
|
||||||
struct wl_signal frame_signal;
|
struct wl_signal frame_signal;
|
||||||
|
struct wl_signal post_latch_signal;
|
||||||
struct wl_signal destroy_signal; /**< sent when disabled */
|
struct wl_signal destroy_signal; /**< sent when disabled */
|
||||||
struct weston_coord_global move;
|
struct weston_coord_global move;
|
||||||
struct timespec frame_time; /* presentation timestamp */
|
struct timespec frame_time; /* presentation timestamp */
|
||||||
|
uint32_t frame_flags; /* presentation flags */
|
||||||
uint64_t msc; /* media stream counter */
|
uint64_t msc; /* media stream counter */
|
||||||
int disable_planes;
|
int disable_planes;
|
||||||
int destroying;
|
int destroying;
|
||||||
|
|
@ -658,13 +510,6 @@ struct weston_output {
|
||||||
void (*set_backlight)(struct weston_output *output, uint32_t value);
|
void (*set_backlight)(struct weston_output *output, uint32_t value);
|
||||||
void (*set_dpms)(struct weston_output *output, enum dpms_enum level);
|
void (*set_dpms)(struct weston_output *output, enum dpms_enum level);
|
||||||
|
|
||||||
uint16_t gamma_size;
|
|
||||||
void (*set_gamma)(struct weston_output *output,
|
|
||||||
uint16_t size,
|
|
||||||
uint16_t *r,
|
|
||||||
uint16_t *g,
|
|
||||||
uint16_t *b);
|
|
||||||
|
|
||||||
bool enabled; /**< is in the output_list, not pending list */
|
bool enabled; /**< is in the output_list, not pending list */
|
||||||
|
|
||||||
struct weston_color_profile *color_profile;
|
struct weston_color_profile *color_profile;
|
||||||
|
|
@ -676,6 +521,8 @@ struct weston_output {
|
||||||
struct weston_output_color_outcome *color_outcome;
|
struct weston_output_color_outcome *color_outcome;
|
||||||
uint64_t color_outcome_serial;
|
uint64_t color_outcome_serial;
|
||||||
|
|
||||||
|
struct weston_output_color_effect *color_effect;
|
||||||
|
|
||||||
int (*enable)(struct weston_output *output);
|
int (*enable)(struct weston_output *output);
|
||||||
int (*disable)(struct weston_output *output);
|
int (*disable)(struct weston_output *output);
|
||||||
|
|
||||||
|
|
@ -706,11 +553,32 @@ struct weston_output {
|
||||||
void (*detach_head)(struct weston_output *output,
|
void (*detach_head)(struct weston_output *output,
|
||||||
struct weston_head *head);
|
struct weston_head *head);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the DRM formats supported by a compatible writeback connector.
|
||||||
|
*/
|
||||||
|
const struct weston_drm_format_array *(*get_writeback_formats)(struct weston_output *output);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When set, this output is a mirror-of another output. See
|
* When set, this output is a mirror-of another output. See
|
||||||
* mirror-of key in [output] section.
|
* mirror-of key in [output] section.
|
||||||
*/
|
*/
|
||||||
struct weston_output *mirror_of;
|
struct weston_output *mirror_of;
|
||||||
|
|
||||||
|
enum weston_vrr_mode vrr_mode;
|
||||||
|
|
||||||
|
enum weston_color_format color_format;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set by the shell to indicate there's some content for this
|
||||||
|
* output to display.
|
||||||
|
*/
|
||||||
|
bool ready;
|
||||||
|
|
||||||
|
/** Needs to rebuild the paint node z ordered list */
|
||||||
|
bool paint_node_list_needs_rebuild;
|
||||||
|
|
||||||
|
/** fifo_v1 - list of surfaces to clear next repaint */
|
||||||
|
struct wl_list fifo_barrier_surfaces;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum weston_pointer_motion_mask {
|
enum weston_pointer_motion_mask {
|
||||||
|
|
@ -1053,6 +921,18 @@ struct weston_tablet {
|
||||||
const char *path;
|
const char *path;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct weston_color_representation {
|
||||||
|
enum weston_alpha_mode alpha_mode;
|
||||||
|
enum weston_color_matrix_coef matrix_coefficients;
|
||||||
|
enum weston_color_quant_range quant_range;
|
||||||
|
enum weston_ycbcr_chroma_location chroma_location;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct weston_color_representation_matrix {
|
||||||
|
struct weston_mat3f matrix;
|
||||||
|
struct weston_vec3f offset;
|
||||||
|
};
|
||||||
|
|
||||||
struct weston_coord_global
|
struct weston_coord_global
|
||||||
weston_pointer_motion_to_abs(struct weston_pointer *pointer,
|
weston_pointer_motion_to_abs(struct weston_pointer *pointer,
|
||||||
struct weston_pointer_motion_event *event);
|
struct weston_pointer_motion_event *event);
|
||||||
|
|
@ -1223,6 +1103,10 @@ struct weston_xkb_info {
|
||||||
xkb_led_index_t num_led;
|
xkb_led_index_t num_led;
|
||||||
xkb_led_index_t caps_led;
|
xkb_led_index_t caps_led;
|
||||||
xkb_led_index_t scroll_led;
|
xkb_led_index_t scroll_led;
|
||||||
|
#ifdef HAVE_COMPOSE_AND_KANA
|
||||||
|
xkb_led_index_t compose_led;
|
||||||
|
xkb_led_index_t kana_led;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_keyboard {
|
struct weston_keyboard {
|
||||||
|
|
@ -1406,6 +1290,9 @@ enum weston_capability {
|
||||||
|
|
||||||
/* renderer supports color management operations */
|
/* renderer supports color management operations */
|
||||||
WESTON_CAP_COLOR_OPS = 0x0040,
|
WESTON_CAP_COLOR_OPS = 0x0040,
|
||||||
|
|
||||||
|
/* renderer supports color representation operations */
|
||||||
|
WESTON_CAP_COLOR_REP = 0x0080,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Configuration struct for a backend.
|
/* Configuration struct for a backend.
|
||||||
|
|
@ -1472,6 +1359,7 @@ struct weston_color_manager;
|
||||||
struct weston_dmabuf_feedback;
|
struct weston_dmabuf_feedback;
|
||||||
struct weston_dmabuf_feedback_format_table;
|
struct weston_dmabuf_feedback_format_table;
|
||||||
struct weston_renderer;
|
struct weston_renderer;
|
||||||
|
struct weston_content_update;
|
||||||
|
|
||||||
/** Main object, container-like structure which aggregates all other objects.
|
/** Main object, container-like structure which aggregates all other objects.
|
||||||
*
|
*
|
||||||
|
|
@ -1531,12 +1419,14 @@ struct weston_compositor {
|
||||||
struct wl_list debug_binding_list;
|
struct wl_list debug_binding_list;
|
||||||
|
|
||||||
bool view_list_needs_rebuild;
|
bool view_list_needs_rebuild;
|
||||||
|
int global_weston_surface_disambiguator; /* surface ids to avoid using PID-reuse */
|
||||||
|
|
||||||
uint32_t state;
|
uint32_t state;
|
||||||
struct wl_event_source *idle_source;
|
struct wl_event_source *idle_source;
|
||||||
uint32_t idle_inhibit;
|
uint32_t idle_inhibit;
|
||||||
int idle_time; /* timeout, s */
|
int idle_time; /* timeout, s */
|
||||||
struct wl_event_source *repaint_timer;
|
int repaint_timer_fd;
|
||||||
|
struct wl_event_source *repaint_timer_source;
|
||||||
|
|
||||||
const struct weston_pointer_grab_interface *default_pointer_grab;
|
const struct weston_pointer_grab_interface *default_pointer_grab;
|
||||||
|
|
||||||
|
|
@ -1592,6 +1482,9 @@ struct weston_compositor {
|
||||||
/* Whether to let the compositor run without any input device. */
|
/* Whether to let the compositor run without any input device. */
|
||||||
bool require_input;
|
bool require_input;
|
||||||
|
|
||||||
|
/* Ignore all libinput-based input devices */
|
||||||
|
bool disable_input;
|
||||||
|
|
||||||
/* Whether to load multiple backends. */
|
/* Whether to load multiple backends. */
|
||||||
bool multi_backend;
|
bool multi_backend;
|
||||||
|
|
||||||
|
|
@ -1615,6 +1508,7 @@ struct weston_compositor {
|
||||||
struct weston_log_scope *debug_scene;
|
struct weston_log_scope *debug_scene;
|
||||||
struct weston_log_scope *timeline;
|
struct weston_log_scope *timeline;
|
||||||
struct weston_log_scope *libseat_debug;
|
struct weston_log_scope *libseat_debug;
|
||||||
|
struct weston_log_filtered *advertised_log_scopes;
|
||||||
|
|
||||||
struct content_protection *content_protection;
|
struct content_protection *content_protection;
|
||||||
|
|
||||||
|
|
@ -1626,6 +1520,34 @@ struct weston_compositor {
|
||||||
struct wl_global *weston_capture_v1;
|
struct wl_global *weston_capture_v1;
|
||||||
struct wl_signal ask_auth;
|
struct wl_signal ask_auth;
|
||||||
} output_capture;
|
} output_capture;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/** interval which we divide the amount of frames */
|
||||||
|
unsigned int frame_counter_interval;
|
||||||
|
|
||||||
|
/** fires with frame_counter_interval rate */
|
||||||
|
struct wl_event_source *frame_counter_timer;
|
||||||
|
} perf_surface_stats;
|
||||||
|
|
||||||
|
/* if set use this placeholder-color to use instead of the default
|
||||||
|
* grenadier one */
|
||||||
|
uint32_t placeholder_color;
|
||||||
|
|
||||||
|
bool no_xwm_decorations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When set the compositor has latched content updates for the
|
||||||
|
* upcoming repaint, and no more updates may be applied until after
|
||||||
|
* that repaint occurs.
|
||||||
|
*/
|
||||||
|
bool latched;
|
||||||
|
|
||||||
|
struct wl_list transaction_queue_list; /* weston_transaction_queue::link */
|
||||||
|
|
||||||
|
/** commit_timing_v1 - target repaint time for content updates for
|
||||||
|
* surfaces with no output
|
||||||
|
*/
|
||||||
|
struct weston_commit_timing_target requested_repaint_fallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_solid_buffer_values {
|
struct weston_solid_buffer_values {
|
||||||
|
|
@ -1774,7 +1696,6 @@ struct weston_view {
|
||||||
|
|
||||||
unsigned int click_to_activate_serial;
|
unsigned int click_to_activate_serial;
|
||||||
|
|
||||||
pixman_region32_t visible; /* Unoccluded region in global space */
|
|
||||||
float alpha; /* part of geometry, see below */
|
float alpha; /* part of geometry, see below */
|
||||||
|
|
||||||
/* Surface geometry state, mutable.
|
/* Surface geometry state, mutable.
|
||||||
|
|
@ -1838,11 +1759,16 @@ struct weston_view {
|
||||||
struct wl_listener output_destroy_listener;
|
struct wl_listener output_destroy_listener;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A more complete representation of all outputs this surface is
|
* A bitfield of outputs this view intersects - though it may not be
|
||||||
* displayed on.
|
* visible on them.
|
||||||
*/
|
*/
|
||||||
uint32_t output_mask;
|
uint32_t output_mask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A bitfield of outputs this view is visible (has unoccluded pixels) on.
|
||||||
|
*/
|
||||||
|
uint32_t output_visibility_mask;
|
||||||
|
|
||||||
bool is_mapped;
|
bool is_mapped;
|
||||||
struct weston_log_pacer subsurface_parent_log_pacer;
|
struct weston_log_pacer subsurface_parent_log_pacer;
|
||||||
};
|
};
|
||||||
|
|
@ -1867,11 +1793,11 @@ enum weston_surface_status {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_surface_state {
|
struct weston_surface_state {
|
||||||
|
uint64_t flow_id;
|
||||||
enum weston_surface_status status;
|
enum weston_surface_status status;
|
||||||
|
|
||||||
/* wl_surface.attach */
|
/* wl_surface.attach */
|
||||||
struct weston_buffer *buffer;
|
struct weston_buffer_reference buffer_ref;
|
||||||
struct wl_listener buffer_destroy_listener;
|
|
||||||
|
|
||||||
struct weston_coord_surface buf_offset;
|
struct weston_coord_surface buf_offset;
|
||||||
|
|
||||||
|
|
@ -1914,6 +1840,18 @@ struct weston_surface_state {
|
||||||
* color_management_surface_v1_interface.unset_image_description */
|
* color_management_surface_v1_interface.unset_image_description */
|
||||||
struct weston_color_profile *color_profile;
|
struct weston_color_profile *color_profile;
|
||||||
const struct weston_render_intent_info *render_intent;
|
const struct weston_render_intent_info *render_intent;
|
||||||
|
|
||||||
|
/* wp_color_representation_surface_v1.set_alpha_mode */
|
||||||
|
/* wp_color_representation_surface_v1.set_coefficients_and_range */
|
||||||
|
/* wp_color_representation_surface_v1.set_chroma_location */
|
||||||
|
struct weston_color_representation color_representation;
|
||||||
|
|
||||||
|
/* wp_fifo_v1 */
|
||||||
|
bool fifo_barrier;
|
||||||
|
bool fifo_wait;
|
||||||
|
|
||||||
|
/* commit_timing_v1 */
|
||||||
|
struct weston_commit_timing_target update_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_surface_activation_data {
|
struct weston_surface_activation_data {
|
||||||
|
|
@ -2043,6 +1981,7 @@ struct weston_surface {
|
||||||
|
|
||||||
bool is_mapped, is_unmapping, is_mapping;
|
bool is_mapped, is_unmapping, is_mapping;
|
||||||
bool is_opaque;
|
bool is_opaque;
|
||||||
|
uint32_t s_id;
|
||||||
|
|
||||||
/* An list of per seat pointer constraints. */
|
/* An list of per seat pointer constraints. */
|
||||||
struct wl_list pointer_constraints;
|
struct wl_list pointer_constraints;
|
||||||
|
|
@ -2068,8 +2007,41 @@ struct weston_surface {
|
||||||
*
|
*
|
||||||
* When a client uses this request, we add the wl_resource we create to
|
* When a client uses this request, we add the wl_resource we create to
|
||||||
* this list. */
|
* this list. */
|
||||||
struct wl_list cm_feedback_surface_resource_list;
|
struct wl_list cm_surface_feedback_resource_list;
|
||||||
struct wl_resource *cm_surface;
|
struct wl_resource *cm_surface;
|
||||||
|
|
||||||
|
struct wl_resource *color_representation_resource;
|
||||||
|
struct weston_color_representation color_representation;
|
||||||
|
|
||||||
|
uint64_t damage_track_id;
|
||||||
|
uint64_t flow_id;
|
||||||
|
|
||||||
|
|
||||||
|
/** increments for each wl_surface::commit,
|
||||||
|
* reset after each frame counter interval */
|
||||||
|
unsigned int frame_commit_counter;
|
||||||
|
|
||||||
|
/** increments after an output repaint when parsing paint node list;
|
||||||
|
* reset as frame_commit_counter */
|
||||||
|
unsigned int painted_frame_counter;
|
||||||
|
|
||||||
|
/** computed after each frame_counter_interval */
|
||||||
|
float frame_commit_fps_counter;
|
||||||
|
float painted_frame_fps_counter;
|
||||||
|
|
||||||
|
/** Visibility won't be calculated until repaint, but we use this to
|
||||||
|
* track whether we can safely use the last repaint's visibility
|
||||||
|
* calculations when considering this surface's visibility.
|
||||||
|
*/
|
||||||
|
uint32_t output_visibility_dirty_mask;
|
||||||
|
|
||||||
|
/** fifo_v1 */
|
||||||
|
struct weston_fifo *fifo;
|
||||||
|
bool fifo_barrier; /* Cleared after display */
|
||||||
|
struct wl_list fifo_barrier_link; /* output::fifo_barrier_surfaces */
|
||||||
|
|
||||||
|
/** commit_timing_v1 */
|
||||||
|
struct weston_commit_timer *commit_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_subsurface {
|
struct weston_subsurface {
|
||||||
|
|
@ -2090,14 +2062,10 @@ struct weston_subsurface {
|
||||||
bool changed;
|
bool changed;
|
||||||
} position;
|
} position;
|
||||||
|
|
||||||
int has_cached_data;
|
|
||||||
struct weston_surface_state cached;
|
struct weston_surface_state cached;
|
||||||
struct weston_buffer_reference cached_buffer_ref;
|
|
||||||
|
|
||||||
/* Sub-surface has been reordered; need to apply damage. */
|
bool synchronized;
|
||||||
bool reordered;
|
bool effectively_synchronized;
|
||||||
|
|
||||||
int synchronized;
|
|
||||||
|
|
||||||
/* Used for constructing the view tree */
|
/* Used for constructing the view tree */
|
||||||
struct wl_list unused_views;
|
struct wl_list unused_views;
|
||||||
|
|
@ -2186,6 +2154,10 @@ void
|
||||||
weston_view_move_to_layer(struct weston_view *view,
|
weston_view_move_to_layer(struct weston_view *view,
|
||||||
struct weston_layer_entry *layer);
|
struct weston_layer_entry *layer);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_view_move_before_layer_entry(struct weston_view *view,
|
||||||
|
struct weston_layer_entry *layer);
|
||||||
|
|
||||||
void
|
void
|
||||||
weston_layer_init(struct weston_layer *layer,
|
weston_layer_init(struct weston_layer *layer,
|
||||||
struct weston_compositor *compositor);
|
struct weston_compositor *compositor);
|
||||||
|
|
@ -2217,8 +2189,6 @@ void
|
||||||
weston_output_schedule_repaint_reset(struct weston_output *output);
|
weston_output_schedule_repaint_reset(struct weston_output *output);
|
||||||
void
|
void
|
||||||
weston_output_schedule_repaint_restart(struct weston_output *output);
|
weston_output_schedule_repaint_restart(struct weston_output *output);
|
||||||
enum weston_compositor_backend
|
|
||||||
weston_get_backend_type(struct weston_backend *backend);
|
|
||||||
void
|
void
|
||||||
weston_compositor_schedule_repaint(struct weston_compositor *compositor);
|
weston_compositor_schedule_repaint(struct weston_compositor *compositor);
|
||||||
void
|
void
|
||||||
|
|
@ -2387,12 +2357,6 @@ void
|
||||||
weston_surface_set_size(struct weston_surface *surface,
|
weston_surface_set_size(struct weston_surface *surface,
|
||||||
int32_t width, int32_t height);
|
int32_t width, int32_t height);
|
||||||
|
|
||||||
void
|
|
||||||
weston_surface_damage(struct weston_surface *surface);
|
|
||||||
|
|
||||||
void
|
|
||||||
weston_view_damage_below(struct weston_view *view);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
weston_view_unmap(struct weston_view *view);
|
weston_view_unmap(struct weston_view *view);
|
||||||
|
|
||||||
|
|
@ -2469,12 +2433,15 @@ enum weston_renderer_type {
|
||||||
WESTON_RENDERER_NOOP = 1,
|
WESTON_RENDERER_NOOP = 1,
|
||||||
WESTON_RENDERER_PIXMAN = 2,
|
WESTON_RENDERER_PIXMAN = 2,
|
||||||
WESTON_RENDERER_GL = 3,
|
WESTON_RENDERER_GL = 3,
|
||||||
|
WESTON_RENDERER_VULKAN = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_backend *
|
struct weston_backend *
|
||||||
weston_compositor_load_backend(struct weston_compositor *compositor,
|
weston_compositor_load_backend(struct weston_compositor *compositor,
|
||||||
enum weston_compositor_backend backend,
|
enum weston_compositor_backend backend,
|
||||||
struct weston_backend_config *config_base);
|
struct weston_backend_config *config_base);
|
||||||
|
enum weston_compositor_backend
|
||||||
|
weston_get_backend_type(struct weston_backend *backend);
|
||||||
void
|
void
|
||||||
weston_compositor_exit(struct weston_compositor *ec);
|
weston_compositor_exit(struct weston_compositor *ec);
|
||||||
void *
|
void *
|
||||||
|
|
@ -2699,6 +2666,13 @@ void
|
||||||
weston_output_set_transform(struct weston_output *output,
|
weston_output_set_transform(struct weston_output *output,
|
||||||
uint32_t transform);
|
uint32_t transform);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_output_color_effect_inversion(struct weston_output *output);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_output_color_effect_cvd_correction(struct weston_output *output,
|
||||||
|
enum weston_cvd_correction_type type);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
weston_output_set_color_profile(struct weston_output *output,
|
weston_output_set_color_profile(struct weston_output *output,
|
||||||
struct weston_color_profile *cprof);
|
struct weston_color_profile *cprof);
|
||||||
|
|
@ -2785,19 +2759,6 @@ void
|
||||||
weston_timeline_refresh_subscription_objects(struct weston_compositor *wc,
|
weston_timeline_refresh_subscription_objects(struct weston_compositor *wc,
|
||||||
void *object);
|
void *object);
|
||||||
|
|
||||||
struct weston_color_profile *
|
|
||||||
weston_color_profile_ref(struct weston_color_profile *cprof);
|
|
||||||
|
|
||||||
void
|
|
||||||
weston_color_profile_unref(struct weston_color_profile *cprof);
|
|
||||||
|
|
||||||
const char *
|
|
||||||
weston_color_profile_get_description(struct weston_color_profile *cprof);
|
|
||||||
|
|
||||||
struct weston_color_profile *
|
|
||||||
weston_compositor_load_icc_file(struct weston_compositor *compositor,
|
|
||||||
const char *path);
|
|
||||||
|
|
||||||
/** Describes who is trying to capture and which output */
|
/** Describes who is trying to capture and which output */
|
||||||
struct weston_output_capture_client {
|
struct weston_output_capture_client {
|
||||||
struct wl_client *client;
|
struct wl_client *client;
|
||||||
|
|
@ -2834,6 +2795,33 @@ int
|
||||||
weston_output_mode_set_native(struct weston_output *output,
|
weston_output_mode_set_native(struct weston_output *output,
|
||||||
struct weston_mode *mode,
|
struct weston_mode *mode,
|
||||||
int32_t scale);
|
int32_t scale);
|
||||||
|
|
||||||
|
int
|
||||||
|
weston_output_set_vrr_mode(struct weston_output *output,
|
||||||
|
enum weston_vrr_mode vrr_mode);
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
weston_output_get_supported_vrr_modes(struct weston_output *output);
|
||||||
|
|
||||||
|
const struct weston_drm_format_array *
|
||||||
|
weston_output_get_writeback_formats(struct weston_output *output);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_compositor_arm_surface_counter_fps(struct weston_compositor *ec);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_compositor_disarm_surface_counter_fps(struct weston_compositor *ec);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_output_set_color_format(struct weston_output *output,
|
||||||
|
enum weston_color_format color_format);
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
weston_output_get_supported_color_formats(struct weston_output *output);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_output_set_ready(struct weston_output *output);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
228
include/libweston/linalg-3.h
Normal file
228
include/libweston/linalg-3.h
Normal file
|
|
@ -0,0 +1,228 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial
|
||||||
|
* portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <libweston/linalg-types.h>
|
||||||
|
|
||||||
|
/* ================= 3-vectors and 3x3 matrices ============== */
|
||||||
|
|
||||||
|
/** Construct a column vector from elements */
|
||||||
|
#define WESTON_VEC3F(x, y, z) ((struct weston_vec3f){ .el = { (x), (y), (z) }})
|
||||||
|
|
||||||
|
/** Construct the [0, 0, 0]^T vector */
|
||||||
|
#define WESTON_VEC3F_ZERO ((struct weston_vec3f){ .el = {}})
|
||||||
|
|
||||||
|
/** Construct matrix from elements a{row}{column} */
|
||||||
|
#define WESTON_MAT3F(a00, a01, a02, \
|
||||||
|
a10, a11, a12, \
|
||||||
|
a20, a21, a22) \
|
||||||
|
((struct weston_mat3f){ .colmaj = { \
|
||||||
|
a00, a10, a20, \
|
||||||
|
a01, a11, a21, \
|
||||||
|
a02, a12, a22, \
|
||||||
|
}})
|
||||||
|
|
||||||
|
/** Construct the identity 3x3 matrix */
|
||||||
|
#define WESTON_MAT3F_IDENTITY \
|
||||||
|
((struct weston_mat3f){ .colmaj = { \
|
||||||
|
1.0f, 0.0f, 0.0f, \
|
||||||
|
0.0f, 1.0f, 0.0f, \
|
||||||
|
0.0f, 0.0f, 1.0f, \
|
||||||
|
}})
|
||||||
|
|
||||||
|
/** Construct a diagonal matrix */
|
||||||
|
static inline struct weston_mat3f
|
||||||
|
weston_m3f_diag(struct weston_vec3f d)
|
||||||
|
{
|
||||||
|
return WESTON_MAT3F(
|
||||||
|
d.x, 0.0f, 0.0f,
|
||||||
|
0.0f, d.y, 0.0f,
|
||||||
|
0.0f, 0.0f, d.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Copy the top-left 3x3 from 4x4 */
|
||||||
|
static inline struct weston_mat3f
|
||||||
|
weston_m3f_from_m4f_xyz(struct weston_mat4f M)
|
||||||
|
{
|
||||||
|
return WESTON_MAT3F(
|
||||||
|
M.col[0].el[0], M.col[1].el[0], M.col[2].el[0],
|
||||||
|
M.col[0].el[1], M.col[1].el[1], M.col[2].el[1],
|
||||||
|
M.col[0].el[2], M.col[1].el[2], M.col[2].el[2]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Drop w from vec4f */
|
||||||
|
static inline struct weston_vec3f
|
||||||
|
weston_v3f_from_v4f_xyz(struct weston_vec4f v)
|
||||||
|
{
|
||||||
|
return WESTON_VEC3F(v.x, v.y, v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 3-vector dot product */
|
||||||
|
static inline float
|
||||||
|
weston_v3f_dot_v3f(struct weston_vec3f a, struct weston_vec3f b)
|
||||||
|
{
|
||||||
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an array of vec3f into planar format
|
||||||
|
*
|
||||||
|
* Takes an array of RGB triplets and converts it into a planar format where all R
|
||||||
|
* values come first, then all G values, then all B values.
|
||||||
|
*
|
||||||
|
* \param planar The destination array for planar data, must have space for 3 * len floats
|
||||||
|
* \param arr Array of RGB triplets as vec3f structs
|
||||||
|
* \param len Number of RGB triplets in the array
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
weston_v3f_array_to_planar(float *planar, const struct weston_vec3f *arr, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
planar[i ] = arr[i].r;
|
||||||
|
planar[i + len] = arr[i].g;
|
||||||
|
planar[i + 2 * len] = arr[i].b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Clamp each element to the range [a, b], replacing NaN with a. */
|
||||||
|
static inline struct weston_vec3f
|
||||||
|
weston_v3f_clamp(struct weston_vec3f v, float a, float b)
|
||||||
|
{
|
||||||
|
return WESTON_VEC3F(v.x >= a ? (v.x <= b ? v.x : b) : a,
|
||||||
|
v.y >= a ? (v.y <= b ? v.y : b) : a,
|
||||||
|
v.z >= a ? (v.z <= b ? v.z : b) : a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matrix infinity-norm
|
||||||
|
*
|
||||||
|
* http://www.netlib.org/lapack/lug/node75.html
|
||||||
|
*/
|
||||||
|
static inline float
|
||||||
|
weston_m3f_inf_norm(struct weston_mat3f M)
|
||||||
|
{
|
||||||
|
unsigned row;
|
||||||
|
double infnorm = -1.0;
|
||||||
|
|
||||||
|
for (row = 0; row < 3; row++) {
|
||||||
|
unsigned col;
|
||||||
|
double sum = 0.0;
|
||||||
|
|
||||||
|
for (col = 0; col < 3; col++)
|
||||||
|
sum += fabsf(M.col[col].el[row]);
|
||||||
|
|
||||||
|
if (infnorm < sum)
|
||||||
|
infnorm = sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return infnorm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Transpose 3x3 matrix */
|
||||||
|
static inline struct weston_mat3f
|
||||||
|
weston_m3f_transpose(struct weston_mat3f M)
|
||||||
|
{
|
||||||
|
struct weston_mat3f R;
|
||||||
|
unsigned i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
for (j = 0; j < 3; j++)
|
||||||
|
R.col[j].el[i] = M.col[i].el[j];
|
||||||
|
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Matrix-vector multiplication A * b */
|
||||||
|
static inline struct weston_vec3f
|
||||||
|
weston_m3f_mul_v3f(struct weston_mat3f A, struct weston_vec3f b)
|
||||||
|
{
|
||||||
|
struct weston_vec3f result;
|
||||||
|
unsigned r;
|
||||||
|
|
||||||
|
for (r = 0; r < 3; r++) {
|
||||||
|
struct weston_vec3f row =
|
||||||
|
WESTON_VEC3F(A.col[0].el[r], A.col[1].el[r], A.col[2].el[r]);
|
||||||
|
result.el[r] = weston_v3f_dot_v3f(row, b);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Matrix multiplication A * B */
|
||||||
|
static inline struct weston_mat3f
|
||||||
|
weston_m3f_mul_m3f(struct weston_mat3f A, struct weston_mat3f B)
|
||||||
|
{
|
||||||
|
struct weston_mat3f result;
|
||||||
|
unsigned c;
|
||||||
|
|
||||||
|
for (c = 0; c < 3; c++)
|
||||||
|
result.col[c] = weston_m3f_mul_v3f(A, B.col[c]);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Element-wise matrix subtraction A - B */
|
||||||
|
static inline struct weston_mat3f
|
||||||
|
weston_m3f_sub_m3f(struct weston_mat3f A, struct weston_mat3f B)
|
||||||
|
{
|
||||||
|
struct weston_mat3f R;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < 3 * 3; i++)
|
||||||
|
R.colmaj[i] = A.colmaj[i] - B.colmaj[i];
|
||||||
|
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Element-wise scalar multiplication */
|
||||||
|
static inline struct weston_mat3f
|
||||||
|
weston_m3f_mul_scalar(struct weston_mat3f M, float scalar)
|
||||||
|
{
|
||||||
|
struct weston_mat3f R;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < 3 * 3; i++)
|
||||||
|
R.colmaj[i] = scalar * M.colmaj[i];
|
||||||
|
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_m3f_invert(struct weston_mat3f *out, struct weston_mat3f M);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
206
include/libweston/linalg-4.h
Normal file
206
include/libweston/linalg-4.h
Normal file
|
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2025 Collabora, Ltd.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the
|
||||||
|
* next paragraph) shall be included in all copies or substantial
|
||||||
|
* portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <libweston/linalg-types.h>
|
||||||
|
|
||||||
|
/* ================= 4-vectors and 4x4 matrices ============== */
|
||||||
|
|
||||||
|
/** Construct a column vector from elements */
|
||||||
|
#define WESTON_VEC4F(x, y, z, w) ((struct weston_vec4f){ .el = { (x), (y), (z), (w) }})
|
||||||
|
|
||||||
|
/** Construct the [0, 0, 0, 0]^T vector */
|
||||||
|
#define WESTON_VEC4F_ZERO ((struct weston_vec4f){ .el = {}})
|
||||||
|
|
||||||
|
/** Construct matrix from elements a{row}{column} */
|
||||||
|
#define WESTON_MAT4F(a00, a01, a02, a03, \
|
||||||
|
a10, a11, a12, a13, \
|
||||||
|
a20, a21, a22, a23, \
|
||||||
|
a30, a31, a32, a33) \
|
||||||
|
((struct weston_mat4f){ .colmaj = { \
|
||||||
|
a00, a10, a20, a30, \
|
||||||
|
a01, a11, a21, a31, \
|
||||||
|
a02, a12, a22, a32, \
|
||||||
|
a03, a13, a23, a33, \
|
||||||
|
}})
|
||||||
|
|
||||||
|
/** Construct the identity 4x4 matrix */
|
||||||
|
#define WESTON_MAT4F_IDENTITY \
|
||||||
|
((struct weston_mat4f){ .colmaj = { \
|
||||||
|
1.0f, 0.0f, 0.0f, 0.0f, \
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f, \
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f, \
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f, \
|
||||||
|
}})
|
||||||
|
|
||||||
|
/** Construct a translation matrix */
|
||||||
|
static inline struct weston_mat4f
|
||||||
|
weston_m4f_translation(float tx, float ty, float tz)
|
||||||
|
{
|
||||||
|
return WESTON_MAT4F(
|
||||||
|
1.0f, 0.0f, 0.0f, tx,
|
||||||
|
0.0f, 1.0f, 0.0f, ty,
|
||||||
|
0.0f, 0.0f, 1.0f, tz,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct a scaling matrix */
|
||||||
|
static inline struct weston_mat4f
|
||||||
|
weston_m4f_scaling(float sx, float sy, float sz)
|
||||||
|
{
|
||||||
|
return WESTON_MAT4F(
|
||||||
|
sx, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, sy, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, sz, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct a 2D x-y rotation matrix
|
||||||
|
*
|
||||||
|
* \param cos_th Cosine of the counter-clockwise angle.
|
||||||
|
* \param sin_th Sine of the counter-clockwise angle.
|
||||||
|
*/
|
||||||
|
static inline struct weston_mat4f
|
||||||
|
weston_m4f_rotation_xy(float cos_th, float sin_th)
|
||||||
|
{
|
||||||
|
return WESTON_MAT4F(
|
||||||
|
cos_th, -sin_th, 0.0f, 0.0f,
|
||||||
|
sin_th, cos_th, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct weston_mat4f
|
||||||
|
weston_m4f_from_m3f_v3f(struct weston_mat3f R, struct weston_vec3f t)
|
||||||
|
{
|
||||||
|
return WESTON_MAT4F(
|
||||||
|
R.col[0].el[0], R.col[1].el[0], R.col[2].el[0], t.el[0],
|
||||||
|
R.col[0].el[1], R.col[1].el[1], R.col[2].el[1], t.el[1],
|
||||||
|
R.col[0].el[2], R.col[1].el[2], R.col[2].el[2], t.el[2],
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 4-vector dot product */
|
||||||
|
static inline float
|
||||||
|
weston_v4f_dot_v4f(struct weston_vec4f a, struct weston_vec4f b)
|
||||||
|
{
|
||||||
|
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matrix infinity-norm
|
||||||
|
*
|
||||||
|
* http://www.netlib.org/lapack/lug/node75.html
|
||||||
|
*/
|
||||||
|
static inline float
|
||||||
|
weston_m4f_inf_norm(struct weston_mat4f M)
|
||||||
|
{
|
||||||
|
unsigned row;
|
||||||
|
double infnorm = -1.0;
|
||||||
|
|
||||||
|
for (row = 0; row < 4; row++) {
|
||||||
|
unsigned col;
|
||||||
|
double sum = 0.0;
|
||||||
|
|
||||||
|
for (col = 0; col < 4; col++)
|
||||||
|
sum += fabsf(M.col[col].el[row]);
|
||||||
|
|
||||||
|
if (infnorm < sum)
|
||||||
|
infnorm = sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return infnorm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Transpose 4x4 matrix */
|
||||||
|
static inline struct weston_mat4f
|
||||||
|
weston_m4f_transpose(struct weston_mat4f M)
|
||||||
|
{
|
||||||
|
struct weston_mat4f R;
|
||||||
|
unsigned i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
R.col[j].el[i] = M.col[i].el[j];
|
||||||
|
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Matrix-vector multiplication A * b */
|
||||||
|
static inline struct weston_vec4f
|
||||||
|
weston_m4f_mul_v4f(struct weston_mat4f A, struct weston_vec4f b)
|
||||||
|
{
|
||||||
|
struct weston_vec4f result;
|
||||||
|
unsigned r;
|
||||||
|
|
||||||
|
for (r = 0; r < 4; r++) {
|
||||||
|
struct weston_vec4f row =
|
||||||
|
WESTON_VEC4F(A.col[0].el[r], A.col[1].el[r], A.col[2].el[r], A.col[3].el[r]);
|
||||||
|
result.el[r] = weston_v4f_dot_v4f(row, b);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Matrix multiplication A * B */
|
||||||
|
static inline struct weston_mat4f
|
||||||
|
weston_m4f_mul_m4f(struct weston_mat4f A, struct weston_mat4f B)
|
||||||
|
{
|
||||||
|
struct weston_mat4f result;
|
||||||
|
unsigned c;
|
||||||
|
|
||||||
|
for (c = 0; c < 4; c++)
|
||||||
|
result.col[c] = weston_m4f_mul_v4f(A, B.col[c]);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Element-wise matrix subtraction A - B */
|
||||||
|
static inline struct weston_mat4f
|
||||||
|
weston_m4f_sub_m4f(struct weston_mat4f A, struct weston_mat4f B)
|
||||||
|
{
|
||||||
|
struct weston_mat4f R;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < 4 * 4; i++)
|
||||||
|
R.colmaj[i] = A.colmaj[i] - B.colmaj[i];
|
||||||
|
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
weston_m4f_invert(struct weston_mat4f *out, struct weston_mat4f M);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2015 Samsung Electronics Co., Ltd
|
* Copyright 2025 Collabora, Ltd.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
@ -23,36 +23,54 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#pragma once
|
||||||
|
|
||||||
/*
|
#ifdef __cplusplus
|
||||||
* Common main() for test programs.
|
extern "C" {
|
||||||
*/
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
/** Column 3-vector */
|
||||||
#include <stdlib.h>
|
struct weston_vec3f {
|
||||||
|
union {
|
||||||
|
float el[3];
|
||||||
|
struct {
|
||||||
|
float x, y, z;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
float r, g, b;
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
float Y, Cb, Cr;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
#include "zunitc/zunitc.h"
|
/** 3x3 matrix, column-major */
|
||||||
|
struct weston_mat3f {
|
||||||
|
union {
|
||||||
|
struct weston_vec3f col[3];
|
||||||
|
float colmaj[3 * 3];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
int
|
/** Column 4-vector */
|
||||||
main(int argc, char* argv[])
|
struct weston_vec4f {
|
||||||
{
|
union {
|
||||||
bool helped = false;
|
float el[4];
|
||||||
int rc = zuc_initialize(&argc, argv, &helped);
|
struct {
|
||||||
|
float x, y, z, w;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
if ((rc == EXIT_SUCCESS) && !helped) {
|
/** 4x4 matrix, column-major */
|
||||||
/* Stop if any unrecognized parameters were encountered. */
|
struct weston_mat4f {
|
||||||
if (argc > 1) {
|
union {
|
||||||
printf("%s: unrecognized option '%s'\n",
|
struct weston_vec4f col[4];
|
||||||
argv[0], argv[1]);
|
float colmaj[4 * 4];
|
||||||
printf("Try '%s --help' for more information.\n",
|
};
|
||||||
argv[0]);
|
};
|
||||||
rc = EXIT_FAILURE;
|
|
||||||
} else {
|
|
||||||
rc = ZUC_RUN_TESTS();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zuc_cleanup();
|
#ifdef __cplusplus
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2015 Samsung Electronics Co., Ltd
|
* Copyright 2025 Collabora, Ltd.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
@ -23,16 +23,16 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ZUC_BASE_LOGGER_H
|
#pragma once
|
||||||
#define ZUC_BASE_LOGGER_H
|
|
||||||
|
|
||||||
struct zuc_event_listener;
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
#include <libweston/linalg-types.h>
|
||||||
* Creates a new logger that outputs data to console in the default
|
#include <libweston/linalg-3.h>
|
||||||
* format.
|
#include <libweston/linalg-4.h>
|
||||||
*/
|
|
||||||
struct zuc_event_listener *
|
|
||||||
zuc_base_logger_create(void);
|
|
||||||
|
|
||||||
#endif /* ZUC_BASE_LOGGER_H */
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include <wayland-server-protocol.h>
|
#include <wayland-server-protocol.h>
|
||||||
|
#include <libweston/linalg-types.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -44,12 +45,12 @@ enum weston_matrix_transform_type {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_matrix {
|
struct weston_matrix {
|
||||||
float d[16];
|
struct weston_mat4f M;
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_vector {
|
struct weston_vector {
|
||||||
float f[4];
|
struct weston_vec4f v;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Arbitrary coordinates in any space */
|
/** Arbitrary coordinates in any space */
|
||||||
|
|
@ -209,7 +210,7 @@ weston_coord_surface_sub(struct weston_coord_surface a,
|
||||||
static inline struct weston_coord __attribute__ ((warn_unused_result))
|
static inline struct weston_coord __attribute__ ((warn_unused_result))
|
||||||
weston_coord_truncate(struct weston_coord in)
|
weston_coord_truncate(struct weston_coord in)
|
||||||
{
|
{
|
||||||
return (struct weston_coord){ (int)in.x, (int)in.y };
|
return (struct weston_coord){ (double)(int) in.x, (double)(int) in.y };
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct weston_coord_surface __attribute__ ((warn_unused_result))
|
static inline struct weston_coord_surface __attribute__ ((warn_unused_result))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
install_headers(
|
install_headers(
|
||||||
|
'colorimetry.h',
|
||||||
'config-parser.h',
|
'config-parser.h',
|
||||||
'libweston.h',
|
'libweston.h',
|
||||||
|
'linalg.h',
|
||||||
|
'linalg-3.h',
|
||||||
|
'linalg-4.h',
|
||||||
|
'linalg-types.h',
|
||||||
'desktop.h',
|
'desktop.h',
|
||||||
'matrix.h',
|
'matrix.h',
|
||||||
'plugin-registry.h',
|
'plugin-registry.h',
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,13 @@ weston_shell_utils_curtain_destroy(struct weston_curtain *curtain);
|
||||||
enum weston_layer_position
|
enum weston_layer_position
|
||||||
weston_shell_utils_view_get_layer_position(struct weston_view *view);
|
weston_shell_utils_view_get_layer_position(struct weston_view *view);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_output_set_shell_private(struct weston_output *output,
|
||||||
|
void *private_data);
|
||||||
|
|
||||||
|
void *
|
||||||
|
weston_output_get_shell_private(struct weston_output *output);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,12 @@ struct weston_log_scope *
|
||||||
weston_log_scopes_iterate(struct weston_log_context *log_ctx,
|
weston_log_scopes_iterate(struct weston_log_context *log_ctx,
|
||||||
struct weston_log_scope *nscope);
|
struct weston_log_scope *nscope);
|
||||||
|
|
||||||
|
void
|
||||||
|
weston_add_scope_to_advertised_list(struct weston_log_context *ctx,
|
||||||
|
const char *name);
|
||||||
|
bool
|
||||||
|
weston_log_scope_to_be_advertised(struct weston_log_context *ctx, const char *name);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,10 @@ extern "C" {
|
||||||
|
|
||||||
#include <libweston/plugin-registry.h>
|
#include <libweston/plugin-registry.h>
|
||||||
|
|
||||||
|
#ifndef ARRAY_LENGTH
|
||||||
|
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||||
|
#endif
|
||||||
|
|
||||||
struct weston_compositor;
|
struct weston_compositor;
|
||||||
struct weston_output;
|
struct weston_output;
|
||||||
|
|
||||||
|
|
@ -99,8 +103,9 @@ weston_windowed_output_get_api(struct weston_compositor *compositor,
|
||||||
if (type >= ARRAY_LENGTH(api_names))
|
if (type >= ARRAY_LENGTH(api_names))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return weston_plugin_api_get(compositor, api_names[type],
|
return (const struct weston_windowed_output_api *)
|
||||||
sizeof(struct weston_windowed_output_api));
|
weston_plugin_api_get(compositor, api_names[type],
|
||||||
|
sizeof(struct weston_windowed_output_api));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -1455,6 +1455,8 @@ ivi_hmi_controller_UI_ready(struct wl_client *client,
|
||||||
hmi_ctrl->interface->commit_changes();
|
hmi_ctrl->interface->commit_changes();
|
||||||
|
|
||||||
ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
|
ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
|
||||||
|
|
||||||
|
hmi_ctrl->interface->screen_ready(hmi_ctrl->workspace_background_output);
|
||||||
hmi_ctrl->is_initialized = 1;
|
hmi_ctrl->is_initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -219,6 +219,17 @@ struct ivi_layout_interface {
|
||||||
*/
|
*/
|
||||||
void (*add_listener_configure_desktop_surface)(struct wl_listener *listener);
|
void (*add_listener_configure_desktop_surface)(struct wl_listener *listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief add a listener for desktop_surface ping timeout notification
|
||||||
|
*
|
||||||
|
* When a desktop_client fails to respond to compositor pings within
|
||||||
|
* the configured timeout period, this signal is emitted to registered
|
||||||
|
* listeners. The void* data argument will contain a pointer to the
|
||||||
|
* weston_desktop_client associated with the unresponsive surface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void (*add_listener_desktop_surface_ping_timeout)(struct wl_listener *listener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get all ivi_surfaces which are currently registered and managed
|
* \brief Get all ivi_surfaces which are currently registered and managed
|
||||||
* by the services
|
* by the services
|
||||||
|
|
@ -636,6 +647,12 @@ struct ivi_layout_interface {
|
||||||
* See add_listener_show_input_panel for more details.
|
* See add_listener_show_input_panel for more details.
|
||||||
*/
|
*/
|
||||||
void (*add_listener_update_input_panel)(struct wl_listener *listener);
|
void (*add_listener_update_input_panel)(struct wl_listener *listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set weston_output ready to be painted
|
||||||
|
*/
|
||||||
|
void (*screen_ready)(struct weston_output *output);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline const struct ivi_layout_interface *
|
static inline const struct ivi_layout_interface *
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ struct ivi_layout {
|
||||||
struct wl_signal removed;
|
struct wl_signal removed;
|
||||||
struct wl_signal configure_changed;
|
struct wl_signal configure_changed;
|
||||||
struct wl_signal configure_desktop_changed;
|
struct wl_signal configure_desktop_changed;
|
||||||
|
struct wl_signal ping_timeout;
|
||||||
} surface_notification;
|
} surface_notification;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,9 @@ void
|
||||||
ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
|
ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
|
||||||
int32_t width, int32_t height);
|
int32_t width, int32_t height);
|
||||||
|
|
||||||
|
void
|
||||||
|
ivi_layout_desktop_surface_ping_timeout(struct weston_desktop_client *client);
|
||||||
|
|
||||||
struct ivi_layout_surface*
|
struct ivi_layout_surface*
|
||||||
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
|
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
|
||||||
struct weston_desktop_surface *surface);
|
struct weston_desktop_surface *surface);
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@
|
||||||
|
|
||||||
#include "frontend/weston.h"
|
#include "frontend/weston.h"
|
||||||
#include <libweston/libweston.h>
|
#include <libweston/libweston.h>
|
||||||
|
#include <libweston/shell-utils.h>
|
||||||
#include "ivi-shell.h"
|
#include "ivi-shell.h"
|
||||||
#include "ivi-layout-export.h"
|
#include "ivi-layout-export.h"
|
||||||
#include "ivi-layout-private.h"
|
#include "ivi-layout-private.h"
|
||||||
|
|
@ -284,7 +285,7 @@ destroy_screen(struct ivi_layout_screen *iviscrn)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
output_destroyed_event(struct wl_listener *listener, void *data)
|
output_destroy_iviscreen(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct weston_output *destroyed_output = data;
|
struct weston_output *destroyed_output = data;
|
||||||
struct ivi_layout_screen *iviscrn;
|
struct ivi_layout_screen *iviscrn;
|
||||||
|
|
@ -295,8 +296,8 @@ output_destroyed_event(struct wl_listener *listener, void *data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static struct ivi_layout_screen *
|
||||||
add_screen(struct weston_output *output)
|
create_screen(struct weston_output *output)
|
||||||
{
|
{
|
||||||
struct ivi_layout *layout = get_instance();
|
struct ivi_layout *layout = get_instance();
|
||||||
struct ivi_layout_screen *iviscrn = NULL;
|
struct ivi_layout_screen *iviscrn = NULL;
|
||||||
|
|
@ -309,26 +310,24 @@ add_screen(struct weston_output *output)
|
||||||
wl_list_init(&iviscrn->pending.layer_list);
|
wl_list_init(&iviscrn->pending.layer_list);
|
||||||
wl_list_init(&iviscrn->order.layer_list);
|
wl_list_init(&iviscrn->order.layer_list);
|
||||||
wl_list_insert(&layout->screen_list, &iviscrn->link);
|
wl_list_insert(&layout->screen_list, &iviscrn->link);
|
||||||
|
|
||||||
|
return iviscrn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
output_created_event(struct wl_listener *listener, void *data)
|
create_ivi_screen(struct ivi_layout *layout, struct weston_output *output)
|
||||||
{
|
{
|
||||||
struct weston_output *created_output = data;
|
create_screen(output);
|
||||||
add_screen(created_output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal API to initialize ivi_screens found from output_list of weston_compositor.
|
|
||||||
* Called by ivi_layout_init.
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
create_screen(struct weston_compositor *ec)
|
output_create_iviscreen(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct weston_output *output = NULL;
|
struct ivi_layout *layout =
|
||||||
|
container_of(listener, struct ivi_layout, output_created);
|
||||||
|
struct weston_output *output = data;
|
||||||
|
|
||||||
wl_list_for_each(output, &ec->output_list, link)
|
create_ivi_screen(layout, output);
|
||||||
add_screen(output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -463,33 +462,33 @@ calc_inverse_matrix_transform(const struct weston_matrix *matrix,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The vectors and matrices involved will always produce f[3] == 1.0. */
|
/* The vectors and matrices involved will always produce f[3] == 1.0. */
|
||||||
top_left.f[0] = rect_input->x;
|
top_left.v.el[0] = rect_input->x;
|
||||||
top_left.f[1] = rect_input->y;
|
top_left.v.el[1] = rect_input->y;
|
||||||
top_left.f[2] = 0.0f;
|
top_left.v.el[2] = 0.0f;
|
||||||
top_left.f[3] = 1.0f;
|
top_left.v.el[3] = 1.0f;
|
||||||
|
|
||||||
bottom_right.f[0] = rect_input->x + rect_input->width;
|
bottom_right.v.el[0] = rect_input->x + rect_input->width;
|
||||||
bottom_right.f[1] = rect_input->y + rect_input->height;
|
bottom_right.v.el[1] = rect_input->y + rect_input->height;
|
||||||
bottom_right.f[2] = 0.0f;
|
bottom_right.v.el[2] = 0.0f;
|
||||||
bottom_right.f[3] = 1.0f;
|
bottom_right.v.el[3] = 1.0f;
|
||||||
|
|
||||||
weston_matrix_transform(&m, &top_left);
|
weston_matrix_transform(&m, &top_left);
|
||||||
weston_matrix_transform(&m, &bottom_right);
|
weston_matrix_transform(&m, &bottom_right);
|
||||||
|
|
||||||
if (top_left.f[0] < bottom_right.f[0]) {
|
if (top_left.v.el[0] < bottom_right.v.el[0]) {
|
||||||
rect_output->x = floorf(top_left.f[0]);
|
rect_output->x = floor(top_left.v.el[0]);
|
||||||
rect_output->width = ceilf(bottom_right.f[0] - rect_output->x);
|
rect_output->width = ceil(bottom_right.v.el[0] - rect_output->x);
|
||||||
} else {
|
} else {
|
||||||
rect_output->x = floorf(bottom_right.f[0]);
|
rect_output->x = floor(bottom_right.v.el[0]);
|
||||||
rect_output->width = ceilf(top_left.f[0] - rect_output->x);
|
rect_output->width = ceil(top_left.v.el[0] - rect_output->x);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (top_left.f[1] < bottom_right.f[1]) {
|
if (top_left.v.el[1] < bottom_right.v.el[1]) {
|
||||||
rect_output->y = floorf(top_left.f[1]);
|
rect_output->y = floor(top_left.v.el[1]);
|
||||||
rect_output->height = ceilf(bottom_right.f[1] - rect_output->y);
|
rect_output->height = ceil(bottom_right.v.el[1] - rect_output->y);
|
||||||
} else {
|
} else {
|
||||||
rect_output->y = floorf(bottom_right.f[1]);
|
rect_output->y = floor(bottom_right.v.el[1]);
|
||||||
rect_output->height = ceilf(top_left.f[1] - rect_output->y);
|
rect_output->height = ceil(top_left.v.el[1] - rect_output->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
ivi_rectangle_intersect(rect_output, boundingbox, rect_output);
|
ivi_rectangle_intersect(rect_output, boundingbox, rect_output);
|
||||||
|
|
@ -988,6 +987,16 @@ ivi_layout_add_listener_configure_desktop_surface(struct wl_listener *listener)
|
||||||
wl_signal_add(&layout->surface_notification.configure_desktop_changed, listener);
|
wl_signal_add(&layout->surface_notification.configure_desktop_changed, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ivi_layout_add_listener_desktop_surface_ping_timeout(struct wl_listener *listener)
|
||||||
|
{
|
||||||
|
struct ivi_layout *layout = get_instance();
|
||||||
|
|
||||||
|
assert(listener);
|
||||||
|
|
||||||
|
wl_signal_add(&layout->surface_notification.ping_timeout, listener);
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t
|
static int32_t
|
||||||
ivi_layout_shell_add_destroy_listener_once(struct wl_listener *listener, wl_notify_func_t destroy_handler)
|
ivi_layout_shell_add_destroy_listener_once(struct wl_listener *listener, wl_notify_func_t destroy_handler)
|
||||||
{
|
{
|
||||||
|
|
@ -1564,6 +1573,12 @@ ivi_layout_screen_set_render_order(struct weston_output *output,
|
||||||
iviscrn->order.dirty = 1;
|
iviscrn->order.dirty = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ivi_layout_set_screen_ready(struct weston_output *output)
|
||||||
|
{
|
||||||
|
weston_output_set_ready(output);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is used by the additional ivi-module because of dumping ivi_surface sceenshot.
|
* This function is used by the additional ivi-module because of dumping ivi_surface sceenshot.
|
||||||
* The ivi-module, e.g. ivi-controller.so, is in wayland-ivi-extension of Genivi's Layer Management.
|
* The ivi-module, e.g. ivi-controller.so, is in wayland-ivi-extension of Genivi's Layer Management.
|
||||||
|
|
@ -1912,6 +1927,14 @@ ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
|
||||||
ivisurf);
|
ivisurf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ivi_layout_desktop_surface_ping_timeout(struct weston_desktop_client *client)
|
||||||
|
{
|
||||||
|
struct ivi_layout *layout = get_instance();
|
||||||
|
|
||||||
|
wl_signal_emit_mutable(&layout->surface_notification.ping_timeout, client);
|
||||||
|
}
|
||||||
|
|
||||||
struct ivi_layout_surface*
|
struct ivi_layout_surface*
|
||||||
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
|
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
|
||||||
struct weston_desktop_surface *surface)
|
struct weston_desktop_surface *surface)
|
||||||
|
|
@ -2098,6 +2121,7 @@ void
|
||||||
ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
|
ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
|
||||||
{
|
{
|
||||||
struct ivi_layout *layout = get_instance();
|
struct ivi_layout *layout = get_instance();
|
||||||
|
struct weston_output *output;
|
||||||
|
|
||||||
layout->shell = shell;
|
layout->shell = shell;
|
||||||
|
|
||||||
|
|
@ -2113,6 +2137,7 @@ ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
|
||||||
wl_signal_init(&layout->surface_notification.removed);
|
wl_signal_init(&layout->surface_notification.removed);
|
||||||
wl_signal_init(&layout->surface_notification.configure_changed);
|
wl_signal_init(&layout->surface_notification.configure_changed);
|
||||||
wl_signal_init(&layout->surface_notification.configure_desktop_changed);
|
wl_signal_init(&layout->surface_notification.configure_desktop_changed);
|
||||||
|
wl_signal_init(&layout->surface_notification.ping_timeout);
|
||||||
|
|
||||||
wl_signal_init(&layout->input_panel_notification.configure_changed);
|
wl_signal_init(&layout->input_panel_notification.configure_changed);
|
||||||
wl_signal_init(&layout->input_panel_notification.show);
|
wl_signal_init(&layout->input_panel_notification.show);
|
||||||
|
|
@ -2126,12 +2151,13 @@ ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
|
||||||
weston_layer_set_position(&layout->layout_layer,
|
weston_layer_set_position(&layout->layout_layer,
|
||||||
WESTON_LAYER_POSITION_NORMAL);
|
WESTON_LAYER_POSITION_NORMAL);
|
||||||
|
|
||||||
create_screen(ec);
|
layout->output_created.notify = output_create_iviscreen;
|
||||||
|
|
||||||
layout->output_created.notify = output_created_event;
|
|
||||||
wl_signal_add(&ec->output_created_signal, &layout->output_created);
|
wl_signal_add(&ec->output_created_signal, &layout->output_created);
|
||||||
|
|
||||||
layout->output_destroyed.notify = output_destroyed_event;
|
wl_list_for_each(output, &ec->output_list, link)
|
||||||
|
create_ivi_screen(layout, output);
|
||||||
|
|
||||||
|
layout->output_destroyed.notify = output_destroy_iviscreen;
|
||||||
wl_signal_add(&ec->output_destroyed_signal, &layout->output_destroyed);
|
wl_signal_add(&ec->output_destroyed_signal, &layout->output_destroyed);
|
||||||
|
|
||||||
layout->transitions = ivi_layout_transition_set_create(ec);
|
layout->transitions = ivi_layout_transition_set_create(ec);
|
||||||
|
|
@ -2146,6 +2172,10 @@ void
|
||||||
ivi_layout_fini(void)
|
ivi_layout_fini(void)
|
||||||
{
|
{
|
||||||
struct ivi_layout *layout = get_instance();
|
struct ivi_layout *layout = get_instance();
|
||||||
|
struct ivi_layout_screen *iviscrn, *iviscrn_tmp;
|
||||||
|
|
||||||
|
wl_list_for_each_safe(iviscrn, iviscrn_tmp, &layout->screen_list, link)
|
||||||
|
destroy_screen(iviscrn);
|
||||||
|
|
||||||
weston_layer_fini(&layout->layout_layer);
|
weston_layer_fini(&layout->layout_layer);
|
||||||
|
|
||||||
|
|
@ -2164,32 +2194,33 @@ static struct ivi_layout_interface ivi_layout_interface = {
|
||||||
/**
|
/**
|
||||||
* surface controller interfaces
|
* surface controller interfaces
|
||||||
*/
|
*/
|
||||||
.add_listener_create_surface = ivi_layout_add_listener_create_surface,
|
.add_listener_create_surface = ivi_layout_add_listener_create_surface,
|
||||||
.add_listener_remove_surface = ivi_layout_add_listener_remove_surface,
|
.add_listener_remove_surface = ivi_layout_add_listener_remove_surface,
|
||||||
.add_listener_configure_surface = ivi_layout_add_listener_configure_surface,
|
.add_listener_configure_surface = ivi_layout_add_listener_configure_surface,
|
||||||
.add_listener_configure_desktop_surface = ivi_layout_add_listener_configure_desktop_surface,
|
.add_listener_configure_desktop_surface = ivi_layout_add_listener_configure_desktop_surface,
|
||||||
.get_surface = shell_get_ivi_layout_surface,
|
.add_listener_desktop_surface_ping_timeout = ivi_layout_add_listener_desktop_surface_ping_timeout,
|
||||||
.get_surfaces = ivi_layout_get_surfaces,
|
.get_surface = shell_get_ivi_layout_surface,
|
||||||
.get_id_of_surface = ivi_layout_get_id_of_surface,
|
.get_surfaces = ivi_layout_get_surfaces,
|
||||||
.get_surface_from_id = ivi_layout_get_surface_from_id,
|
.get_id_of_surface = ivi_layout_get_id_of_surface,
|
||||||
.get_properties_of_surface = ivi_layout_get_properties_of_surface,
|
.get_surface_from_id = ivi_layout_get_surface_from_id,
|
||||||
.get_surfaces_on_layer = ivi_layout_get_surfaces_on_layer,
|
.get_properties_of_surface = ivi_layout_get_properties_of_surface,
|
||||||
.surface_set_visibility = ivi_layout_surface_set_visibility,
|
.get_surfaces_on_layer = ivi_layout_get_surfaces_on_layer,
|
||||||
.surface_set_opacity = ivi_layout_surface_set_opacity,
|
.surface_set_visibility = ivi_layout_surface_set_visibility,
|
||||||
.surface_set_source_rectangle = ivi_layout_surface_set_source_rectangle,
|
.surface_set_opacity = ivi_layout_surface_set_opacity,
|
||||||
.surface_set_destination_rectangle = ivi_layout_surface_set_destination_rectangle,
|
.surface_set_source_rectangle = ivi_layout_surface_set_source_rectangle,
|
||||||
.surface_add_listener = ivi_layout_surface_add_listener,
|
.surface_set_destination_rectangle = ivi_layout_surface_set_destination_rectangle,
|
||||||
.surface_get_weston_surface = ivi_layout_surface_get_weston_surface,
|
.surface_add_listener = ivi_layout_surface_add_listener,
|
||||||
.surface_set_transition = ivi_layout_surface_set_transition,
|
.surface_get_weston_surface = ivi_layout_surface_get_weston_surface,
|
||||||
.surface_set_transition_duration = ivi_layout_surface_set_transition_duration,
|
.surface_set_transition = ivi_layout_surface_set_transition,
|
||||||
.surface_set_id = ivi_layout_surface_set_id,
|
.surface_set_transition_duration = ivi_layout_surface_set_transition_duration,
|
||||||
.surface_activate = ivi_layout_surface_activate,
|
.surface_set_id = ivi_layout_surface_set_id,
|
||||||
.surface_is_active = ivi_layout_surface_is_active,
|
.surface_activate = ivi_layout_surface_activate,
|
||||||
|
.surface_is_active = ivi_layout_surface_is_active,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* layer controller interfaces
|
* layer controller interfaces
|
||||||
*/
|
*/
|
||||||
.add_listener_create_layer = ivi_layout_add_listener_create_layer,
|
.add_listener_create_layer = ivi_layout_add_listener_create_layer,
|
||||||
.add_listener_remove_layer = ivi_layout_add_listener_remove_layer,
|
.add_listener_remove_layer = ivi_layout_add_listener_remove_layer,
|
||||||
.layer_create_with_dimension = ivi_layout_layer_create_with_dimension,
|
.layer_create_with_dimension = ivi_layout_layer_create_with_dimension,
|
||||||
.layer_destroy = ivi_layout_layer_destroy,
|
.layer_destroy = ivi_layout_layer_destroy,
|
||||||
|
|
@ -2216,6 +2247,7 @@ static struct ivi_layout_interface ivi_layout_interface = {
|
||||||
.screen_add_layer = ivi_layout_screen_add_layer,
|
.screen_add_layer = ivi_layout_screen_add_layer,
|
||||||
.screen_remove_layer = ivi_layout_screen_remove_layer,
|
.screen_remove_layer = ivi_layout_screen_remove_layer,
|
||||||
.screen_set_render_order = ivi_layout_screen_set_render_order,
|
.screen_set_render_order = ivi_layout_screen_set_render_order,
|
||||||
|
.screen_ready = ivi_layout_set_screen_ready,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* animation
|
* animation
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
#include "shared/helpers.h"
|
#include "shared/helpers.h"
|
||||||
#include "shared/xalloc.h"
|
#include "shared/xalloc.h"
|
||||||
#include "frontend/weston.h"
|
#include "frontend/weston.h"
|
||||||
|
#include <libweston/shell-utils.h>
|
||||||
|
|
||||||
/* Representation of ivi_surface protocol object. */
|
/* Representation of ivi_surface protocol object. */
|
||||||
struct ivi_shell_surface
|
struct ivi_shell_surface
|
||||||
|
|
@ -214,7 +215,7 @@ ivi_shell_surface_get_label(struct weston_surface *surface,
|
||||||
{
|
{
|
||||||
struct ivi_shell_surface *shell_surf = get_ivi_shell_surface(surface);
|
struct ivi_shell_surface *shell_surf = get_ivi_shell_surface(surface);
|
||||||
|
|
||||||
return snprintf(buf, len, "ivi-surface %#x", shell_surf->id_surface);
|
return snprintf(buf, len, "ivi-surface %u", shell_surf->id_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -622,7 +623,7 @@ static void
|
||||||
desktop_surface_ping_timeout(struct weston_desktop_client *client,
|
desktop_surface_ping_timeout(struct weston_desktop_client *client,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
/* Not supported */
|
ivi_layout_desktop_surface_ping_timeout(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -646,6 +647,8 @@ desktop_surface_added(struct weston_desktop_surface *surface,
|
||||||
|
|
||||||
ivisurf = xzalloc(sizeof *ivisurf);
|
ivisurf = xzalloc(sizeof *ivisurf);
|
||||||
|
|
||||||
|
weston_surface_set_label_func(weston_surf, weston_shell_utils_surface_get_label);
|
||||||
|
|
||||||
ivisurf->shell = shell;
|
ivisurf->shell = shell;
|
||||||
ivisurf->id_surface = IVI_INVALID_ID;
|
ivisurf->id_surface = IVI_INVALID_ID;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,3 +96,9 @@ workspace-id=3
|
||||||
icon-id=4010
|
icon-id=4010
|
||||||
icon=@westondatadir@/icon_ivi_smoke.png
|
icon=@westondatadir@/icon_ivi_smoke.png
|
||||||
path=@bindir@/weston-smoke
|
path=@bindir@/weston-smoke
|
||||||
|
|
||||||
|
[ivi-launcher]
|
||||||
|
workspace-id=3
|
||||||
|
icon-id=4011
|
||||||
|
icon=@westondatadir@/icon_ivi_simple-egl-vertical.png
|
||||||
|
command=@bindir@/weston-simple-egl -v
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ xwayland_get_xwayland_name(struct kiosk_shell_surface *shsurf, enum window_atom_
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
||||||
struct weston_output *output);
|
struct kiosk_shell_output *shoutput);
|
||||||
static void
|
static void
|
||||||
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
|
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
|
||||||
struct kiosk_shell_surface *parent);
|
struct kiosk_shell_surface *parent);
|
||||||
|
|
@ -147,9 +147,6 @@ kiosk_shell_output_set_active_surface_tree(struct kiosk_shell_output *shoutput,
|
||||||
static void
|
static void
|
||||||
kiosk_shell_output_raise_surface_subtree(struct kiosk_shell_output *shoutput,
|
kiosk_shell_output_raise_surface_subtree(struct kiosk_shell_output *shoutput,
|
||||||
struct kiosk_shell_surface *shroot);
|
struct kiosk_shell_surface *shroot);
|
||||||
static struct kiosk_shell_output *
|
|
||||||
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
|
|
||||||
struct weston_output *output);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kiosk_shell_surface_notify_parent_destroy(struct wl_listener *listener, void *data)
|
kiosk_shell_surface_notify_parent_destroy(struct wl_listener *listener, void *data)
|
||||||
|
|
@ -183,7 +180,7 @@ kiosk_shell_surface_get_parent_root(struct kiosk_shell_surface *shsurf)
|
||||||
static bool
|
static bool
|
||||||
kiosk_shell_output_has_app_id(char *config_app_ids, const char *app_id);
|
kiosk_shell_output_has_app_id(char *config_app_ids, const char *app_id);
|
||||||
|
|
||||||
static struct weston_output *
|
static struct kiosk_shell_output *
|
||||||
kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *shsurf)
|
kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *shsurf)
|
||||||
{
|
{
|
||||||
struct kiosk_shell_output *shoutput;
|
struct kiosk_shell_output *shoutput;
|
||||||
|
|
@ -208,7 +205,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
||||||
|
|
||||||
if (found_wm_name && found_wm_class) {
|
if (found_wm_name && found_wm_class) {
|
||||||
shsurf->appid_output_assigned = true;
|
shsurf->appid_output_assigned = true;
|
||||||
return shoutput->output;
|
return shoutput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,7 +216,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
||||||
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_name_app_ids,
|
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_name_app_ids,
|
||||||
wm_name)) {
|
wm_name)) {
|
||||||
shsurf->appid_output_assigned = true;
|
shsurf->appid_output_assigned = true;
|
||||||
return shoutput->output;
|
return shoutput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -229,7 +226,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
||||||
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_class_app_ids,
|
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_class_app_ids,
|
||||||
wm_class)) {
|
wm_class)) {
|
||||||
shsurf->appid_output_assigned = true;
|
shsurf->appid_output_assigned = true;
|
||||||
return shoutput->output;
|
return shoutput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -237,7 +234,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct weston_output *
|
static struct kiosk_shell_output *
|
||||||
kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
|
kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
|
||||||
{
|
{
|
||||||
struct weston_output *output;
|
struct weston_output *output;
|
||||||
|
|
@ -255,14 +252,14 @@ kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
|
||||||
wl_list_for_each(shoutput, &shsurf->shell->output_list, link) {
|
wl_list_for_each(shoutput, &shsurf->shell->output_list, link) {
|
||||||
if (kiosk_shell_output_has_app_id(shoutput->app_ids, app_id)) {
|
if (kiosk_shell_output_has_app_id(shoutput->app_ids, app_id)) {
|
||||||
shsurf->appid_output_assigned = true;
|
shsurf->appid_output_assigned = true;
|
||||||
return shoutput->output;
|
return shoutput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output = kiosk_shell_surface_find_best_output_for_xwayland(shsurf);
|
shoutput = kiosk_shell_surface_find_best_output_for_xwayland(shsurf);
|
||||||
if (output)
|
if (shoutput)
|
||||||
return output;
|
return shoutput;
|
||||||
|
|
||||||
/* Group all related windows in the same output. */
|
/* Group all related windows in the same output. */
|
||||||
root = kiosk_shell_surface_get_parent_root(shsurf);
|
root = kiosk_shell_surface_get_parent_root(shsurf);
|
||||||
|
|
@ -271,20 +268,20 @@ kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
|
||||||
|
|
||||||
output = weston_shell_utils_get_focused_output(shsurf->shell->compositor);
|
output = weston_shell_utils_get_focused_output(shsurf->shell->compositor);
|
||||||
if (output)
|
if (output)
|
||||||
return output;
|
return weston_output_get_shell_private(output);
|
||||||
|
|
||||||
output = weston_shell_utils_get_default_output(shsurf->shell->compositor);
|
output = weston_shell_utils_get_default_output(shsurf->shell->compositor);
|
||||||
if (output)
|
if (output)
|
||||||
return output;
|
return weston_output_get_shell_private(output);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
||||||
struct weston_output *output)
|
struct kiosk_shell_output *shoutput)
|
||||||
{
|
{
|
||||||
shsurf->output = output;
|
shsurf->output = shoutput;
|
||||||
|
|
||||||
if (shsurf->output_destroy_listener.notify) {
|
if (shsurf->output_destroy_listener.notify) {
|
||||||
wl_list_remove(&shsurf->output_destroy_listener.link);
|
wl_list_remove(&shsurf->output_destroy_listener.link);
|
||||||
|
|
@ -296,39 +293,39 @@ kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
||||||
|
|
||||||
shsurf->output_destroy_listener.notify =
|
shsurf->output_destroy_listener.notify =
|
||||||
kiosk_shell_surface_notify_output_destroy;
|
kiosk_shell_surface_notify_output_destroy;
|
||||||
wl_signal_add(&shsurf->output->destroy_signal,
|
wl_signal_add(&shsurf->output->output->destroy_signal,
|
||||||
&shsurf->output_destroy_listener);
|
&shsurf->output_destroy_listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kiosk_shell_surface_set_fullscreen(struct kiosk_shell_surface *shsurf,
|
kiosk_shell_surface_set_fullscreen(struct kiosk_shell_surface *shsurf,
|
||||||
struct weston_output *output)
|
struct kiosk_shell_output *shoutput)
|
||||||
{
|
{
|
||||||
if (!output)
|
if (!shoutput)
|
||||||
output = kiosk_shell_surface_find_best_output(shsurf);
|
shoutput = kiosk_shell_surface_find_best_output(shsurf);
|
||||||
|
|
||||||
kiosk_shell_surface_set_output(shsurf, output);
|
kiosk_shell_surface_set_output(shsurf, shoutput);
|
||||||
|
|
||||||
weston_desktop_surface_set_fullscreen(shsurf->desktop_surface, true);
|
weston_desktop_surface_set_fullscreen(shsurf->desktop_surface, true);
|
||||||
if (shsurf->output)
|
if (shsurf->output)
|
||||||
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
||||||
shsurf->output->width,
|
shsurf->output->output->width,
|
||||||
shsurf->output->height);
|
shsurf->output->output->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kiosk_shell_surface_set_maximized(struct kiosk_shell_surface *shsurf)
|
kiosk_shell_surface_set_maximized(struct kiosk_shell_surface *shsurf)
|
||||||
{
|
{
|
||||||
struct weston_output *output =
|
struct kiosk_shell_output *shoutput =
|
||||||
kiosk_shell_surface_find_best_output(shsurf);
|
kiosk_shell_surface_find_best_output(shsurf);
|
||||||
|
|
||||||
kiosk_shell_surface_set_output(shsurf, output);
|
kiosk_shell_surface_set_output(shsurf, shoutput);
|
||||||
|
|
||||||
weston_desktop_surface_set_maximized(shsurf->desktop_surface, true);
|
weston_desktop_surface_set_maximized(shsurf->desktop_surface, true);
|
||||||
if (shsurf->output)
|
if (shsurf->output)
|
||||||
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
||||||
shsurf->output->width,
|
shsurf->output->output->width,
|
||||||
shsurf->output->height);
|
shsurf->output->output->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -382,9 +379,7 @@ static void
|
||||||
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
|
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
|
||||||
struct kiosk_shell_surface *parent)
|
struct kiosk_shell_surface *parent)
|
||||||
{
|
{
|
||||||
struct kiosk_shell_output *shoutput =
|
struct kiosk_shell_output *shoutput = shsurf->output;
|
||||||
kiosk_shell_find_shell_output(shsurf->shell,
|
|
||||||
shsurf->output);
|
|
||||||
struct kiosk_shell_surface *shroot = parent ?
|
struct kiosk_shell_surface *shroot = parent ?
|
||||||
kiosk_shell_surface_get_parent_root(parent) :
|
kiosk_shell_surface_get_parent_root(parent) :
|
||||||
kiosk_shell_surface_get_parent_root(shsurf);
|
kiosk_shell_surface_get_parent_root(shsurf);
|
||||||
|
|
@ -436,20 +431,22 @@ static void
|
||||||
kiosk_shell_surface_reconfigure_for_output(struct kiosk_shell_surface *shsurf)
|
kiosk_shell_surface_reconfigure_for_output(struct kiosk_shell_surface *shsurf)
|
||||||
{
|
{
|
||||||
struct weston_desktop_surface *desktop_surface;
|
struct weston_desktop_surface *desktop_surface;
|
||||||
|
struct weston_output *w_output;
|
||||||
|
|
||||||
if (!shsurf->output)
|
if (!shsurf->output)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
w_output = shsurf->output->output;
|
||||||
desktop_surface = shsurf->desktop_surface;
|
desktop_surface = shsurf->desktop_surface;
|
||||||
|
|
||||||
if (weston_desktop_surface_get_maximized(desktop_surface) ||
|
if (weston_desktop_surface_get_maximized(desktop_surface) ||
|
||||||
weston_desktop_surface_get_fullscreen(desktop_surface)) {
|
weston_desktop_surface_get_fullscreen(desktop_surface)) {
|
||||||
weston_desktop_surface_set_size(desktop_surface,
|
weston_desktop_surface_set_size(desktop_surface,
|
||||||
shsurf->output->width,
|
w_output->width,
|
||||||
shsurf->output->height);
|
w_output->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
weston_shell_utils_center_on_output(shsurf->view, shsurf->output);
|
weston_shell_utils_center_on_output(shsurf->view, w_output);
|
||||||
weston_view_update_transform(shsurf->view);
|
weston_view_update_transform(shsurf->view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -530,8 +527,7 @@ kiosk_shell_surface_activate(struct kiosk_shell_surface *shsurf,
|
||||||
struct weston_desktop_surface *dsurface = shsurf->desktop_surface;
|
struct weston_desktop_surface *dsurface = shsurf->desktop_surface;
|
||||||
struct weston_surface *surface =
|
struct weston_surface *surface =
|
||||||
weston_desktop_surface_get_surface(dsurface);
|
weston_desktop_surface_get_surface(dsurface);
|
||||||
struct kiosk_shell_output *shoutput =
|
struct kiosk_shell_output *shoutput = shsurf->output;
|
||||||
kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
|
|
||||||
|
|
||||||
/* keyboard focus */
|
/* keyboard focus */
|
||||||
weston_view_activate_input(shsurf->view, kiosk_seat->seat, activate_flags);
|
weston_view_activate_input(shsurf->view, kiosk_seat->seat, activate_flags);
|
||||||
|
|
@ -824,8 +820,11 @@ kiosk_shell_output_create(struct kiosk_shell *shell, struct weston_output *outpu
|
||||||
|
|
||||||
wl_list_insert(shell->output_list.prev, &shoutput->link);
|
wl_list_insert(shell->output_list.prev, &shoutput->link);
|
||||||
|
|
||||||
|
weston_output_set_shell_private(output, shoutput);
|
||||||
|
|
||||||
kiosk_shell_output_recreate_background(shoutput);
|
kiosk_shell_output_recreate_background(shoutput);
|
||||||
kiosk_shell_output_configure(shoutput);
|
kiosk_shell_output_configure(shoutput);
|
||||||
|
weston_output_set_ready(output);
|
||||||
|
|
||||||
return shoutput;
|
return shoutput;
|
||||||
}
|
}
|
||||||
|
|
@ -870,6 +869,9 @@ find_focus_successor(struct kiosk_shell_surface *shsurf,
|
||||||
struct weston_layer *layer;
|
struct weston_layer *layer;
|
||||||
struct weston_view *view;
|
struct weston_view *view;
|
||||||
|
|
||||||
|
if (!shsurf->output)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
wl_list_for_each(layer, layers, link) {
|
wl_list_for_each(layer, layers, link) {
|
||||||
struct kiosk_shell *shell = shsurf->shell;
|
struct kiosk_shell *shell = shsurf->shell;
|
||||||
|
|
||||||
|
|
@ -885,7 +887,7 @@ find_focus_successor(struct kiosk_shell_surface *shsurf,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* pick views only on the same output */
|
/* pick views only on the same output */
|
||||||
if (view->output != shsurf->output)
|
if (view->output != shsurf->output->output)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
view_shsurf = get_kiosk_shell_surface(view->surface);
|
view_shsurf = get_kiosk_shell_surface(view->surface);
|
||||||
|
|
@ -947,7 +949,7 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
|
||||||
|
|
||||||
successor = find_focus_successor(shsurf,
|
successor = find_focus_successor(shsurf,
|
||||||
kiosk_seat->focused_surface);
|
kiosk_seat->focused_surface);
|
||||||
shoutput = kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
|
shoutput = shsurf->output;
|
||||||
if (shoutput && successor) {
|
if (shoutput && successor) {
|
||||||
enum weston_layer_position succesor_view_layer_pos;
|
enum weston_layer_position succesor_view_layer_pos;
|
||||||
|
|
||||||
|
|
@ -991,17 +993,17 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!shsurf->appid_output_assigned && app_id) {
|
if (!shsurf->appid_output_assigned && app_id) {
|
||||||
struct weston_output *output = NULL;
|
struct kiosk_shell_output *shoutput = NULL;
|
||||||
|
|
||||||
/* reset previous output being set in _added() as the output is
|
/* reset previous output being set in _added() as the output is
|
||||||
* being cached */
|
* being cached */
|
||||||
shsurf->output = NULL;
|
shsurf->output = NULL;
|
||||||
output = kiosk_shell_surface_find_best_output(shsurf);
|
shoutput = kiosk_shell_surface_find_best_output(shsurf);
|
||||||
|
|
||||||
kiosk_shell_surface_set_output(shsurf, output);
|
kiosk_shell_surface_set_output(shsurf, shoutput);
|
||||||
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
||||||
shsurf->output->width,
|
shoutput->output->width,
|
||||||
shsurf->output->height);
|
shoutput->output->height);
|
||||||
/* even if we couldn't find an appid set for a particular
|
/* even if we couldn't find an appid set for a particular
|
||||||
* output still flag the shsurf as to a avoid changing the
|
* output still flag the shsurf as to a avoid changing the
|
||||||
* output every time */
|
* output every time */
|
||||||
|
|
@ -1021,7 +1023,7 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
||||||
if (!weston_surface_is_mapped(surface) || (is_resized && is_fullscreen)) {
|
if (!weston_surface_is_mapped(surface) || (is_resized && is_fullscreen)) {
|
||||||
if (is_fullscreen || !shsurf->xwayland.is_set) {
|
if (is_fullscreen || !shsurf->xwayland.is_set) {
|
||||||
weston_shell_utils_center_on_output(shsurf->view,
|
weston_shell_utils_center_on_output(shsurf->view,
|
||||||
shsurf->output);
|
shsurf->output->output);
|
||||||
} else {
|
} else {
|
||||||
struct weston_coord_surface offset;
|
struct weston_coord_surface offset;
|
||||||
struct weston_geometry geometry =
|
struct weston_geometry geometry =
|
||||||
|
|
@ -1040,9 +1042,7 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
||||||
if (!weston_surface_is_mapped(surface)) {
|
if (!weston_surface_is_mapped(surface)) {
|
||||||
struct weston_seat *seat =
|
struct weston_seat *seat =
|
||||||
get_kiosk_shell_first_seat(shsurf->shell);
|
get_kiosk_shell_first_seat(shsurf->shell);
|
||||||
struct kiosk_shell_output *shoutput =
|
struct kiosk_shell_output *shoutput = shsurf->output;
|
||||||
kiosk_shell_find_shell_output(shsurf->shell,
|
|
||||||
shsurf->output);
|
|
||||||
struct kiosk_shell_seat *kiosk_seat;
|
struct kiosk_shell_seat *kiosk_seat;
|
||||||
|
|
||||||
weston_surface_map(surface);
|
weston_surface_map(surface);
|
||||||
|
|
@ -1134,6 +1134,10 @@ desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surf
|
||||||
{
|
{
|
||||||
struct kiosk_shell_surface *shsurf =
|
struct kiosk_shell_surface *shsurf =
|
||||||
weston_desktop_surface_get_user_data(desktop_surface);
|
weston_desktop_surface_get_user_data(desktop_surface);
|
||||||
|
struct kiosk_shell_output *shoutput = NULL;
|
||||||
|
|
||||||
|
if (output)
|
||||||
|
shoutput = weston_output_get_shell_private(output);
|
||||||
|
|
||||||
/* We should normally be able to ignore fullscreen requests for
|
/* We should normally be able to ignore fullscreen requests for
|
||||||
* top-level surfaces, since we set them as fullscreen at creation
|
* top-level surfaces, since we set them as fullscreen at creation
|
||||||
|
|
@ -1148,7 +1152,7 @@ desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!shsurf->parent || fullscreen)
|
if (!shsurf->parent || fullscreen)
|
||||||
kiosk_shell_surface_set_fullscreen(shsurf, output);
|
kiosk_shell_surface_set_fullscreen(shsurf, shoutput);
|
||||||
else
|
else
|
||||||
kiosk_shell_surface_set_normal(shsurf);
|
kiosk_shell_surface_set_normal(shsurf);
|
||||||
}
|
}
|
||||||
|
|
@ -1232,20 +1236,6 @@ static const struct weston_desktop_api kiosk_shell_desktop_api = {
|
||||||
* kiosk_shell
|
* kiosk_shell
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct kiosk_shell_output *
|
|
||||||
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
|
|
||||||
struct weston_output *output)
|
|
||||||
{
|
|
||||||
struct kiosk_shell_output *shoutput;
|
|
||||||
|
|
||||||
wl_list_for_each(shoutput, &shell->output_list, link) {
|
|
||||||
if (shoutput->output == output)
|
|
||||||
return shoutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kiosk_shell_activate_view(struct kiosk_shell *shell,
|
kiosk_shell_activate_view(struct kiosk_shell *shell,
|
||||||
struct weston_view *view,
|
struct weston_view *view,
|
||||||
|
|
@ -1334,7 +1324,7 @@ kiosk_shell_handle_output_resized(struct wl_listener *listener, void *data)
|
||||||
container_of(listener, struct kiosk_shell, output_resized_listener);
|
container_of(listener, struct kiosk_shell, output_resized_listener);
|
||||||
struct weston_output *output = data;
|
struct weston_output *output = data;
|
||||||
struct kiosk_shell_output *shoutput =
|
struct kiosk_shell_output *shoutput =
|
||||||
kiosk_shell_find_shell_output(shell, output);
|
weston_output_get_shell_private(output);
|
||||||
struct weston_view *view;
|
struct weston_view *view;
|
||||||
|
|
||||||
kiosk_shell_output_recreate_background(shoutput);
|
kiosk_shell_output_recreate_background(shoutput);
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ struct kiosk_shell_surface {
|
||||||
|
|
||||||
struct kiosk_shell *shell;
|
struct kiosk_shell *shell;
|
||||||
|
|
||||||
struct weston_output *output;
|
struct kiosk_shell_output *output;
|
||||||
struct wl_listener output_destroy_listener;
|
struct wl_listener output_destroy_listener;
|
||||||
|
|
||||||
struct wl_signal destroy_signal;
|
struct wl_signal destroy_signal;
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,19 @@ weston_view_animation_frame(struct weston_animation *base,
|
||||||
struct weston_compositor *compositor =
|
struct weston_compositor *compositor =
|
||||||
animation->view->surface->compositor;
|
animation->view->surface->compositor;
|
||||||
|
|
||||||
if (base->frame_counter <= 1)
|
/* Animations are created with timestamp 0, so we need to set a
|
||||||
|
* real time base on the first repaint.
|
||||||
|
*
|
||||||
|
* In some cases, such as when the repaint loop has just started
|
||||||
|
* for a new display, the time we're given could be 0 for our
|
||||||
|
* second call - but this is ok because weston_spring_update() will
|
||||||
|
* do nothing as long as spring.timestamp == time.
|
||||||
|
*
|
||||||
|
* We can safely just keep updating the timestamp until we get
|
||||||
|
* something non-zero, and the spring will start updating after
|
||||||
|
* that.
|
||||||
|
*/
|
||||||
|
if (!timespec_to_msec(&animation->spring.timestamp))
|
||||||
animation->spring.timestamp = *time;
|
animation->spring.timestamp = *time;
|
||||||
|
|
||||||
weston_spring_update(&animation->spring, time);
|
weston_spring_update(&animation->spring, time);
|
||||||
|
|
@ -275,7 +287,6 @@ weston_view_animation_run(struct weston_view_animation *animation)
|
||||||
{
|
{
|
||||||
struct timespec zero_time = { 0 };
|
struct timespec zero_time = { 0 };
|
||||||
|
|
||||||
animation->animation.frame_counter = 0;
|
|
||||||
weston_view_animation_frame(&animation->animation, NULL, &zero_time);
|
weston_view_animation_frame(&animation->animation, NULL, &zero_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,26 +40,12 @@
|
||||||
#include "pixman-renderer.h"
|
#include "pixman-renderer.h"
|
||||||
#include "pixel-formats.h"
|
#include "pixel-formats.h"
|
||||||
#include "renderer-gl/gl-renderer.h"
|
#include "renderer-gl/gl-renderer.h"
|
||||||
|
#include "renderer-vulkan/vulkan-renderer.h"
|
||||||
|
#include "shared/weston-assert.h"
|
||||||
#include "shared/weston-egl-ext.h"
|
#include "shared/weston-egl-ext.h"
|
||||||
#include "linux-dmabuf.h"
|
#include "linux-dmabuf.h"
|
||||||
#include "linux-explicit-synchronization.h"
|
#include "linux-explicit-synchronization.h"
|
||||||
|
#include "shared/xalloc.h"
|
||||||
static struct gbm_device *
|
|
||||||
create_gbm_device(int fd)
|
|
||||||
{
|
|
||||||
struct gbm_device *gbm;
|
|
||||||
|
|
||||||
/* GBM will load a dri driver, but even though they need symbols from
|
|
||||||
* libglapi, in some version of Mesa they are not linked to it. Since
|
|
||||||
* only the gl-renderer module links to it, the call above won't make
|
|
||||||
* these symbols globally available, and loading the DRI driver fails.
|
|
||||||
* Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
|
|
||||||
dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
|
|
||||||
|
|
||||||
gbm = gbm_create_device(fd);
|
|
||||||
|
|
||||||
return gbm;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When initializing EGL, if the preferred buffer format isn't available
|
/* When initializing EGL, if the preferred buffer format isn't available
|
||||||
* we may be able to substitute an ARGB format for an XRGB one.
|
* we may be able to substitute an ARGB format for an XRGB one.
|
||||||
|
|
@ -99,12 +85,32 @@ drm_backend_create_gl_renderer(struct drm_backend *b)
|
||||||
&options.base);
|
&options.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
drm_backend_create_vulkan_renderer(struct drm_backend *b)
|
||||||
|
{
|
||||||
|
const struct pixel_format_info *format[3] = {
|
||||||
|
b->format,
|
||||||
|
fallback_format_for(b->format),
|
||||||
|
};
|
||||||
|
struct vulkan_renderer_display_options options = {
|
||||||
|
.formats = format,
|
||||||
|
.formats_count = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (format[1])
|
||||||
|
options.formats_count = 2;
|
||||||
|
|
||||||
|
return weston_compositor_init_renderer(b->compositor,
|
||||||
|
WESTON_RENDERER_VULKAN,
|
||||||
|
&options.base);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
init_egl(struct drm_backend *b)
|
init_egl(struct drm_backend *b)
|
||||||
{
|
{
|
||||||
struct drm_device *device = b->drm;
|
struct drm_device *device = b->drm;
|
||||||
|
|
||||||
b->gbm = create_gbm_device(device->drm.fd);
|
b->gbm = gbm_create_device(device->drm.fd);
|
||||||
if (!b->gbm)
|
if (!b->gbm)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
@ -117,6 +123,24 @@ init_egl(struct drm_backend *b)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
init_vulkan(struct drm_backend *b)
|
||||||
|
{
|
||||||
|
struct drm_device *device = b->drm;
|
||||||
|
|
||||||
|
b->gbm = gbm_create_device(device->drm.fd);
|
||||||
|
if (!b->gbm)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (drm_backend_create_vulkan_renderer(b) < 0) {
|
||||||
|
gbm_device_destroy(b->gbm);
|
||||||
|
b->gbm = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void drm_output_fini_cursor_egl(struct drm_output *output)
|
static void drm_output_fini_cursor_egl(struct drm_output *output)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
@ -130,6 +154,19 @@ static void drm_output_fini_cursor_egl(struct drm_output *output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void drm_output_fini_cursor_vulkan(struct drm_output *output)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||||
|
/* This cursor does not have a GBM device */
|
||||||
|
if (output->gbm_cursor_fb[i] && !output->gbm_cursor_fb[i]->bo)
|
||||||
|
output->gbm_cursor_fb[i]->type = BUFFER_PIXMAN_DUMB;
|
||||||
|
drm_fb_unref(output->gbm_cursor_fb[i]);
|
||||||
|
output->gbm_cursor_fb[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
|
drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
|
||||||
{
|
{
|
||||||
|
|
@ -179,6 +216,55 @@ err:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
drm_output_init_cursor_vulkan(struct drm_output *output, struct drm_backend *b)
|
||||||
|
{
|
||||||
|
struct drm_device *device = output->device;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* No point creating cursors if we don't have a plane for them. */
|
||||||
|
if (!output->cursor_plane)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||||
|
struct gbm_bo *bo;
|
||||||
|
|
||||||
|
if (gbm_device_get_fd(b->gbm) != output->device->drm.fd) {
|
||||||
|
output->gbm_cursor_fb[i] =
|
||||||
|
drm_fb_create_dumb(output->device,
|
||||||
|
device->cursor_width,
|
||||||
|
device->cursor_height,
|
||||||
|
DRM_FORMAT_ARGB8888);
|
||||||
|
/* Override buffer type, since we know it is a cursor */
|
||||||
|
output->gbm_cursor_fb[i]->type = BUFFER_CURSOR;
|
||||||
|
output->gbm_cursor_handle[i] =
|
||||||
|
output->gbm_cursor_fb[i]->handles[0];
|
||||||
|
} else {
|
||||||
|
bo = gbm_bo_create(b->gbm, device->cursor_width, device->cursor_height,
|
||||||
|
GBM_FORMAT_ARGB8888,
|
||||||
|
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||||
|
if (!bo)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
output->gbm_cursor_fb[i] =
|
||||||
|
drm_fb_get_from_bo(bo, device, false, BUFFER_CURSOR);
|
||||||
|
if (!output->gbm_cursor_fb[i]) {
|
||||||
|
gbm_bo_destroy(bo);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
output->gbm_cursor_handle[i] = gbm_bo_get_handle(bo).s32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
weston_log("cursor buffers unavailable, using vulkan cursors\n");
|
||||||
|
device->cursors_are_broken = true;
|
||||||
|
drm_output_fini_cursor_vulkan(output);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
|
create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
|
||||||
{
|
{
|
||||||
|
|
@ -229,26 +315,213 @@ create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
|
||||||
output->gbm_bo_flags);
|
output->gbm_bo_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum format_alpha_required {
|
||||||
|
FORMAT_ALPHA_REQUIRED = true,
|
||||||
|
FORMAT_ALPHA_NOT_REQUIRED = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum format_component_type {
|
||||||
|
FORMAT_COMPONENT_TYPE_ANY,
|
||||||
|
FORMAT_COMPONENT_TYPE_FLOAT_ONLY,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pixel_format_info *
|
||||||
|
find_compatible_format(struct weston_compositor *compositor,
|
||||||
|
struct wl_array *formats, int min_bpc,
|
||||||
|
enum format_component_type component_type,
|
||||||
|
enum format_alpha_required alpha_required)
|
||||||
|
{
|
||||||
|
const struct pixel_format_info **tmp, *p;
|
||||||
|
const struct pixel_format_info *candidate = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a format array, this looks for a format respecting a few
|
||||||
|
* criteria. First of all, this ignores formats that do not contain an
|
||||||
|
* alpha channel when alpha_required == FORMAT_ALPHA_REQUIRED. Similar
|
||||||
|
* for formats that are not floating point when component_type ==
|
||||||
|
* FORMAT_COMPONENT_TYPE_FLOAT_ONLY. Also, it ignores formats that do
|
||||||
|
* not have bits per color channel (bpc) bigger or equal to min_bpc.
|
||||||
|
*
|
||||||
|
* When we have multiple formats matching these criteria, we use the
|
||||||
|
* following to choose:
|
||||||
|
*
|
||||||
|
* 1. a format with lower bytes per pixel (bpp) is favored.
|
||||||
|
*
|
||||||
|
* 2. if FORMAT_ALPHA_REQUIRED:
|
||||||
|
* we prefer the format with more bits on the alpha channel
|
||||||
|
* else
|
||||||
|
* we prefer the format with more bits on the color channels
|
||||||
|
*/
|
||||||
|
wl_array_for_each(tmp, formats) {
|
||||||
|
p = *tmp;
|
||||||
|
|
||||||
|
/* Skip candidates that do not match minimum criteria. */
|
||||||
|
if (component_type == FORMAT_COMPONENT_TYPE_FLOAT_ONLY &&
|
||||||
|
p->component_type != PIXEL_COMPONENT_TYPE_FLOAT)
|
||||||
|
continue;
|
||||||
|
if (alpha_required == FORMAT_ALPHA_REQUIRED && p->bits.a == 0)
|
||||||
|
continue;
|
||||||
|
if (p->bits.r < min_bpc || p->bits.g < min_bpc || p->bits.b < min_bpc)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* No other good candidate so far, so pick this one. */
|
||||||
|
if (!candidate) {
|
||||||
|
candidate = p;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New candidate, let's compare with old and untie.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (p->bpp > candidate->bpp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (alpha_required == FORMAT_ALPHA_REQUIRED) {
|
||||||
|
if (p->bits.a <= candidate->bits.a)
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (p->bits.r + p->bits.g + p->bits.b <=
|
||||||
|
candidate->bits.r + candidate->bits.g + candidate->bits.b)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
candidate = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
drm_output_pick_format_egl(struct drm_output *output)
|
||||||
|
{
|
||||||
|
struct drm_device *device = output->device;
|
||||||
|
struct drm_backend *b = device->backend;
|
||||||
|
struct weston_compositor *compositor = b->compositor;
|
||||||
|
const struct weston_renderer *renderer = compositor->renderer;
|
||||||
|
const struct pixel_format_info **renderer_formats;
|
||||||
|
const struct pixel_format_info **f;
|
||||||
|
unsigned int renderer_formats_count;
|
||||||
|
struct wl_array supported_formats;
|
||||||
|
enum format_component_type component_type;
|
||||||
|
uint32_t min_bpc;
|
||||||
|
unsigned int i;
|
||||||
|
bool ret = true;
|
||||||
|
bool found;
|
||||||
|
|
||||||
|
wl_array_init(&supported_formats);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This computes the intersection between renderer formats supported by
|
||||||
|
* EGL and the output->scanout_plane supported formats. We need that as
|
||||||
|
* we want to select a format supported by both.
|
||||||
|
*/
|
||||||
|
renderer_formats =
|
||||||
|
renderer->gl->get_supported_rendering_formats(b->compositor,
|
||||||
|
&renderer_formats_count);
|
||||||
|
for (i = 0; i < renderer_formats_count; i++) {
|
||||||
|
if (!weston_drm_format_array_find_format(&output->scanout_plane->formats,
|
||||||
|
renderer_formats[i]->format))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
f = wl_array_add(&supported_formats, sizeof(*f));
|
||||||
|
*f = renderer_formats[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output->base.from_blend_to_output_by_backend) {
|
||||||
|
component_type = FORMAT_COMPONENT_TYPE_FLOAT_ONLY;
|
||||||
|
min_bpc = 16;
|
||||||
|
} else if (output->base.eotf_mode != WESTON_EOTF_MODE_SDR) {
|
||||||
|
component_type = FORMAT_COMPONENT_TYPE_ANY;
|
||||||
|
min_bpc = 10;
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* If no requirements, we simply use b->format instead of
|
||||||
|
* looking for a format with bpc >= min_bpc.
|
||||||
|
*/
|
||||||
|
min_bpc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min_bpc != 0) {
|
||||||
|
if (b->has_underlay) {
|
||||||
|
output->format =
|
||||||
|
find_compatible_format(compositor, &supported_formats,
|
||||||
|
min_bpc, component_type,
|
||||||
|
FORMAT_ALPHA_REQUIRED);
|
||||||
|
if (output->format)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
weston_log("Disabling underlay planes: EGL GBM or the primary plane for output '%s'\n" \
|
||||||
|
"does not support format with min bpc %u and alpha channel.\n",
|
||||||
|
output->base.name, min_bpc);
|
||||||
|
b->has_underlay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->format =
|
||||||
|
find_compatible_format(compositor, &supported_formats,
|
||||||
|
min_bpc, component_type,
|
||||||
|
FORMAT_ALPHA_NOT_REQUIRED);
|
||||||
|
if (output->format)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
weston_log("Error: EGL GBM or the primary plane for output '%s' does not support format\n" \
|
||||||
|
"with min bpc %u.\n", output->base.name, min_bpc);
|
||||||
|
ret = false;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
found = false;
|
||||||
|
wl_array_for_each(f, &supported_formats) {
|
||||||
|
if ((*f)->format == b->format->format) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
weston_log("Error: format %s unsupported by EGL GBM or the primary plane for output '%s'.\n",
|
||||||
|
b->format->drm_format_name, output->base.name);
|
||||||
|
ret = false;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b->has_underlay && (b->format->bits.a == 0)) {
|
||||||
|
weston_log("Disabling underlay planes: b->format %s does not have alpha channel,\n"
|
||||||
|
"which is required to support underlay planes.\n",
|
||||||
|
b->format->drm_format_name);
|
||||||
|
b->has_underlay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->format = b->format;
|
||||||
|
|
||||||
|
done:
|
||||||
|
wl_array_release(&supported_formats);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Init output state that depends on gl or gbm */
|
/* Init output state that depends on gl or gbm */
|
||||||
int
|
int
|
||||||
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
||||||
{
|
{
|
||||||
const struct weston_renderer *renderer = b->compositor->renderer;
|
const struct weston_renderer *renderer = b->compositor->renderer;
|
||||||
const struct weston_mode *mode = output->base.current_mode;
|
const struct weston_mode *mode = output->base.current_mode;
|
||||||
const struct pixel_format_info *format[2] = {
|
const struct pixel_format_info *format[2] = { 0 };
|
||||||
output->format,
|
struct gl_renderer_output_options options;
|
||||||
fallback_format_for(output->format),
|
|
||||||
};
|
if (!output->format && !drm_output_pick_format_egl(output))
|
||||||
struct gl_renderer_output_options options = {
|
return -1;
|
||||||
.formats = format,
|
|
||||||
.formats_count = 1,
|
format[0] = output->format;
|
||||||
.area.x = 0,
|
if (!b->has_underlay)
|
||||||
.area.y = 0,
|
format[1] = fallback_format_for(output->format);
|
||||||
.area.width = mode->width,
|
|
||||||
.area.height = mode->height,
|
options.formats = format;
|
||||||
.fb_size.width = mode->width,
|
options.formats_count = format[1] ? 2 : 1;
|
||||||
.fb_size.height = mode->height,
|
options.area.x = 0;
|
||||||
};
|
options.area.y = 0;
|
||||||
|
options.area.width = mode->width;
|
||||||
|
options.area.height = mode->height;
|
||||||
|
options.fb_size.width = mode->width;
|
||||||
|
options.fb_size.height = mode->height;
|
||||||
|
|
||||||
assert(output->gbm_surface == NULL);
|
assert(output->gbm_surface == NULL);
|
||||||
create_gbm_surface(b->gbm, output);
|
create_gbm_surface(b->gbm, output);
|
||||||
|
|
@ -257,8 +530,6 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.formats[1])
|
|
||||||
options.formats_count = 2;
|
|
||||||
options.window_for_legacy = (EGLNativeWindowType) output->gbm_surface;
|
options.window_for_legacy = (EGLNativeWindowType) output->gbm_surface;
|
||||||
options.window_for_platform = output->gbm_surface;
|
options.window_for_platform = output->gbm_surface;
|
||||||
if (renderer->gl->output_window_create(&output->base, &options) < 0) {
|
if (renderer->gl->output_window_create(&output->base, &options) < 0) {
|
||||||
|
|
@ -273,6 +544,208 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct gbm_bo *
|
||||||
|
drm_gbm_create_bo(struct gbm_device *gbm, struct drm_output *output)
|
||||||
|
{
|
||||||
|
struct weston_mode *mode = output->base.current_mode;
|
||||||
|
struct drm_plane *plane = output->scanout_plane;
|
||||||
|
struct weston_drm_format *fmt;
|
||||||
|
const uint64_t *modifiers;
|
||||||
|
unsigned int num_modifiers;
|
||||||
|
struct gbm_bo *bo = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Currently, this method allocates a buffer based on the list
|
||||||
|
* of acceptable modifiers received from the DRM backend but does not
|
||||||
|
* check it against formats renderable by the renderer.
|
||||||
|
* To support cases where the renderer may not support the same
|
||||||
|
* modifiers (e.g. Vulkan software renderer) it should match against
|
||||||
|
* renderer modifiers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fmt = weston_drm_format_array_find_format(&plane->formats,
|
||||||
|
output->format->format);
|
||||||
|
if (!fmt) {
|
||||||
|
weston_log("format %s not supported by output %s\n",
|
||||||
|
output->format->drm_format_name,
|
||||||
|
output->base.name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!weston_drm_format_has_modifier(fmt, DRM_FORMAT_MOD_INVALID)) {
|
||||||
|
modifiers = weston_drm_format_get_modifiers(fmt, &num_modifiers);
|
||||||
|
bo = gbm_bo_create_with_modifiers(gbm, mode->width, mode->height,
|
||||||
|
output->format->format,
|
||||||
|
modifiers, num_modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we cannot use modifiers to allocate the GBM surface and
|
||||||
|
* the GBM device differs from the KMS display device, try to
|
||||||
|
* use linear buffers and hope that the allocated GBM surface
|
||||||
|
* is correctly displayed on the KMS device.
|
||||||
|
*/
|
||||||
|
if (gbm_device_get_fd(gbm) != output->device->drm.fd)
|
||||||
|
output->gbm_bo_flags |= GBM_BO_USE_LINEAR;
|
||||||
|
|
||||||
|
if (!bo) {
|
||||||
|
bo = gbm_bo_create(gbm, mode->width, mode->height,
|
||||||
|
output->format->format, output->gbm_bo_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bo;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drm_gbm_dmabuf {
|
||||||
|
struct linux_dmabuf_memory base;
|
||||||
|
struct gbm_bo *bo;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
drm_gbm_dmabuf_destroy(struct linux_dmabuf_memory *dmabuf)
|
||||||
|
{
|
||||||
|
struct dmabuf_attributes *attributes;
|
||||||
|
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
|
||||||
|
struct gbm_bo *bo;
|
||||||
|
|
||||||
|
drm_gbm_dmabuf = container_of(dmabuf, struct drm_gbm_dmabuf, base);
|
||||||
|
bo = drm_gbm_dmabuf->bo;
|
||||||
|
assert(bo);
|
||||||
|
|
||||||
|
gbm_bo_destroy(bo);
|
||||||
|
|
||||||
|
attributes = dmabuf->attributes;
|
||||||
|
for (int i = 0; i < attributes->n_planes; ++i)
|
||||||
|
close(attributes->fd[i]);
|
||||||
|
free(dmabuf->attributes);
|
||||||
|
|
||||||
|
free(dmabuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct drm_gbm_dmabuf *
|
||||||
|
drm_gbm_bo_get_dmabuf(struct gbm_device *gbm, struct drm_output *output, struct gbm_bo *bo)
|
||||||
|
{
|
||||||
|
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
|
||||||
|
struct dmabuf_attributes *attributes;
|
||||||
|
|
||||||
|
attributes = xzalloc(sizeof(*attributes));
|
||||||
|
attributes->width = gbm_bo_get_width(bo);
|
||||||
|
attributes->height = gbm_bo_get_height(bo);
|
||||||
|
attributes->format = gbm_bo_get_format(bo);
|
||||||
|
attributes->n_planes = gbm_bo_get_plane_count(bo);
|
||||||
|
for (int i = 0; i < attributes->n_planes; ++i) {
|
||||||
|
attributes->fd[i] = gbm_bo_get_fd(bo);
|
||||||
|
attributes->stride[i] = gbm_bo_get_stride_for_plane(bo, i);
|
||||||
|
attributes->offset[i] = gbm_bo_get_offset(bo, i);
|
||||||
|
}
|
||||||
|
attributes->modifier = gbm_bo_get_modifier(bo);
|
||||||
|
|
||||||
|
drm_gbm_dmabuf = xzalloc(sizeof(*drm_gbm_dmabuf));
|
||||||
|
drm_gbm_dmabuf->base.attributes = attributes;
|
||||||
|
drm_gbm_dmabuf->base.destroy = drm_gbm_dmabuf_destroy;
|
||||||
|
drm_gbm_dmabuf->bo = bo;
|
||||||
|
|
||||||
|
return drm_gbm_dmabuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_renderbuffers(struct gbm_device *gbm, struct drm_output *output, unsigned int n)
|
||||||
|
{
|
||||||
|
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < n; i++) {
|
||||||
|
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
|
||||||
|
struct gbm_bo *bo;
|
||||||
|
|
||||||
|
bo = drm_gbm_create_bo(gbm, output);
|
||||||
|
if (!bo) {
|
||||||
|
weston_log("failed to allocate bo\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_gbm_dmabuf = drm_gbm_bo_get_dmabuf(gbm, output, bo);
|
||||||
|
if (!drm_gbm_dmabuf) {
|
||||||
|
weston_log("failed to allocate dmabuf\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->renderbuffer[i] =
|
||||||
|
renderer->create_renderbuffer_dmabuf(&output->base,
|
||||||
|
&drm_gbm_dmabuf->base,
|
||||||
|
NULL, NULL);
|
||||||
|
if (!output->renderbuffer[i]) {
|
||||||
|
weston_log("failed to allocate renderbuffer\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->linux_dmabuf_memory[i] = &drm_gbm_dmabuf->base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
drm_output_pick_format_vulkan(struct drm_output *output)
|
||||||
|
{
|
||||||
|
struct drm_device *device = output->device;
|
||||||
|
struct drm_backend *b = device->backend;
|
||||||
|
|
||||||
|
/* Any other value of eotf_mode requires color-management, which is not
|
||||||
|
* yet supported by vulkan-renderer. */
|
||||||
|
assert(output->base.eotf_mode == WESTON_EOTF_MODE_SDR);
|
||||||
|
|
||||||
|
if (!b->format->vulkan_format) {
|
||||||
|
weston_log("Error: failed to pick format for output '%s', format %s unsupported by vulkan-renderer.\n",
|
||||||
|
output->base.name, b->format->drm_format_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(b->format);
|
||||||
|
output->format = b->format;
|
||||||
|
|
||||||
|
if (b->has_underlay && (output->format->bits.a == 0)) {
|
||||||
|
weston_log("Disabling underlay planes: output '%s' with format %s does not have alpha channel,\n"
|
||||||
|
"which is required to support underlay planes.\n",
|
||||||
|
output->base.name, output->format->drm_format_name);
|
||||||
|
b->has_underlay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init output state that depends on vulkan */
|
||||||
|
int
|
||||||
|
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b)
|
||||||
|
{
|
||||||
|
const struct weston_mode *mode = output->base.current_mode;
|
||||||
|
struct weston_renderer *renderer = b->compositor->renderer;
|
||||||
|
|
||||||
|
if (!output->format && !drm_output_pick_format_vulkan(output))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
const struct vulkan_renderer_surfaceless_options options = {
|
||||||
|
.area.x = 0,
|
||||||
|
.area.y = 0,
|
||||||
|
.area.width = mode->width,
|
||||||
|
.area.height = mode->height,
|
||||||
|
.fb_size.width = mode->width,
|
||||||
|
.fb_size.height = mode->height,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
|
||||||
|
weston_log("failed to create vulkan renderer output state\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
create_renderbuffers(b->gbm, output, ARRAY_LENGTH(output->renderbuffer));
|
||||||
|
if (!output->linux_dmabuf_memory[0]) {
|
||||||
|
weston_log("failed to create dmabufs\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_output_init_cursor_vulkan(output, b);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
drm_output_fini_egl(struct drm_output *output)
|
drm_output_fini_egl(struct drm_output *output)
|
||||||
{
|
{
|
||||||
|
|
@ -293,6 +766,26 @@ drm_output_fini_egl(struct drm_output *output)
|
||||||
drm_output_fini_cursor_egl(output);
|
drm_output_fini_cursor_egl(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
drm_output_fini_vulkan(struct drm_output *output)
|
||||||
|
{
|
||||||
|
struct drm_backend *b = output->backend;
|
||||||
|
const struct weston_renderer *renderer = b->compositor->renderer;
|
||||||
|
|
||||||
|
if (!b->compositor->shutting_down &&
|
||||||
|
output->scanout_plane->state_cur->fb &&
|
||||||
|
output->scanout_plane->state_cur->fb->type == BUFFER_DMABUF_BACKEND) {
|
||||||
|
drm_plane_reset_state(output->scanout_plane);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < ARRAY_LENGTH(output->renderbuffer); i++)
|
||||||
|
renderer->destroy_renderbuffer(output->renderbuffer[i]);
|
||||||
|
|
||||||
|
renderer->vulkan->output_destroy(&output->base);
|
||||||
|
|
||||||
|
drm_output_fini_cursor_vulkan(output);
|
||||||
|
}
|
||||||
|
|
||||||
struct drm_fb *
|
struct drm_fb *
|
||||||
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
||||||
{
|
{
|
||||||
|
|
@ -324,3 +817,36 @@ drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct drm_fb *
|
||||||
|
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage)
|
||||||
|
{
|
||||||
|
struct drm_output *output = state->output;
|
||||||
|
struct drm_device *device = output->device;
|
||||||
|
struct linux_dmabuf_memory *dmabuf;
|
||||||
|
struct drm_fb *ret;
|
||||||
|
|
||||||
|
output->base.compositor->renderer->repaint_output(&output->base,
|
||||||
|
damage,
|
||||||
|
output->renderbuffer[output->current_image]);
|
||||||
|
|
||||||
|
dmabuf = output->linux_dmabuf_memory[output->current_image];
|
||||||
|
if (!dmabuf) {
|
||||||
|
weston_log("failed to get dmabuf\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output transparent/opaque image according to the format required by
|
||||||
|
* the client. */
|
||||||
|
ret = drm_fb_get_from_dmabuf_attributes(dmabuf->attributes, device,
|
||||||
|
!output->format->opaque_substitute,
|
||||||
|
false, true, NULL);
|
||||||
|
if (!ret) {
|
||||||
|
weston_log("failed to get drm_fb for dmabuf\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->current_image = (output->current_image + 1) % ARRAY_LENGTH(output->renderbuffer);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,10 @@
|
||||||
#define DRM_PLANE_ALPHA_OPAQUE 0xffffUL
|
#define DRM_PLANE_ALPHA_OPAQUE 0xffffUL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_DMABUF_PLANES
|
||||||
|
#define MAX_DMABUF_PLANES 4
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A small wrapper to print information into the 'drm-backend' debug scope.
|
* A small wrapper to print information into the 'drm-backend' debug scope.
|
||||||
*
|
*
|
||||||
|
|
@ -149,27 +153,6 @@ struct drm_property_info {
|
||||||
uint64_t range_values[2];
|
uint64_t range_values[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Reasons why placing a view on a plane failed. Needed by the dma-buf feedback.
|
|
||||||
*/
|
|
||||||
enum try_view_on_plane_failure_reasons {
|
|
||||||
FAILURE_REASONS_NONE = 0,
|
|
||||||
FAILURE_REASONS_FORCE_RENDERER = 1 << 0,
|
|
||||||
FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE = 1 << 1,
|
|
||||||
FAILURE_REASONS_DMABUF_MODIFIER_INVALID = 1 << 2,
|
|
||||||
FAILURE_REASONS_ADD_FB_FAILED = 1 << 3,
|
|
||||||
FAILURE_REASONS_NO_PLANES_AVAILABLE = 1 << 4,
|
|
||||||
FAILURE_REASONS_PLANES_REJECTED = 1 << 5,
|
|
||||||
FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION = 1 << 6,
|
|
||||||
FAILURE_REASONS_INCOMPATIBLE_TRANSFORM = 1 << 7,
|
|
||||||
FAILURE_REASONS_NO_BUFFER = 1 << 8,
|
|
||||||
FAILURE_REASONS_BUFFER_TYPE = 1 << 9,
|
|
||||||
FAILURE_REASONS_GLOBAL_ALPHA = 1 << 10,
|
|
||||||
FAILURE_REASONS_NO_GBM = 1 << 11,
|
|
||||||
FAILURE_REASONS_GBM_BO_IMPORT_FAILED = 1 << 12,
|
|
||||||
FAILURE_REASONS_GBM_BO_GET_HANDLE_FAILED = 1 << 13,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We use this to keep track of actions we need to do with the dma-buf feedback
|
* We use this to keep track of actions we need to do with the dma-buf feedback
|
||||||
* in order to keep it up-to-date with the info we get from the DRM-backend.
|
* in order to keep it up-to-date with the info we get from the DRM-backend.
|
||||||
|
|
@ -180,6 +163,12 @@ enum actions_needed_dmabuf_feedback {
|
||||||
ACTION_NEEDED_REMOVE_SCANOUT_TRANCHE = (1 << 1),
|
ACTION_NEEDED_REMOVE_SCANOUT_TRANCHE = (1 << 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum drm_plane_subtype {
|
||||||
|
PLANE_SUBTYPE_OVERLAY_ONLY = 0,
|
||||||
|
PLANE_SUBTYPE_UNDERLAY_ONLY = 1,
|
||||||
|
PLANE_SUBTYPE_BOTH = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct drm_device {
|
struct drm_device {
|
||||||
struct drm_backend *backend;
|
struct drm_backend *backend;
|
||||||
|
|
||||||
|
|
@ -232,6 +221,9 @@ struct drm_device {
|
||||||
|
|
||||||
/* drm_backend::kms_list */
|
/* drm_backend::kms_list */
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
|
||||||
|
/* struct drm_colorop_3x1d_lut::link */
|
||||||
|
struct wl_list drm_colorop_3x1d_lut_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drm_backend {
|
struct drm_backend {
|
||||||
|
|
@ -253,6 +245,8 @@ struct drm_backend {
|
||||||
|
|
||||||
bool use_pixman_shadow;
|
bool use_pixman_shadow;
|
||||||
|
|
||||||
|
bool offload_blend_to_output;
|
||||||
|
|
||||||
struct udev_input input;
|
struct udev_input input;
|
||||||
|
|
||||||
uint32_t pageflip_timeout;
|
uint32_t pageflip_timeout;
|
||||||
|
|
@ -261,6 +255,15 @@ struct drm_backend {
|
||||||
bool has_underlay;
|
bool has_underlay;
|
||||||
|
|
||||||
struct weston_log_scope *debug;
|
struct weston_log_scope *debug;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t frame_counter_interval;
|
||||||
|
struct wl_event_source *pageflip_timer_counter;
|
||||||
|
bool timer_armed;
|
||||||
|
} perf_page_flips_stats;
|
||||||
|
|
||||||
|
/* True if we need a workaround for some very old kernels */
|
||||||
|
bool stale_timestamp_workaround;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drm_mode {
|
struct drm_mode {
|
||||||
|
|
@ -273,6 +276,7 @@ enum drm_fb_type {
|
||||||
BUFFER_INVALID = 0, /**< never used */
|
BUFFER_INVALID = 0, /**< never used */
|
||||||
BUFFER_CLIENT, /**< directly sourced from client */
|
BUFFER_CLIENT, /**< directly sourced from client */
|
||||||
BUFFER_DMABUF, /**< imported from linux_dmabuf client */
|
BUFFER_DMABUF, /**< imported from linux_dmabuf client */
|
||||||
|
BUFFER_DMABUF_BACKEND, /**< imported from dmabuf renderbuffer */
|
||||||
BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
|
BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
|
||||||
BUFFER_GBM_SURFACE, /**< internal EGL rendering */
|
BUFFER_GBM_SURFACE, /**< internal EGL rendering */
|
||||||
BUFFER_CURSOR, /**< internal cursor buffer */
|
BUFFER_CURSOR, /**< internal cursor buffer */
|
||||||
|
|
@ -287,9 +291,9 @@ struct drm_fb {
|
||||||
int refcnt;
|
int refcnt;
|
||||||
|
|
||||||
uint32_t fb_id, size;
|
uint32_t fb_id, size;
|
||||||
uint32_t handles[4];
|
uint32_t handles[MAX_DMABUF_PLANES];
|
||||||
uint32_t strides[4];
|
uint32_t strides[MAX_DMABUF_PLANES];
|
||||||
uint32_t offsets[4];
|
uint32_t offsets[MAX_DMABUF_PLANES];
|
||||||
int num_planes;
|
int num_planes;
|
||||||
const struct pixel_format_info *format;
|
const struct pixel_format_info *format;
|
||||||
uint64_t modifier;
|
uint64_t modifier;
|
||||||
|
|
@ -302,6 +306,12 @@ struct drm_fb {
|
||||||
struct gbm_bo *bo;
|
struct gbm_bo *bo;
|
||||||
struct gbm_surface *gbm_surface;
|
struct gbm_surface *gbm_surface;
|
||||||
|
|
||||||
|
/* Used when direct-display extension is turned on for that dmabuf */
|
||||||
|
bool direct_display;
|
||||||
|
int fds[MAX_DMABUF_PLANES];
|
||||||
|
/* tracks how many fds we've dup'ed */
|
||||||
|
int num_duped_fds;
|
||||||
|
|
||||||
/* Used by dumb fbs */
|
/* Used by dumb fbs */
|
||||||
void *map;
|
void *map;
|
||||||
};
|
};
|
||||||
|
|
@ -329,6 +339,15 @@ struct drm_pending_state {
|
||||||
struct wl_list output_list;
|
struct wl_list output_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum drm_output_propose_state_mode {
|
||||||
|
DRM_OUTPUT_PROPOSE_STATE_INVALID = 0, /**< Invalid state */
|
||||||
|
DRM_OUTPUT_PROPOSE_STATE_MIXED, /**< mix renderer & planes */
|
||||||
|
DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR, /**< only assign to renderer & cursor plane */
|
||||||
|
DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY, /**< only assign to renderer */
|
||||||
|
DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY, /**< no renderer use, only planes */
|
||||||
|
DRM_OUTPUT_PROPOSE_STATE_REUSE = 128, /**< bit indicates reuse prior state with new buffers */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
|
* Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
|
||||||
* plus >= 1 each of encoder/connector/plane. Since everything but the planes
|
* plus >= 1 each of encoder/connector/plane. Since everything but the planes
|
||||||
|
|
@ -342,11 +361,13 @@ struct drm_pending_state {
|
||||||
struct drm_output_state {
|
struct drm_output_state {
|
||||||
struct drm_pending_state *pending_state;
|
struct drm_pending_state *pending_state;
|
||||||
struct drm_output *output;
|
struct drm_output *output;
|
||||||
|
enum drm_output_propose_state_mode mode;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
enum dpms_enum dpms;
|
enum dpms_enum dpms;
|
||||||
enum weston_hdcp_protection protection;
|
enum weston_hdcp_protection protection;
|
||||||
struct wl_list plane_list;
|
struct wl_list plane_list;
|
||||||
bool tear;
|
bool tear;
|
||||||
|
bool planes_enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -379,6 +400,9 @@ struct drm_plane_state {
|
||||||
uint64_t zpos;
|
uint64_t zpos;
|
||||||
uint16_t alpha;
|
uint16_t alpha;
|
||||||
|
|
||||||
|
enum wdrm_plane_color_encoding color_encoding;
|
||||||
|
enum wdrm_plane_color_range color_range;
|
||||||
|
|
||||||
bool complete;
|
bool complete;
|
||||||
|
|
||||||
/* We don't own the fd, so we shouldn't close it */
|
/* We don't own the fd, so we shouldn't close it */
|
||||||
|
|
@ -410,6 +434,8 @@ struct drm_plane {
|
||||||
struct drm_device *device;
|
struct drm_device *device;
|
||||||
|
|
||||||
enum wdrm_plane_type type;
|
enum wdrm_plane_type type;
|
||||||
|
/* Whether this plane supports overlay, underlay, or both */
|
||||||
|
enum drm_plane_subtype subtype;
|
||||||
|
|
||||||
uint32_t possible_crtcs;
|
uint32_t possible_crtcs;
|
||||||
uint32_t plane_id;
|
uint32_t plane_id;
|
||||||
|
|
@ -417,8 +443,6 @@ struct drm_plane {
|
||||||
uint32_t crtc_id;
|
uint32_t crtc_id;
|
||||||
|
|
||||||
struct drm_property_info props[WDRM_PLANE__COUNT];
|
struct drm_property_info props[WDRM_PLANE__COUNT];
|
||||||
/* True if the plane's zpos_max < primary plane's zpos_min. */
|
|
||||||
bool is_underlay;
|
|
||||||
|
|
||||||
/* The last state submitted to the kernel for this plane. */
|
/* The last state submitted to the kernel for this plane. */
|
||||||
struct drm_plane_state *state_cur;
|
struct drm_plane_state *state_cur;
|
||||||
|
|
@ -492,6 +516,19 @@ struct drm_writeback {
|
||||||
struct weston_drm_format_array formats;
|
struct weston_drm_format_array formats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct drm_colorop_3x1d_lut {
|
||||||
|
/* drm_device::drm_colorop_3x1d_lut_list */
|
||||||
|
struct wl_list link;
|
||||||
|
struct drm_device *device;
|
||||||
|
|
||||||
|
uint64_t lut_size;
|
||||||
|
|
||||||
|
struct weston_color_transform *xform;
|
||||||
|
struct wl_listener destroy_listener;
|
||||||
|
|
||||||
|
uint32_t blob_id;
|
||||||
|
};
|
||||||
|
|
||||||
struct drm_head {
|
struct drm_head {
|
||||||
struct weston_head base;
|
struct weston_head base;
|
||||||
struct drm_connector connector;
|
struct drm_connector connector;
|
||||||
|
|
@ -522,6 +559,9 @@ struct drm_crtc {
|
||||||
|
|
||||||
/* Holds the properties for the CRTC */
|
/* Holds the properties for the CRTC */
|
||||||
struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
|
struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
|
||||||
|
|
||||||
|
/* CRTC prop WDRM_CRTC_GAMMA_LUT_SIZE */
|
||||||
|
uint32_t lut_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drm_output {
|
struct drm_output {
|
||||||
|
|
@ -548,6 +588,7 @@ struct drm_output {
|
||||||
int current_cursor;
|
int current_cursor;
|
||||||
|
|
||||||
struct gbm_surface *gbm_surface;
|
struct gbm_surface *gbm_surface;
|
||||||
|
struct linux_dmabuf_memory *linux_dmabuf_memory[2];
|
||||||
const struct pixel_format_info *format;
|
const struct pixel_format_info *format;
|
||||||
uint32_t gbm_bo_flags;
|
uint32_t gbm_bo_flags;
|
||||||
|
|
||||||
|
|
@ -557,8 +598,9 @@ struct drm_output {
|
||||||
unsigned max_bpc;
|
unsigned max_bpc;
|
||||||
enum wdrm_colorspace connector_colorspace;
|
enum wdrm_colorspace connector_colorspace;
|
||||||
|
|
||||||
bool deprecated_gamma_is_set;
|
|
||||||
bool legacy_gamma_not_supported;
|
bool legacy_gamma_not_supported;
|
||||||
|
uint16_t legacy_gamma_size;
|
||||||
|
struct drm_colorop_3x1d_lut *blend_to_output_xform;
|
||||||
|
|
||||||
/* Plane being displayed directly on the CRTC */
|
/* Plane being displayed directly on the CRTC */
|
||||||
struct drm_plane *scanout_plane;
|
struct drm_plane *scanout_plane;
|
||||||
|
|
@ -573,7 +615,7 @@ struct drm_output {
|
||||||
struct drm_writeback_state *wb_state;
|
struct drm_writeback_state *wb_state;
|
||||||
|
|
||||||
struct drm_fb *dumb[2];
|
struct drm_fb *dumb[2];
|
||||||
struct weston_renderbuffer *renderbuffer[2];
|
weston_renderbuffer_t renderbuffer[2];
|
||||||
int current_image;
|
int current_image;
|
||||||
|
|
||||||
struct vaapi_recorder *recorder;
|
struct vaapi_recorder *recorder;
|
||||||
|
|
@ -581,6 +623,12 @@ struct drm_output {
|
||||||
|
|
||||||
struct wl_event_source *pageflip_timer;
|
struct wl_event_source *pageflip_timer;
|
||||||
|
|
||||||
|
/* how many page flips */
|
||||||
|
uint32_t page_flips_counted;
|
||||||
|
|
||||||
|
/* how many page flips / interval */
|
||||||
|
float page_flips_per_timer_interval;
|
||||||
|
|
||||||
bool is_virtual;
|
bool is_virtual;
|
||||||
void (*virtual_destroy)(struct weston_output *base);
|
void (*virtual_destroy)(struct weston_output *base);
|
||||||
|
|
||||||
|
|
@ -656,7 +704,18 @@ drm_output_get_plane_type_name(struct drm_plane *p)
|
||||||
case WDRM_PLANE_TYPE_CURSOR:
|
case WDRM_PLANE_TYPE_CURSOR:
|
||||||
return "cursor";
|
return "cursor";
|
||||||
case WDRM_PLANE_TYPE_OVERLAY:
|
case WDRM_PLANE_TYPE_OVERLAY:
|
||||||
return p->is_underlay ? "underlay" : "overlay";
|
switch (p->subtype) {
|
||||||
|
case PLANE_SUBTYPE_OVERLAY_ONLY:
|
||||||
|
return "overlay";
|
||||||
|
case PLANE_SUBTYPE_UNDERLAY_ONLY:
|
||||||
|
return "underlay";
|
||||||
|
case PLANE_SUBTYPE_BOTH:
|
||||||
|
return "over/underlay";
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// fall through
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
|
|
@ -748,10 +807,6 @@ drm_pending_state_apply(struct drm_pending_state *pending_state);
|
||||||
int
|
int
|
||||||
drm_pending_state_apply_sync(struct drm_pending_state *pending_state);
|
drm_pending_state_apply_sync(struct drm_pending_state *pending_state);
|
||||||
|
|
||||||
void
|
|
||||||
drm_output_set_gamma(struct weston_output *output_base,
|
|
||||||
uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
drm_output_update_msc(struct drm_output *output, unsigned int seq);
|
drm_output_update_msc(struct drm_output *output, unsigned int seq);
|
||||||
void
|
void
|
||||||
|
|
@ -768,6 +823,11 @@ drm_fb_unref(struct drm_fb *fb);
|
||||||
struct drm_fb *
|
struct drm_fb *
|
||||||
drm_fb_create_dumb(struct drm_device *device, int width, int height,
|
drm_fb_create_dumb(struct drm_device *device, int width, int height,
|
||||||
uint32_t format);
|
uint32_t format);
|
||||||
|
|
||||||
|
struct drm_fb *
|
||||||
|
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||||
|
struct drm_device *device, bool is_opaque,
|
||||||
|
uint32_t *try_view_on_plane_failure_reasons);
|
||||||
struct drm_fb *
|
struct drm_fb *
|
||||||
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
|
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
|
||||||
bool is_opaque, enum drm_fb_type type);
|
bool is_opaque, enum drm_fb_type type);
|
||||||
|
|
@ -784,15 +844,23 @@ wdrm_colorspace_from_output(struct weston_output *output);
|
||||||
#ifdef BUILD_DRM_GBM
|
#ifdef BUILD_DRM_GBM
|
||||||
extern struct drm_fb *
|
extern struct drm_fb *
|
||||||
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||||
struct weston_paint_node *pnode);
|
struct weston_paint_node *pnode,
|
||||||
|
uint32_t *try_view_on_plane_failure_reasons);
|
||||||
|
|
||||||
extern bool
|
extern bool
|
||||||
drm_can_scanout_dmabuf(struct weston_backend *backend,
|
drm_can_scanout_dmabuf(struct weston_backend *backend,
|
||||||
struct linux_dmabuf_buffer *dmabuf);
|
struct linux_dmabuf_buffer *dmabuf);
|
||||||
|
|
||||||
|
struct drm_fb *
|
||||||
|
drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
||||||
|
struct drm_device *device, bool is_opaque,
|
||||||
|
bool direct_display, bool is_internal,
|
||||||
|
uint32_t *try_view_on_plane_failure_reasons);
|
||||||
#else
|
#else
|
||||||
static inline struct drm_fb *
|
static inline struct drm_fb *
|
||||||
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||||
struct weston_paint_node *pnode)
|
struct weston_paint_node *pnode,
|
||||||
|
uint32_t *try_view_on_plane_failure_reasons)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -849,7 +917,7 @@ void
|
||||||
drm_plane_state_free(struct drm_plane_state *state, bool force);
|
drm_plane_state_free(struct drm_plane_state *state, bool force);
|
||||||
void
|
void
|
||||||
drm_plane_state_put_back(struct drm_plane_state *state);
|
drm_plane_state_put_back(struct drm_plane_state *state);
|
||||||
bool
|
void
|
||||||
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
||||||
struct weston_paint_node *node,
|
struct weston_paint_node *node,
|
||||||
uint64_t zpos);
|
uint64_t zpos);
|
||||||
|
|
@ -862,6 +930,14 @@ drm_assign_planes(struct weston_output *output_base);
|
||||||
bool
|
bool
|
||||||
drm_plane_is_available(struct drm_plane *plane, struct drm_output *output);
|
drm_plane_is_available(struct drm_plane *plane, struct drm_output *output);
|
||||||
|
|
||||||
|
bool
|
||||||
|
drm_plane_supports_color_encoding(struct drm_plane *plane,
|
||||||
|
enum wdrm_plane_color_encoding encoding);
|
||||||
|
|
||||||
|
bool
|
||||||
|
drm_plane_supports_color_range(struct drm_plane *plane,
|
||||||
|
enum wdrm_plane_color_range range);
|
||||||
|
|
||||||
void
|
void
|
||||||
drm_output_render(struct drm_output_state *state);
|
drm_output_render(struct drm_output_state *state);
|
||||||
|
|
||||||
|
|
@ -893,6 +969,18 @@ drm_output_fini_egl(struct drm_output *output);
|
||||||
struct drm_fb *
|
struct drm_fb *
|
||||||
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage);
|
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage);
|
||||||
|
|
||||||
|
int
|
||||||
|
init_vulkan(struct drm_backend *b);
|
||||||
|
|
||||||
|
int
|
||||||
|
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b);
|
||||||
|
|
||||||
|
void
|
||||||
|
drm_output_fini_vulkan(struct drm_output *output);
|
||||||
|
|
||||||
|
struct drm_fb *
|
||||||
|
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
inline static int
|
inline static int
|
||||||
init_egl(struct drm_backend *b)
|
init_egl(struct drm_backend *b)
|
||||||
|
|
@ -917,4 +1005,29 @@ drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static int
|
||||||
|
init_vulkan(struct drm_backend *b)
|
||||||
|
{
|
||||||
|
weston_log("Compiled without GBM support\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static int
|
||||||
|
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void
|
||||||
|
drm_output_fini_vulkan(struct drm_output *output)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static struct drm_fb *
|
||||||
|
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ enum wdrm_plane_property {
|
||||||
WDRM_PLANE_ZPOS,
|
WDRM_PLANE_ZPOS,
|
||||||
WDRM_PLANE_ROTATION,
|
WDRM_PLANE_ROTATION,
|
||||||
WDRM_PLANE_ALPHA,
|
WDRM_PLANE_ALPHA,
|
||||||
|
WDRM_PLANE_COLOR_ENCODING,
|
||||||
|
WDRM_PLANE_COLOR_RANGE,
|
||||||
WDRM_PLANE__COUNT
|
WDRM_PLANE__COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -82,6 +84,27 @@ enum wdrm_plane_rotation {
|
||||||
WDRM_PLANE_ROTATION__COUNT,
|
WDRM_PLANE_ROTATION__COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible values for the WDRM_PLANE_COLOR_ENCODING property.
|
||||||
|
*/
|
||||||
|
enum wdrm_plane_color_encoding {
|
||||||
|
WDRM_PLANE_COLOR_ENCODING_BT601 = 0,
|
||||||
|
WDRM_PLANE_COLOR_ENCODING_BT709,
|
||||||
|
WDRM_PLANE_COLOR_ENCODING_BT2020,
|
||||||
|
WDRM_PLANE_COLOR_ENCODING__COUNT
|
||||||
|
};
|
||||||
|
#define WDRM_PLANE_COLOR_ENCODING_DEFAULT WDRM_PLANE_COLOR_ENCODING_BT709
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible values for the WDRM_PLANE_COLOR_RANGE property.
|
||||||
|
*/
|
||||||
|
enum wdrm_plane_color_range {
|
||||||
|
WDRM_PLANE_COLOR_RANGE_LIMITED = 0,
|
||||||
|
WDRM_PLANE_COLOR_RANGE_FULL,
|
||||||
|
WDRM_PLANE_COLOR_RANGE__COUNT
|
||||||
|
};
|
||||||
|
#define WDRM_PLANE_COLOR_RANGE_DEFAULT WDRM_PLANE_COLOR_RANGE_LIMITED
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of properties attached to a DRM connector
|
* List of properties attached to a DRM connector
|
||||||
*/
|
*/
|
||||||
|
|
@ -100,6 +123,7 @@ enum wdrm_connector_property {
|
||||||
WDRM_CONNECTOR_MAX_BPC,
|
WDRM_CONNECTOR_MAX_BPC,
|
||||||
WDRM_CONNECTOR_CONTENT_TYPE,
|
WDRM_CONNECTOR_CONTENT_TYPE,
|
||||||
WDRM_CONNECTOR_COLORSPACE,
|
WDRM_CONNECTOR_COLORSPACE,
|
||||||
|
WDRM_CONNECTOR_VRR_CAPABLE,
|
||||||
WDRM_CONNECTOR__COUNT
|
WDRM_CONNECTOR__COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
#include "drm-internal.h"
|
#include "drm-internal.h"
|
||||||
#include "pixel-formats.h"
|
#include "pixel-formats.h"
|
||||||
#include "renderer-gl/gl-renderer.h"
|
#include "renderer-gl/gl-renderer.h"
|
||||||
|
#include "shared/weston-assert.h"
|
||||||
|
|
||||||
#define POISON_PTR ((void *)8)
|
#define POISON_PTR ((void *)8)
|
||||||
|
|
||||||
|
|
@ -205,6 +206,7 @@ static int
|
||||||
drm_virtual_output_repaint(struct weston_output *output_base)
|
drm_virtual_output_repaint(struct weston_output *output_base)
|
||||||
{
|
{
|
||||||
struct drm_output_state *state = NULL;
|
struct drm_output_state *state = NULL;
|
||||||
|
struct weston_compositor *compositor = output_base->compositor;
|
||||||
struct drm_output *output = to_drm_output(output_base);
|
struct drm_output *output = to_drm_output(output_base);
|
||||||
struct drm_plane *scanout_plane = output->scanout_plane;
|
struct drm_plane *scanout_plane = output->scanout_plane;
|
||||||
struct drm_plane_state *scanout_state;
|
struct drm_plane_state *scanout_state;
|
||||||
|
|
@ -227,14 +229,10 @@ drm_virtual_output_repaint(struct weston_output *output_base)
|
||||||
|
|
||||||
assert(!output->state_last);
|
assert(!output->state_last);
|
||||||
|
|
||||||
/* If planes have been disabled in the core, we might not have
|
/* assign_planes() is always called before a repaint, so we must have a
|
||||||
* hit assign_planes at all, so might not have valid output state
|
* valid output state here. */
|
||||||
* here. */
|
|
||||||
state = drm_pending_state_get_output(pending_state, output);
|
state = drm_pending_state_get_output(pending_state, output);
|
||||||
if (!state)
|
weston_assert_ptr_not_null(compositor, state);
|
||||||
state = drm_output_state_duplicate(output->state_cur,
|
|
||||||
pending_state,
|
|
||||||
DRM_OUTPUT_STATE_CLEAR_PLANES);
|
|
||||||
|
|
||||||
drm_output_render(state);
|
drm_output_render(state);
|
||||||
scanout_state = drm_output_state_get_plane(state, scanout_plane);
|
scanout_state = drm_output_state_get_plane(state, scanout_plane);
|
||||||
|
|
@ -318,8 +316,6 @@ drm_virtual_output_enable(struct weston_output *output_base)
|
||||||
output->base.assign_planes = drm_assign_planes;
|
output->base.assign_planes = drm_assign_planes;
|
||||||
output->base.set_dpms = NULL;
|
output->base.set_dpms = NULL;
|
||||||
output->base.switch_mode = NULL;
|
output->base.switch_mode = NULL;
|
||||||
output->base.gamma_size = 0;
|
|
||||||
output->base.set_gamma = NULL;
|
|
||||||
|
|
||||||
weston_compositor_stack_plane(b->compositor,
|
weston_compositor_stack_plane(b->compositor,
|
||||||
&output->scanout_plane->base,
|
&output->scanout_plane->base,
|
||||||
|
|
@ -343,6 +339,13 @@ drm_virtual_output_disable(struct weston_output *base)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
drm_virtual_prepare_repaint(struct weston_output *base)
|
||||||
|
{
|
||||||
|
struct drm_output *output = to_drm_output(base);
|
||||||
|
output->device->will_repaint = true;
|
||||||
|
}
|
||||||
|
|
||||||
static struct weston_output *
|
static struct weston_output *
|
||||||
drm_virtual_output_create(struct weston_compositor *c, char *name,
|
drm_virtual_output_create(struct weston_compositor *c, char *name,
|
||||||
void (*destroy_func)(struct weston_output *))
|
void (*destroy_func)(struct weston_output *))
|
||||||
|
|
@ -372,9 +375,11 @@ drm_virtual_output_create(struct weston_compositor *c, char *name,
|
||||||
output->base.enable = drm_virtual_output_enable;
|
output->base.enable = drm_virtual_output_enable;
|
||||||
output->base.destroy = drm_virtual_output_destroy;
|
output->base.destroy = drm_virtual_output_destroy;
|
||||||
output->base.disable = drm_virtual_output_disable;
|
output->base.disable = drm_virtual_output_disable;
|
||||||
|
output->base.prepare_repaint = drm_virtual_prepare_repaint;
|
||||||
output->base.attach_head = NULL;
|
output->base.attach_head = NULL;
|
||||||
|
|
||||||
output->backend = b;
|
output->backend = b;
|
||||||
|
output->base.backend = &b->base;
|
||||||
output->state_cur = drm_output_state_alloc(output);
|
output->state_cur = drm_output_state_alloc(output);
|
||||||
|
|
||||||
weston_compositor_add_pending_output(&output->base, c);
|
weston_compositor_add_pending_output(&output->base, c);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -114,13 +114,21 @@ static void gem_handle_put(struct drm_device *device, int handle)
|
||||||
static int
|
static int
|
||||||
drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
|
drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
|
||||||
{
|
{
|
||||||
int bo_fd;
|
int bo_fd = -1;
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
bo_fd = gbm_bo_get_fd_for_plane(fb->bo, plane);
|
/* neither a BO nor a direct-display means we shouldn't be calling this */
|
||||||
if (bo_fd < 0)
|
assert(!!fb->bo ^ fb->direct_display);
|
||||||
return bo_fd;
|
|
||||||
|
if (fb->bo) {
|
||||||
|
bo_fd = gbm_bo_get_fd_for_plane(fb->bo, plane);
|
||||||
|
if (bo_fd < 0)
|
||||||
|
return bo_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fb->direct_display)
|
||||||
|
bo_fd = fb->fds[plane];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* drmPrimeFDToHandle is dangerous, because the GEM handles are
|
* drmPrimeFDToHandle is dangerous, because the GEM handles are
|
||||||
|
|
@ -147,7 +155,10 @@ drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
|
||||||
fb->handles[plane] = gem_handle_get(device, handle);
|
fb->handles[plane] = gem_handle_get(device, handle);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
close(bo_fd);
|
/* on the direct-display path the dup'ed fds will be closed by
|
||||||
|
* drm_fb_destroy_dmabuf */
|
||||||
|
if (fb->bo)
|
||||||
|
close(bo_fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -171,23 +182,32 @@ drm_fb_maybe_import(struct drm_device *device, struct drm_fb *fb)
|
||||||
struct gbm_device *gbm_device;
|
struct gbm_device *gbm_device;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int plane;
|
int plane;
|
||||||
|
int num_planes;
|
||||||
|
|
||||||
/* No import possible, if there is no gbm bo */
|
/* No import possible, if there is no gbm bo or fb is not using
|
||||||
if (!fb->bo)
|
* direct-display */
|
||||||
|
if (!fb->bo && !fb->direct_display)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* No import necessary, if the gbm bo and the fb use the same device */
|
if (fb->bo) {
|
||||||
gbm_device = gbm_bo_get_device(fb->bo);
|
/* No import necessary, if the gbm bo and the fb use the same device */
|
||||||
if (gbm_device_get_fd(gbm_device) == fb->fd)
|
gbm_device = gbm_bo_get_device(fb->bo);
|
||||||
return 0;
|
if (gbm_device_get_fd(gbm_device) == fb->fd)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (fb->fd != device->drm.fd) {
|
if (fb->fd != device->drm.fd) {
|
||||||
weston_log("fb was not allocated for scanout device %s\n",
|
weston_log("fb was not allocated for scanout device %s\n",
|
||||||
device->drm.filename);
|
device->drm.filename);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_planes = gbm_bo_get_plane_count(fb->bo);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (plane = 0; plane < gbm_bo_get_plane_count(fb->bo); plane++) {
|
if (fb->direct_display)
|
||||||
|
num_planes = fb->num_planes;
|
||||||
|
|
||||||
|
for (plane = 0; plane < num_planes; plane++) {
|
||||||
ret = drm_fb_import_plane(device, fb, plane);
|
ret = drm_fb_import_plane(device, fb, plane);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -364,27 +384,35 @@ drm_fb_destroy_dmabuf(struct drm_fb *fb)
|
||||||
* If we imported the dmabuf into a scanout device, we are responsible
|
* If we imported the dmabuf into a scanout device, we are responsible
|
||||||
* for closing the GEM handle.
|
* for closing the GEM handle.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < MAX_DMABUF_PLANES; i++) {
|
||||||
if (fb->scanout_device && fb->handles[i] != 0)
|
if (fb->scanout_device && fb->handles[i] != 0) {
|
||||||
gem_handle_put(fb->scanout_device, fb->handles[i]);
|
gem_handle_put(fb->scanout_device, fb->handles[i]);
|
||||||
|
fb->handles[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < fb->num_duped_fds; i++)
|
||||||
|
close(fb->fds[i]);
|
||||||
|
|
||||||
drm_fb_destroy(fb);
|
drm_fb_destroy(fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct drm_fb *
|
struct drm_fb *
|
||||||
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
||||||
struct drm_device *device, bool is_opaque,
|
struct drm_device *device, bool is_opaque,
|
||||||
uint32_t *try_view_on_plane_failure_reasons)
|
bool direct_display, bool is_internal,
|
||||||
|
uint32_t *try_view_on_plane_failure_reasons)
|
||||||
{
|
{
|
||||||
struct drm_backend *backend = device->backend;
|
struct drm_backend *backend = device->backend;
|
||||||
struct drm_fb *fb;
|
struct drm_fb *fb;
|
||||||
int i;
|
int i;
|
||||||
struct gbm_import_fd_modifier_data import_mod = {
|
struct gbm_import_fd_modifier_data import_mod = {
|
||||||
.width = dmabuf->attributes.width,
|
.width = attributes->width,
|
||||||
.height = dmabuf->attributes.height,
|
.height = attributes->height,
|
||||||
.format = dmabuf->attributes.format,
|
.format = attributes->format,
|
||||||
.num_fds = dmabuf->attributes.n_planes,
|
.num_fds = attributes->n_planes,
|
||||||
.modifier = dmabuf->attributes.modifier,
|
.modifier = attributes->modifier,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* We should not import to KMS a buffer that has been allocated using no
|
/* We should not import to KMS a buffer that has been allocated using no
|
||||||
|
|
@ -394,7 +422,7 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||||
* KMS driver can't know. So giving the buffer to KMS is not safe, as
|
* KMS driver can't know. So giving the buffer to KMS is not safe, as
|
||||||
* not knowing its layout can result in garbage being displayed. In
|
* not knowing its layout can result in garbage being displayed. In
|
||||||
* short, importing a buffer to KMS requires explicit modifiers. */
|
* short, importing a buffer to KMS requires explicit modifiers. */
|
||||||
if (dmabuf->attributes.modifier == DRM_FORMAT_MOD_INVALID) {
|
if (attributes->modifier == DRM_FORMAT_MOD_INVALID) {
|
||||||
if (try_view_on_plane_failure_reasons)
|
if (try_view_on_plane_failure_reasons)
|
||||||
*try_view_on_plane_failure_reasons |=
|
*try_view_on_plane_failure_reasons |=
|
||||||
FAILURE_REASONS_DMABUF_MODIFIER_INVALID;
|
FAILURE_REASONS_DMABUF_MODIFIER_INVALID;
|
||||||
|
|
@ -410,7 +438,7 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||||
* these types of buffers should be handled through buffer
|
* these types of buffers should be handled through buffer
|
||||||
* transforms and not as spot-checks requiring specific
|
* transforms and not as spot-checks requiring specific
|
||||||
* knowledge. */
|
* knowledge. */
|
||||||
if (dmabuf->attributes.flags)
|
if (attributes->flags)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fb = zalloc(sizeof *fb);
|
fb = zalloc(sizeof *fb);
|
||||||
|
|
@ -418,12 +446,30 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fb->refcnt = 1;
|
fb->refcnt = 1;
|
||||||
fb->type = BUFFER_DMABUF;
|
fb->type = is_internal ? BUFFER_DMABUF_BACKEND : BUFFER_DMABUF;
|
||||||
fb->backend = device->backend;
|
fb->backend = device->backend;
|
||||||
|
|
||||||
ARRAY_COPY(import_mod.fds, dmabuf->attributes.fd);
|
ARRAY_COPY(import_mod.fds, attributes->fd);
|
||||||
ARRAY_COPY(import_mod.strides, dmabuf->attributes.stride);
|
ARRAY_COPY(import_mod.strides, attributes->stride);
|
||||||
ARRAY_COPY(import_mod.offsets, dmabuf->attributes.offset);
|
ARRAY_COPY(import_mod.offsets, attributes->offset);
|
||||||
|
|
||||||
|
/* skip bo import if dmabuf is using direct-display extension */
|
||||||
|
if (direct_display) {
|
||||||
|
fb->direct_display = true;
|
||||||
|
/* we're making a dup of the fds from attributes->fd as
|
||||||
|
* opposed to just copying the fds with ARRAY_COPY() */
|
||||||
|
for (i = 0; i < attributes->n_planes; i++) {
|
||||||
|
fb->fds[i] = dup(attributes->fd[i]);
|
||||||
|
if (fb->fds[i] == -1) {
|
||||||
|
weston_log("failed to dup dmabuf attribute fd: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
fb->num_duped_fds++;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto bo_import_skip;
|
||||||
|
}
|
||||||
|
|
||||||
fb->bo = gbm_bo_import(backend->gbm, GBM_BO_IMPORT_FD_MODIFIER,
|
fb->bo = gbm_bo_import(backend->gbm, GBM_BO_IMPORT_FD_MODIFIER,
|
||||||
&import_mod, GBM_BO_USE_SCANOUT);
|
&import_mod, GBM_BO_USE_SCANOUT);
|
||||||
|
|
@ -434,19 +480,20 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||||
goto err_free;
|
goto err_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
fb->width = dmabuf->attributes.width;
|
bo_import_skip:
|
||||||
fb->height = dmabuf->attributes.height;
|
fb->width = attributes->width;
|
||||||
fb->modifier = dmabuf->attributes.modifier;
|
fb->height = attributes->height;
|
||||||
|
fb->modifier = attributes->modifier;
|
||||||
fb->size = 0;
|
fb->size = 0;
|
||||||
fb->fd = device->drm.fd;
|
fb->fd = device->drm.fd;
|
||||||
|
|
||||||
ARRAY_COPY(fb->strides, dmabuf->attributes.stride);
|
ARRAY_COPY(fb->strides, attributes->stride);
|
||||||
ARRAY_COPY(fb->offsets, dmabuf->attributes.offset);
|
ARRAY_COPY(fb->offsets, attributes->offset);
|
||||||
|
|
||||||
fb->format = pixel_format_get_info(dmabuf->attributes.format);
|
fb->format = pixel_format_get_info(attributes->format);
|
||||||
if (!fb->format) {
|
if (!fb->format) {
|
||||||
weston_log("couldn't look up format info for 0x%lx\n",
|
weston_log("couldn't look up format info for 0x%lx\n",
|
||||||
(unsigned long) dmabuf->attributes.format);
|
(unsigned long) attributes->format);
|
||||||
goto err_free;
|
goto err_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -461,8 +508,8 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||||
goto err_free;
|
goto err_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
fb->num_planes = dmabuf->attributes.n_planes;
|
fb->num_planes = attributes->n_planes;
|
||||||
for (i = 0; i < dmabuf->attributes.n_planes; i++) {
|
for (i = 0; fb->bo && i < attributes->n_planes; i++) {
|
||||||
union gbm_bo_handle handle;
|
union gbm_bo_handle handle;
|
||||||
|
|
||||||
handle = gbm_bo_get_handle_for_plane(fb->bo, i);
|
handle = gbm_bo_get_handle_for_plane(fb->bo, i);
|
||||||
|
|
@ -488,6 +535,18 @@ err_free:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct drm_fb *
|
||||||
|
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||||
|
struct drm_device *device, bool is_opaque,
|
||||||
|
uint32_t *try_view_on_plane_failure_reasons)
|
||||||
|
{
|
||||||
|
return drm_fb_get_from_dmabuf_attributes(&dmabuf->attributes,
|
||||||
|
device, is_opaque,
|
||||||
|
dmabuf->direct_display,
|
||||||
|
false,
|
||||||
|
try_view_on_plane_failure_reasons);
|
||||||
|
}
|
||||||
|
|
||||||
struct drm_fb *
|
struct drm_fb *
|
||||||
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
|
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
|
||||||
bool is_opaque, enum drm_fb_type type)
|
bool is_opaque, enum drm_fb_type type)
|
||||||
|
|
@ -582,6 +641,7 @@ drm_fb_unref(struct drm_fb *fb)
|
||||||
gbm_surface_release_buffer(fb->gbm_surface, fb->bo);
|
gbm_surface_release_buffer(fb->gbm_surface, fb->bo);
|
||||||
break;
|
break;
|
||||||
case BUFFER_DMABUF:
|
case BUFFER_DMABUF:
|
||||||
|
case BUFFER_DMABUF_BACKEND:
|
||||||
drm_fb_destroy_dmabuf(fb);
|
drm_fb_destroy_dmabuf(fb);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -674,7 +734,8 @@ drm_fb_handle_buffer_destroy(struct wl_listener *listener, void *data)
|
||||||
|
|
||||||
struct drm_fb *
|
struct drm_fb *
|
||||||
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||||
struct weston_paint_node *pnode)
|
struct weston_paint_node *pnode,
|
||||||
|
uint32_t *try_view_on_plane_failure_reasons)
|
||||||
{
|
{
|
||||||
struct drm_output *output = state->output;
|
struct drm_output *output = state->output;
|
||||||
struct drm_backend *b = output->backend;
|
struct drm_backend *b = output->backend;
|
||||||
|
|
@ -689,13 +750,13 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||||
|
|
||||||
if (ev->surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
|
if (ev->surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
|
||||||
ev->surface->desired_protection > output->base.current_protection) {
|
ev->surface->desired_protection > output->base.current_protection) {
|
||||||
pnode->try_view_on_plane_failure_reasons |=
|
*try_view_on_plane_failure_reasons |=
|
||||||
FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION;
|
FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_BUFFER;
|
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_BUFFER;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -711,7 +772,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||||
|
|
||||||
wl_list_for_each(buf_fb, &private->buffer_fb_list, link) {
|
wl_list_for_each(buf_fb, &private->buffer_fb_list, link) {
|
||||||
if (buf_fb->device == device) {
|
if (buf_fb->device == device) {
|
||||||
pnode->try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
*try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
||||||
return buf_fb->fb ? drm_fb_ref(buf_fb->fb) : NULL;
|
return buf_fb->fb ? drm_fb_ref(buf_fb->fb) : NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -722,7 +783,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||||
|
|
||||||
/* GBM is used for dmabuf import as well as from client wl_buffer. */
|
/* GBM is used for dmabuf import as well as from client wl_buffer. */
|
||||||
if (!b->gbm) {
|
if (!b->gbm) {
|
||||||
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_GBM;
|
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_GBM;
|
||||||
goto unsuitable;
|
goto unsuitable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -741,13 +802,13 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||||
|
|
||||||
fb = drm_fb_get_from_bo(bo, device, is_opaque, BUFFER_CLIENT);
|
fb = drm_fb_get_from_bo(bo, device, is_opaque, BUFFER_CLIENT);
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
pnode->try_view_on_plane_failure_reasons |=
|
*try_view_on_plane_failure_reasons |=
|
||||||
(1 << FAILURE_REASONS_ADD_FB_FAILED);
|
FAILURE_REASONS_ADD_FB_FAILED;
|
||||||
gbm_bo_destroy(bo);
|
gbm_bo_destroy(bo);
|
||||||
goto unsuitable;
|
goto unsuitable;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_BUFFER_TYPE;
|
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_BUFFER_TYPE;
|
||||||
goto unsuitable;
|
goto unsuitable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -776,7 +837,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||||
return fb;
|
return fb;
|
||||||
|
|
||||||
unsuitable:
|
unsuitable:
|
||||||
pnode->try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
*try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,27 @@ struct drm_property_enum_info plane_rotation_enums[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct drm_property_enum_info plane_color_encoding_enums[] = {
|
||||||
|
[WDRM_PLANE_COLOR_ENCODING_BT601] = {
|
||||||
|
.name = "ITU-R BT.601 YCbCr",
|
||||||
|
},
|
||||||
|
[WDRM_PLANE_COLOR_ENCODING_BT709] = {
|
||||||
|
.name = "ITU-R BT.709 YCbCr",
|
||||||
|
},
|
||||||
|
[WDRM_PLANE_COLOR_ENCODING_BT2020] = {
|
||||||
|
.name = "ITU-R BT.2020 YCbCr",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_property_enum_info plane_color_range_enums[] = {
|
||||||
|
[WDRM_PLANE_COLOR_RANGE_LIMITED] = {
|
||||||
|
.name = "YCbCr limited range",
|
||||||
|
},
|
||||||
|
[WDRM_PLANE_COLOR_RANGE_FULL] = {
|
||||||
|
.name = "YCbCr full range",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const struct drm_property_info plane_props[] = {
|
const struct drm_property_info plane_props[] = {
|
||||||
[WDRM_PLANE_TYPE] = {
|
[WDRM_PLANE_TYPE] = {
|
||||||
.name = "type",
|
.name = "type",
|
||||||
|
|
@ -103,8 +124,18 @@ const struct drm_property_info plane_props[] = {
|
||||||
.name = "rotation",
|
.name = "rotation",
|
||||||
.enum_values = plane_rotation_enums,
|
.enum_values = plane_rotation_enums,
|
||||||
.num_enum_values = WDRM_PLANE_ROTATION__COUNT,
|
.num_enum_values = WDRM_PLANE_ROTATION__COUNT,
|
||||||
},
|
},
|
||||||
[WDRM_PLANE_ALPHA] = { .name = "alpha" },
|
[WDRM_PLANE_ALPHA] = { .name = "alpha" },
|
||||||
|
[WDRM_PLANE_COLOR_ENCODING] = {
|
||||||
|
.name = "COLOR_ENCODING",
|
||||||
|
.enum_values = plane_color_encoding_enums,
|
||||||
|
.num_enum_values = WDRM_PLANE_COLOR_ENCODING__COUNT,
|
||||||
|
},
|
||||||
|
[WDRM_PLANE_COLOR_RANGE] = {
|
||||||
|
.name = "COLOR_RANGE",
|
||||||
|
.enum_values = plane_color_range_enums,
|
||||||
|
.num_enum_values = WDRM_PLANE_COLOR_RANGE__COUNT,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drm_property_enum_info dpms_state_enums[] = {
|
struct drm_property_enum_info dpms_state_enums[] = {
|
||||||
|
|
@ -218,6 +249,9 @@ const struct drm_property_info connector_props[] = {
|
||||||
.enum_values = colorspace_enums,
|
.enum_values = colorspace_enums,
|
||||||
.num_enum_values = WDRM_COLORSPACE__COUNT,
|
.num_enum_values = WDRM_COLORSPACE__COUNT,
|
||||||
},
|
},
|
||||||
|
[WDRM_CONNECTOR_VRR_CAPABLE] = {
|
||||||
|
.name = "vrr_capable",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct drm_property_info crtc_props[] = {
|
const struct drm_property_info crtc_props[] = {
|
||||||
|
|
@ -395,6 +429,17 @@ drm_rotation_from_output_transform(struct drm_plane *plane,
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
wdrm_vrr_enabled_from_output(struct drm_output *drm_output)
|
||||||
|
{
|
||||||
|
struct weston_output *output = &drm_output->base;
|
||||||
|
|
||||||
|
if (output->vrr_mode == WESTON_VRR_MODE_GAME)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache DRM property values
|
* Cache DRM property values
|
||||||
*
|
*
|
||||||
|
|
@ -626,26 +671,36 @@ fallback:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
drm_output_set_gamma(struct weston_output *output_base,
|
drm_plane_supports_color_encoding(struct drm_plane *plane,
|
||||||
uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b)
|
enum wdrm_plane_color_encoding encoding)
|
||||||
{
|
{
|
||||||
int rc;
|
const struct drm_property_info *info;
|
||||||
struct drm_output *output = to_drm_output(output_base);
|
const struct drm_property_enum_info *enum_info;
|
||||||
struct drm_device *device = output->device;
|
|
||||||
|
|
||||||
assert(output);
|
assert(encoding >= 0);
|
||||||
|
assert(encoding < WDRM_PLANE_COLOR_ENCODING__COUNT);
|
||||||
|
|
||||||
/* check */
|
info = &plane->props[WDRM_PLANE_COLOR_ENCODING];
|
||||||
if (output_base->gamma_size != size)
|
enum_info = &info->enum_values[encoding];
|
||||||
return;
|
|
||||||
|
|
||||||
output->deprecated_gamma_is_set = true;
|
return enum_info->valid;
|
||||||
rc = drmModeCrtcSetGamma(device->drm.fd,
|
}
|
||||||
output->crtc->crtc_id,
|
|
||||||
size, r, g, b);
|
bool
|
||||||
if (rc)
|
drm_plane_supports_color_range(struct drm_plane *plane,
|
||||||
weston_log("set gamma failed: %s\n", strerror(errno));
|
enum wdrm_plane_color_range range)
|
||||||
|
{
|
||||||
|
const struct drm_property_info *info;
|
||||||
|
const struct drm_property_enum_info *enum_info;
|
||||||
|
|
||||||
|
assert(range >= 0);
|
||||||
|
assert(range < WDRM_PLANE_COLOR_RANGE__COUNT);
|
||||||
|
|
||||||
|
info = &plane->props[WDRM_PLANE_COLOR_RANGE];
|
||||||
|
enum_info = &info->enum_values[range];
|
||||||
|
|
||||||
|
return enum_info->valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -765,7 +820,7 @@ err:
|
||||||
static void
|
static void
|
||||||
drm_output_reset_legacy_gamma(struct drm_output *output)
|
drm_output_reset_legacy_gamma(struct drm_output *output)
|
||||||
{
|
{
|
||||||
uint32_t len = output->base.gamma_size;
|
uint32_t len = output->legacy_gamma_size;
|
||||||
uint16_t *lut;
|
uint16_t *lut;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -820,18 +875,6 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
||||||
connectors[n_conn++] = head->connector.connector_id;
|
connectors[n_conn++] = head->connector.connector_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If disable_planes is set then assign_planes() wasn't
|
|
||||||
* called for this render, so we could still have a stale
|
|
||||||
* cursor plane set up.
|
|
||||||
*/
|
|
||||||
if (output->base.disable_planes) {
|
|
||||||
drm_output_set_cursor_view(output, NULL);
|
|
||||||
if (output->cursor_plane) {
|
|
||||||
output->cursor_plane->base.x = INT32_MIN;
|
|
||||||
output->cursor_plane->base.y = INT32_MIN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state->dpms != WESTON_DPMS_ON) {
|
if (state->dpms != WESTON_DPMS_ON) {
|
||||||
if (output->cursor_plane) {
|
if (output->cursor_plane) {
|
||||||
ret = drmModeSetCursor(device->drm.fd, crtc->crtc_id,
|
ret = drmModeSetCursor(device->drm.fd, crtc->crtc_id,
|
||||||
|
|
@ -890,8 +933,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!output->deprecated_gamma_is_set)
|
drm_output_reset_legacy_gamma(output);
|
||||||
drm_output_reset_legacy_gamma(output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pinfo = scanout_state->fb->format;
|
pinfo = scanout_state->fb->format;
|
||||||
|
|
@ -1197,6 +1239,47 @@ drm_connector_set_colorspace(struct drm_connector *connector,
|
||||||
WDRM_CONNECTOR_COLORSPACE, enum_info->value);
|
WDRM_CONNECTOR_COLORSPACE, enum_info->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
drm_plane_set_color_encoding(struct drm_plane *plane,
|
||||||
|
enum wdrm_plane_color_encoding color_encoding,
|
||||||
|
drmModeAtomicReq *req)
|
||||||
|
{
|
||||||
|
if (color_encoding == WDRM_PLANE_COLOR_ENCODING__COUNT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (plane->props[WDRM_PLANE_COLOR_ENCODING].prop_id == 0) {
|
||||||
|
if (color_encoding == WDRM_PLANE_COLOR_ENCODING_DEFAULT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(drm_plane_supports_color_encoding(plane, color_encoding));
|
||||||
|
|
||||||
|
return plane_add_prop(req, plane, WDRM_PLANE_COLOR_ENCODING,
|
||||||
|
color_encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
drm_plane_set_color_range(struct drm_plane *plane,
|
||||||
|
enum wdrm_plane_color_range color_range,
|
||||||
|
drmModeAtomicReq *req)
|
||||||
|
{
|
||||||
|
if (color_range == WDRM_PLANE_COLOR_RANGE__COUNT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (plane->props[WDRM_PLANE_COLOR_RANGE].prop_id == 0) {
|
||||||
|
if (color_range == WDRM_PLANE_COLOR_RANGE_DEFAULT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(drm_plane_supports_color_range(plane, color_range));
|
||||||
|
|
||||||
|
return plane_add_prop(req, plane, WDRM_PLANE_COLOR_RANGE, color_range);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
drm_output_apply_state_atomic(struct drm_output_state *state,
|
drm_output_apply_state_atomic(struct drm_output_state *state,
|
||||||
drmModeAtomicReq *req,
|
drmModeAtomicReq *req,
|
||||||
|
|
@ -1238,14 +1321,18 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
||||||
current_mode->blob_id);
|
current_mode->blob_id);
|
||||||
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_ACTIVE, 1);
|
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_ACTIVE, 1);
|
||||||
|
|
||||||
if (!output->deprecated_gamma_is_set) {
|
if (output->base.from_blend_to_output_by_backend &&
|
||||||
ret |= crtc_add_prop_zero_ok(req, crtc,
|
output->blend_to_output_xform)
|
||||||
WDRM_CRTC_GAMMA_LUT, 0);
|
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_GAMMA_LUT,
|
||||||
ret |= crtc_add_prop_zero_ok(req, crtc,
|
output->blend_to_output_xform->blob_id);
|
||||||
WDRM_CRTC_DEGAMMA_LUT, 0);
|
else
|
||||||
}
|
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_GAMMA_LUT, 0);
|
||||||
|
|
||||||
|
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_DEGAMMA_LUT, 0);
|
||||||
|
|
||||||
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_CTM, 0);
|
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_CTM, 0);
|
||||||
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_VRR_ENABLED, 0);
|
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_VRR_ENABLED,
|
||||||
|
wdrm_vrr_enabled_from_output(output));
|
||||||
|
|
||||||
/* No need for the DPMS property, since it is implicit in
|
/* No need for the DPMS property, since it is implicit in
|
||||||
* routing and CRTC activity. */
|
* routing and CRTC activity. */
|
||||||
|
|
@ -1265,6 +1352,11 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
||||||
ret |= connector_add_prop(req, &wb_state->wb->connector,
|
ret |= connector_add_prop(req, &wb_state->wb->connector,
|
||||||
WDRM_CONNECTOR_WRITEBACK_OUT_FENCE_PTR,
|
WDRM_CONNECTOR_WRITEBACK_OUT_FENCE_PTR,
|
||||||
(uintptr_t)&wb_state->out_fence_fd);
|
(uintptr_t)&wb_state->out_fence_fd);
|
||||||
|
|
||||||
|
drm_debug(b, "\t\t\t[CONN:%lu] FORMAT: %s\n",
|
||||||
|
(unsigned long) wb_state->wb->connector.connector_id,
|
||||||
|
wb_state->fb->format->drm_format_name);
|
||||||
|
|
||||||
if (!(*flags & DRM_MODE_ATOMIC_TEST_ONLY))
|
if (!(*flags & DRM_MODE_ATOMIC_TEST_ONLY))
|
||||||
wb_state->state = DRM_OUTPUT_WB_SCREENSHOT_CHECK_FENCE;
|
wb_state->state = DRM_OUTPUT_WB_SCREENSHOT_CHECK_FENCE;
|
||||||
}
|
}
|
||||||
|
|
@ -1282,11 +1374,13 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
||||||
wl_list_for_each(head, &output->base.head_list, base.output_link)
|
wl_list_for_each(head, &output->base.head_list, base.output_link)
|
||||||
ret |= connector_add_prop(req, &head->connector,
|
ret |= connector_add_prop(req, &head->connector,
|
||||||
WDRM_CONNECTOR_CRTC_ID, 0);
|
WDRM_CONNECTOR_CRTC_ID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
wl_list_for_each_safe(head, tmp, &output->disable_head,
|
wl_list_for_each_safe(head, tmp, &output->disable_head, disable_head_link) {
|
||||||
disable_head_link) {
|
ret |= connector_add_prop(req, &head->connector,
|
||||||
ret |= connector_add_prop(req, &head->connector,
|
WDRM_CONNECTOR_CRTC_ID, 0);
|
||||||
WDRM_CONNECTOR_CRTC_ID, 0);
|
*flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||||
|
if (!(*flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
|
||||||
wl_list_remove(&head->disable_head_link);
|
wl_list_remove(&head->disable_head_link);
|
||||||
wl_list_init(&head->disable_head_link);
|
wl_list_init(&head->disable_head_link);
|
||||||
}
|
}
|
||||||
|
|
@ -1373,6 +1467,13 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
||||||
WDRM_PLANE_ALPHA,
|
WDRM_PLANE_ALPHA,
|
||||||
plane_state->alpha);
|
plane_state->alpha);
|
||||||
|
|
||||||
|
ret |= drm_plane_set_color_encoding(plane,
|
||||||
|
plane_state->color_encoding,
|
||||||
|
req);
|
||||||
|
|
||||||
|
ret |= drm_plane_set_color_range(plane,
|
||||||
|
plane_state->color_range, req);
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
weston_log("couldn't set plane state\n");
|
weston_log("couldn't set plane state\n");
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -1524,7 +1625,10 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
weston_log("atomic: couldn't compile atomic state\n");
|
weston_log("atomic: couldn't compile atomic state\n");
|
||||||
goto out;
|
if (mode == DRM_STATE_TEST_ONLY)
|
||||||
|
goto out_test_only;
|
||||||
|
else
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
if (may_tear)
|
if (may_tear)
|
||||||
tear_flag = DRM_MODE_PAGE_FLIP_ASYNC;
|
tear_flag = DRM_MODE_PAGE_FLIP_ASYNC;
|
||||||
|
|
@ -1542,12 +1646,8 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
drm_pending_state_clear_tearing(pending_state);
|
drm_pending_state_clear_tearing(pending_state);
|
||||||
}
|
}
|
||||||
/* Test commits do not take ownership of the state; return
|
if (mode == DRM_STATE_TEST_ONLY)
|
||||||
* without freeing here. */
|
goto out_test_only;
|
||||||
if (mode == DRM_STATE_TEST_ONLY) {
|
|
||||||
drmModeAtomicFree(req);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
wl_list_for_each(output_state, &pending_state->output_list, link)
|
wl_list_for_each(output_state, &pending_state->output_list, link)
|
||||||
|
|
@ -1568,8 +1668,11 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
||||||
assert(wl_list_empty(&pending_state->output_list));
|
assert(wl_list_empty(&pending_state->output_list));
|
||||||
|
|
||||||
out:
|
out:
|
||||||
drmModeAtomicFree(req);
|
|
||||||
drm_pending_state_free(pending_state);
|
drm_pending_state_free(pending_state);
|
||||||
|
/* Test commits do not take ownership of the state; return
|
||||||
|
* without freeing here. */
|
||||||
|
out_test_only:
|
||||||
|
drmModeAtomicFree(req);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1665,6 +1768,9 @@ drm_pending_state_apply(struct drm_pending_state *pending_state)
|
||||||
if (b->compositor->renderer->type == WESTON_RENDERER_GL) {
|
if (b->compositor->renderer->type == WESTON_RENDERER_GL) {
|
||||||
drm_output_fini_egl(output);
|
drm_output_fini_egl(output);
|
||||||
drm_output_init_egl(output, b);
|
drm_output_init_egl(output, b);
|
||||||
|
} else if (b->compositor->renderer->type == WESTON_RENDERER_VULKAN) {
|
||||||
|
drm_output_fini_vulkan(output);
|
||||||
|
drm_output_init_vulkan(output, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1758,6 +1864,7 @@ page_flip_handler(int fd, unsigned int frame,
|
||||||
assert(output->page_flip_pending);
|
assert(output->page_flip_pending);
|
||||||
output->page_flip_pending = false;
|
output->page_flip_pending = false;
|
||||||
|
|
||||||
|
output->page_flips_counted++;
|
||||||
drm_output_update_complete(output, flags, sec, usec);
|
drm_output_update_complete(output, flags, sec, usec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1771,6 +1878,8 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
struct drm_output *output;
|
struct drm_output *output;
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
|
float page_flips_per_timer_interval;
|
||||||
|
uint32_t frame_counter_interval;
|
||||||
uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
|
uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
|
||||||
WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
|
WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
|
||||||
WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
|
WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
|
||||||
|
|
@ -1786,6 +1895,14 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
|
||||||
if (!output || !output->base.enabled)
|
if (!output || !output->base.enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
output->page_flips_counted++;
|
||||||
|
/* store them temporarily as drm_output_update_complete might destroy
|
||||||
|
* the output */
|
||||||
|
page_flips_per_timer_interval = output->page_flips_per_timer_interval;
|
||||||
|
frame_counter_interval =
|
||||||
|
output->backend->perf_page_flips_stats.frame_counter_interval;
|
||||||
|
|
||||||
|
|
||||||
drm_output_update_msc(output, frame);
|
drm_output_update_msc(output, frame);
|
||||||
|
|
||||||
if (output->state_cur->tear) {
|
if (output->state_cur->tear) {
|
||||||
|
|
@ -1806,6 +1923,8 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
|
||||||
|
|
||||||
drm_output_update_complete(output, flags, sec, usec);
|
drm_output_update_complete(output, flags, sec, usec);
|
||||||
drm_debug(b, "[atomic][CRTC:%u] flip processing completed\n", crtc_id);
|
drm_debug(b, "[atomic][CRTC:%u] flip processing completed\n", crtc_id);
|
||||||
|
drm_debug(b, "[atomic][CRTC:%u] %.2f page flips computed in %d seconds\n",
|
||||||
|
crtc_id, page_flips_per_timer_interval, frame_counter_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -1875,10 +1994,29 @@ init_kms_caps(struct drm_device *device)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = drmGetCap(device->drm.fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &cap);
|
||||||
|
if (ret != 0)
|
||||||
|
cap = 0;
|
||||||
|
|
||||||
|
/* Between Linux 3.16 and Linux 4.1 there was a bug that
|
||||||
|
* could result in a stale timestamp being returned.
|
||||||
|
*
|
||||||
|
* The workaround for this has can make it impossible
|
||||||
|
* to display images with precise timing.
|
||||||
|
*
|
||||||
|
* It's somewhat difficult to determine whether we need
|
||||||
|
* that workaround or not, but we know that the
|
||||||
|
* DRM_CAP_CRTC_IN_VBLANK_EVENT drm cap exists in 4.12
|
||||||
|
* and on. We'll use its presence to gate the workaround.
|
||||||
|
*/
|
||||||
|
if (!cap) {
|
||||||
|
weston_log("DRM Warning: stale timestamp workaround for Kernel older than 4.12\n");
|
||||||
|
device->backend->stale_timestamp_workaround = true;
|
||||||
|
} else {
|
||||||
|
device->backend->stale_timestamp_workaround = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!getenv("WESTON_DISABLE_ATOMIC")) {
|
if (!getenv("WESTON_DISABLE_ATOMIC")) {
|
||||||
ret = drmGetCap(device->drm.fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &cap);
|
|
||||||
if (ret != 0)
|
|
||||||
cap = 0;
|
|
||||||
ret = drmSetClientCap(device->drm.fd, DRM_CLIENT_CAP_ATOMIC, 1);
|
ret = drmSetClientCap(device->drm.fd, DRM_CLIENT_CAP_ATOMIC, 1);
|
||||||
device->atomic_modeset = ((ret == 0) && (cap == 1));
|
device->atomic_modeset = ((ret == 0) && (cap == 1));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,6 @@ if not get_option('backend-drm')
|
||||||
subdir_done()
|
subdir_done()
|
||||||
endif
|
endif
|
||||||
|
|
||||||
dep_libdisplay_info = dependency(
|
|
||||||
'libdisplay-info',
|
|
||||||
version: ['>= 0.1.1', '< 0.3.0'],
|
|
||||||
fallback: ['display-info', 'di_dep'],
|
|
||||||
default_options: [
|
|
||||||
'werror=false',
|
|
||||||
],
|
|
||||||
required: true,
|
|
||||||
not_found_message: 'Required by DRM-backend.',
|
|
||||||
)
|
|
||||||
if dep_libdisplay_info.version().version_compare('>= 0.2.0')
|
|
||||||
config_h.set('HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY', '1')
|
|
||||||
endif
|
|
||||||
|
|
||||||
lib_backlight = static_library(
|
lib_backlight = static_library(
|
||||||
'backlight',
|
'backlight',
|
||||||
'libbacklight.c',
|
'libbacklight.c',
|
||||||
|
|
@ -48,6 +34,7 @@ srcs_drm = [
|
||||||
|
|
||||||
deps_drm = [
|
deps_drm = [
|
||||||
dep_egl, # optional
|
dep_egl, # optional
|
||||||
|
dep_vulkan, # optional
|
||||||
dep_libm,
|
dep_libm,
|
||||||
dep_libdl,
|
dep_libdl,
|
||||||
dep_libshared,
|
dep_libshared,
|
||||||
|
|
@ -69,7 +56,17 @@ if get_option('renderer-gl')
|
||||||
config_h.set('BUILD_DRM_GBM', '1')
|
config_h.set('BUILD_DRM_GBM', '1')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get_option('backend-drm-screencast-vaapi')
|
if get_option('renderer-vulkan')
|
||||||
|
if not dep_gbm.found()
|
||||||
|
error('drm-backend with Vulkan renderer requires gbm which was not found. Or, you can use \'-Drenderer-vulkan=false\'.')
|
||||||
|
endif
|
||||||
|
deps_drm += dep_gbm
|
||||||
|
srcs_drm += 'drm-gbm.c'
|
||||||
|
config_h.set('BUILD_DRM_GBM', '1')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get_option('deprecated-backend-drm-screencast-vaapi')
|
||||||
|
warning('deprecated-backend-drm-screencast-vaapi enabled. This option will be removed in future versions.')
|
||||||
foreach name : [ 'libva', 'libva-drm' ]
|
foreach name : [ 'libva', 'libva-drm' ]
|
||||||
d = dependency(name, version: '>= 0.34.0', required: false)
|
d = dependency(name, version: '>= 0.34.0', required: false)
|
||||||
if not d.found()
|
if not d.found()
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
|
#include <libdisplay-info/cta.h>
|
||||||
|
#include <libdisplay-info/edid.h>
|
||||||
#include <libdisplay-info/info.h>
|
#include <libdisplay-info/info.h>
|
||||||
|
|
||||||
#include "drm-internal.h"
|
#include "drm-internal.h"
|
||||||
|
|
@ -51,6 +53,10 @@ struct drm_head_info {
|
||||||
* enum weston_colorimetry_mode bits.
|
* enum weston_colorimetry_mode bits.
|
||||||
*/
|
*/
|
||||||
uint32_t colorimetry_mask;
|
uint32_t colorimetry_mask;
|
||||||
|
|
||||||
|
/* The monitor supported color foramts, combination of
|
||||||
|
* enum_weston_color_format bits. */
|
||||||
|
uint32_t color_format_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -227,8 +233,6 @@ parse_modeline(const char *s, drmModeModeInfo *mode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY
|
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
get_eotf_mask(const struct di_info *info)
|
get_eotf_mask(const struct di_info *info)
|
||||||
{
|
{
|
||||||
|
|
@ -284,21 +288,75 @@ get_colorimetry_mask(const struct di_info *info)
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY */
|
static bool
|
||||||
|
has_yuv420_cap_map(const struct di_edid_cta *cta)
|
||||||
static uint32_t
|
|
||||||
get_eotf_mask(const struct di_info *info)
|
|
||||||
{
|
{
|
||||||
return WESTON_EOTF_MODE_SDR;
|
const struct di_cta_data_block *const *data_blocks;
|
||||||
|
enum di_cta_data_block_tag db_tag;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
data_blocks = di_edid_cta_get_data_blocks(cta);
|
||||||
|
for (i = 0; data_blocks[i] != NULL; i++) {
|
||||||
|
db_tag = di_cta_data_block_get_tag(data_blocks[i]);
|
||||||
|
if (db_tag == DI_CTA_DATA_BLOCK_YCBCR420_CAP_MAP)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
get_colorimetry_mask(const struct di_info *info)
|
get_color_format_mask(const struct di_info *info)
|
||||||
{
|
{
|
||||||
return WESTON_COLORIMETRY_MODE_DEFAULT;
|
const struct di_edid *edid = di_info_get_edid(info);
|
||||||
}
|
const struct di_edid_color_encoding_formats *fmts =
|
||||||
|
di_edid_get_color_encoding_formats(edid);
|
||||||
|
const struct di_edid_ext *const *exts = di_edid_get_extensions(edid);
|
||||||
|
uint32_t mask = WESTON_COLOR_FORMAT_AUTO;
|
||||||
|
int i;
|
||||||
|
|
||||||
#endif /* HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY */
|
if (fmts) {
|
||||||
|
if (fmts->rgb444)
|
||||||
|
mask |= WESTON_COLOR_FORMAT_RGB;
|
||||||
|
|
||||||
|
if (fmts->ycrcb444)
|
||||||
|
mask |= WESTON_COLOR_FORMAT_YUV444;
|
||||||
|
|
||||||
|
if (fmts->ycrcb422)
|
||||||
|
mask |= WESTON_COLOR_FORMAT_YUV422;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; exts[i] ; i++) {
|
||||||
|
const struct di_edid_cta *cta;
|
||||||
|
const struct di_edid_cta_flags *cta_flags;
|
||||||
|
|
||||||
|
switch (di_edid_ext_get_tag(exts[i])) {
|
||||||
|
case DI_EDID_EXT_CEA:
|
||||||
|
cta = di_edid_ext_get_cta(exts[i]);
|
||||||
|
cta_flags = di_edid_cta_get_flags(cta);
|
||||||
|
|
||||||
|
mask |= WESTON_COLOR_FORMAT_RGB;
|
||||||
|
|
||||||
|
if (cta_flags->ycc444)
|
||||||
|
mask |= WESTON_COLOR_FORMAT_YUV444;
|
||||||
|
|
||||||
|
if (cta_flags->ycc422)
|
||||||
|
mask |= WESTON_COLOR_FORMAT_YUV422;
|
||||||
|
|
||||||
|
/* FIXME: YUV420 detection is really complicated,
|
||||||
|
* do it properly at some point...
|
||||||
|
*/
|
||||||
|
if (has_yuv420_cap_map(cta))
|
||||||
|
mask |= WESTON_COLOR_FORMAT_YUV420;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
static struct di_info *
|
static struct di_info *
|
||||||
drm_head_info_from_edid(struct drm_head_info *dhi,
|
drm_head_info_from_edid(struct drm_head_info *dhi,
|
||||||
|
|
@ -325,6 +383,7 @@ drm_head_info_from_edid(struct drm_head_info *dhi,
|
||||||
dhi->serial_number = di_info_get_serial(di_ctx);
|
dhi->serial_number = di_info_get_serial(di_ctx);
|
||||||
dhi->eotf_mask = get_eotf_mask(di_ctx);
|
dhi->eotf_mask = get_eotf_mask(di_ctx);
|
||||||
dhi->colorimetry_mask = get_colorimetry_mask(di_ctx);
|
dhi->colorimetry_mask = get_colorimetry_mask(di_ctx);
|
||||||
|
dhi->color_format_mask = get_color_format_mask(di_ctx);
|
||||||
|
|
||||||
return di_ctx;
|
return di_ctx;
|
||||||
}
|
}
|
||||||
|
|
@ -597,26 +656,46 @@ void
|
||||||
update_head_from_connector(struct drm_head *head)
|
update_head_from_connector(struct drm_head *head)
|
||||||
{
|
{
|
||||||
struct drm_connector *connector = &head->connector;
|
struct drm_connector *connector = &head->connector;
|
||||||
|
struct drm_backend *b = head->connector.device->backend;
|
||||||
drmModeObjectProperties *props = connector->props_drm;
|
drmModeObjectProperties *props = connector->props_drm;
|
||||||
drmModeConnector *conn = connector->conn;
|
drmModeConnector *conn = connector->conn;
|
||||||
|
int vrr_capable;
|
||||||
|
uint32_t vrr_mode_mask = 0;
|
||||||
|
uint32_t conn_id = head->connector.connector_id;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
weston_head_set_non_desktop(&head->base,
|
ret = weston_head_set_non_desktop(&head->base,
|
||||||
check_non_desktop(connector, props));
|
check_non_desktop(connector, props));
|
||||||
weston_head_set_subpixel(&head->base,
|
if (ret)
|
||||||
|
drm_debug(b, "\t[CONN:%d] non-desktop property changed\n", conn_id);
|
||||||
|
|
||||||
|
ret = weston_head_set_subpixel(&head->base,
|
||||||
drm_subpixel_to_wayland(conn->subpixel));
|
drm_subpixel_to_wayland(conn->subpixel));
|
||||||
|
if (ret)
|
||||||
|
drm_debug(b, "\t[CONN:%d] subpixel property changed\n", conn_id);
|
||||||
|
|
||||||
weston_head_set_physical_size(&head->base, conn->mmWidth, conn->mmHeight);
|
ret = weston_head_set_physical_size(&head->base, conn->mmWidth, conn->mmHeight);
|
||||||
|
if (ret)
|
||||||
|
drm_debug(b, "\t[CONN:%d] physical size changed\n", conn_id);
|
||||||
|
|
||||||
weston_head_set_transform(&head->base,
|
ret = weston_head_set_transform(&head->base,
|
||||||
get_panel_orientation(connector, props));
|
get_panel_orientation(connector, props));
|
||||||
|
if (ret)
|
||||||
|
drm_debug(b, "\t[CONN:%d] transform property changed\n", conn_id);
|
||||||
|
|
||||||
/* Unknown connection status is assumed disconnected. */
|
/* Unknown connection status is assumed disconnected. */
|
||||||
weston_head_set_connection_status(&head->base,
|
ret = weston_head_set_connection_status(&head->base,
|
||||||
conn->connection == DRM_MODE_CONNECTED);
|
conn->connection == DRM_MODE_CONNECTED);
|
||||||
|
if (ret)
|
||||||
|
drm_debug(b, "\t[CONN:%d] connection status changed\n", conn_id);
|
||||||
|
|
||||||
/* If EDID did not change, skip everything about it */
|
/* If EDID did not change, skip everything about it */
|
||||||
if (!drm_head_maybe_update_display_data(head, props))
|
if (!drm_head_maybe_update_display_data(head, props)) {
|
||||||
|
if (!ret)
|
||||||
|
drm_debug(b, "\t[CONN:%d] Hot-plug event received "
|
||||||
|
"but no connector changes detected\n", conn_id);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct drm_head_info dhi;
|
struct drm_head_info dhi;
|
||||||
|
|
||||||
|
|
@ -630,11 +709,18 @@ update_head_from_connector(struct drm_head *head)
|
||||||
dhi.serial_number);
|
dhi.serial_number);
|
||||||
|
|
||||||
prune_eotf_modes_by_kms_support(head, &dhi.eotf_mask);
|
prune_eotf_modes_by_kms_support(head, &dhi.eotf_mask);
|
||||||
|
|
||||||
weston_head_set_supported_eotf_mask(&head->base, dhi.eotf_mask);
|
weston_head_set_supported_eotf_mask(&head->base, dhi.eotf_mask);
|
||||||
|
|
||||||
dhi.colorimetry_mask &= drm_head_get_kms_colorimetry_modes(head);
|
dhi.colorimetry_mask &= drm_head_get_kms_colorimetry_modes(head);
|
||||||
weston_head_set_supported_colorimetry_mask(&head->base, dhi.colorimetry_mask);
|
weston_head_set_supported_colorimetry_mask(&head->base, dhi.colorimetry_mask);
|
||||||
|
|
||||||
|
vrr_capable = drm_property_get_value(&head->connector.props[WDRM_CONNECTOR_VRR_CAPABLE],
|
||||||
|
head->connector.props_drm, 0);
|
||||||
|
if (vrr_capable)
|
||||||
|
vrr_mode_mask = WESTON_VRR_MODE_GAME;
|
||||||
|
weston_head_set_supported_vrr_modes_mask(&head->base, vrr_mode_mask);
|
||||||
|
|
||||||
drm_head_info_fini(&dhi);
|
drm_head_info_fini(&dhi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -912,7 +998,7 @@ drm_output_set_mode(struct weston_output *base,
|
||||||
output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
|
output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
|
||||||
|
|
||||||
/* Set native_ fields, so weston_output_mode_switch_to_native() works */
|
/* Set native_ fields, so weston_output_mode_switch_to_native() works */
|
||||||
output->base.native_mode = output->base.current_mode;
|
weston_output_copy_native_mode(&output->base, output->base.current_mode);
|
||||||
output->base.native_scale = output->base.current_scale;
|
output->base.native_scale = output->base.current_scale;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,9 @@ drm_plane_state_alloc(struct drm_output_state *state_output,
|
||||||
state->alpha = (plane->alpha_max < DRM_PLANE_ALPHA_OPAQUE) ?
|
state->alpha = (plane->alpha_max < DRM_PLANE_ALPHA_OPAQUE) ?
|
||||||
plane->alpha_max : DRM_PLANE_ALPHA_OPAQUE;
|
plane->alpha_max : DRM_PLANE_ALPHA_OPAQUE;
|
||||||
|
|
||||||
|
state->color_encoding = WDRM_PLANE_COLOR_ENCODING__COUNT;
|
||||||
|
state->color_range = WDRM_PLANE_COLOR_RANGE__COUNT;
|
||||||
|
|
||||||
/* Here we only add the plane state to the desired link, and not
|
/* Here we only add the plane state to the desired link, and not
|
||||||
* set the member. Having an output pointer set means that the
|
* set the member. Having an output pointer set means that the
|
||||||
* plane will be displayed on the output; this won't be the case
|
* plane will be displayed on the output; this won't be the case
|
||||||
|
|
@ -213,7 +216,7 @@ drm_plane_state_put_back(struct drm_plane_state *state)
|
||||||
* Given a weston_view, fill the drm_plane_state's co-ordinates to display on
|
* Given a weston_view, fill the drm_plane_state's co-ordinates to display on
|
||||||
* a given plane.
|
* a given plane.
|
||||||
*/
|
*/
|
||||||
bool
|
void
|
||||||
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
||||||
struct weston_paint_node *node,
|
struct weston_paint_node *node,
|
||||||
uint64_t zpos)
|
uint64_t zpos)
|
||||||
|
|
@ -228,8 +231,11 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
||||||
uint16_t min_alpha = state->plane->alpha_min;
|
uint16_t min_alpha = state->plane->alpha_min;
|
||||||
uint16_t max_alpha = state->plane->alpha_max;
|
uint16_t max_alpha = state->plane->alpha_max;
|
||||||
|
|
||||||
if (!drm_paint_node_transform_supported(node, state->plane))
|
/* The caller has already checked supported transforms when creating
|
||||||
return false;
|
* a list of candidate planes, so we should only ever get here with
|
||||||
|
* a supported transform.
|
||||||
|
*/
|
||||||
|
assert(drm_paint_node_transform_supported(node, state->plane));
|
||||||
|
|
||||||
assert(node->valid_transform);
|
assert(node->valid_transform);
|
||||||
state->rotation = drm_rotation_from_output_transform(state->plane, node->transform);
|
state->rotation = drm_rotation_from_output_transform(state->plane, node->transform);
|
||||||
|
|
@ -312,8 +318,6 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
||||||
* never exceed max_alpha if ev->alpha <= 1.0.
|
* never exceed max_alpha if ev->alpha <= 1.0.
|
||||||
*/
|
*/
|
||||||
state->alpha = min_alpha + (uint16_t)round((max_alpha - min_alpha) * ev->alpha);
|
state->alpha = min_alpha + (uint16_t)round((max_alpha - min_alpha) * ev->alpha);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -403,6 +407,9 @@ drm_output_state_duplicate(struct drm_output_state *src,
|
||||||
|
|
||||||
assert(dst);
|
assert(dst);
|
||||||
|
|
||||||
|
/* The reuse bit isn't stored in the state */
|
||||||
|
assert(!(src->mode & DRM_OUTPUT_PROPOSE_STATE_REUSE));
|
||||||
|
|
||||||
/* Copy the whole structure, then individually modify the
|
/* Copy the whole structure, then individually modify the
|
||||||
* pending_state, as well as the list link into our pending
|
* pending_state, as well as the list link into our pending
|
||||||
* state. */
|
* state. */
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -42,7 +42,8 @@
|
||||||
#include "pixel-formats.h"
|
#include "pixel-formats.h"
|
||||||
#include "pixman-renderer.h"
|
#include "pixman-renderer.h"
|
||||||
#include "renderer-gl/gl-renderer.h"
|
#include "renderer-gl/gl-renderer.h"
|
||||||
#include "gl-borders.h"
|
#include "renderer-vulkan/vulkan-renderer.h"
|
||||||
|
#include "renderer-borders.h"
|
||||||
#include "shared/weston-drm-fourcc.h"
|
#include "shared/weston-drm-fourcc.h"
|
||||||
#include "shared/weston-egl-ext.h"
|
#include "shared/weston-egl-ext.h"
|
||||||
#include "shared/cairo-util.h"
|
#include "shared/cairo-util.h"
|
||||||
|
|
@ -69,6 +70,8 @@ struct headless_backend {
|
||||||
|
|
||||||
int refresh;
|
int refresh;
|
||||||
bool repaint_only_on_capture;
|
bool repaint_only_on_capture;
|
||||||
|
|
||||||
|
bool use_fake_seat;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct headless_head {
|
struct headless_head {
|
||||||
|
|
@ -81,12 +84,10 @@ struct headless_output {
|
||||||
|
|
||||||
struct weston_mode mode;
|
struct weston_mode mode;
|
||||||
struct wl_event_source *finish_frame_timer;
|
struct wl_event_source *finish_frame_timer;
|
||||||
struct weston_renderbuffer *renderbuffer;
|
weston_renderbuffer_t renderbuffer;
|
||||||
|
|
||||||
struct frame *frame;
|
struct frame *frame;
|
||||||
struct {
|
struct weston_renderer_borders borders;
|
||||||
struct weston_gl_borders borders;
|
|
||||||
} gl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t headless_formats[] = {
|
static const uint32_t headless_formats[] = {
|
||||||
|
|
@ -144,15 +145,15 @@ finish_frame_handler(void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
headless_output_update_gl_border(struct headless_output *output)
|
headless_output_update_renderer_border(struct headless_output *output)
|
||||||
{
|
{
|
||||||
if (!output->frame)
|
if (!output->frame)
|
||||||
return;
|
return;
|
||||||
if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
|
if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
weston_gl_borders_update(&output->gl.borders, output->frame,
|
weston_renderer_borders_update(&output->borders, output->frame,
|
||||||
&output->base);
|
&output->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
@ -161,13 +162,12 @@ headless_output_repaint(struct weston_output *output_base)
|
||||||
struct headless_output *output = to_headless_output(output_base);
|
struct headless_output *output = to_headless_output(output_base);
|
||||||
struct weston_compositor *ec;
|
struct weston_compositor *ec;
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
int delay_msec;
|
|
||||||
|
|
||||||
assert(output);
|
assert(output);
|
||||||
|
|
||||||
ec = output->base.compositor;
|
ec = output->base.compositor;
|
||||||
|
|
||||||
headless_output_update_gl_border(output);
|
headless_output_update_renderer_border(output);
|
||||||
|
|
||||||
pixman_region32_init(&damage);
|
pixman_region32_init(&damage);
|
||||||
|
|
||||||
|
|
@ -178,8 +178,7 @@ headless_output_repaint(struct weston_output *output_base)
|
||||||
|
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
|
|
||||||
delay_msec = millihz_to_nsec(output->mode.refresh) / 1000000;
|
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
|
||||||
wl_event_source_timer_update(output->finish_frame_timer, delay_msec);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -190,9 +189,9 @@ headless_output_disable_gl(struct headless_output *output)
|
||||||
struct weston_compositor *compositor = output->base.compositor;
|
struct weston_compositor *compositor = output->base.compositor;
|
||||||
const struct weston_renderer *renderer = compositor->renderer;
|
const struct weston_renderer *renderer = compositor->renderer;
|
||||||
|
|
||||||
weston_gl_borders_fini(&output->gl.borders, &output->base);
|
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||||
|
|
||||||
weston_renderbuffer_unref(output->renderbuffer);
|
renderer->destroy_renderbuffer(output->renderbuffer);
|
||||||
output->renderbuffer = NULL;
|
output->renderbuffer = NULL;
|
||||||
renderer->gl->output_destroy(&output->base);
|
renderer->gl->output_destroy(&output->base);
|
||||||
|
|
||||||
|
|
@ -202,12 +201,30 @@ headless_output_disable_gl(struct headless_output *output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
headless_output_disable_vulkan(struct headless_output *output)
|
||||||
|
{
|
||||||
|
struct weston_compositor *compositor = output->base.compositor;
|
||||||
|
const struct weston_renderer *renderer = compositor->renderer;
|
||||||
|
|
||||||
|
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||||
|
|
||||||
|
renderer->destroy_renderbuffer(output->renderbuffer);
|
||||||
|
output->renderbuffer = NULL;
|
||||||
|
renderer->vulkan->output_destroy(&output->base);
|
||||||
|
|
||||||
|
if (output->frame) {
|
||||||
|
frame_destroy(output->frame);
|
||||||
|
output->frame = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
headless_output_disable_pixman(struct headless_output *output)
|
headless_output_disable_pixman(struct headless_output *output)
|
||||||
{
|
{
|
||||||
struct weston_renderer *renderer = output->base.compositor->renderer;
|
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||||
|
|
||||||
weston_renderbuffer_unref(output->renderbuffer);
|
renderer->destroy_renderbuffer(output->renderbuffer);
|
||||||
output->renderbuffer = NULL;
|
output->renderbuffer = NULL;
|
||||||
renderer->pixman->output_destroy(&output->base);
|
renderer->pixman->output_destroy(&output->base);
|
||||||
}
|
}
|
||||||
|
|
@ -231,6 +248,9 @@ headless_output_disable(struct weston_output *base)
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
headless_output_disable_gl(output);
|
headless_output_disable_gl(output);
|
||||||
break;
|
break;
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
headless_output_disable_vulkan(output);
|
||||||
|
break;
|
||||||
case WESTON_RENDERER_PIXMAN:
|
case WESTON_RENDERER_PIXMAN:
|
||||||
headless_output_disable_pixman(output);
|
headless_output_disable_pixman(output);
|
||||||
break;
|
break;
|
||||||
|
|
@ -301,9 +321,8 @@ headless_output_enable_gl(struct headless_output *output)
|
||||||
}
|
}
|
||||||
|
|
||||||
output->renderbuffer =
|
output->renderbuffer =
|
||||||
renderer->gl->create_fbo(&output->base, b->formats[0],
|
renderer->create_renderbuffer(&output->base, b->formats[0],
|
||||||
options.fb_size.width,
|
NULL, 0, NULL, NULL);
|
||||||
options.fb_size.height, NULL);
|
|
||||||
if (!output->renderbuffer)
|
if (!output->renderbuffer)
|
||||||
goto err_renderbuffer;
|
goto err_renderbuffer;
|
||||||
|
|
||||||
|
|
@ -315,10 +334,67 @@ err_renderbuffer:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
headless_output_enable_vulkan(struct headless_output *output)
|
||||||
|
{
|
||||||
|
struct headless_backend *b = output->backend;
|
||||||
|
const struct weston_renderer *renderer = b->compositor->renderer;
|
||||||
|
const struct weston_mode *mode = output->base.current_mode;
|
||||||
|
struct vulkan_renderer_surfaceless_options options = { 0 };
|
||||||
|
|
||||||
|
if (b->decorate) {
|
||||||
|
/*
|
||||||
|
* Start with a dummy exterior size and then resize, because
|
||||||
|
* there is no frame_create() with interior size.
|
||||||
|
*/
|
||||||
|
output->frame = frame_create(b->theme, 100, 100,
|
||||||
|
FRAME_BUTTON_CLOSE, NULL, NULL);
|
||||||
|
if (!output->frame) {
|
||||||
|
weston_log("failed to create frame for output\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
frame_resize_inside(output->frame, mode->width, mode->height);
|
||||||
|
|
||||||
|
options.fb_size.width = frame_width(output->frame);
|
||||||
|
options.fb_size.height = frame_height(output->frame);
|
||||||
|
frame_interior(output->frame, &options.area.x, &options.area.y,
|
||||||
|
&options.area.width, &options.area.height);
|
||||||
|
} else {
|
||||||
|
options.area.x = 0;
|
||||||
|
options.area.y = 0;
|
||||||
|
options.area.width = mode->width;
|
||||||
|
options.area.height = mode->height;
|
||||||
|
options.fb_size.width = mode->width;
|
||||||
|
options.fb_size.height = mode->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
|
||||||
|
weston_log("failed to create vulkan renderer output state\n");
|
||||||
|
if (output->frame) {
|
||||||
|
frame_destroy(output->frame);
|
||||||
|
output->frame = NULL;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->renderbuffer =
|
||||||
|
renderer->create_renderbuffer(&output->base, b->formats[0],
|
||||||
|
NULL, 0, NULL, NULL);
|
||||||
|
if (!output->renderbuffer)
|
||||||
|
goto err_renderbuffer;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_renderbuffer:
|
||||||
|
renderer->vulkan->output_destroy(&output->base);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
headless_output_enable_pixman(struct headless_output *output)
|
headless_output_enable_pixman(struct headless_output *output)
|
||||||
{
|
{
|
||||||
const struct pixman_renderer_interface *pixman;
|
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||||
const struct pixman_renderer_output_options options = {
|
const struct pixman_renderer_output_options options = {
|
||||||
.use_shadow = true,
|
.use_shadow = true,
|
||||||
.fb_size = {
|
.fb_size = {
|
||||||
|
|
@ -328,22 +404,19 @@ headless_output_enable_pixman(struct headless_output *output)
|
||||||
.format = pixel_format_get_info(headless_formats[0])
|
.format = pixel_format_get_info(headless_formats[0])
|
||||||
};
|
};
|
||||||
|
|
||||||
pixman = output->base.compositor->renderer->pixman;
|
if (renderer->pixman->output_create(&output->base, &options) < 0)
|
||||||
|
|
||||||
if (pixman->output_create(&output->base, &options) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
output->renderbuffer =
|
output->renderbuffer =
|
||||||
pixman->create_image(&output->base, options.format,
|
renderer->create_renderbuffer(&output->base, options.format,
|
||||||
output->base.current_mode->width,
|
NULL, 0, NULL, NULL);
|
||||||
output->base.current_mode->height);
|
|
||||||
if (!output->renderbuffer)
|
if (!output->renderbuffer)
|
||||||
goto err_renderer;
|
goto err_renderer;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_renderer:
|
err_renderer:
|
||||||
pixman->output_destroy(&output->base);
|
renderer->pixman->output_destroy(&output->base);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -373,6 +446,9 @@ headless_output_enable(struct weston_output *base)
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
ret = headless_output_enable_gl(output);
|
ret = headless_output_enable_gl(output);
|
||||||
break;
|
break;
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
ret = headless_output_enable_vulkan(output);
|
||||||
|
break;
|
||||||
case WESTON_RENDERER_PIXMAN:
|
case WESTON_RENDERER_PIXMAN:
|
||||||
ret = headless_output_enable_pixman(output);
|
ret = headless_output_enable_pixman(output);
|
||||||
break;
|
break;
|
||||||
|
|
@ -390,6 +466,19 @@ headless_output_enable(struct weston_output *base)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
headless_set_dpms(struct weston_output *base, enum dpms_enum level)
|
||||||
|
{
|
||||||
|
struct headless_output *output = to_headless_output(base);
|
||||||
|
|
||||||
|
if (level == WESTON_DPMS_ON)
|
||||||
|
weston_output_schedule_repaint(base);
|
||||||
|
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
|
||||||
|
wl_event_source_timer_update(output->finish_frame_timer, 0);
|
||||||
|
weston_output_schedule_repaint_reset(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
headless_output_set_size(struct weston_output *base,
|
headless_output_set_size(struct weston_output *base,
|
||||||
int width, int height)
|
int width, int height)
|
||||||
|
|
@ -431,7 +520,7 @@ headless_output_set_size(struct weston_output *base,
|
||||||
output->base.repaint = headless_output_repaint;
|
output->base.repaint = headless_output_repaint;
|
||||||
output->base.assign_planes = NULL;
|
output->base.assign_planes = NULL;
|
||||||
output->base.set_backlight = NULL;
|
output->base.set_backlight = NULL;
|
||||||
output->base.set_dpms = NULL;
|
output->base.set_dpms = headless_set_dpms;
|
||||||
output->base.switch_mode = NULL;
|
output->base.switch_mode = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -511,6 +600,25 @@ headless_head_destroy(struct weston_head *base)
|
||||||
free(head);
|
free(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
headless_input_create(struct headless_backend *b)
|
||||||
|
{
|
||||||
|
weston_seat_init(&b->fake_seat, b->compositor, "default");
|
||||||
|
|
||||||
|
weston_seat_init_pointer(&b->fake_seat);
|
||||||
|
|
||||||
|
if (weston_seat_init_keyboard(&b->fake_seat, NULL) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
headless_input_destroy(struct headless_backend *b)
|
||||||
|
{
|
||||||
|
weston_seat_release(&b->fake_seat);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
headless_destroy(struct weston_backend *backend)
|
headless_destroy(struct weston_backend *backend)
|
||||||
{
|
{
|
||||||
|
|
@ -528,6 +636,9 @@ headless_destroy(struct weston_backend *backend)
|
||||||
if (b->theme)
|
if (b->theme)
|
||||||
theme_destroy(b->theme);
|
theme_destroy(b->theme);
|
||||||
|
|
||||||
|
if (b->use_fake_seat)
|
||||||
|
headless_input_destroy(b);
|
||||||
|
|
||||||
free(b->formats);
|
free(b->formats);
|
||||||
free(b);
|
free(b);
|
||||||
|
|
||||||
|
|
@ -559,6 +670,12 @@ headless_backend_create(struct weston_compositor *compositor,
|
||||||
b->base.supported_presentation_clocks =
|
b->base.supported_presentation_clocks =
|
||||||
WESTON_PRESENTATION_CLOCKS_SOFTWARE;
|
WESTON_PRESENTATION_CLOCKS_SOFTWARE;
|
||||||
|
|
||||||
|
if (config->fake_seat) {
|
||||||
|
b->use_fake_seat = headless_input_create(b);
|
||||||
|
if (!b->use_fake_seat)
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
b->base.destroy = headless_destroy;
|
b->base.destroy = headless_destroy;
|
||||||
b->base.create_output = headless_output_create;
|
b->base.create_output = headless_output_create;
|
||||||
|
|
||||||
|
|
@ -600,6 +717,16 @@ headless_backend_create(struct weston_compositor *compositor,
|
||||||
&options.base);
|
&options.base);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WESTON_RENDERER_VULKAN: {
|
||||||
|
const struct vulkan_renderer_display_options options = {
|
||||||
|
.formats = b->formats,
|
||||||
|
.formats_count = b->formats_count,
|
||||||
|
};
|
||||||
|
ret = weston_compositor_init_renderer(compositor,
|
||||||
|
WESTON_RENDERER_VULKAN,
|
||||||
|
&options.base);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case WESTON_RENDERER_PIXMAN:
|
case WESTON_RENDERER_PIXMAN:
|
||||||
if (config->decorate) {
|
if (config->decorate) {
|
||||||
weston_log("Error: Pixman renderer does not support decorations.\n");
|
weston_log("Error: Pixman renderer does not support decorations.\n");
|
||||||
|
|
@ -647,6 +774,8 @@ err_input:
|
||||||
if (b->theme)
|
if (b->theme)
|
||||||
theme_destroy(b->theme);
|
theme_destroy(b->theme);
|
||||||
err_free:
|
err_free:
|
||||||
|
if (b->use_fake_seat)
|
||||||
|
headless_input_destroy(b);
|
||||||
wl_list_remove(&b->base.link);
|
wl_list_remove(&b->base.link);
|
||||||
free(b);
|
free(b);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -656,6 +785,7 @@ static void
|
||||||
config_init_to_defaults(struct weston_headless_backend_config *config)
|
config_init_to_defaults(struct weston_headless_backend_config *config)
|
||||||
{
|
{
|
||||||
config->refresh = DEFAULT_OUTPUT_REPAINT_REFRESH;
|
config->refresh = DEFAULT_OUTPUT_REPAINT_REFRESH;
|
||||||
|
config->fake_seat = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
WL_EXPORT int
|
WL_EXPORT int
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ plugin_headless = shared_library(
|
||||||
dep_libweston_private,
|
dep_libweston_private,
|
||||||
dep_libdrm_headers,
|
dep_libdrm_headers,
|
||||||
dep_lib_cairo_shared,
|
dep_lib_cairo_shared,
|
||||||
dep_lib_gl_borders,
|
dep_lib_renderer_borders,
|
||||||
],
|
],
|
||||||
name_prefix: '',
|
name_prefix: '',
|
||||||
install: true,
|
install: true,
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,11 @@
|
||||||
#include <libweston/backend-pipewire.h>
|
#include <libweston/backend-pipewire.h>
|
||||||
#include <libweston/linux-dmabuf.h>
|
#include <libweston/linux-dmabuf.h>
|
||||||
#include <libweston/weston-log.h>
|
#include <libweston/weston-log.h>
|
||||||
|
#include "output-capture.h"
|
||||||
#include "pixel-formats.h"
|
#include "pixel-formats.h"
|
||||||
#include "pixman-renderer.h"
|
#include "pixman-renderer.h"
|
||||||
#include "renderer-gl/gl-renderer.h"
|
#include "renderer-gl/gl-renderer.h"
|
||||||
|
#include "renderer-vulkan/vulkan-renderer.h"
|
||||||
#include "shared/weston-egl-ext.h"
|
#include "shared/weston-egl-ext.h"
|
||||||
|
|
||||||
struct pipewire_backend {
|
struct pipewire_backend {
|
||||||
|
|
@ -101,7 +103,7 @@ struct pipewire_head {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pipewire_frame_data {
|
struct pipewire_frame_data {
|
||||||
struct weston_renderbuffer *renderbuffer;
|
weston_renderbuffer_t renderbuffer;
|
||||||
struct pipewire_memfd *memfd;
|
struct pipewire_memfd *memfd;
|
||||||
struct pipewire_dmabuf *dmabuf;
|
struct pipewire_dmabuf *dmabuf;
|
||||||
};
|
};
|
||||||
|
|
@ -266,14 +268,16 @@ pipewire_output_connect(struct pipewire_output *output)
|
||||||
/* TODO: Add support for modifier discovery and negotiation. */
|
/* TODO: Add support for modifier discovery and negotiation. */
|
||||||
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
|
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
|
||||||
params[i++] = spa_pod_build_format(&builder,
|
params[i++] = spa_pod_build_format(&builder,
|
||||||
output->base.width, output->base.height,
|
output->base.current_mode->width,
|
||||||
|
output->base.current_mode->height,
|
||||||
output->base.current_mode->refresh / 1000,
|
output->base.current_mode->refresh / 1000,
|
||||||
output->pixel_format->format,
|
output->pixel_format->format,
|
||||||
modifier);
|
modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
params[i++] = spa_pod_build_format(&builder,
|
params[i++] = spa_pod_build_format(&builder,
|
||||||
output->base.width, output->base.height,
|
output->base.current_mode->width,
|
||||||
|
output->base.current_mode->height,
|
||||||
output->base.current_mode->refresh / 1000,
|
output->base.current_mode->refresh / 1000,
|
||||||
output->pixel_format->format, NULL);
|
output->pixel_format->format, NULL);
|
||||||
|
|
||||||
|
|
@ -307,8 +311,8 @@ pipewire_output_enable_pixman(struct pipewire_output *output)
|
||||||
const struct pixman_renderer_output_options options = {
|
const struct pixman_renderer_output_options options = {
|
||||||
.use_shadow = true,
|
.use_shadow = true,
|
||||||
.fb_size = {
|
.fb_size = {
|
||||||
.width = output->base.width,
|
.width = output->base.current_mode->width,
|
||||||
.height = output->base.height,
|
.height = output->base.current_mode->height,
|
||||||
},
|
},
|
||||||
.format = output->pixel_format,
|
.format = output->pixel_format,
|
||||||
};
|
};
|
||||||
|
|
@ -347,6 +351,29 @@ pipewire_output_enable_gl(struct pipewire_output *output)
|
||||||
return renderer->gl->output_fbo_create(&output->base, &options);
|
return renderer->gl->output_fbo_create(&output->base, &options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pipewire_output_enable_vulkan(struct pipewire_output *output)
|
||||||
|
{
|
||||||
|
struct pipewire_backend *b = output->backend;
|
||||||
|
struct weston_renderer *renderer = b->compositor->renderer;
|
||||||
|
const struct weston_size fb_size = {
|
||||||
|
output->base.current_mode->width,
|
||||||
|
output->base.current_mode->height
|
||||||
|
};
|
||||||
|
const struct weston_geometry area = {
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = fb_size.width,
|
||||||
|
.height = fb_size.height
|
||||||
|
};
|
||||||
|
const struct vulkan_renderer_surfaceless_options options = {
|
||||||
|
.fb_size = fb_size,
|
||||||
|
.area = area,
|
||||||
|
};
|
||||||
|
|
||||||
|
return renderer->vulkan->output_surfaceless_create(&output->base, &options);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pipewire_output_disable_gl(struct pipewire_output *output)
|
pipewire_output_disable_gl(struct pipewire_output *output)
|
||||||
{
|
{
|
||||||
|
|
@ -355,6 +382,14 @@ pipewire_output_disable_gl(struct pipewire_output *output)
|
||||||
renderer->gl->output_destroy(&output->base);
|
renderer->gl->output_destroy(&output->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pipewire_output_disable_vulkan(struct pipewire_output *output)
|
||||||
|
{
|
||||||
|
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||||
|
|
||||||
|
renderer->vulkan->output_destroy(&output->base);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pipewire_output_enable(struct weston_output *base)
|
pipewire_output_enable(struct weston_output *base)
|
||||||
{
|
{
|
||||||
|
|
@ -373,6 +408,9 @@ pipewire_output_enable(struct weston_output *base)
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
ret = pipewire_output_enable_gl(output);
|
ret = pipewire_output_enable_gl(output);
|
||||||
break;
|
break;
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
ret = pipewire_output_enable_vulkan(output);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
unreachable("Valid renderer should have been selected");
|
unreachable("Valid renderer should have been selected");
|
||||||
}
|
}
|
||||||
|
|
@ -398,6 +436,9 @@ err:
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
pipewire_output_disable_gl(output);
|
pipewire_output_disable_gl(output);
|
||||||
break;
|
break;
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
pipewire_output_disable_vulkan(output);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
unreachable("Valid renderer should have been selected");
|
unreachable("Valid renderer should have been selected");
|
||||||
}
|
}
|
||||||
|
|
@ -426,6 +467,9 @@ pipewire_output_disable(struct weston_output *base)
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
pipewire_output_disable_gl(output);
|
pipewire_output_disable_gl(output);
|
||||||
break;
|
break;
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
pipewire_output_disable_vulkan(output);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
unreachable("Valid renderer should have been selected");
|
unreachable("Valid renderer should have been selected");
|
||||||
}
|
}
|
||||||
|
|
@ -490,8 +534,8 @@ pipewire_output_create_dmabuf(struct pipewire_output *output)
|
||||||
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
|
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
|
||||||
|
|
||||||
format = output->pixel_format;
|
format = output->pixel_format;
|
||||||
width = output->base.width;
|
width = output->base.current_mode->width;
|
||||||
height = output->base.height;
|
height = output->base.current_mode->height;
|
||||||
|
|
||||||
linux_dmabuf_memory = renderer->dmabuf_alloc(renderer, width, height,
|
linux_dmabuf_memory = renderer->dmabuf_alloc(renderer, width, height,
|
||||||
format->format,
|
format->format,
|
||||||
|
|
@ -593,59 +637,6 @@ pipewire_output_stream_param_changed(void *data, uint32_t id,
|
||||||
pw_stream_update_params(output->stream, params, 2);
|
pw_stream_update_params(output->stream, params, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct weston_renderbuffer *
|
|
||||||
pipewire_output_stream_add_buffer_pixman(struct pipewire_output *output,
|
|
||||||
struct pw_buffer *buffer)
|
|
||||||
{
|
|
||||||
struct weston_compositor *ec = output->base.compositor;
|
|
||||||
const struct weston_renderer *renderer = ec->renderer;
|
|
||||||
struct spa_buffer *buf = buffer->buffer;
|
|
||||||
struct spa_data *d = buf->datas;
|
|
||||||
const struct pixel_format_info *format;
|
|
||||||
unsigned int width;
|
|
||||||
unsigned int height;
|
|
||||||
unsigned int stride;
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
format = output->pixel_format;
|
|
||||||
width = output->base.width;
|
|
||||||
height = output->base.height;
|
|
||||||
stride = width * format->bpp / 8;
|
|
||||||
ptr = d[0].data;
|
|
||||||
|
|
||||||
return renderer->pixman->create_image_from_ptr(&output->base,
|
|
||||||
format, width, height,
|
|
||||||
ptr, stride);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct weston_renderbuffer *
|
|
||||||
pipewire_output_stream_add_buffer_gl(struct pipewire_output *output,
|
|
||||||
struct pw_buffer *buffer)
|
|
||||||
{
|
|
||||||
struct weston_compositor *ec = output->base.compositor;
|
|
||||||
const struct weston_renderer *renderer = ec->renderer;
|
|
||||||
struct spa_buffer *buf = buffer->buffer;
|
|
||||||
struct spa_data *d = buf->datas;
|
|
||||||
const struct pixel_format_info *format;
|
|
||||||
unsigned int width;
|
|
||||||
unsigned int height;
|
|
||||||
void *ptr;
|
|
||||||
struct pipewire_frame_data *frame_data = buffer->user_data;
|
|
||||||
struct pipewire_dmabuf *dmabuf = frame_data->dmabuf;
|
|
||||||
|
|
||||||
if (dmabuf)
|
|
||||||
return renderer->create_renderbuffer_dmabuf(&output->base,
|
|
||||||
dmabuf->linux_dmabuf_memory);
|
|
||||||
|
|
||||||
format = output->pixel_format;
|
|
||||||
width = output->base.width;
|
|
||||||
height = output->base.height;
|
|
||||||
ptr = d[0].data;
|
|
||||||
|
|
||||||
return renderer->gl->create_fbo(&output->base,
|
|
||||||
format, width, height, ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pipewire_memfd {
|
struct pipewire_memfd {
|
||||||
int fd;
|
int fd;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
|
@ -665,8 +656,8 @@ pipewire_output_create_memfd(struct pipewire_output *output)
|
||||||
memfd = xzalloc(sizeof *memfd);
|
memfd = xzalloc(sizeof *memfd);
|
||||||
|
|
||||||
format = output->pixel_format;
|
format = output->pixel_format;
|
||||||
width = output->base.width;
|
width = output->base.current_mode->width;
|
||||||
height = output->base.height;
|
height = output->base.current_mode->height;
|
||||||
stride = width * format->bpp / 8;
|
stride = width * format->bpp / 8;
|
||||||
size = height * stride;
|
size = height * stride;
|
||||||
|
|
||||||
|
|
@ -755,8 +746,15 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pipewire_output_setup_dmabuf(output, buffer, dmabuf);
|
pipewire_output_setup_dmabuf(output, buffer, dmabuf);
|
||||||
|
|
||||||
|
frame_data->renderbuffer =
|
||||||
|
renderer->create_renderbuffer_dmabuf(&output->base,
|
||||||
|
dmabuf->linux_dmabuf_memory,
|
||||||
|
NULL, NULL);
|
||||||
frame_data->dmabuf = dmabuf;
|
frame_data->dmabuf = dmabuf;
|
||||||
} else if (buffertype & (1u << SPA_DATA_MemFd)) {
|
} else if (buffertype & (1u << SPA_DATA_MemFd)) {
|
||||||
|
const struct pixel_format_info *format = output->pixel_format;
|
||||||
|
int stride = output->base.current_mode->width * format->bpp / 8;
|
||||||
struct pipewire_memfd *memfd;
|
struct pipewire_memfd *memfd;
|
||||||
|
|
||||||
memfd = pipewire_output_create_memfd(output);
|
memfd = pipewire_output_create_memfd(output);
|
||||||
|
|
@ -766,18 +764,12 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pipewire_output_setup_memfd(output, buffer, memfd);
|
pipewire_output_setup_memfd(output, buffer, memfd);
|
||||||
frame_data->memfd = memfd;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (renderer->type) {
|
frame_data->renderbuffer =
|
||||||
case WESTON_RENDERER_PIXMAN:
|
renderer->create_renderbuffer(&output->base, format,
|
||||||
frame_data->renderbuffer = pipewire_output_stream_add_buffer_pixman(output, buffer);
|
d[0].data, stride, NULL,
|
||||||
break;
|
NULL);
|
||||||
case WESTON_RENDERER_GL:
|
frame_data->memfd = memfd;
|
||||||
frame_data->renderbuffer = pipewire_output_stream_add_buffer_gl(output, buffer);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
unreachable("Valid renderer should have been selected");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -800,21 +792,20 @@ pipewire_output_stream_remove_buffer(void *data, struct pw_buffer *buffer)
|
||||||
|
|
||||||
pipewire_output_debug(output, "remove buffer: %p", buffer);
|
pipewire_output_debug(output, "remove buffer: %p", buffer);
|
||||||
|
|
||||||
if (frame_data->dmabuf) {
|
if (frame_data->dmabuf)
|
||||||
struct weston_compositor *ec = output->base.compositor;
|
|
||||||
const struct weston_renderer *renderer = ec->renderer;
|
|
||||||
|
|
||||||
renderer->remove_renderbuffer_dmabuf(&output->base,
|
|
||||||
frame_data->renderbuffer);
|
|
||||||
pipewire_destroy_dmabuf(output, frame_data->dmabuf);
|
pipewire_destroy_dmabuf(output, frame_data->dmabuf);
|
||||||
}
|
|
||||||
if (frame_data->memfd) {
|
if (frame_data->memfd) {
|
||||||
munmap(d[0].data, d[0].maxsize);
|
munmap(d[0].data, d[0].maxsize);
|
||||||
pipewire_destroy_memfd(output, frame_data->memfd);
|
pipewire_destroy_memfd(output, frame_data->memfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame_data->renderbuffer)
|
if (frame_data->renderbuffer) {
|
||||||
weston_renderbuffer_unref(frame_data->renderbuffer);
|
struct weston_compositor *ec = output->base.compositor;
|
||||||
|
const struct weston_renderer *renderer = ec->renderer;
|
||||||
|
|
||||||
|
renderer->destroy_renderbuffer(frame_data->renderbuffer);
|
||||||
|
}
|
||||||
wl_list_for_each(fence_data, &output->fence_list, link) {
|
wl_list_for_each(fence_data, &output->fence_list, link) {
|
||||||
if (fence_data->buffer == buffer)
|
if (fence_data->buffer == buffer)
|
||||||
fence_data->buffer = NULL;
|
fence_data->buffer = NULL;
|
||||||
|
|
@ -955,7 +946,7 @@ pipewire_submit_buffer(struct pipewire_output *output,
|
||||||
if (dmabuf)
|
if (dmabuf)
|
||||||
stride = dmabuf->linux_dmabuf_memory->attributes->stride[0];
|
stride = dmabuf->linux_dmabuf_memory->attributes->stride[0];
|
||||||
else
|
else
|
||||||
stride = output->base.width * pixel_format->bpp / 8;
|
stride = output->base.current_mode->width * pixel_format->bpp / 8;
|
||||||
size = output->base.height * stride;
|
size = output->base.height * stride;
|
||||||
|
|
||||||
spa_buffer = buffer->buffer;
|
spa_buffer = buffer->buffer;
|
||||||
|
|
@ -1008,9 +999,20 @@ pipewire_schedule_submit_buffer(struct pipewire_output *output,
|
||||||
struct wl_event_loop *loop;
|
struct wl_event_loop *loop;
|
||||||
int fence_sync_fd;
|
int fence_sync_fd;
|
||||||
|
|
||||||
fence_sync_fd = renderer->gl->create_fence_fd(&output->base);
|
switch (renderer->type) {
|
||||||
if (fence_sync_fd == -1)
|
case WESTON_RENDERER_GL:
|
||||||
return -1;
|
fence_sync_fd = renderer->gl->create_fence_fd(&output->base);
|
||||||
|
if (fence_sync_fd == -1)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
fence_sync_fd = renderer->vulkan->create_fence_fd(&output->base);
|
||||||
|
if (fence_sync_fd == -1)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unreachable("invalid renderer");
|
||||||
|
}
|
||||||
|
|
||||||
fence_data = zalloc(sizeof *fence_data);
|
fence_data = zalloc(sizeof *fence_data);
|
||||||
if (!fence_data) {
|
if (!fence_data) {
|
||||||
|
|
@ -1042,6 +1044,7 @@ pipewire_output_repaint(struct weston_output *base)
|
||||||
struct pipewire_frame_data *frame_data;
|
struct pipewire_frame_data *frame_data;
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
bool submit_scheduled = false;
|
bool submit_scheduled = false;
|
||||||
|
bool rendered = false;
|
||||||
|
|
||||||
assert(output);
|
assert(output);
|
||||||
|
|
||||||
|
|
@ -1052,7 +1055,8 @@ pipewire_output_repaint(struct weston_output *base)
|
||||||
|
|
||||||
weston_output_flush_damage_for_primary_plane(base, &damage);
|
weston_output_flush_damage_for_primary_plane(base, &damage);
|
||||||
|
|
||||||
if (!pixman_region32_not_empty(&damage))
|
if (!pixman_region32_not_empty(&damage) &&
|
||||||
|
!weston_output_has_renderer_capture_tasks(base))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
buffer = pw_stream_dequeue_buffer(output->stream);
|
buffer = pw_stream_dequeue_buffer(output->stream);
|
||||||
|
|
@ -1063,9 +1067,10 @@ pipewire_output_repaint(struct weston_output *base)
|
||||||
pipewire_output_debug(output, "dequeued buffer: %p", buffer);
|
pipewire_output_debug(output, "dequeued buffer: %p", buffer);
|
||||||
|
|
||||||
frame_data = buffer->user_data;
|
frame_data = buffer->user_data;
|
||||||
if (frame_data->renderbuffer)
|
if (frame_data->renderbuffer) {
|
||||||
ec->renderer->repaint_output(&output->base, &damage, frame_data->renderbuffer);
|
ec->renderer->repaint_output(&output->base, &damage, frame_data->renderbuffer);
|
||||||
else
|
rendered = true;
|
||||||
|
} else
|
||||||
output->base.full_repaint_needed = true;
|
output->base.full_repaint_needed = true;
|
||||||
|
|
||||||
if (buffer->buffer->datas[0].type == SPA_DATA_DmaBuf) {
|
if (buffer->buffer->datas[0].type == SPA_DATA_DmaBuf) {
|
||||||
|
|
@ -1076,6 +1081,21 @@ pipewire_output_repaint(struct weston_output *base)
|
||||||
pipewire_submit_buffer(output, buffer);
|
pipewire_submit_buffer(output, buffer);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
/* We didn't have anywhere to render to, so capture tasks could be
|
||||||
|
* left dangling. Shoot them down.
|
||||||
|
*/
|
||||||
|
if (!rendered && weston_output_has_renderer_capture_tasks(base)) {
|
||||||
|
int width = base->current_mode->width;
|
||||||
|
int height = base->current_mode->height;
|
||||||
|
struct weston_capture_task *ct;
|
||||||
|
|
||||||
|
while ((ct = weston_output_pull_capture_task(base,
|
||||||
|
WESTON_OUTPUT_CAPTURE_SOURCE_FRAMEBUFFER,
|
||||||
|
width, height,
|
||||||
|
ec->read_format,
|
||||||
|
NULL)))
|
||||||
|
weston_capture_task_retire_failed(ct, "No pipewire buffer");
|
||||||
|
}
|
||||||
|
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
|
|
||||||
|
|
@ -1116,6 +1136,19 @@ pipewire_ensure_matching_mode(struct weston_output *output, struct weston_mode *
|
||||||
target->refresh);
|
target->refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pipewire_set_dpms(struct weston_output *base, enum dpms_enum level)
|
||||||
|
{
|
||||||
|
struct pipewire_output *output = to_pipewire_output(base);
|
||||||
|
|
||||||
|
if (level == WESTON_DPMS_ON)
|
||||||
|
weston_output_schedule_repaint(base);
|
||||||
|
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
|
||||||
|
wl_event_source_timer_update(output->finish_frame_timer, 0);
|
||||||
|
weston_output_schedule_repaint_reset(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
|
pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
|
||||||
{
|
{
|
||||||
|
|
@ -1129,7 +1162,8 @@ pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode
|
||||||
|
|
||||||
base->current_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
|
base->current_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
|
||||||
|
|
||||||
base->current_mode = base->native_mode = local_mode;
|
base->current_mode = local_mode;
|
||||||
|
weston_output_copy_native_mode(base, local_mode);
|
||||||
base->current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
|
base->current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
|
||||||
|
|
||||||
fb_size.width = target_mode->width;
|
fb_size.width = target_mode->width;
|
||||||
|
|
@ -1141,14 +1175,13 @@ pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pipewire_output_set_size(struct weston_output *base, int width, int height)
|
pipewire_output_set_size(struct weston_output *base, int width, int height, int framerate)
|
||||||
{
|
{
|
||||||
struct pipewire_output *output = to_pipewire_output(base);
|
struct pipewire_output *output = to_pipewire_output(base);
|
||||||
struct weston_head *head;
|
struct weston_head *head;
|
||||||
struct pipewire_head *pw_head;
|
struct pipewire_head *pw_head;
|
||||||
struct weston_mode *current_mode;
|
struct weston_mode *current_mode;
|
||||||
struct weston_mode init_mode;
|
struct weston_mode init_mode;
|
||||||
int framerate = -1;
|
|
||||||
|
|
||||||
/* We can only be called once. */
|
/* We can only be called once. */
|
||||||
assert(!output->base.current_mode);
|
assert(!output->base.current_mode);
|
||||||
|
|
@ -1160,7 +1193,8 @@ pipewire_output_set_size(struct weston_output *base, int width, int height)
|
||||||
width = pw_head->config.width;
|
width = pw_head->config.width;
|
||||||
if (height == -1)
|
if (height == -1)
|
||||||
height = pw_head->config.height;
|
height = pw_head->config.height;
|
||||||
framerate = pw_head->config.framerate;
|
if (framerate == -1)
|
||||||
|
framerate = pw_head->config.framerate;
|
||||||
}
|
}
|
||||||
if (framerate == -1 || width == -1 || height == -1)
|
if (framerate == -1 || width == -1 || height == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -1172,13 +1206,13 @@ pipewire_output_set_size(struct weston_output *base, int width, int height)
|
||||||
current_mode = pipewire_ensure_matching_mode(&output->base, &init_mode);
|
current_mode = pipewire_ensure_matching_mode(&output->base, &init_mode);
|
||||||
current_mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
|
current_mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
|
||||||
|
|
||||||
output->base.current_mode = output->base.native_mode = current_mode;
|
output->base.current_mode = current_mode;
|
||||||
|
weston_output_copy_native_mode(base, current_mode);
|
||||||
output->base.start_repaint_loop = pipewire_output_start_repaint_loop;
|
output->base.start_repaint_loop = pipewire_output_start_repaint_loop;
|
||||||
output->base.repaint = pipewire_output_repaint;
|
output->base.repaint = pipewire_output_repaint;
|
||||||
output->base.assign_planes = NULL;
|
output->base.assign_planes = NULL;
|
||||||
output->base.set_backlight = NULL;
|
output->base.set_backlight = NULL;
|
||||||
output->base.set_dpms = NULL;
|
output->base.set_dpms = pipewire_set_dpms;
|
||||||
output->base.switch_mode = pipewire_switch_mode;
|
output->base.switch_mode = pipewire_switch_mode;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1351,6 +1385,16 @@ pipewire_backend_create(struct weston_compositor *compositor,
|
||||||
&options.base);
|
&options.base);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WESTON_RENDERER_VULKAN: {
|
||||||
|
const struct vulkan_renderer_display_options options = {
|
||||||
|
.formats = backend->formats,
|
||||||
|
.formats_count = backend->formats_count,
|
||||||
|
};
|
||||||
|
ret = weston_compositor_init_renderer(compositor,
|
||||||
|
WESTON_RENDERER_VULKAN,
|
||||||
|
&options.base);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
weston_log("Unsupported renderer requested\n");
|
weston_log("Unsupported renderer requested\n");
|
||||||
goto err_compositor;
|
goto err_compositor;
|
||||||
|
|
@ -1416,6 +1460,7 @@ weston_backend_init(struct weston_compositor *compositor,
|
||||||
switch (compositor->renderer->type) {
|
switch (compositor->renderer->type) {
|
||||||
case WESTON_RENDERER_PIXMAN:
|
case WESTON_RENDERER_PIXMAN:
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
weston_log("Renderer not supported by PipeWire backend\n");
|
weston_log("Renderer not supported by PipeWire backend\n");
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ dep_frdp2 = dependency('freerdp2', version: '>= 2.3.0', required: false)
|
||||||
|
|
||||||
if dep_frdp3.found()
|
if dep_frdp3.found()
|
||||||
config_h.set('USE_FREERDP_VERSION', '3')
|
config_h.set('USE_FREERDP_VERSION', '3')
|
||||||
|
config_h.set('WITHOUT_FREERDP_3x_DEPRECATED', '1')
|
||||||
dep_frdp = dep_frdp3
|
dep_frdp = dep_frdp3
|
||||||
dep_frdp_server = dependency('freerdp-server3', version: '>= 3.0.0', required: false)
|
dep_frdp_server = dependency('freerdp-server3', version: '>= 3.0.0', required: false)
|
||||||
if not dep_frdp_server.found()
|
if not dep_frdp_server.found()
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
#include <libweston/pixel-formats.h>
|
#include <libweston/pixel-formats.h>
|
||||||
#include "pixman-renderer.h"
|
#include "pixman-renderer.h"
|
||||||
#include "renderer-gl/gl-renderer.h"
|
#include "renderer-gl/gl-renderer.h"
|
||||||
|
#include "renderer-vulkan/vulkan-renderer.h"
|
||||||
#include "shared/weston-egl-ext.h"
|
#include "shared/weston-egl-ext.h"
|
||||||
|
|
||||||
/* These can be removed when we bump FreeRDP dependency past 3.0.0 in the future */
|
/* These can be removed when we bump FreeRDP dependency past 3.0.0 in the future */
|
||||||
|
|
@ -58,6 +59,12 @@
|
||||||
|
|
||||||
extern PWtsApiFunctionTable FreeRDP_InitWtsApi(void);
|
extern PWtsApiFunctionTable FreeRDP_InitWtsApi(void);
|
||||||
|
|
||||||
|
static struct rdp_buffer *
|
||||||
|
rdp_buffer_create(struct rdp_output *output);
|
||||||
|
|
||||||
|
static void
|
||||||
|
rdp_buffer_destroy(struct rdp_buffer *buffer);
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
xf_peer_adjust_monitor_layout(freerdp_peer *client);
|
xf_peer_adjust_monitor_layout(freerdp_peer *client);
|
||||||
|
|
||||||
|
|
@ -261,11 +268,11 @@ rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer)
|
||||||
rdpSettings *settings = peer->context->settings;
|
rdpSettings *settings = peer->context->settings;
|
||||||
|
|
||||||
if (freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec))
|
if (freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec))
|
||||||
rdp_peer_refresh_rfx(region, output->shadow_surface, peer);
|
rdp_peer_refresh_rfx(region, output->buffer->shadow_surface, peer);
|
||||||
else if (freerdp_settings_get_bool(settings, FreeRDP_NSCodec))
|
else if (freerdp_settings_get_bool(settings, FreeRDP_NSCodec))
|
||||||
rdp_peer_refresh_nsc(region, output->shadow_surface, peer);
|
rdp_peer_refresh_nsc(region, output->buffer->shadow_surface, peer);
|
||||||
else
|
else
|
||||||
rdp_peer_refresh_raw(region, output->shadow_surface, peer);
|
rdp_peer_refresh_raw(region, output->buffer->shadow_surface, peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
@ -295,7 +302,7 @@ rdp_output_repaint(struct weston_output *output_base)
|
||||||
weston_output_flush_damage_for_primary_plane(output_base, &damage);
|
weston_output_flush_damage_for_primary_plane(output_base, &damage);
|
||||||
|
|
||||||
ec->renderer->repaint_output(&output->base, &damage,
|
ec->renderer->repaint_output(&output->base, &damage,
|
||||||
output->renderbuffer);
|
output->buffer->rb);
|
||||||
|
|
||||||
if (pixman_region32_not_empty(&damage)) {
|
if (pixman_region32_not_empty(&damage)) {
|
||||||
pixman_region32_t transformed_damage;
|
pixman_region32_t transformed_damage;
|
||||||
|
|
@ -346,53 +353,15 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
|
||||||
struct weston_output *output = base;
|
struct weston_output *output = base;
|
||||||
struct rdp_peers_item *rdpPeer;
|
struct rdp_peers_item *rdpPeer;
|
||||||
rdpSettings *settings;
|
rdpSettings *settings;
|
||||||
struct weston_renderbuffer *new_renderbuffer;
|
|
||||||
|
|
||||||
mode->refresh = b->rdp_monitor_refresh_rate;
|
mode->refresh = b->rdp_monitor_refresh_rate;
|
||||||
weston_output_set_single_mode(base, mode);
|
weston_output_set_single_mode(base, mode);
|
||||||
|
|
||||||
if (base->enabled) {
|
if (base->enabled)
|
||||||
const struct weston_renderer *renderer;
|
|
||||||
pixman_image_t *new_image;
|
|
||||||
|
|
||||||
weston_renderer_resize_output(output, &(struct weston_size){
|
weston_renderer_resize_output(output, &(struct weston_size){
|
||||||
.width = output->current_mode->width,
|
.width = output->current_mode->width,
|
||||||
.height = output->current_mode->height }, NULL);
|
.height = output->current_mode->height }, NULL);
|
||||||
|
|
||||||
new_image = pixman_image_create_bits(b->formats[0]->pixman_format,
|
|
||||||
mode->width, mode->height,
|
|
||||||
NULL, mode->width * 4);
|
|
||||||
renderer = b->compositor->renderer;
|
|
||||||
switch (renderer->type) {
|
|
||||||
case WESTON_RENDERER_PIXMAN: {
|
|
||||||
const struct pixman_renderer_interface *pixman;
|
|
||||||
|
|
||||||
pixman = renderer->pixman;
|
|
||||||
new_renderbuffer =
|
|
||||||
pixman->create_image_from_ptr(output, b->formats[0],
|
|
||||||
mode->width, mode->height,
|
|
||||||
pixman_image_get_data(new_image),
|
|
||||||
mode->width * 4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WESTON_RENDERER_GL:
|
|
||||||
new_renderbuffer =
|
|
||||||
renderer->gl->create_fbo(output, b->formats[0],
|
|
||||||
mode->width, mode->height,
|
|
||||||
pixman_image_get_data(new_image));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
unreachable("cannot have auto renderer at runtime");
|
|
||||||
}
|
|
||||||
pixman_image_composite32(PIXMAN_OP_SRC, rdpOutput->shadow_surface,
|
|
||||||
0, new_image, 0, 0, 0, 0, 0, 0,
|
|
||||||
mode->width, mode->height);
|
|
||||||
weston_renderbuffer_unref(rdpOutput->renderbuffer);
|
|
||||||
rdpOutput->renderbuffer = new_renderbuffer;
|
|
||||||
pixman_image_unref(rdpOutput->shadow_surface);
|
|
||||||
rdpOutput->shadow_surface = new_image;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apparently settings->DesktopWidth is supposed to be primary only.
|
/* Apparently settings->DesktopWidth is supposed to be primary only.
|
||||||
* For now we only work with a single monitor, so we don't need to
|
* For now we only work with a single monitor, so we don't need to
|
||||||
* check that we're primary here.
|
* check that we're primary here.
|
||||||
|
|
@ -415,6 +384,19 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rdp_output_set_dpms(struct weston_output *base, enum dpms_enum level)
|
||||||
|
{
|
||||||
|
struct rdp_output *output = to_rdp_output(base);
|
||||||
|
|
||||||
|
if (level == WESTON_DPMS_ON)
|
||||||
|
weston_output_schedule_repaint(base);
|
||||||
|
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
|
||||||
|
wl_event_source_timer_update(output->finish_frame_timer, 0);
|
||||||
|
weston_output_schedule_repaint_reset(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rdp_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
|
rdp_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
|
||||||
{
|
{
|
||||||
|
|
@ -436,11 +418,88 @@ rdp_head_get_monitor(struct weston_head *base,
|
||||||
monitor->desktop_scale = h->config.attributes.desktopScaleFactor;
|
monitor->desktop_scale = h->config.attributes.desktopScaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
rdp_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
|
||||||
|
{
|
||||||
|
struct rdp_buffer *buffer = (struct rdp_buffer *) data;
|
||||||
|
struct rdp_output *output = buffer->output;
|
||||||
|
|
||||||
|
rdp_buffer_destroy(buffer);
|
||||||
|
output->buffer = rdp_buffer_create(output);
|
||||||
|
if (output->buffer == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rdp_buffer *
|
||||||
|
rdp_buffer_create(struct rdp_output *output)
|
||||||
|
{
|
||||||
|
const struct pixel_format_info *format = output->backend->formats[0];
|
||||||
|
struct weston_renderer *rdr = output->base.compositor->renderer;
|
||||||
|
pixman_image_t *shadow_surface;
|
||||||
|
weston_renderbuffer_t rb;
|
||||||
|
struct rdp_buffer *buffer;
|
||||||
|
|
||||||
|
shadow_surface = pixman_image_create_bits(format->pixman_format,
|
||||||
|
output->base.current_mode->width,
|
||||||
|
output->base.current_mode->height,
|
||||||
|
NULL,
|
||||||
|
output->base.current_mode->width * 4);
|
||||||
|
buffer = xmalloc(sizeof *buffer);
|
||||||
|
|
||||||
|
rb = rdr->create_renderbuffer(&output->base, format,
|
||||||
|
pixman_image_get_data(shadow_surface),
|
||||||
|
output->base.current_mode->width * 4,
|
||||||
|
rdp_rb_discarded_cb, buffer);
|
||||||
|
if (rb == NULL) {
|
||||||
|
weston_log("Failed to create offscreen renderbuffer.\n");
|
||||||
|
pixman_image_unref(shadow_surface);
|
||||||
|
free(buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->output = output;
|
||||||
|
buffer->shadow_surface = shadow_surface;
|
||||||
|
buffer->rb = rb;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rdp_buffer_destroy(struct rdp_buffer *buffer)
|
||||||
|
{
|
||||||
|
struct weston_renderer *rdr = buffer->output->base.compositor->renderer;
|
||||||
|
|
||||||
|
pixman_image_unref(buffer->shadow_surface);
|
||||||
|
rdr->destroy_renderbuffer(buffer->rb);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rdp_renderer_output_destroy(struct weston_output *base)
|
||||||
|
{
|
||||||
|
struct weston_renderer *rdr = base->compositor->renderer;
|
||||||
|
|
||||||
|
switch (rdr->type) {
|
||||||
|
case WESTON_RENDERER_PIXMAN:
|
||||||
|
rdr->pixman->output_destroy(base);
|
||||||
|
break;
|
||||||
|
case WESTON_RENDERER_GL:
|
||||||
|
rdr->gl->output_destroy(base);
|
||||||
|
break;
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
rdr->vulkan->output_destroy(base);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unreachable("cannot have auto renderer at runtime");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rdp_output_enable(struct weston_output *base)
|
rdp_output_enable(struct weston_output *base)
|
||||||
{
|
{
|
||||||
const struct weston_renderer *renderer = base->compositor->renderer;
|
const struct weston_renderer *renderer = base->compositor->renderer;
|
||||||
const struct pixman_renderer_interface *pixman = renderer->pixman;
|
|
||||||
struct rdp_output *output = to_rdp_output(base);
|
struct rdp_output *output = to_rdp_output(base);
|
||||||
struct rdp_backend *b;
|
struct rdp_backend *b;
|
||||||
struct wl_event_loop *loop;
|
struct wl_event_loop *loop;
|
||||||
|
|
@ -449,12 +508,6 @@ rdp_output_enable(struct weston_output *base)
|
||||||
|
|
||||||
b = output->backend;
|
b = output->backend;
|
||||||
|
|
||||||
output->shadow_surface = pixman_image_create_bits(b->formats[0]->pixman_format,
|
|
||||||
output->base.current_mode->width,
|
|
||||||
output->base.current_mode->height,
|
|
||||||
NULL,
|
|
||||||
output->base.current_mode->width * 4);
|
|
||||||
|
|
||||||
switch (renderer->type) {
|
switch (renderer->type) {
|
||||||
case WESTON_RENDERER_PIXMAN: {
|
case WESTON_RENDERER_PIXMAN: {
|
||||||
const struct pixman_renderer_output_options options = {
|
const struct pixman_renderer_output_options options = {
|
||||||
|
|
@ -465,23 +518,8 @@ rdp_output_enable(struct weston_output *base)
|
||||||
.format = b->formats[0],
|
.format = b->formats[0],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (renderer->pixman->output_create(&output->base, &options) < 0) {
|
if (renderer->pixman->output_create(&output->base, &options) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
output->renderbuffer =
|
|
||||||
pixman->create_image_from_ptr(&output->base, options.format,
|
|
||||||
output->base.current_mode->width,
|
|
||||||
output->base.current_mode->height,
|
|
||||||
pixman_image_get_data(output->shadow_surface),
|
|
||||||
output->base.current_mode->width * 4);
|
|
||||||
if (output->renderbuffer == NULL) {
|
|
||||||
weston_log("Failed to create surface for frame buffer.\n");
|
|
||||||
renderer->pixman->output_destroy(&output->base);
|
|
||||||
pixman_image_unref(output->shadow_surface);
|
|
||||||
output->shadow_surface = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WESTON_RENDERER_GL: {
|
case WESTON_RENDERER_GL: {
|
||||||
|
|
@ -496,19 +534,24 @@ rdp_output_enable(struct weston_output *base)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (renderer->gl->output_fbo_create(&output->base, &options) < 0)
|
if (renderer->gl->output_fbo_create(&output->base, &options) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WESTON_RENDERER_VULKAN: {
|
||||||
|
const struct vulkan_renderer_surfaceless_options options = {
|
||||||
|
.area = {
|
||||||
|
.width = output->base.current_mode->width,
|
||||||
|
.height = output->base.current_mode->height,
|
||||||
|
},
|
||||||
|
.fb_size = {
|
||||||
|
.width = output->base.current_mode->width,
|
||||||
|
.height = output->base.current_mode->height,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
output->renderbuffer =
|
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
|
||||||
renderer->gl->create_fbo(&output->base, b->formats[0],
|
|
||||||
output->base.current_mode->width,
|
|
||||||
output->base.current_mode->height,
|
|
||||||
pixman_image_get_data(output->shadow_surface));
|
|
||||||
if (output->renderbuffer == NULL) {
|
|
||||||
weston_log("Failed to create surface for frame buffer.\n");
|
|
||||||
renderer->pixman->output_destroy(&output->base);
|
|
||||||
pixman_image_unref(output->shadow_surface);
|
|
||||||
output->shadow_surface = NULL;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -517,6 +560,12 @@ rdp_output_enable(struct weston_output *base)
|
||||||
unreachable("cannot have auto renderer at runtime");
|
unreachable("cannot have auto renderer at runtime");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output->buffer = rdp_buffer_create(output);
|
||||||
|
if (output->buffer == NULL) {
|
||||||
|
rdp_renderer_output_destroy(base);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
loop = wl_display_get_event_loop(b->compositor->wl_display);
|
loop = wl_display_get_event_loop(b->compositor->wl_display);
|
||||||
output->finish_frame_timer = wl_event_loop_add_timer(loop, finish_frame_handler, output);
|
output->finish_frame_timer = wl_event_loop_add_timer(loop, finish_frame_handler, output);
|
||||||
|
|
||||||
|
|
@ -526,7 +575,6 @@ rdp_output_enable(struct weston_output *base)
|
||||||
static int
|
static int
|
||||||
rdp_output_disable(struct weston_output *base)
|
rdp_output_disable(struct weston_output *base)
|
||||||
{
|
{
|
||||||
struct weston_renderer *renderer = base->compositor->renderer;
|
|
||||||
struct rdp_output *output = to_rdp_output(base);
|
struct rdp_output *output = to_rdp_output(base);
|
||||||
|
|
||||||
assert(output);
|
assert(output);
|
||||||
|
|
@ -534,21 +582,9 @@ rdp_output_disable(struct weston_output *base)
|
||||||
if (!output->base.enabled)
|
if (!output->base.enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
weston_renderbuffer_unref(output->renderbuffer);
|
rdp_buffer_destroy(output->buffer);
|
||||||
output->renderbuffer = NULL;
|
output->buffer = NULL;
|
||||||
switch (renderer->type) {
|
rdp_renderer_output_destroy(base);
|
||||||
case WESTON_RENDERER_PIXMAN:
|
|
||||||
renderer->pixman->output_destroy(&output->base);
|
|
||||||
break;
|
|
||||||
case WESTON_RENDERER_GL:
|
|
||||||
renderer->gl->output_destroy(&output->base);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
unreachable("cannot have auto renderer at runtime");
|
|
||||||
}
|
|
||||||
pixman_image_unref(output->shadow_surface);
|
|
||||||
output->shadow_surface = NULL;
|
|
||||||
|
|
||||||
wl_event_source_remove(output->finish_frame_timer);
|
wl_event_source_remove(output->finish_frame_timer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -584,6 +620,7 @@ rdp_output_create(struct weston_backend *backend, const char *name)
|
||||||
|
|
||||||
output->base.start_repaint_loop = rdp_output_start_repaint_loop;
|
output->base.start_repaint_loop = rdp_output_start_repaint_loop;
|
||||||
output->base.repaint = rdp_output_repaint;
|
output->base.repaint = rdp_output_repaint;
|
||||||
|
output->base.set_dpms = rdp_output_set_dpms;
|
||||||
output->base.switch_mode = rdp_output_switch_mode;
|
output->base.switch_mode = rdp_output_switch_mode;
|
||||||
|
|
||||||
output->backend = b;
|
output->backend = b;
|
||||||
|
|
@ -985,6 +1022,9 @@ struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = {
|
||||||
{KBD_IRISH, 0, 0},
|
{KBD_IRISH, 0, 0},
|
||||||
{KBD_BOSNIAN_CYRILLIC, "ba", "us"},
|
{KBD_BOSNIAN_CYRILLIC, "ba", "us"},
|
||||||
{KBD_UNITED_STATES_DVORAK, "us", "dvorak"},
|
{KBD_UNITED_STATES_DVORAK, "us", "dvorak"},
|
||||||
|
{KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND, "us", "dvorak-l"},
|
||||||
|
{KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND, "us", "dvorak-r"},
|
||||||
|
{KBD_UNITED_STATES_DVORAK_PROGRAMMER, "us", "dvp"},
|
||||||
{KBD_PORTUGUESE_BRAZILIAN_ABNT2, "br", "abnt2"},
|
{KBD_PORTUGUESE_BRAZILIAN_ABNT2, "br", "abnt2"},
|
||||||
{KBD_CANADIAN_MULTILINGUAL_STANDARD, "ca", "multix"},
|
{KBD_CANADIAN_MULTILINGUAL_STANDARD, "ca", "multix"},
|
||||||
{KBD_GAELIC, "ie", "CloGaelach"},
|
{KBD_GAELIC, "ie", "CloGaelach"},
|
||||||
|
|
@ -1989,6 +2029,18 @@ rdp_backend_create(struct weston_compositor *compositor,
|
||||||
goto err_compositor;
|
goto err_compositor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WESTON_RENDERER_VULKAN: {
|
||||||
|
const struct vulkan_renderer_display_options options = {
|
||||||
|
.formats = b->formats,
|
||||||
|
.formats_count = b->formats_count,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (weston_compositor_init_renderer(compositor,
|
||||||
|
WESTON_RENDERER_VULKAN,
|
||||||
|
&options.base) < 0)
|
||||||
|
goto err_compositor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
weston_log("Unsupported renderer requested\n");
|
weston_log("Unsupported renderer requested\n");
|
||||||
goto err_free_strings;
|
goto err_free_strings;
|
||||||
|
|
@ -2113,6 +2165,7 @@ weston_backend_init(struct weston_compositor *compositor,
|
||||||
switch (compositor->renderer->type) {
|
switch (compositor->renderer->type) {
|
||||||
case WESTON_RENDERER_PIXMAN:
|
case WESTON_RENDERER_PIXMAN:
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
weston_log("Renderer not supported by RDP backend\n");
|
weston_log("Renderer not supported by RDP backend\n");
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,6 @@
|
||||||
#ifndef RDP_H
|
#ifndef RDP_H
|
||||||
#define RDP_H
|
#define RDP_H
|
||||||
|
|
||||||
/* Workaround an issue with clang and freerdp 3 headers. Another
|
|
||||||
* option would be to build with --std=c11 but weston itself isn't
|
|
||||||
* quite ready for that
|
|
||||||
*/
|
|
||||||
#if USE_FREERDP_VERSION >= 3 && defined(__clang__)
|
|
||||||
#pragma clang diagnostic ignored "-Wtypedef-redefinition"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <freerdp/version.h>
|
#include <freerdp/version.h>
|
||||||
|
|
||||||
#include <freerdp/freerdp.h>
|
#include <freerdp/freerdp.h>
|
||||||
|
|
@ -55,6 +47,7 @@
|
||||||
#include <winpr/string.h>
|
#include <winpr/string.h>
|
||||||
|
|
||||||
#include "backend.h"
|
#include "backend.h"
|
||||||
|
#include "libweston-internal.h"
|
||||||
|
|
||||||
#include "shared/helpers.h"
|
#include "shared/helpers.h"
|
||||||
#include "shared/string-helpers.h"
|
#include "shared/string-helpers.h"
|
||||||
|
|
@ -145,12 +138,17 @@ struct rdp_head {
|
||||||
rdpMonitor config;
|
rdpMonitor config;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rdp_buffer {
|
||||||
|
struct rdp_output *output;
|
||||||
|
pixman_image_t *shadow_surface;
|
||||||
|
weston_renderbuffer_t rb;
|
||||||
|
};
|
||||||
|
|
||||||
struct rdp_output {
|
struct rdp_output {
|
||||||
struct weston_output base;
|
struct weston_output base;
|
||||||
struct rdp_backend *backend;
|
struct rdp_backend *backend;
|
||||||
struct wl_event_source *finish_frame_timer;
|
struct wl_event_source *finish_frame_timer;
|
||||||
struct weston_renderbuffer *renderbuffer;
|
struct rdp_buffer *buffer;
|
||||||
pixman_image_t *shadow_surface;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rdp_peer_context {
|
struct rdp_peer_context {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ if not get_option('backend-vnc')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
config_h.set('BUILD_VNC_COMPOSITOR', '1')
|
config_h.set('BUILD_VNC_COMPOSITOR', '1')
|
||||||
dep_neatvnc = dependency('neatvnc', version: ['>= 0.7.0', '< 0.9.0'], required: false, fallback: ['neatvnc', 'neatvnc_dep'])
|
dep_neatvnc = dependency('neatvnc', version: ['>= 0.7.0', '< 0.10.0'], required: false, fallback: ['neatvnc', 'neatvnc_dep'])
|
||||||
if not dep_neatvnc.found()
|
if not dep_neatvnc.found()
|
||||||
error('VNC backend requires neatvnc which was not found. Or, you can use \'-Dbackend-vnc=false\'.')
|
error('VNC backend requires neatvnc which was not found. Or, you can use \'-Dbackend-vnc=false\'.')
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@
|
||||||
#include "pixel-formats.h"
|
#include "pixel-formats.h"
|
||||||
#include "pixman-renderer.h"
|
#include "pixman-renderer.h"
|
||||||
#include "renderer-gl/gl-renderer.h"
|
#include "renderer-gl/gl-renderer.h"
|
||||||
|
#include "renderer-vulkan/vulkan-renderer.h"
|
||||||
#include "shared/weston-egl-ext.h"
|
#include "shared/weston-egl-ext.h"
|
||||||
|
|
||||||
#define DEFAULT_AXIS_STEP_DISTANCE 10
|
#define DEFAULT_AXIS_STEP_DISTANCE 10
|
||||||
|
|
@ -108,9 +109,18 @@ struct vnc_head {
|
||||||
struct weston_head base;
|
struct weston_head base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct vnc_buffer {
|
||||||
|
weston_renderbuffer_t rb;
|
||||||
|
struct nvnc_fb *fb;
|
||||||
|
struct vnc_output *output;
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vnc_output_destroy(struct weston_output *base);
|
vnc_output_destroy(struct weston_output *base);
|
||||||
|
|
||||||
|
static void
|
||||||
|
vnc_buffer_destroy(struct vnc_buffer *buffer);
|
||||||
|
|
||||||
static inline struct vnc_output *
|
static inline struct vnc_output *
|
||||||
to_vnc_output(struct weston_output *base)
|
to_vnc_output(struct weston_output *base)
|
||||||
{
|
{
|
||||||
|
|
@ -653,8 +663,7 @@ vnc_log_scope_print_region(struct weston_log_scope *log, pixman_region32_t *regi
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *buffer_damage,
|
vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *damage)
|
||||||
pixman_region32_t *update_damage)
|
|
||||||
{
|
{
|
||||||
char timestr[128];
|
char timestr[128];
|
||||||
|
|
||||||
|
|
@ -663,15 +672,51 @@ vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *buffer_damage,
|
||||||
|
|
||||||
weston_log_scope_timestamp(backend->debug, timestr, sizeof timestr);
|
weston_log_scope_timestamp(backend->debug, timestr, sizeof timestr);
|
||||||
|
|
||||||
weston_log_scope_printf(backend->debug, "%s buffer damage:", timestr);
|
weston_log_scope_printf(backend->debug, "%s damage:", timestr);
|
||||||
vnc_log_scope_print_region(backend->debug, buffer_damage);
|
vnc_log_scope_print_region(backend->debug, damage);
|
||||||
weston_log_scope_printf(backend->debug, "\n");
|
|
||||||
|
|
||||||
weston_log_scope_printf(backend->debug, "%s update damage:", timestr);
|
|
||||||
vnc_log_scope_print_region(backend->debug, update_damage);
|
|
||||||
weston_log_scope_printf(backend->debug, "\n\n");
|
weston_log_scope_printf(backend->debug, "\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
vnc_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
|
||||||
|
{
|
||||||
|
struct vnc_buffer *buffer = (struct vnc_buffer *) data;
|
||||||
|
|
||||||
|
assert(nvnc_get_userdata(buffer->fb) == buffer);
|
||||||
|
|
||||||
|
nvnc_set_userdata(buffer->fb, NULL, NULL);
|
||||||
|
vnc_buffer_destroy(buffer);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct vnc_buffer *
|
||||||
|
vnc_buffer_create(struct nvnc_fb* fb, struct vnc_output *output)
|
||||||
|
{
|
||||||
|
const struct pixel_format_info *pfmt =
|
||||||
|
pixel_format_get_info(DRM_FORMAT_XRGB8888);
|
||||||
|
struct weston_renderer *rdr = output->base.compositor->renderer;
|
||||||
|
struct vnc_buffer *buffer = xmalloc(sizeof *buffer);
|
||||||
|
|
||||||
|
buffer->rb = rdr->create_renderbuffer(&output->base, pfmt,
|
||||||
|
nvnc_fb_get_addr(fb),
|
||||||
|
output->base.current_mode->width * 4,
|
||||||
|
vnc_rb_discarded_cb, buffer);
|
||||||
|
buffer->fb = fb;
|
||||||
|
buffer->output = output;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vnc_buffer_destroy(struct vnc_buffer *buffer)
|
||||||
|
{
|
||||||
|
struct weston_renderer *rdr = buffer->output->base.compositor->renderer;
|
||||||
|
|
||||||
|
rdr->destroy_renderbuffer(buffer->rb);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
|
vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
|
||||||
{
|
{
|
||||||
|
|
@ -679,7 +724,7 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
|
||||||
struct vnc_backend *backend = nvnc_get_userdata(server);
|
struct vnc_backend *backend = nvnc_get_userdata(server);
|
||||||
struct vnc_output *output = backend->output;
|
struct vnc_output *output = backend->output;
|
||||||
struct weston_compositor *ec = output->base.compositor;
|
struct weston_compositor *ec = output->base.compositor;
|
||||||
struct weston_renderbuffer *renderbuffer;
|
struct vnc_buffer *buffer;
|
||||||
pixman_region32_t local_damage;
|
pixman_region32_t local_damage;
|
||||||
pixman_region16_t nvnc_damage;
|
pixman_region16_t nvnc_damage;
|
||||||
struct nvnc_fb *fb;
|
struct nvnc_fb *fb;
|
||||||
|
|
@ -687,49 +732,16 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
|
||||||
fb = nvnc_fb_pool_acquire(output->fb_pool);
|
fb = nvnc_fb_pool_acquire(output->fb_pool);
|
||||||
assert(fb);
|
assert(fb);
|
||||||
|
|
||||||
renderbuffer = nvnc_get_userdata(fb);
|
buffer = nvnc_get_userdata(fb);
|
||||||
if (!renderbuffer) {
|
if (!buffer) {
|
||||||
const struct pixel_format_info *pfmt;
|
buffer = vnc_buffer_create(fb, output);
|
||||||
|
nvnc_set_userdata(fb, buffer,
|
||||||
pfmt = pixel_format_get_info(DRM_FORMAT_XRGB8888);
|
(nvnc_cleanup_fn) vnc_buffer_destroy);
|
||||||
|
|
||||||
switch (ec->renderer->type) {
|
|
||||||
case WESTON_RENDERER_PIXMAN: {
|
|
||||||
const struct pixman_renderer_interface *pixman;
|
|
||||||
|
|
||||||
pixman = ec->renderer->pixman;
|
|
||||||
|
|
||||||
renderbuffer =
|
|
||||||
pixman->create_image_from_ptr(&output->base, pfmt,
|
|
||||||
output->base.width,
|
|
||||||
output->base.height,
|
|
||||||
nvnc_fb_get_addr(fb),
|
|
||||||
output->base.width * 4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WESTON_RENDERER_GL: {
|
|
||||||
renderbuffer =
|
|
||||||
ec->renderer->gl->create_fbo(&output->base, pfmt,
|
|
||||||
output->base.width,
|
|
||||||
output->base.height,
|
|
||||||
nvnc_fb_get_addr(fb));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
unreachable("cannot have auto renderer at runtime");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is a new buffer, so the whole surface is damaged. */
|
|
||||||
pixman_region32_copy(&renderbuffer->damage,
|
|
||||||
&output->base.region);
|
|
||||||
|
|
||||||
nvnc_set_userdata(fb, renderbuffer,
|
|
||||||
(nvnc_cleanup_fn)weston_renderbuffer_unref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vnc_log_damage(backend, &renderbuffer->damage, damage);
|
vnc_log_damage(backend, damage);
|
||||||
|
|
||||||
ec->renderer->repaint_output(&output->base, damage, renderbuffer);
|
ec->renderer->repaint_output(&output->base, damage, buffer->rb);
|
||||||
|
|
||||||
/* Convert to local coordinates */
|
/* Convert to local coordinates */
|
||||||
pixman_region32_init(&local_damage);
|
pixman_region32_init(&local_damage);
|
||||||
|
|
@ -809,8 +821,8 @@ vnc_output_enable(struct weston_output *base)
|
||||||
case WESTON_RENDERER_PIXMAN: {
|
case WESTON_RENDERER_PIXMAN: {
|
||||||
const struct pixman_renderer_output_options options = {
|
const struct pixman_renderer_output_options options = {
|
||||||
.fb_size = {
|
.fb_size = {
|
||||||
.width = output->base.width,
|
.width = output->base.current_mode->width,
|
||||||
.height = output->base.height,
|
.height = output->base.current_mode->height,
|
||||||
},
|
},
|
||||||
.format = backend->formats[0],
|
.format = backend->formats[0],
|
||||||
};
|
};
|
||||||
|
|
@ -821,18 +833,33 @@ vnc_output_enable(struct weston_output *base)
|
||||||
case WESTON_RENDERER_GL: {
|
case WESTON_RENDERER_GL: {
|
||||||
const struct gl_renderer_fbo_options options = {
|
const struct gl_renderer_fbo_options options = {
|
||||||
.area = {
|
.area = {
|
||||||
.width = output->base.width,
|
.width = output->base.current_mode->width,
|
||||||
.height = output->base.height,
|
.height = output->base.current_mode->height,
|
||||||
},
|
},
|
||||||
.fb_size = {
|
.fb_size = {
|
||||||
.width = output->base.width,
|
.width = output->base.current_mode->width,
|
||||||
.height = output->base.height,
|
.height = output->base.current_mode->height,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if (renderer->gl->output_fbo_create(&output->base, &options) < 0)
|
if (renderer->gl->output_fbo_create(&output->base, &options) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WESTON_RENDERER_VULKAN: {
|
||||||
|
const struct vulkan_renderer_surfaceless_options options = {
|
||||||
|
.area = {
|
||||||
|
.width = output->base.current_mode->width,
|
||||||
|
.height = output->base.current_mode->height,
|
||||||
|
},
|
||||||
|
.fb_size = {
|
||||||
|
.width = output->base.current_mode->width,
|
||||||
|
.height = output->base.current_mode->height,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
unreachable("cannot have auto renderer at runtime");
|
unreachable("cannot have auto renderer at runtime");
|
||||||
}
|
}
|
||||||
|
|
@ -842,10 +869,10 @@ vnc_output_enable(struct weston_output *base)
|
||||||
finish_frame_handler,
|
finish_frame_handler,
|
||||||
output);
|
output);
|
||||||
|
|
||||||
output->fb_pool = nvnc_fb_pool_new(output->base.width,
|
output->fb_pool = nvnc_fb_pool_new(output->base.current_mode->width,
|
||||||
output->base.height,
|
output->base.current_mode->height,
|
||||||
backend->formats[0]->format,
|
backend->formats[0]->format,
|
||||||
output->base.width);
|
output->base.current_mode->width);
|
||||||
|
|
||||||
output->display = nvnc_display_new(0, 0);
|
output->display = nvnc_display_new(0, 0);
|
||||||
|
|
||||||
|
|
@ -879,6 +906,9 @@ vnc_output_disable(struct weston_output *base)
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
renderer->gl->output_destroy(&output->base);
|
renderer->gl->output_destroy(&output->base);
|
||||||
break;
|
break;
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
renderer->vulkan->output_destroy(&output->base);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
unreachable("cannot have auto renderer at runtime");
|
unreachable("cannot have auto renderer at runtime");
|
||||||
}
|
}
|
||||||
|
|
@ -1052,6 +1082,9 @@ vnc_output_assign_planes(struct weston_output *base)
|
||||||
|
|
||||||
assert(output);
|
assert(output);
|
||||||
|
|
||||||
|
if (output->base.disable_planes)
|
||||||
|
return;
|
||||||
|
|
||||||
if (wl_list_empty(&output->peers))
|
if (wl_list_empty(&output->peers))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -1060,6 +1093,19 @@ vnc_output_assign_planes(struct weston_output *base)
|
||||||
vnc_output_assign_cursor_plane(output);
|
vnc_output_assign_cursor_plane(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vnc_set_dpms(struct weston_output *base, enum dpms_enum level)
|
||||||
|
{
|
||||||
|
struct vnc_output *output = to_vnc_output(base);
|
||||||
|
|
||||||
|
if (level == WESTON_DPMS_ON)
|
||||||
|
weston_output_schedule_repaint(base);
|
||||||
|
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
|
||||||
|
wl_event_source_timer_update(output->finish_frame_timer, 0);
|
||||||
|
weston_output_schedule_repaint_reset(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vnc_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
|
vnc_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
|
||||||
{
|
{
|
||||||
|
|
@ -1073,7 +1119,14 @@ vnc_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
|
||||||
fb_size.width = target_mode->width;
|
fb_size.width = target_mode->width;
|
||||||
fb_size.height = target_mode->height;
|
fb_size.height = target_mode->height;
|
||||||
|
|
||||||
weston_renderer_resize_output(base, &fb_size, NULL);
|
/* vnc_buffers are stored as user data pointers into the renderbuffers
|
||||||
|
* for the discarded callback. weston_renderer_resize_output(), which
|
||||||
|
* triggers the renderbuffer's discarded callbacks, must be called
|
||||||
|
* before nvnc_fb_pool_resize(), which destroys all the nvnc_fbs and
|
||||||
|
* their associated vnc_buffers, so that the vnc_buffers are valid at
|
||||||
|
* callback. */
|
||||||
|
if (!weston_renderer_resize_output(base, &fb_size, NULL))
|
||||||
|
return -1;
|
||||||
|
|
||||||
nvnc_fb_pool_resize(output->fb_pool, target_mode->width,
|
nvnc_fb_pool_resize(output->fb_pool, target_mode->width,
|
||||||
target_mode->height, DRM_FORMAT_XRGB8888,
|
target_mode->height, DRM_FORMAT_XRGB8888,
|
||||||
|
|
@ -1105,7 +1158,7 @@ vnc_output_set_size(struct weston_output *base, int width, int height,
|
||||||
output->base.repaint = vnc_output_repaint;
|
output->base.repaint = vnc_output_repaint;
|
||||||
output->base.assign_planes = vnc_output_assign_planes;
|
output->base.assign_planes = vnc_output_assign_planes;
|
||||||
output->base.set_backlight = NULL;
|
output->base.set_backlight = NULL;
|
||||||
output->base.set_dpms = NULL;
|
output->base.set_dpms = vnc_set_dpms;
|
||||||
output->base.switch_mode = vnc_switch_mode;
|
output->base.switch_mode = vnc_switch_mode;
|
||||||
|
|
||||||
output->resizeable = resizeable;
|
output->resizeable = resizeable;
|
||||||
|
|
@ -1183,6 +1236,17 @@ vnc_backend_create(struct weston_compositor *compositor,
|
||||||
goto err_compositor;
|
goto err_compositor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WESTON_RENDERER_VULKAN: {
|
||||||
|
const struct vulkan_renderer_display_options options = {
|
||||||
|
.formats = backend->formats,
|
||||||
|
.formats_count = backend->formats_count,
|
||||||
|
};
|
||||||
|
if (weston_compositor_init_renderer(compositor,
|
||||||
|
WESTON_RENDERER_VULKAN,
|
||||||
|
&options.base) < 0)
|
||||||
|
goto err_compositor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
weston_log("Unsupported renderer requested\n");
|
weston_log("Unsupported renderer requested\n");
|
||||||
goto err_compositor;
|
goto err_compositor;
|
||||||
|
|
@ -1324,6 +1388,7 @@ weston_backend_init(struct weston_compositor *compositor,
|
||||||
switch (compositor->renderer->type) {
|
switch (compositor->renderer->type) {
|
||||||
case WESTON_RENDERER_PIXMAN:
|
case WESTON_RENDERER_PIXMAN:
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
weston_log("Renderer not supported by VNC backend\n");
|
weston_log("Renderer not supported by VNC backend\n");
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@ config_h.set('BUILD_WAYLAND_COMPOSITOR', '1')
|
||||||
|
|
||||||
srcs_wlwl = [
|
srcs_wlwl = [
|
||||||
'wayland.c',
|
'wayland.c',
|
||||||
fullscreen_shell_unstable_v1_client_protocol_h,
|
|
||||||
fullscreen_shell_unstable_v1_protocol_c,
|
|
||||||
presentation_time_protocol_c,
|
presentation_time_protocol_c,
|
||||||
presentation_time_server_protocol_h,
|
presentation_time_server_protocol_h,
|
||||||
xdg_shell_client_protocol_h,
|
xdg_shell_client_protocol_h,
|
||||||
|
|
@ -21,7 +19,7 @@ deps_wlwl = [
|
||||||
dep_libweston_private,
|
dep_libweston_private,
|
||||||
dep_libdrm_headers,
|
dep_libdrm_headers,
|
||||||
dep_lib_cairo_shared,
|
dep_lib_cairo_shared,
|
||||||
dep_lib_gl_borders,
|
dep_lib_renderer_borders,
|
||||||
]
|
]
|
||||||
|
|
||||||
if get_option('renderer-gl')
|
if get_option('renderer-gl')
|
||||||
|
|
@ -33,6 +31,10 @@ if get_option('renderer-gl')
|
||||||
deps_wlwl += dep_egl # for gl-renderer.h
|
deps_wlwl += dep_egl # for gl-renderer.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if get_option('renderer-vulkan')
|
||||||
|
deps_wlwl += dep_vulkan # for vulkan-renderer.h
|
||||||
|
endif
|
||||||
|
|
||||||
plugin_wlwl = shared_library(
|
plugin_wlwl = shared_library(
|
||||||
'wayland-backend',
|
'wayland-backend',
|
||||||
srcs_wlwl,
|
srcs_wlwl,
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,8 @@
|
||||||
#include <libweston/libweston.h>
|
#include <libweston/libweston.h>
|
||||||
#include <libweston/backend-wayland.h>
|
#include <libweston/backend-wayland.h>
|
||||||
#include "renderer-gl/gl-renderer.h"
|
#include "renderer-gl/gl-renderer.h"
|
||||||
#include "gl-borders.h"
|
#include "renderer-vulkan/vulkan-renderer.h"
|
||||||
|
#include "renderer-borders.h"
|
||||||
#include "shared/weston-drm-fourcc.h"
|
#include "shared/weston-drm-fourcc.h"
|
||||||
#include "shared/weston-egl-ext.h"
|
#include "shared/weston-egl-ext.h"
|
||||||
#include "pixman-renderer.h"
|
#include "pixman-renderer.h"
|
||||||
|
|
@ -58,7 +59,6 @@
|
||||||
#include "shared/cairo-util.h"
|
#include "shared/cairo-util.h"
|
||||||
#include "shared/timespec-util.h"
|
#include "shared/timespec-util.h"
|
||||||
#include "shared/xalloc.h"
|
#include "shared/xalloc.h"
|
||||||
#include "fullscreen-shell-unstable-v1-client-protocol.h"
|
|
||||||
#include "xdg-shell-client-protocol.h"
|
#include "xdg-shell-client-protocol.h"
|
||||||
#include "presentation-time-server-protocol.h"
|
#include "presentation-time-server-protocol.h"
|
||||||
#include "linux-dmabuf.h"
|
#include "linux-dmabuf.h"
|
||||||
|
|
@ -86,7 +86,6 @@ struct wayland_backend {
|
||||||
struct wl_registry *registry;
|
struct wl_registry *registry;
|
||||||
struct wl_compositor *compositor;
|
struct wl_compositor *compositor;
|
||||||
struct xdg_wm_base *xdg_wm_base;
|
struct xdg_wm_base *xdg_wm_base;
|
||||||
struct zwp_fullscreen_shell_v1 *fshell;
|
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
|
|
||||||
struct wl_list output_list;
|
struct wl_list output_list;
|
||||||
|
|
@ -99,7 +98,6 @@ struct wayland_backend {
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
|
|
||||||
struct theme *theme;
|
struct theme *theme;
|
||||||
cairo_device_t *frame_device;
|
|
||||||
struct wl_cursor_theme *cursor_theme;
|
struct wl_cursor_theme *cursor_theme;
|
||||||
struct wl_cursor *cursor;
|
struct wl_cursor *cursor;
|
||||||
|
|
||||||
|
|
@ -135,7 +133,6 @@ struct wayland_output {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_egl_window *egl_window;
|
struct wl_egl_window *egl_window;
|
||||||
struct weston_gl_borders borders;
|
|
||||||
} gl;
|
} gl;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -143,6 +140,8 @@ struct wayland_output {
|
||||||
struct wl_list free_buffers;
|
struct wl_list free_buffers;
|
||||||
} shm;
|
} shm;
|
||||||
|
|
||||||
|
struct weston_renderer_borders borders;
|
||||||
|
|
||||||
struct weston_mode mode;
|
struct weston_mode mode;
|
||||||
struct weston_mode native_mode;
|
struct weston_mode native_mode;
|
||||||
|
|
||||||
|
|
@ -192,7 +191,7 @@ struct wayland_shm_buffer {
|
||||||
int height;
|
int height;
|
||||||
int frame_damaged;
|
int frame_damaged;
|
||||||
|
|
||||||
struct weston_renderbuffer *renderbuffer;
|
weston_renderbuffer_t renderbuffer;
|
||||||
cairo_surface_t *c_surface;
|
cairo_surface_t *c_surface;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -266,9 +265,14 @@ to_wayland_backend(struct weston_backend *base)
|
||||||
static void
|
static void
|
||||||
wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
|
wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
|
||||||
{
|
{
|
||||||
|
struct wayland_output *output = buffer->output;
|
||||||
|
const struct weston_renderer *renderer;
|
||||||
|
|
||||||
cairo_surface_destroy(buffer->c_surface);
|
cairo_surface_destroy(buffer->c_surface);
|
||||||
if (buffer->output)
|
if (output) {
|
||||||
weston_renderbuffer_unref(buffer->renderbuffer);
|
renderer = output->base.compositor->renderer;
|
||||||
|
renderer->destroy_renderbuffer(buffer->renderbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
wl_buffer_destroy(buffer->buffer);
|
wl_buffer_destroy(buffer->buffer);
|
||||||
munmap(buffer->data, buffer->size);
|
munmap(buffer->data, buffer->size);
|
||||||
|
|
@ -290,6 +294,22 @@ buffer_release(void *data, struct wl_buffer *buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wayland_rb_discarded_cb(weston_renderbuffer_t renderbuffer, void *data)
|
||||||
|
{
|
||||||
|
struct wayland_shm_buffer *sb = data;
|
||||||
|
const struct weston_renderer *renderer;
|
||||||
|
|
||||||
|
if (sb->renderbuffer) {
|
||||||
|
renderer = sb->output->backend->compositor->renderer;
|
||||||
|
renderer->destroy_renderbuffer(sb->renderbuffer);
|
||||||
|
sb->renderbuffer = NULL;
|
||||||
|
}
|
||||||
|
sb->output = NULL;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wl_buffer_listener buffer_listener = {
|
static const struct wl_buffer_listener buffer_listener = {
|
||||||
buffer_release
|
buffer_release
|
||||||
};
|
};
|
||||||
|
|
@ -298,7 +318,6 @@ static struct wayland_shm_buffer *
|
||||||
wayland_output_get_shm_buffer(struct wayland_output *output)
|
wayland_output_get_shm_buffer(struct wayland_output *output)
|
||||||
{
|
{
|
||||||
const struct weston_renderer *renderer;
|
const struct weston_renderer *renderer;
|
||||||
const struct pixman_renderer_interface *pixman;
|
|
||||||
struct wayland_backend *b = output->backend;
|
struct wayland_backend *b = output->backend;
|
||||||
const struct pixel_format_info *pfmt = b->formats[0];
|
const struct pixel_format_info *pfmt = b->formats[0];
|
||||||
uint32_t shm_format = pixel_format_get_shm_format(pfmt);
|
uint32_t shm_format = pixel_format_get_shm_format(pfmt);
|
||||||
|
|
@ -384,26 +403,23 @@ wayland_output_get_shm_buffer(struct wayland_output *output)
|
||||||
if (output->frame) {
|
if (output->frame) {
|
||||||
frame_interior(output->frame, &area.x, &area.y,
|
frame_interior(output->frame, &area.x, &area.y,
|
||||||
&area.width, &area.height);
|
&area.width, &area.height);
|
||||||
|
assert(area.width == output->base.current_mode->width);
|
||||||
|
assert(area.height == output->base.current_mode->height);
|
||||||
} else {
|
} else {
|
||||||
area.x = 0;
|
area.x = 0;
|
||||||
area.y = 0;
|
area.y = 0;
|
||||||
area.width = output->base.current_mode->width;
|
|
||||||
area.height = output->base.current_mode->height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer = b->compositor->renderer;
|
renderer = b->compositor->renderer;
|
||||||
pixman = renderer->pixman;
|
|
||||||
|
|
||||||
/* Address only the interior, excluding output decorations */
|
/* Address only the interior, excluding output decorations */
|
||||||
if (renderer->type == WESTON_RENDERER_PIXMAN) {
|
if (renderer->type == WESTON_RENDERER_PIXMAN)
|
||||||
sb->renderbuffer =
|
sb->renderbuffer =
|
||||||
pixman->create_image_from_ptr(&output->base, pfmt,
|
renderer->create_renderbuffer(&output->base, pfmt,
|
||||||
area.width, area.height,
|
|
||||||
(uint32_t *)(data + area.y * stride) + area.x,
|
(uint32_t *)(data + area.y * stride) + area.x,
|
||||||
stride);
|
stride,
|
||||||
pixman_region32_copy(&sb->renderbuffer->damage,
|
wayland_rb_discarded_cb,
|
||||||
&output->base.region);
|
sb);
|
||||||
}
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
@ -435,34 +451,17 @@ static const struct wl_callback_listener frame_listener = {
|
||||||
frame_done
|
frame_done
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(ENABLE_EGL) || defined(ENABLE_VULKAN)
|
||||||
static void
|
static void
|
||||||
draw_initial_frame(struct wayland_output *output)
|
wayland_output_update_renderer_border(struct wayland_output *output)
|
||||||
{
|
|
||||||
struct wayland_shm_buffer *sb;
|
|
||||||
|
|
||||||
sb = wayland_output_get_shm_buffer(output);
|
|
||||||
|
|
||||||
/* If we are rendering with GL, then orphan it so that it gets
|
|
||||||
* destroyed immediately */
|
|
||||||
if (output->gl.egl_window)
|
|
||||||
sb->output = NULL;
|
|
||||||
|
|
||||||
wl_surface_attach(output->parent.surface, sb->buffer, 0, 0);
|
|
||||||
wl_surface_damage(output->parent.surface, 0, 0,
|
|
||||||
sb->width, sb->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_EGL
|
|
||||||
static void
|
|
||||||
wayland_output_update_gl_border(struct wayland_output *output)
|
|
||||||
{
|
{
|
||||||
if (!output->frame)
|
if (!output->frame)
|
||||||
return;
|
return;
|
||||||
if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
|
if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
weston_gl_borders_update(&output->gl.borders, output->frame,
|
weston_renderer_borders_update(&output->borders, output->frame,
|
||||||
&output->base);
|
&output->base);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -502,7 +501,36 @@ wayland_output_repaint_gl(struct weston_output *output_base)
|
||||||
output->frame_cb = wl_surface_frame(output->parent.surface);
|
output->frame_cb = wl_surface_frame(output->parent.surface);
|
||||||
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
|
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
|
||||||
|
|
||||||
wayland_output_update_gl_border(output);
|
wayland_output_update_renderer_border(output);
|
||||||
|
|
||||||
|
ec->renderer->repaint_output(&output->base, &damage, NULL);
|
||||||
|
|
||||||
|
pixman_region32_fini(&damage);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_VULKAN
|
||||||
|
static int
|
||||||
|
wayland_output_repaint_vulkan(struct weston_output *output_base)
|
||||||
|
{
|
||||||
|
struct wayland_output *output = to_wayland_output(output_base);
|
||||||
|
struct weston_compositor *ec;
|
||||||
|
pixman_region32_t damage;
|
||||||
|
|
||||||
|
assert(output);
|
||||||
|
|
||||||
|
ec = output->base.compositor;
|
||||||
|
|
||||||
|
pixman_region32_init(&damage);
|
||||||
|
|
||||||
|
weston_output_flush_damage_for_primary_plane(output_base, &damage);
|
||||||
|
|
||||||
|
output->frame_cb = wl_surface_frame(output->parent.surface);
|
||||||
|
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
|
||||||
|
|
||||||
|
wayland_output_update_renderer_border(output);
|
||||||
|
|
||||||
ec->renderer->repaint_output(&output->base, &damage, NULL);
|
ec->renderer->repaint_output(&output->base, &damage, NULL);
|
||||||
|
|
||||||
|
|
@ -665,14 +693,6 @@ wayland_output_destroy_shm_buffers(struct wayland_output *output)
|
||||||
/* Throw away any remaining SHM buffers */
|
/* Throw away any remaining SHM buffers */
|
||||||
wl_list_for_each_safe(buffer, next, &output->shm.free_buffers, free_link)
|
wl_list_for_each_safe(buffer, next, &output->shm.free_buffers, free_link)
|
||||||
wayland_shm_buffer_destroy(buffer);
|
wayland_shm_buffer_destroy(buffer);
|
||||||
/* These will get thrown away when they get released */
|
|
||||||
wl_list_for_each(buffer, &output->shm.buffers, link) {
|
|
||||||
if (buffer->renderbuffer) {
|
|
||||||
weston_renderbuffer_unref(buffer->renderbuffer);
|
|
||||||
buffer->renderbuffer = NULL;
|
|
||||||
}
|
|
||||||
buffer->output = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
@ -694,11 +714,18 @@ wayland_output_disable(struct weston_output *base)
|
||||||
break;
|
break;
|
||||||
#ifdef ENABLE_EGL
|
#ifdef ENABLE_EGL
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
weston_gl_borders_fini(&output->gl.borders, &output->base);
|
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||||
|
|
||||||
renderer->gl->output_destroy(&output->base);
|
renderer->gl->output_destroy(&output->base);
|
||||||
wl_egl_window_destroy(output->gl.egl_window);
|
wl_egl_window_destroy(output->gl.egl_window);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_VULKAN
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||||
|
|
||||||
|
renderer->vulkan->output_destroy(&output->base);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
unreachable("invalid renderer");
|
unreachable("invalid renderer");
|
||||||
|
|
@ -780,6 +807,47 @@ cleanup_window:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_VULKAN
|
||||||
|
static int
|
||||||
|
wayland_output_init_vulkan_renderer(struct wayland_output *output)
|
||||||
|
{
|
||||||
|
const struct weston_mode *mode = output->base.current_mode;
|
||||||
|
struct wayland_backend *b = output->backend;
|
||||||
|
const struct weston_renderer *renderer;
|
||||||
|
struct vulkan_renderer_surface_options options = {
|
||||||
|
.formats = b->formats,
|
||||||
|
.formats_count = b->formats_count,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (output->frame) {
|
||||||
|
frame_interior(output->frame, &options.area.x, &options.area.y,
|
||||||
|
&options.area.width, &options.area.height);
|
||||||
|
options.fb_size.width = frame_width(output->frame);
|
||||||
|
options.fb_size.height = frame_height(output->frame);
|
||||||
|
} else {
|
||||||
|
options.area.x = 0;
|
||||||
|
options.area.y = 0;
|
||||||
|
options.area.width = mode->width;
|
||||||
|
options.area.height = mode->height;
|
||||||
|
options.fb_size.width = mode->width;
|
||||||
|
options.fb_size.height = mode->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
options.wayland_display = b->parent.wl_display;
|
||||||
|
options.wayland_surface = output->parent.surface;
|
||||||
|
|
||||||
|
renderer = output->base.compositor->renderer;
|
||||||
|
|
||||||
|
if (renderer->vulkan->output_surface_create(&output->base, &options) < 0)
|
||||||
|
goto cleanup_window;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup_window:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wayland_output_init_pixman_renderer(struct wayland_output *output)
|
wayland_output_init_pixman_renderer(struct wayland_output *output)
|
||||||
{
|
{
|
||||||
|
|
@ -814,6 +882,9 @@ wayland_output_resize_surface(struct wayland_output *output)
|
||||||
struct weston_geometry opa = area;
|
struct weston_geometry opa = area;
|
||||||
struct wl_region *region;
|
struct wl_region *region;
|
||||||
|
|
||||||
|
assert(b->compositor);
|
||||||
|
assert(b->compositor->renderer);
|
||||||
|
|
||||||
if (output->frame) {
|
if (output->frame) {
|
||||||
frame_resize_inside(output->frame, area.width, area.height);
|
frame_resize_inside(output->frame, area.width, area.height);
|
||||||
frame_interior(output->frame, &area.x, &area.y, NULL, NULL);
|
frame_interior(output->frame, &area.x, &area.y, NULL, NULL);
|
||||||
|
|
@ -849,7 +920,15 @@ wayland_output_resize_surface(struct wayland_output *output)
|
||||||
weston_renderer_resize_output(&output->base, &fb_size, &area);
|
weston_renderer_resize_output(&output->base, &fb_size, &area);
|
||||||
|
|
||||||
/* These will need to be re-created due to the resize */
|
/* These will need to be re-created due to the resize */
|
||||||
weston_gl_borders_fini(&output->gl.borders, &output->base);
|
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_VULKAN
|
||||||
|
if (b->compositor->renderer->type == WESTON_RENDERER_VULKAN) {
|
||||||
|
weston_renderer_resize_output(&output->base, &fb_size, &area);
|
||||||
|
|
||||||
|
/* These will need to be re-created due to the resize */
|
||||||
|
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|
@ -917,104 +996,6 @@ wayland_output_set_fullscreen(struct wayland_output *output,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct weston_mode *
|
|
||||||
wayland_output_choose_mode(struct wayland_output *output,
|
|
||||||
struct weston_mode *ref_mode)
|
|
||||||
{
|
|
||||||
struct weston_mode *mode;
|
|
||||||
|
|
||||||
/* First look for an exact match */
|
|
||||||
wl_list_for_each(mode, &output->base.mode_list, link)
|
|
||||||
if (mode->width == ref_mode->width &&
|
|
||||||
mode->height == ref_mode->height &&
|
|
||||||
mode->refresh == ref_mode->refresh)
|
|
||||||
return mode;
|
|
||||||
|
|
||||||
/* If we can't find an exact match, ignore refresh and try again */
|
|
||||||
wl_list_for_each(mode, &output->base.mode_list, link)
|
|
||||||
if (mode->width == ref_mode->width &&
|
|
||||||
mode->height == ref_mode->height)
|
|
||||||
return mode;
|
|
||||||
|
|
||||||
/* Yeah, we failed */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum mode_status {
|
|
||||||
MODE_STATUS_UNKNOWN,
|
|
||||||
MODE_STATUS_SUCCESS,
|
|
||||||
MODE_STATUS_FAIL,
|
|
||||||
MODE_STATUS_CANCEL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
mode_feedback_successful(void *data,
|
|
||||||
struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
|
|
||||||
{
|
|
||||||
enum mode_status *value = data;
|
|
||||||
|
|
||||||
printf("Mode switch successful\n");
|
|
||||||
|
|
||||||
*value = MODE_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mode_feedback_failed(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
|
|
||||||
{
|
|
||||||
enum mode_status *value = data;
|
|
||||||
|
|
||||||
printf("Mode switch failed\n");
|
|
||||||
|
|
||||||
*value = MODE_STATUS_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
mode_feedback_cancelled(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
|
|
||||||
{
|
|
||||||
enum mode_status *value = data;
|
|
||||||
|
|
||||||
printf("Mode switch cancelled\n");
|
|
||||||
|
|
||||||
*value = MODE_STATUS_CANCEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct zwp_fullscreen_shell_mode_feedback_v1_listener mode_feedback_listener = {
|
|
||||||
mode_feedback_successful,
|
|
||||||
mode_feedback_failed,
|
|
||||||
mode_feedback_cancelled,
|
|
||||||
};
|
|
||||||
|
|
||||||
static enum mode_status
|
|
||||||
wayland_output_fullscreen_shell_mode_feedback(struct wayland_output *output,
|
|
||||||
struct weston_mode *mode)
|
|
||||||
{
|
|
||||||
struct wayland_backend *b = output->backend;
|
|
||||||
struct zwp_fullscreen_shell_mode_feedback_v1 *mode_feedback;
|
|
||||||
enum mode_status mode_status;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
mode_feedback =
|
|
||||||
zwp_fullscreen_shell_v1_present_surface_for_mode(b->parent.fshell,
|
|
||||||
output->parent.surface,
|
|
||||||
output->parent.output,
|
|
||||||
mode->refresh);
|
|
||||||
|
|
||||||
zwp_fullscreen_shell_mode_feedback_v1_add_listener(mode_feedback,
|
|
||||||
&mode_feedback_listener,
|
|
||||||
&mode_status);
|
|
||||||
|
|
||||||
draw_initial_frame(output);
|
|
||||||
wl_surface_commit(output->parent.surface);
|
|
||||||
|
|
||||||
mode_status = MODE_STATUS_UNKNOWN;
|
|
||||||
while (mode_status == MODE_STATUS_UNKNOWN && ret >= 0)
|
|
||||||
ret = wl_display_dispatch(b->parent.wl_display);
|
|
||||||
|
|
||||||
zwp_fullscreen_shell_mode_feedback_v1_destroy(mode_feedback);
|
|
||||||
|
|
||||||
return mode_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wayland_output_switch_mode_finish(struct wayland_output *output)
|
wayland_output_switch_mode_finish(struct wayland_output *output)
|
||||||
{
|
{
|
||||||
|
|
@ -1033,6 +1014,13 @@ wayland_output_switch_mode_finish(struct wayland_output *output)
|
||||||
if (wayland_output_init_gl_renderer(output) < 0)
|
if (wayland_output_init_gl_renderer(output) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_VULKAN
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
renderer->vulkan->output_destroy(&output->base);
|
||||||
|
if (wayland_output_init_vulkan_renderer(output) < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
unreachable("invalid renderer");
|
unreachable("invalid renderer");
|
||||||
|
|
@ -1043,56 +1031,6 @@ wayland_output_switch_mode_finish(struct wayland_output *output)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
wayland_output_switch_mode_fshell(struct wayland_output *output,
|
|
||||||
struct weston_mode *mode)
|
|
||||||
{
|
|
||||||
struct wayland_backend *b;
|
|
||||||
struct wl_surface *old_surface;
|
|
||||||
struct weston_mode *old_mode;
|
|
||||||
enum mode_status mode_status;
|
|
||||||
|
|
||||||
b = output->backend;
|
|
||||||
|
|
||||||
mode = wayland_output_choose_mode(output, mode);
|
|
||||||
if (mode == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (output->base.current_mode == mode)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
old_mode = output->base.current_mode;
|
|
||||||
old_surface = output->parent.surface;
|
|
||||||
output->base.current_mode = mode;
|
|
||||||
output->parent.surface =
|
|
||||||
wl_compositor_create_surface(b->parent.compositor);
|
|
||||||
wl_surface_set_user_data(output->parent.surface, output);
|
|
||||||
|
|
||||||
/* Blow the old buffers because we changed size/surfaces */
|
|
||||||
wayland_output_resize_surface(output);
|
|
||||||
|
|
||||||
mode_status = wayland_output_fullscreen_shell_mode_feedback(output, mode);
|
|
||||||
|
|
||||||
/* This should kick-start things again */
|
|
||||||
wayland_output_start_repaint_loop(&output->base);
|
|
||||||
|
|
||||||
if (mode_status == MODE_STATUS_FAIL) {
|
|
||||||
output->base.current_mode = old_mode;
|
|
||||||
wl_surface_destroy(output->parent.surface);
|
|
||||||
output->parent.surface = old_surface;
|
|
||||||
wayland_output_resize_surface(output);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
old_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
|
|
||||||
output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
|
|
||||||
|
|
||||||
wl_surface_destroy(old_surface);
|
|
||||||
|
|
||||||
return wayland_output_switch_mode_finish(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wayland_output_switch_mode_xdg(struct wayland_output *output,
|
wayland_output_switch_mode_xdg(struct wayland_output *output,
|
||||||
struct weston_mode *mode)
|
struct weston_mode *mode)
|
||||||
|
|
@ -1136,8 +1074,6 @@ wayland_output_switch_mode(struct weston_output *output_base,
|
||||||
|
|
||||||
if (output->parent.xdg_surface)
|
if (output->parent.xdg_surface)
|
||||||
return wayland_output_switch_mode_xdg(output, mode);
|
return wayland_output_switch_mode_xdg(output, mode);
|
||||||
if (output->backend->parent.fshell)
|
|
||||||
return wayland_output_switch_mode_fshell(output, mode);
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1257,7 +1193,6 @@ wayland_output_enable(struct weston_output *base)
|
||||||
const struct weston_renderer *renderer = base->compositor->renderer;
|
const struct weston_renderer *renderer = base->compositor->renderer;
|
||||||
struct wayland_output *output = to_wayland_output(base);
|
struct wayland_output *output = to_wayland_output(base);
|
||||||
struct wayland_backend *b;
|
struct wayland_backend *b;
|
||||||
enum mode_status mode_status;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
assert(output);
|
assert(output);
|
||||||
|
|
@ -1293,6 +1228,14 @@ wayland_output_enable(struct weston_output *base)
|
||||||
|
|
||||||
output->base.repaint = wayland_output_repaint_gl;
|
output->base.repaint = wayland_output_repaint_gl;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_VULKAN
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
if (wayland_output_init_vulkan_renderer(output) < 0)
|
||||||
|
goto err_output;
|
||||||
|
|
||||||
|
output->base.repaint = wayland_output_repaint_vulkan;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
unreachable("invalid renderer");
|
unreachable("invalid renderer");
|
||||||
|
|
@ -1304,20 +1247,7 @@ wayland_output_enable(struct weston_output *base)
|
||||||
output->base.set_dpms = NULL;
|
output->base.set_dpms = NULL;
|
||||||
output->base.switch_mode = wayland_output_switch_mode;
|
output->base.switch_mode = wayland_output_switch_mode;
|
||||||
|
|
||||||
if (b->sprawl_across_outputs) {
|
if (b->fullscreen) {
|
||||||
if (b->parent.fshell) {
|
|
||||||
wayland_output_resize_surface(output);
|
|
||||||
|
|
||||||
mode_status = wayland_output_fullscreen_shell_mode_feedback(output, &output->mode);
|
|
||||||
|
|
||||||
if (mode_status == MODE_STATUS_FAIL)
|
|
||||||
zwp_fullscreen_shell_v1_present_surface(b->parent.fshell,
|
|
||||||
output->parent.surface,
|
|
||||||
ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER,
|
|
||||||
output->parent.output);
|
|
||||||
|
|
||||||
}
|
|
||||||
} else if (b->fullscreen) {
|
|
||||||
wayland_output_set_fullscreen(output, 0, NULL);
|
wayland_output_set_fullscreen(output, 0, NULL);
|
||||||
} else {
|
} else {
|
||||||
wayland_output_set_windowed(output);
|
wayland_output_set_windowed(output);
|
||||||
|
|
@ -2690,10 +2620,6 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
&xdg_wm_base_interface, 1);
|
&xdg_wm_base_interface, 1);
|
||||||
xdg_wm_base_add_listener(b->parent.xdg_wm_base,
|
xdg_wm_base_add_listener(b->parent.xdg_wm_base,
|
||||||
&wm_base_listener, b);
|
&wm_base_listener, b);
|
||||||
} else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
|
|
||||||
b->parent.fshell =
|
|
||||||
wl_registry_bind(registry, name,
|
|
||||||
&zwp_fullscreen_shell_v1_interface, 1);
|
|
||||||
} else if (strcmp(interface, "wl_seat") == 0) {
|
} else if (strcmp(interface, "wl_seat") == 0) {
|
||||||
display_start_add_seat(b, name, version);
|
display_start_add_seat(b, name, version);
|
||||||
} else if (strcmp(interface, "wl_output") == 0) {
|
} else if (strcmp(interface, "wl_output") == 0) {
|
||||||
|
|
@ -2791,18 +2717,12 @@ wayland_destroy(struct weston_backend *backend)
|
||||||
if (b->parent.xdg_wm_base)
|
if (b->parent.xdg_wm_base)
|
||||||
xdg_wm_base_destroy(b->parent.xdg_wm_base);
|
xdg_wm_base_destroy(b->parent.xdg_wm_base);
|
||||||
|
|
||||||
if (b->parent.fshell)
|
|
||||||
zwp_fullscreen_shell_v1_release(b->parent.fshell);
|
|
||||||
|
|
||||||
if (b->parent.compositor)
|
if (b->parent.compositor)
|
||||||
wl_compositor_destroy(b->parent.compositor);
|
wl_compositor_destroy(b->parent.compositor);
|
||||||
|
|
||||||
if (b->theme)
|
if (b->theme)
|
||||||
theme_destroy(b->theme);
|
theme_destroy(b->theme);
|
||||||
|
|
||||||
if (b->frame_device)
|
|
||||||
cairo_device_destroy(b->frame_device);
|
|
||||||
|
|
||||||
wl_cursor_theme_destroy(b->cursor_theme);
|
wl_cursor_theme_destroy(b->cursor_theme);
|
||||||
|
|
||||||
free(b->formats);
|
free(b->formats);
|
||||||
|
|
@ -2951,6 +2871,22 @@ wayland_backend_create(struct weston_compositor *compositor,
|
||||||
goto err_display;
|
goto err_display;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case WESTON_RENDERER_VULKAN: {
|
||||||
|
const struct vulkan_renderer_display_options options = {
|
||||||
|
.formats = b->formats,
|
||||||
|
.formats_count = b->formats_count,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (weston_compositor_init_renderer(compositor,
|
||||||
|
WESTON_RENDERER_VULKAN,
|
||||||
|
&options.base) < 0) {
|
||||||
|
weston_log("Failed to initialize the Vulkan renderer\n");
|
||||||
|
goto err_display;
|
||||||
|
}
|
||||||
|
/* For now Vulkan does not fall back to anything automatically,
|
||||||
|
* like GL renderer does. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
weston_log("Unsupported renderer requested\n");
|
weston_log("Unsupported renderer requested\n");
|
||||||
goto err_display;
|
goto err_display;
|
||||||
|
|
@ -2990,8 +2926,6 @@ wayland_backend_destroy(struct wayland_backend *b)
|
||||||
|
|
||||||
if (b->theme)
|
if (b->theme)
|
||||||
theme_destroy(b->theme);
|
theme_destroy(b->theme);
|
||||||
if (b->frame_device)
|
|
||||||
cairo_device_destroy(b->frame_device);
|
|
||||||
wl_cursor_theme_destroy(b->cursor_theme);
|
wl_cursor_theme_destroy(b->cursor_theme);
|
||||||
|
|
||||||
wl_list_remove(&b->base.link);
|
wl_list_remove(&b->base.link);
|
||||||
|
|
@ -3039,7 +2973,7 @@ weston_backend_init(struct weston_compositor *compositor,
|
||||||
if (!b)
|
if (!b)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (new_config.sprawl || b->parent.fshell) {
|
if (new_config.sprawl) {
|
||||||
b->sprawl_across_outputs = true;
|
b->sprawl_across_outputs = true;
|
||||||
wl_display_roundtrip(b->parent.wl_display);
|
wl_display_roundtrip(b->parent.wl_display);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@
|
||||||
#include "shared/timespec-util.h"
|
#include "shared/timespec-util.h"
|
||||||
#include "shared/file-util.h"
|
#include "shared/file-util.h"
|
||||||
#include "renderer-gl/gl-renderer.h"
|
#include "renderer-gl/gl-renderer.h"
|
||||||
|
#include "renderer-vulkan/vulkan-renderer.h"
|
||||||
#include "shared/weston-drm-fourcc.h"
|
#include "shared/weston-drm-fourcc.h"
|
||||||
#include "shared/weston-egl-ext.h"
|
#include "shared/weston-egl-ext.h"
|
||||||
#include "shared/xalloc.h"
|
#include "shared/xalloc.h"
|
||||||
|
|
@ -140,7 +141,7 @@ struct x11_output {
|
||||||
|
|
||||||
xcb_gc_t gc;
|
xcb_gc_t gc;
|
||||||
xcb_shm_seg_t segment;
|
xcb_shm_seg_t segment;
|
||||||
struct weston_renderbuffer *renderbuffer;
|
weston_renderbuffer_t renderbuffer;
|
||||||
int shm_id;
|
int shm_id;
|
||||||
void *buf;
|
void *buf;
|
||||||
uint8_t depth;
|
uint8_t depth;
|
||||||
|
|
@ -168,6 +169,10 @@ to_x11_head(struct weston_head *base)
|
||||||
static void
|
static void
|
||||||
x11_output_destroy(struct weston_output *base);
|
x11_output_destroy(struct weston_output *base);
|
||||||
|
|
||||||
|
static int
|
||||||
|
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
|
||||||
|
const struct pixel_format_info *pfmt);
|
||||||
|
|
||||||
static inline struct x11_output *
|
static inline struct x11_output *
|
||||||
to_x11_output(struct weston_output *base)
|
to_x11_output(struct weston_output *base)
|
||||||
{
|
{
|
||||||
|
|
@ -451,6 +456,29 @@ x11_output_repaint_gl(struct weston_output *output_base)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
x11_output_repaint_vulkan(struct weston_output *output_base)
|
||||||
|
{
|
||||||
|
struct x11_output *output = to_x11_output(output_base);
|
||||||
|
struct weston_compositor *ec;
|
||||||
|
pixman_region32_t damage;
|
||||||
|
|
||||||
|
assert(output);
|
||||||
|
|
||||||
|
ec = output->base.compositor;
|
||||||
|
|
||||||
|
pixman_region32_init(&damage);
|
||||||
|
|
||||||
|
weston_output_flush_damage_for_primary_plane(output_base, &damage);
|
||||||
|
|
||||||
|
ec->renderer->repaint_output(output_base, &damage, NULL);
|
||||||
|
|
||||||
|
pixman_region32_fini(&damage);
|
||||||
|
|
||||||
|
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region)
|
set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region)
|
||||||
{
|
{
|
||||||
|
|
@ -507,8 +535,6 @@ static int
|
||||||
x11_output_repaint_shm(struct weston_output *output_base)
|
x11_output_repaint_shm(struct weston_output *output_base)
|
||||||
{
|
{
|
||||||
struct x11_output *output = to_x11_output(output_base);
|
struct x11_output *output = to_x11_output(output_base);
|
||||||
const struct weston_renderer *renderer;
|
|
||||||
pixman_image_t *image;
|
|
||||||
struct weston_compositor *ec;
|
struct weston_compositor *ec;
|
||||||
struct x11_backend *b;
|
struct x11_backend *b;
|
||||||
xcb_void_cookie_t cookie;
|
xcb_void_cookie_t cookie;
|
||||||
|
|
@ -518,11 +544,8 @@ x11_output_repaint_shm(struct weston_output *output_base)
|
||||||
assert(output);
|
assert(output);
|
||||||
|
|
||||||
ec = output->base.compositor;
|
ec = output->base.compositor;
|
||||||
renderer = ec->renderer;
|
|
||||||
b = output->backend;
|
b = output->backend;
|
||||||
|
|
||||||
image = renderer->pixman->renderbuffer_get_image(output->renderbuffer);
|
|
||||||
|
|
||||||
pixman_region32_init(&damage);
|
pixman_region32_init(&damage);
|
||||||
|
|
||||||
weston_output_flush_damage_for_primary_plane(output_base, &damage);
|
weston_output_flush_damage_for_primary_plane(output_base, &damage);
|
||||||
|
|
@ -534,13 +557,13 @@ x11_output_repaint_shm(struct weston_output *output_base)
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
|
|
||||||
cookie = xcb_shm_put_image_checked(b->conn, output->window, output->gc,
|
cookie = xcb_shm_put_image_checked(b->conn, output->window, output->gc,
|
||||||
pixman_image_get_width(image),
|
output_base->current_mode->width,
|
||||||
pixman_image_get_height(image),
|
output_base->current_mode->height,
|
||||||
0, 0,
|
0, 0,
|
||||||
pixman_image_get_width(image),
|
output_base->current_mode->width,
|
||||||
pixman_image_get_height(image),
|
output_base->current_mode->height,
|
||||||
0, 0, output->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
|
0, 0, output->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||||
0, output->segment, 0);
|
0, output->segment, 0);
|
||||||
err = xcb_request_check(b->conn, cookie);
|
err = xcb_request_check(b->conn, cookie);
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
weston_log("Failed to put shm image, err: %d\n", err->error_code);
|
weston_log("Failed to put shm image, err: %d\n", err->error_code);
|
||||||
|
|
@ -568,7 +591,7 @@ x11_output_deinit_shm(struct x11_backend *b, struct x11_output *output)
|
||||||
xcb_generic_error_t *err;
|
xcb_generic_error_t *err;
|
||||||
xcb_free_gc(b->conn, output->gc);
|
xcb_free_gc(b->conn, output->gc);
|
||||||
|
|
||||||
weston_renderbuffer_unref(output->renderbuffer);
|
b->compositor->renderer->destroy_renderbuffer(output->renderbuffer);
|
||||||
output->renderbuffer = NULL;
|
output->renderbuffer = NULL;
|
||||||
cookie = xcb_shm_detach_checked(b->conn, output->segment);
|
cookie = xcb_shm_detach_checked(b->conn, output->segment);
|
||||||
err = xcb_request_check(b->conn, cookie);
|
err = xcb_request_check(b->conn, cookie);
|
||||||
|
|
@ -793,17 +816,40 @@ x11_output_get_shm_pixel_format(struct x11_output *output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
x11_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
|
||||||
|
{
|
||||||
|
struct x11_output *output = (struct x11_output *) data;
|
||||||
|
const struct pixel_format_info *pfmt;
|
||||||
|
|
||||||
|
if (output->base.compositor->renderer->type == WESTON_RENDERER_PIXMAN) {
|
||||||
|
x11_output_deinit_shm(output->backend, output);
|
||||||
|
pfmt = x11_output_get_shm_pixel_format(output);
|
||||||
|
if (!pfmt)
|
||||||
|
return false;
|
||||||
|
if (x11_output_init_shm(output->backend, output, pfmt) < 0) {
|
||||||
|
weston_log("Failed to initialize SHM for the X11 output\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
|
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
|
||||||
const struct pixel_format_info *pfmt, int width, int height)
|
const struct pixel_format_info *pfmt)
|
||||||
{
|
{
|
||||||
struct weston_renderer *renderer = output->base.compositor->renderer;
|
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||||
int bitsperpixel = pfmt->bpp;
|
int bitsperpixel = pfmt->bpp;
|
||||||
|
size_t size = output->base.current_mode->width *
|
||||||
|
output->base.current_mode->height * (bitsperpixel / 8);
|
||||||
|
int stride = output->base.current_mode->width * (bitsperpixel / 8);
|
||||||
xcb_void_cookie_t cookie;
|
xcb_void_cookie_t cookie;
|
||||||
xcb_generic_error_t *err;
|
xcb_generic_error_t *err;
|
||||||
|
|
||||||
/* Create SHM segment and attach it */
|
/* Create SHM segment and attach it */
|
||||||
output->shm_id = shmget(IPC_PRIVATE, width * height * (bitsperpixel / 8), IPC_CREAT | S_IRWXU);
|
output->shm_id = shmget(IPC_PRIVATE, size, IPC_CREAT | S_IRWXU);
|
||||||
if (output->shm_id == -1) {
|
if (output->shm_id == -1) {
|
||||||
weston_log("x11shm: failed to allocate SHM segment\n");
|
weston_log("x11shm: failed to allocate SHM segment\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -827,10 +873,9 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
|
||||||
|
|
||||||
/* Now create pixman image */
|
/* Now create pixman image */
|
||||||
output->renderbuffer =
|
output->renderbuffer =
|
||||||
renderer->pixman->create_image_from_ptr(&output->base,
|
renderer->create_renderbuffer(&output->base, pfmt, output->buf,
|
||||||
pfmt, width, height,
|
stride, x11_rb_discarded_cb,
|
||||||
output->buf,
|
output);
|
||||||
width * (bitsperpixel / 8));
|
|
||||||
|
|
||||||
output->gc = xcb_generate_id(b->conn);
|
output->gc = xcb_generate_id(b->conn);
|
||||||
xcb_create_gc(b->conn, output->gc, output->window, 0, NULL);
|
xcb_create_gc(b->conn, output->gc, output->window, 0, NULL);
|
||||||
|
|
@ -838,6 +883,19 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
x11_set_dpms(struct weston_output *base, enum dpms_enum level)
|
||||||
|
{
|
||||||
|
struct x11_output *output = to_x11_output(base);
|
||||||
|
|
||||||
|
if (level == WESTON_DPMS_ON)
|
||||||
|
weston_output_schedule_repaint(base);
|
||||||
|
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
|
||||||
|
wl_event_source_timer_update(output->finish_frame_timer, 0);
|
||||||
|
weston_output_schedule_repaint_reset(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
|
x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
|
||||||
{
|
{
|
||||||
|
|
@ -875,20 +933,8 @@ x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
|
||||||
fb_size.width = output->mode.width = mode->width;
|
fb_size.width = output->mode.width = mode->width;
|
||||||
fb_size.height = output->mode.height = mode->height;
|
fb_size.height = output->mode.height = mode->height;
|
||||||
|
|
||||||
weston_renderer_resize_output(&output->base, &fb_size, NULL);
|
if (!weston_renderer_resize_output(&output->base, &fb_size, NULL))
|
||||||
|
return -1;
|
||||||
if (base->compositor->renderer->type == WESTON_RENDERER_PIXMAN) {
|
|
||||||
const struct pixel_format_info *pfmt;
|
|
||||||
x11_output_deinit_shm(b, output);
|
|
||||||
pfmt = x11_output_get_shm_pixel_format(output);
|
|
||||||
if (!pfmt)
|
|
||||||
return -1;
|
|
||||||
if (x11_output_init_shm(b, output, pfmt,
|
|
||||||
fb_size.width, fb_size.height) < 0) {
|
|
||||||
weston_log("Failed to initialize SHM for the X11 output\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output->resize_pending = false;
|
output->resize_pending = false;
|
||||||
output->window_resized = false;
|
output->window_resized = false;
|
||||||
|
|
@ -920,6 +966,9 @@ x11_output_disable(struct weston_output *base)
|
||||||
case WESTON_RENDERER_GL:
|
case WESTON_RENDERER_GL:
|
||||||
renderer->gl->output_destroy(&output->base);
|
renderer->gl->output_destroy(&output->base);
|
||||||
break;
|
break;
|
||||||
|
case WESTON_RENDERER_VULKAN:
|
||||||
|
renderer->vulkan->output_destroy(&output->base);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
unreachable("invalid renderer");
|
unreachable("invalid renderer");
|
||||||
}
|
}
|
||||||
|
|
@ -1068,8 +1117,7 @@ x11_output_enable(struct weston_output *base)
|
||||||
weston_log("Failed to create pixman renderer for output\n");
|
weston_log("Failed to create pixman renderer for output\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (x11_output_init_shm(b, output, options.format,
|
if (x11_output_init_shm(b, output, options.format) < 0) {
|
||||||
mode->width, mode->height) < 0) {
|
|
||||||
weston_log("Failed to initialize SHM for the X11 output\n");
|
weston_log("Failed to initialize SHM for the X11 output\n");
|
||||||
renderer->pixman->output_destroy(&output->base);
|
renderer->pixman->output_destroy(&output->base);
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -1102,6 +1150,29 @@ x11_output_enable(struct weston_output *base)
|
||||||
output->base.repaint = x11_output_repaint_gl;
|
output->base.repaint = x11_output_repaint_gl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WESTON_RENDERER_VULKAN: {
|
||||||
|
struct vulkan_renderer_surface_options options = {
|
||||||
|
.formats = b->formats,
|
||||||
|
.formats_count = b->formats_count,
|
||||||
|
.area.x = 0,
|
||||||
|
.area.y = 0,
|
||||||
|
.area.width = mode->width,
|
||||||
|
.area.height = mode->height,
|
||||||
|
.fb_size.width = mode->width,
|
||||||
|
.fb_size.height = mode->height,
|
||||||
|
};
|
||||||
|
|
||||||
|
options.xcb_connection = b->conn;
|
||||||
|
options.xcb_visualid = screen->root_visual;
|
||||||
|
options.xcb_window = output->window;
|
||||||
|
|
||||||
|
ret = renderer->vulkan->output_surface_create(base, &options);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
output->base.repaint = x11_output_repaint_vulkan;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
unreachable("invalid renderer");
|
unreachable("invalid renderer");
|
||||||
}
|
}
|
||||||
|
|
@ -1109,7 +1180,7 @@ x11_output_enable(struct weston_output *base)
|
||||||
output->base.start_repaint_loop = x11_output_start_repaint_loop;
|
output->base.start_repaint_loop = x11_output_start_repaint_loop;
|
||||||
output->base.assign_planes = NULL;
|
output->base.assign_planes = NULL;
|
||||||
output->base.set_backlight = NULL;
|
output->base.set_backlight = NULL;
|
||||||
output->base.set_dpms = NULL;
|
output->base.set_dpms = x11_set_dpms;
|
||||||
output->base.switch_mode = x11_output_switch_mode;
|
output->base.switch_mode = x11_output_switch_mode;
|
||||||
|
|
||||||
loop = wl_display_get_event_loop(b->compositor->wl_display);
|
loop = wl_display_get_event_loop(b->compositor->wl_display);
|
||||||
|
|
@ -1182,7 +1253,7 @@ x11_output_set_size(struct weston_output *base, int width, int height)
|
||||||
wl_list_insert(&output->base.mode_list, &output->mode.link);
|
wl_list_insert(&output->base.mode_list, &output->mode.link);
|
||||||
|
|
||||||
output->base.current_mode = &output->mode;
|
output->base.current_mode = &output->mode;
|
||||||
output->base.native_mode = &output->native;
|
weston_output_copy_native_mode(&output->base, &output->mode);
|
||||||
output->base.native_scale = output->base.current_scale;
|
output->base.native_scale = output->base.current_scale;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1952,6 +2023,17 @@ x11_backend_create(struct weston_compositor *compositor,
|
||||||
goto err_xdisplay;
|
goto err_xdisplay;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WESTON_RENDERER_VULKAN: {
|
||||||
|
const struct vulkan_renderer_display_options options = {
|
||||||
|
.formats = b->formats,
|
||||||
|
.formats_count = b->formats_count,
|
||||||
|
};
|
||||||
|
if (weston_compositor_init_renderer(compositor,
|
||||||
|
WESTON_RENDERER_VULKAN,
|
||||||
|
&options.base) < 0)
|
||||||
|
goto err_xdisplay;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
weston_log("Unsupported renderer requested\n");
|
weston_log("Unsupported renderer requested\n");
|
||||||
goto err_xdisplay;
|
goto err_xdisplay;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue