Compare commits
808 Commits
css-render
...
rendering-
Author | SHA1 | Date | |
---|---|---|---|
|
b8f6b36339 | ||
|
e70a961ac1 | ||
|
ffdc8c8f60 | ||
|
fd78bd3eaf | ||
|
f2ccba0988 | ||
|
8ee465c630 | ||
|
31b655c9eb | ||
|
7fd65cc3c1 | ||
|
8089222fc3 | ||
|
0667bd39fb | ||
|
a4854dfa9e | ||
|
6c54d0a7e2 | ||
|
341860eb4d | ||
|
876445f080 | ||
|
03ef6a7719 | ||
|
fde8c6df79 | ||
|
6c06e1855e | ||
|
c60ae0b575 | ||
|
e58f9ea1b4 | ||
|
3d55d733dc | ||
|
582dba54b1 | ||
|
0775432ed9 | ||
|
d9e15ff6e9 | ||
|
c04edfc76e | ||
|
71d6392572 | ||
|
dbd16cd9da | ||
|
950d266894 | ||
|
884974eeaa | ||
|
e836166664 | ||
|
c1a99bf901 | ||
|
f9c9a03404 | ||
|
3a337824e6 | ||
|
7dab23e38a | ||
|
78935ec83c | ||
|
b8989b7ff6 | ||
|
96cd47d0a0 | ||
|
d6a6cfe6c5 | ||
|
501356116d | ||
|
e11e5525db | ||
|
16431da3f2 | ||
|
842949fcf3 | ||
|
3d3e935c91 | ||
|
d5ae94ca5d | ||
|
87e9c940a4 | ||
|
6a02fa4be8 | ||
|
9f548efd32 | ||
|
9eebe8e547 | ||
|
f9612533c2 | ||
|
c9c0d444a2 | ||
|
13a8704f51 | ||
|
f20714262c | ||
|
11ffeeb55c | ||
|
ffc89e40a0 | ||
|
1c92f2d963 | ||
|
12e0ec0b48 | ||
|
5574bf59f6 | ||
|
7ee27cc0ad | ||
|
040974c8a2 | ||
|
126d689086 | ||
|
8e676c7360 | ||
|
84847e46fa | ||
|
3fca84f974 | ||
|
2be48a8f86 | ||
|
389d246af8 | ||
|
9e0f41bd05 | ||
|
564a237454 | ||
|
86b59ba643 | ||
|
487e568722 | ||
|
67080dab21 | ||
|
0809e6585d | ||
|
809b98c96e | ||
|
059af1365a | ||
|
fbcffb36c8 | ||
|
3af0cfb53b | ||
|
96422fcf52 | ||
|
2754f2be2d | ||
|
3d802177be | ||
|
a02d4ba2a1 | ||
|
249cf0833c | ||
|
20b00d3947 | ||
|
269dcaaadf | ||
|
322bbd2376 | ||
|
52bec248ce | ||
|
9f71528a05 | ||
|
65e02a3bae | ||
|
defc4d335e | ||
|
bdcfcfa5b9 | ||
|
4a94c91772 | ||
|
cc3ed89e34 | ||
|
87e8265a2d | ||
|
9fd6d431e3 | ||
|
5059ae1d7b | ||
|
50bb42f0f3 | ||
|
d71a7c901d | ||
|
65f727731c | ||
|
ff60b19e4b | ||
|
b8f12c5d28 | ||
|
bfb779ac2f | ||
|
84c28d2efb | ||
|
06372c5f2a | ||
|
3d75292c4d | ||
|
541ffbe4b5 | ||
|
17524f2794 | ||
|
1040d7c7e4 | ||
|
1b53359cd3 | ||
|
1987738d16 | ||
|
b8890ca27d | ||
|
2e7916cf4f | ||
|
24cf5b6df8 | ||
|
214f5a6f98 | ||
|
50ea9450ea | ||
|
d2028c7323 | ||
|
76c1ea0449 | ||
|
a97f378d64 | ||
|
ffe82b7641 | ||
|
785709d51c | ||
|
8406c34166 | ||
|
2ee1f3e8cf | ||
|
1373a7a6f0 | ||
|
a5aac30843 | ||
|
3149493679 | ||
|
a60cda3daa | ||
|
660c6c8d6f | ||
|
ad679187d3 | ||
|
b769295682 | ||
|
6649af5ec6 | ||
|
ca7094296c | ||
|
15a09c79f9 | ||
|
e2a7dc5427 | ||
|
d301d16aee | ||
|
ec489e673c | ||
|
a904da12b7 | ||
|
91865d172b | ||
|
adedb89779 | ||
|
514dbcacd4 | ||
|
25c812fa87 | ||
|
45e76c1604 | ||
|
a9c3163a64 | ||
|
a8bb71383a | ||
|
3b08f8026e | ||
|
2cdc2287a5 | ||
|
c80c4ee75c | ||
|
082691ba16 | ||
|
d09a610433 | ||
|
ea9f8b2f77 | ||
|
e2d337740f | ||
|
45c5b250b9 | ||
|
f4b35093bd | ||
|
5e52cefb28 | ||
|
bf43aee690 | ||
|
62f359a494 | ||
|
cbe09373a5 | ||
|
b3451dda04 | ||
|
d477bf3d93 | ||
|
12c7f2d4fd | ||
|
feca09b8a4 | ||
|
150f57f706 | ||
|
33131ad24d | ||
|
d53b3f9941 | ||
|
da07f1221f | ||
|
9aed7ab25f | ||
|
5ae225fe52 | ||
|
cc8fa39110 | ||
|
c673a0bcc3 | ||
|
efc6d15dde | ||
|
50403fbca8 | ||
|
7de91d1777 | ||
|
6f9a70bd4e | ||
|
de1dfb99bc | ||
|
103296d948 | ||
|
0001562850 | ||
|
1f3c88b995 | ||
|
5e7f227d92 | ||
|
6bbda619f9 | ||
|
e216fa3b6d | ||
|
c9443dd04d | ||
|
29cb5051d4 | ||
|
5f2e70df8e | ||
|
d8775d0194 | ||
|
8d87ed1a6a | ||
|
a46bcc2755 | ||
|
229edc5225 | ||
|
b1962de51a | ||
|
fb10b61528 | ||
|
e415ec9ca5 | ||
|
226652edb0 | ||
|
64f4967867 | ||
|
c37fa3a895 | ||
|
d907c0a42e | ||
|
4255230e36 | ||
|
d8a0915ada | ||
|
32b348776e | ||
|
bbe552d6a8 | ||
|
cfc871f031 | ||
|
b435f3c543 | ||
|
ebc4bb2363 | ||
|
23e4c788fa | ||
|
4e0a64c46c | ||
|
e46e61643c | ||
|
cc5526e019 | ||
|
e6cafa890d | ||
|
293d2fd19f | ||
|
7bca467e01 | ||
|
40e25218e2 | ||
|
9e27acb0a6 | ||
|
67b9fb43d0 | ||
|
762b981dfe | ||
|
5e027ae5d9 | ||
|
7dd3680d7d | ||
|
14a7b4b4b4 | ||
|
f5096fd11a | ||
|
9c5ac13301 | ||
|
ecc33d6e62 | ||
|
03c34021af | ||
|
1b2156493b | ||
|
7b76170f46 | ||
|
8109e8e3b6 | ||
|
163278af0d | ||
|
677b6c1a81 | ||
|
1331a10e88 | ||
|
dc9f0869b1 | ||
|
ea6253c1df | ||
|
b481fd854f | ||
|
68baa93460 | ||
|
52db54e803 | ||
|
71e412e8f8 | ||
|
9644fc2e8f | ||
|
0795d86df7 | ||
|
21988ea700 | ||
|
23081d2bc4 | ||
|
b1e441d18a | ||
|
a118cbb3ff | ||
|
4639b3bc4c | ||
|
821eb92dfb | ||
|
0370043775 | ||
|
82bcc05ca1 | ||
|
527852e1b8 | ||
|
2e1686091f | ||
|
5353e28dca | ||
|
b58e89f380 | ||
|
c1e008fa86 | ||
|
c47a3c54fd | ||
|
3bc1e0534f | ||
|
7fb11dfeb0 | ||
|
6d09eed90e | ||
|
496211727d | ||
|
ee5e3b5927 | ||
|
2087595747 | ||
|
25268c2086 | ||
|
2a9056b49e | ||
|
46363b617e | ||
|
adb3baa7d2 | ||
|
31a79fbd9f | ||
|
d8919311b1 | ||
|
0e0158a825 | ||
|
619926ec83 | ||
|
1afb832ff0 | ||
|
823b529f89 | ||
|
4707784755 | ||
|
1ebcd27605 | ||
|
300639e537 | ||
|
ad218f0786 | ||
|
4966f8cdf8 | ||
|
1580490670 | ||
|
3cf5e8cf4e | ||
|
d21ac80178 | ||
|
effbaa7770 | ||
|
a9a61abc81 | ||
|
e5b05424c8 | ||
|
8f920101f3 | ||
|
1c59474f45 | ||
|
9be7104b71 | ||
|
31e0ec71f2 | ||
|
6c33afc13c | ||
|
03daf42fb5 | ||
|
b33b68ef75 | ||
|
0ee8ca43d1 | ||
|
77da45a173 | ||
|
5e1c3c5d69 | ||
|
05953a20cc | ||
|
3c8a93b972 | ||
|
11543a229a | ||
|
d448e12cf4 | ||
|
fee4ad0174 | ||
|
38f01cf1f2 | ||
|
37bea9d162 | ||
|
b241fcd418 | ||
|
86e735cd5c | ||
|
4c40395a38 | ||
|
d32fd76b31 | ||
|
5f8e83d75d | ||
|
b08a17064e | ||
|
3f39cb38c4 | ||
|
2031ec1b57 | ||
|
533aaba5eb | ||
|
72c782af17 | ||
|
af8a3eff10 | ||
|
ee7ba54a7f | ||
|
53d99f5521 | ||
|
52d2975af3 | ||
|
926a651f12 | ||
|
7aeab7a63f | ||
|
a2389b3169 | ||
|
54e5cc296f | ||
|
457fd68168 | ||
|
2d69f35e0e | ||
|
648c780e91 | ||
|
f36618f02a | ||
|
8548a1dd7f | ||
|
5e1d58c41c | ||
|
a61d7f3864 | ||
|
c7fcaaf443 | ||
|
6d263f8680 | ||
|
d9ab6495ef | ||
|
ceac0ce9aa | ||
|
e975d6db17 | ||
|
d54b68b93c | ||
|
761346ed5a | ||
|
6d71dd0025 | ||
|
d0e2d9e2f4 | ||
|
b0effee9b3 | ||
|
abb7e85260 | ||
|
3ccd03e226 | ||
|
2ae345aa8f | ||
|
1c1b78aa1c | ||
|
cdb2308ddd | ||
|
c581f722bd | ||
|
340c98c6cd | ||
|
39f5c5bf49 | ||
|
392f6855ca | ||
|
1cae48ab93 | ||
|
25f04f3c37 | ||
|
d0f8ef09a0 | ||
|
0516dca116 | ||
|
ebc6a043c9 | ||
|
8e2ae79875 | ||
|
27ac764653 | ||
|
80df6e2b8d | ||
|
bfda8cf820 | ||
|
cb91f96fd3 | ||
|
549ec0aac8 | ||
|
5cea9f9e17 | ||
|
a9cce55693 | ||
|
e1152c33c4 | ||
|
e40ad5faa5 | ||
|
dd393a4a0e | ||
|
881954dfca | ||
|
cf12503fec | ||
|
ad757cccb6 | ||
|
b801eae00f | ||
|
2fe9ff7918 | ||
|
c407582096 | ||
|
0fc3dbaa9b | ||
|
77ed264714 | ||
|
a14efce914 | ||
|
08f90a188c | ||
|
df46eeafdb | ||
|
0029286a1e | ||
|
0e46d4eb98 | ||
|
f80e3fff92 | ||
|
504c6ba792 | ||
|
c0aba9aee1 | ||
|
fa33af248e | ||
|
e6cfbc00fc | ||
|
b97cf2b9d9 | ||
|
f81e7b2112 | ||
|
b59e4a929e | ||
|
099d72f037 | ||
|
73acb41931 | ||
|
ebb7fdb099 | ||
|
ec3cb0ad9a | ||
|
7ffef6792f | ||
|
383148dc31 | ||
|
a31601ccfc | ||
|
a587492cad | ||
|
f65d4914e4 | ||
|
88dc49a5b6 | ||
|
91d970e9c5 | ||
|
6c5ae48a05 | ||
|
d85ec2cbb4 | ||
|
527f305690 | ||
|
b05c9c26bd | ||
|
05b79bc378 | ||
|
3ba63315d5 | ||
|
eccdb594eb | ||
|
a78796f22c | ||
|
4fa6f791f4 | ||
|
6287eaa745 | ||
|
2ae13229ea | ||
|
2879d35f3d | ||
|
ab7d969700 | ||
|
e1031ac5ad | ||
|
1b1e7f4296 | ||
|
5a7d7cc9f5 | ||
|
4253bb9922 | ||
|
1bbf5f7a17 | ||
|
9abc83fdad | ||
|
8d5325b816 | ||
|
ad6fd451fb | ||
|
db3b3c62bb | ||
|
dfd181d7d5 | ||
|
de76045939 | ||
|
b707568fc1 | ||
|
16c29a7db5 | ||
|
b5b0002d24 | ||
|
127b92e3db | ||
|
a7ceb8ce66 | ||
|
6dea23128a | ||
|
5297c5f2ee | ||
|
bdb6b10be8 | ||
|
7f9031eae8 | ||
|
aa746bc0c8 | ||
|
01ca59ea91 | ||
|
2f4e19d514 | ||
|
8d5224eba7 | ||
|
c8436d3c1e | ||
|
1273413c7b | ||
|
ef3f48a2be | ||
|
4b1bca8b6e | ||
|
2478dd8322 | ||
|
4c1edd3881 | ||
|
14541480ae | ||
|
fff78b60e9 | ||
|
9abc7fc80b | ||
|
d8059ebdd2 | ||
|
1001445d3e | ||
|
fff72cf322 | ||
|
fd9306a282 | ||
|
7c0c2a8085 | ||
|
b5b58ced2a | ||
|
8c988a7b07 | ||
|
e68f58940c | ||
|
4f2b639a24 | ||
|
3e01924ca3 | ||
|
3841ae935c | ||
|
4d2884bde7 | ||
|
a4a7255216 | ||
|
6065165060 | ||
|
61c22d1c72 | ||
|
efacf2ff09 | ||
|
9272bf96f6 | ||
|
ae3efb2d2f | ||
|
b9ecae84f5 | ||
|
cd3286c71a | ||
|
83c2766e3f | ||
|
5f719c8ea3 | ||
|
555f7d5404 | ||
|
73b2913be3 | ||
|
3bcfc5539c | ||
|
4cfcc7e521 | ||
|
3221a8bdab | ||
|
930f059f5e | ||
|
bd3e596243 | ||
|
9a6e61e510 | ||
|
56d2d65e25 | ||
|
ae08963acc | ||
|
ed4f51436c | ||
|
7837354c6c | ||
|
a203a28de0 | ||
|
5dc6f134c5 | ||
|
6daeb7e504 | ||
|
fcf59ad135 | ||
|
1dd905d976 | ||
|
155f7cdeec | ||
|
960967623a | ||
|
3c963f65a2 | ||
|
168203ab0c | ||
|
f2fff53169 | ||
|
f74b8f715a | ||
|
aeac2b547f | ||
|
827aa9ca05 | ||
|
95c21acec1 | ||
|
4d035dce5d | ||
|
7f6dce1c22 | ||
|
58568a36ce | ||
|
9c2a2f01b7 | ||
|
657e536941 | ||
|
a81b6ea6af | ||
|
1887504666 | ||
|
8a61b01c06 | ||
|
6d564075f3 | ||
|
4cdf7aa65a | ||
|
329dc9e0cf | ||
|
e02de45537 | ||
|
29fbda49bb | ||
|
1b155341bd | ||
|
96c02c1eb4 | ||
|
116d662e0f | ||
|
d81cd4751f | ||
|
dd33068943 | ||
|
09c1e51b8a | ||
|
af9a9422c4 | ||
|
df3c85ea7f | ||
|
b14a115fc0 | ||
|
355a88d002 | ||
|
1014b3d972 | ||
|
1a2b1575d6 | ||
|
cc25fdf602 | ||
|
444eb2630c | ||
|
9c032bec89 | ||
|
5a59548d72 | ||
|
39913c2001 | ||
|
a858736516 | ||
|
880c33a777 | ||
|
c32ab9440d | ||
|
3a97b44321 | ||
|
2f18d5584d | ||
|
287b27dad3 | ||
|
33f0f2a2b1 | ||
|
bf6ba18048 | ||
|
058252e895 | ||
|
c594de8302 | ||
|
8eaf05a3ef | ||
|
9736bea29f | ||
|
ea392cf2b6 | ||
|
b0f8550b01 | ||
|
ba05963729 | ||
|
f14f7e7df6 | ||
|
daa97d4b79 | ||
|
4822b85cb0 | ||
|
7f61d7ac8b | ||
|
010ca5feef | ||
|
31a907be35 | ||
|
ab37fed974 | ||
|
10a7650411 | ||
|
fc4c6525e6 | ||
|
d7308f2d73 | ||
|
ead566b841 | ||
|
ecc2e02453 | ||
|
012c4b9425 | ||
|
be8fef9811 | ||
|
2938b48939 | ||
|
16c2e0a642 | ||
|
017510ea5f | ||
|
c43c0275e3 | ||
|
df5d233155 | ||
|
a8238c2251 | ||
|
c12d1fe29c | ||
|
347cdc63f8 | ||
|
32625381fa | ||
|
350f9e2636 | ||
|
4d9d50d8e1 | ||
|
106db1a9be | ||
|
e6d22fd8df | ||
|
8e2de53c3f | ||
|
0057af3668 | ||
|
7f7e4ab69e | ||
|
db4f60cc9d | ||
|
77cf390727 | ||
|
dcadf1422b | ||
|
53ac80d6c8 | ||
|
2e9fcdad6e | ||
|
0f55b3bc18 | ||
|
9c249fefc3 | ||
|
eae7ee6c25 | ||
|
bf7f302ff5 | ||
|
0d6981bd54 | ||
|
148d7bcc25 | ||
|
71161b6352 | ||
|
dd33a2f280 | ||
|
9d48d684a5 | ||
|
eb252d33a9 | ||
|
40bdf7e0d4 | ||
|
6aba047ace | ||
|
554045de6e | ||
|
fa42081556 | ||
|
54d0bcab71 | ||
|
3539128d42 | ||
|
372c68a1c9 | ||
|
f9856d547f | ||
|
d0d8f6b5ee | ||
|
28c91bf767 | ||
|
a8bfe4e6f2 | ||
|
1f076432db | ||
|
b6e79a7234 | ||
|
68b05cadd8 | ||
|
93c5fb0b31 | ||
|
cfdbf95cb6 | ||
|
b80e33b209 | ||
|
9f7254a2d0 | ||
|
00e59c385e | ||
|
43c2b53811 | ||
|
c645acc214 | ||
|
33d87bc22e | ||
|
a35f9102f2 | ||
|
525d773a30 | ||
|
d22812ae35 | ||
|
1dc70ebb07 | ||
|
297e4f6134 | ||
|
4e73297cb8 | ||
|
8fe16190b9 | ||
|
047ab10a5c | ||
|
3c8e9231ea | ||
|
cb9c57f223 | ||
|
253e8f0d64 | ||
|
4aee2c3c41 | ||
|
2641aad318 | ||
|
346fcdb405 | ||
|
9564e4c178 | ||
|
50dd958890 | ||
|
9126bf2c9d | ||
|
a692f0cb07 | ||
|
2bbfa92504 | ||
|
0e74355782 | ||
|
be137358f1 | ||
|
d9564df6a7 | ||
|
3f9ad44948 | ||
|
c73ff197e0 | ||
|
1ad1a13085 | ||
|
50e3a37b7a | ||
|
7d3970546c | ||
|
3d739c6a15 | ||
|
16692f9f5e | ||
|
4f453ab521 | ||
|
72a4fae8dc | ||
|
36c7d05445 | ||
|
f3d5683f67 | ||
|
120887979d | ||
|
77434fc9f9 | ||
|
830846b39c | ||
|
3073704010 | ||
|
e165dcf78d | ||
|
2d2fc59597 | ||
|
89020892a8 | ||
|
653f4d4183 | ||
|
d998d703ff | ||
|
43bec39794 | ||
|
e2067e3703 | ||
|
0e19a7d024 | ||
|
cdd0aa4cfd | ||
|
157c714d86 | ||
|
4873bb3099 | ||
|
7207810ce4 | ||
|
f072ff3861 | ||
|
3f05b17d37 | ||
|
4fef3c157a | ||
|
38602823bb | ||
|
6e02b9d5bc | ||
|
03337534f9 | ||
|
613a004d18 | ||
|
6fa23794fc | ||
|
82027bb51e | ||
|
9e5ce813c4 | ||
|
b7f3beda00 | ||
|
f4509a63b0 | ||
|
29559deeeb | ||
|
0cff62335b | ||
|
e4325e5b2b | ||
|
f57010180c | ||
|
5807b68d5b | ||
|
1af746e136 | ||
|
d3c78c8811 | ||
|
28a4f7a60a | ||
|
d54a9d241d | ||
|
8814c00573 | ||
|
36b55a8b57 | ||
|
e027843cb0 | ||
|
5de0ebab26 | ||
|
cc463d52f6 | ||
|
eeca361418 | ||
|
bdf56ec6d6 | ||
|
ee9e302b24 | ||
|
17b50f08b3 | ||
|
d58297fa15 | ||
|
c27516a1db | ||
|
cf4cd4abd8 | ||
|
a4cc95b293 | ||
|
a8bb6d5918 | ||
|
496c75617c | ||
|
6b14f221c1 | ||
|
9948e0a564 | ||
|
c89e029223 | ||
|
0ca569baab | ||
|
40b13bfa35 | ||
|
1df3c87ed5 | ||
|
0b57bd5a53 | ||
|
5df9b1cb5b | ||
|
f5b7e131d6 | ||
|
51012c1802 | ||
|
b5c1e77d4c | ||
|
85149445e0 | ||
|
61d0043f9c | ||
|
5c97089e59 | ||
|
6f5c610858 | ||
|
a05dd4d194 | ||
|
b1a840bec0 | ||
|
31fabecddd | ||
|
96cb38dd05 | ||
|
b672dabee8 | ||
|
5fbdec2a29 | ||
|
f22ae99b98 | ||
|
3be7ef17ff | ||
|
146422fabd | ||
|
a274a5ff4b | ||
|
d1d4d80a1d | ||
|
167d32811d | ||
|
6ec4a2a4a5 | ||
|
a11abf57e1 | ||
|
a63a201812 | ||
|
f09caced9b | ||
|
01cd2fe4bb | ||
|
45b93644b7 | ||
|
76a80d8f45 | ||
|
153b8399f7 | ||
|
da41271dd5 | ||
|
5610af1b77 | ||
|
8da70fec91 | ||
|
f9cd30a859 | ||
|
763d620a23 | ||
|
500a3a6dee | ||
|
57073e1057 | ||
|
6bbfd2f62a | ||
|
6c69a96cd7 | ||
|
fa247d5a84 | ||
|
0320c4ac14 | ||
|
36993ac707 | ||
|
2f93eb4a28 | ||
|
5a2982ac31 | ||
|
441b704afd | ||
|
abf6ebd7fe | ||
|
34fb08af6e | ||
|
0b9dfdd41f | ||
|
701e0812e4 | ||
|
4918a46172 | ||
|
ef5e3fae64 | ||
|
9fcf55571e | ||
|
260898ecf6 | ||
|
66c9132abe | ||
|
c5abdfb72b | ||
|
4fe37847ba | ||
|
c99a0b0518 | ||
|
31f3edec5c | ||
|
dee372c08e | ||
|
8c0a4e5a6e | ||
|
7195514fb5 | ||
|
420bd5bc16 | ||
|
f024ee1adf | ||
|
18c2c71cd5 | ||
|
2d1bfc84b9 | ||
|
8edfa759fb | ||
|
2d1e978599 | ||
|
d71fc41152 | ||
|
d141cb7b72 | ||
|
b19cf5998f | ||
|
7010067884 | ||
|
0ec29c4176 | ||
|
42c6e0249f | ||
|
54eb85f814 | ||
|
18b3b4feed | ||
|
0045ac839b | ||
|
a9da807de3 | ||
|
366639b7e4 | ||
|
7d2e2171be | ||
|
e3ceda15ac | ||
|
7291a21a85 | ||
|
888afe3e46 | ||
|
171bfde133 | ||
|
82d1fdb714 | ||
|
82b19daa7e | ||
|
dc1ff3c2e3 | ||
|
6602ac5eae | ||
|
5dab5bf0e9 | ||
|
721be8fe9f | ||
|
58fe590eae | ||
|
c18a7ff5cf | ||
|
24fc38b287 | ||
|
aa03c50f05 | ||
|
03e971b2e3 | ||
|
a595133b77 | ||
|
e50f4ecccf | ||
|
67913e4af0 | ||
|
b3d1795327 | ||
|
6edcc8f256 | ||
|
d5e5f47666 | ||
|
0524c40640 | ||
|
b5fd894f77 | ||
|
d8492121aa | ||
|
4a0bf603d7 | ||
|
02fa89df9e | ||
|
5b6dde9a73 | ||
|
e9d8ebdfc9 | ||
|
366efc3d61 | ||
|
3b890fd3c1 | ||
|
5de373a14b | ||
|
24cb9d2437 | ||
|
83aa176466 | ||
|
0e94e5ecda | ||
|
130485a583 | ||
|
f34c10abb5 | ||
|
48b00f0ac1 | ||
|
743329a3af | ||
|
f5783f1637 | ||
|
67f61a8d39 | ||
|
f7df663dea | ||
|
c99278aa58 | ||
|
1765e1b7c2 | ||
|
bf1a434d5c | ||
|
9256b5b552 | ||
|
577e4afb3c | ||
|
2a05c04db7 | ||
|
a6ffd6b3b2 | ||
|
24eba7c4c1 | ||
|
80de844922 | ||
|
a2223c0884 | ||
|
5ffa2b757c | ||
|
b660fa27d3 | ||
|
77f0e5e1ba | ||
|
32a4f805b8 |
@@ -117,10 +117,11 @@ release-build:
|
||||
EXTRA_MESON_FLAGS: "--buildtype=release"
|
||||
script:
|
||||
- .gitlab-ci/show-info-linux.sh
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- mkdir _install
|
||||
- export PATH="$HOME/.local/bin:${CI_PROJECT_DIR}/_install/bin:$PATH"
|
||||
- .gitlab-ci/install-meson-project.sh --prefix ${CI_PROJECT_DIR}/_install https://gitlab.gnome.org/jadahl/catch.git main
|
||||
- meson subprojects download
|
||||
- meson subprojects update --reset
|
||||
- mkdir _install
|
||||
- meson setup
|
||||
--prefix=${CI_PROJECT_DIR}/_install
|
||||
${COMMON_MESON_FLAGS}
|
||||
@@ -445,9 +446,10 @@ reference:
|
||||
--force-fallback-for=gdk-pixbuf,pango
|
||||
-Dintrospection=enabled
|
||||
-Ddocumentation=true
|
||||
-Dman-pages=true
|
||||
-Dgdk-pixbuf:gtk_doc=true
|
||||
-Dpango:documentation=true
|
||||
-Dbuild-demos=false
|
||||
-Dbuild-demos=true
|
||||
-Dbuild-examples=false
|
||||
-Dbuild-tests=false
|
||||
-Dbuild-testsuite=false
|
||||
|
91
.gitlab-ci/install-meson-project.sh
Executable file
91
.gitlab-ci/install-meson-project.sh
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
usage() {
|
||||
cat <<-EOF
|
||||
Usage: $(basename $0) [OPTION…] REPO_URL COMMIT
|
||||
|
||||
Check out and install a meson project
|
||||
|
||||
Options:
|
||||
-Dkey=val Option to pass on to meson
|
||||
--prefix Prefix to install to
|
||||
--subdir Build subdirectory instead of whole project
|
||||
--prepare Script to run before build
|
||||
|
||||
-h, --help Display this help
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
TEMP=$(getopt \
|
||||
--name=$(basename $0) \
|
||||
--options='D:h' \
|
||||
--longoptions='prefix:' \
|
||||
--longoptions='subdir:' \
|
||||
--longoptions='prepare:' \
|
||||
--longoptions='help' \
|
||||
-- "$@")
|
||||
|
||||
eval set -- "$TEMP"
|
||||
unset TEMP
|
||||
|
||||
MESON_OPTIONS=()
|
||||
PREFIX=/usr
|
||||
SUBDIR=.
|
||||
PREPARE=:
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
-D)
|
||||
MESON_OPTIONS+=( -D$2 )
|
||||
shift 2
|
||||
;;
|
||||
|
||||
--prefix)
|
||||
PREFIX=$2
|
||||
shift 2
|
||||
;;
|
||||
|
||||
--subdir)
|
||||
SUBDIR=$2
|
||||
shift 2
|
||||
;;
|
||||
|
||||
--prepare)
|
||||
PREPARE=$2
|
||||
shift 2
|
||||
;;
|
||||
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $# -lt 2 ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REPO_URL="$1"
|
||||
COMMIT="$2"
|
||||
|
||||
CHECKOUT_DIR=$(mktemp --directory)
|
||||
trap "rm -rf $CHECKOUT_DIR" EXIT
|
||||
|
||||
git clone --depth 1 "$REPO_URL" -b "$COMMIT" "$CHECKOUT_DIR"
|
||||
|
||||
pushd "$CHECKOUT_DIR/$SUBDIR"
|
||||
sh -c "$PREPARE"
|
||||
meson setup --prefix "$PREFIX" _build "${MESON_OPTIONS[@]}"
|
||||
meson compile -C _build
|
||||
meson install -C _build
|
||||
popd
|
@@ -100,14 +100,16 @@ development tools appropriate for your operating system, including:
|
||||
- Meson
|
||||
- Ninja
|
||||
- Gettext (19.7 or newer)
|
||||
- a [C99 compatible compiler](https://wiki.gnome.org/Projects/GLib/CompilerRequirements)
|
||||
- a [C99 compatible compiler][glib-toolchain-reqs]
|
||||
|
||||
Up-to-date instructions about developing GNOME applications and libraries
|
||||
can be found on [the GNOME Developer Center](https://developer.gnome.org).
|
||||
|
||||
The GTK project uses GitLab for code hosting and for tracking issues. More
|
||||
information about using GitLab can be found [on the GNOME
|
||||
wiki](https://wiki.gnome.org/GitLab).
|
||||
information about using GitLab can be found on [the GNOME handbook][handbook].
|
||||
|
||||
[glib-toolchain-reqs]: https://gitlab.gnome.org/GNOME/glib/-/blob/main/docs/toolchain-requirements.md
|
||||
[handbook]: https://handbook.gnome.org/infrastructure/gitlab.html
|
||||
|
||||
### Dependencies
|
||||
|
||||
@@ -131,7 +133,7 @@ GTK will attempt to download and build some of these dependencies if it
|
||||
cannot find them on your system.
|
||||
|
||||
Additionally, you may want to look at projects that create a development
|
||||
environment for you, like [jhbuild](https://wiki.gnome.org/HowDoI/Jhbuild)
|
||||
environment for you, like [jhbuild](https://gitlab.gnome.org/GNOME/jhbuild)
|
||||
and [gvsbuild](https://github.com/wingtk/gvsbuild).
|
||||
|
||||
### Getting started
|
||||
|
138
NEWS
138
NEWS
@@ -1,6 +1,142 @@
|
||||
Overview of Changes in 4.15.2, xx-xx-xxxx
|
||||
Overview of Changes in 4.15.5, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
Overview of Changes in 4.15.4, 30-07-2024
|
||||
=========================================
|
||||
|
||||
* GtkPopover:
|
||||
- Fix size allocation with wrapping labels
|
||||
|
||||
* GtkColumnView:
|
||||
- Check column visibility when measuring
|
||||
|
||||
* CSS:
|
||||
- Fix fallout from recent changes
|
||||
- Make implementation of currentcolor inheritance match browsers
|
||||
|
||||
* Gdk:
|
||||
- Introduce GdkColorState for encoding color space information
|
||||
Currently, we support srgb, srgb-linear, rec2100-pq and rec2100-linear
|
||||
- Add color states to GdkTexture, as well as to the texture builder
|
||||
and downloader objects, and convert as necessary
|
||||
- Add GdkMemoryTextureBuilder
|
||||
- Attach color states when loading or saving textures
|
||||
- Add GdkCicpParams to create color state objects for cicp tuples
|
||||
- Drop GDK_DEBUG=vulkan-validate
|
||||
Use VK_INSTEANCE_LAYERS=VK_LAYER_KHRONOS_validation instead
|
||||
|
||||
* Gsk:
|
||||
- Improve caching of glyphs and textures
|
||||
- Remove the uber shader
|
||||
- Numerous bug fixes
|
||||
- Fix corner cases in offload handling
|
||||
- Implement occlusion culling for opaque content
|
||||
- Allow offloading (some) transformed textures
|
||||
- Take colorstate into account when compositing
|
||||
- Add GDK_DEBUG=linear to opt into linear compositing
|
||||
- Implement tiling for large textures
|
||||
- Stop using descriptors and go back to simpler texture
|
||||
management that should work better with older GL
|
||||
- Use correct shader clip mode for glyphs
|
||||
- Improve shadow rendering
|
||||
|
||||
* Media:
|
||||
- Attach color states to textures obtained from gstreamer
|
||||
|
||||
* Wayland:
|
||||
- Allow offloading GL textures via dmabuf export
|
||||
- Suppot the xx-color-management-v4 protocol
|
||||
|
||||
* Deprecations:
|
||||
- GskGLShader and the render node
|
||||
|
||||
* Tools:
|
||||
- Improve the rendernode tool extract command
|
||||
- Add an image tool that is about manipulating textures
|
||||
|
||||
* Build:
|
||||
- GTK now requires a C11 compiler
|
||||
|
||||
* Translation updates
|
||||
Georgian
|
||||
Hebrew
|
||||
Hindi
|
||||
Occitan
|
||||
Slovenian
|
||||
|
||||
|
||||
Overview of Changes in 4.15.3, 29-06-2024
|
||||
=========================================
|
||||
|
||||
* Accessibility:
|
||||
- Only emit notifications when cursor positions change in GtkText
|
||||
- Fix handling of help text properties
|
||||
|
||||
* CSS:
|
||||
- Fix some crashes introduced in recent currentcolor changes
|
||||
|
||||
* DND:
|
||||
- Avoid a critical
|
||||
|
||||
* Documentation:
|
||||
- Fix many oversights and missing docs
|
||||
|
||||
* maxOS:
|
||||
- Add native keyboard shortcuts
|
||||
|
||||
|
||||
Overview of Changes in 4.15.2, 28-06-2024
|
||||
=========================================
|
||||
|
||||
* GtkFileChooserWidget:
|
||||
- Plug some memory leaks
|
||||
- Make Ctrl-Shift-N create a new folder
|
||||
|
||||
* GtkPopover:
|
||||
- Handle resizing and position changes better
|
||||
|
||||
* CSS:
|
||||
- Support color(), oklab(), etc (https://www.w3.org/TR/css-color-4/)
|
||||
- Support color-mix() (https://www.w3.org/TR/css-color-5/)
|
||||
- Support relative colors (https://www.w3.org/TR/css-color-5/)
|
||||
- Support more colorspaces in color()
|
||||
- Allow percentages for opacity
|
||||
- Handle currentcolor more correctly
|
||||
|
||||
* Accessibility:
|
||||
- Avoid markup when reading labels
|
||||
|
||||
* GSK:
|
||||
- Subset fonts when serializing node trees
|
||||
- Make ngl export render_texture results as dmabufs
|
||||
|
||||
* Wayland:
|
||||
- Use xdg-dialog protocol for attached dialogs
|
||||
|
||||
* Windows:
|
||||
- Build with UNICODE
|
||||
|
||||
* macOS:
|
||||
- Implement fullscreen-on-monitor
|
||||
|
||||
* Documentation:
|
||||
- Widget shortcuts and actions are now described in the docs
|
||||
|
||||
* Debugging:
|
||||
- Add GTK_DEBUG=css for warning about deprecated css syntax
|
||||
|
||||
* Tools:
|
||||
- rendernode-tool: Add an extract command for data urls
|
||||
|
||||
* Deprecations:
|
||||
- CSS Color functions shade(), lighter(), darker(), alpha(), mix()
|
||||
|
||||
* Translation updates:
|
||||
Czech
|
||||
Hebrew
|
||||
Serbian
|
||||
|
||||
|
||||
Overview of Changes in 4.15.1, 21-05-2024
|
||||
=========================================
|
||||
|
||||
|
15
README.md
15
README.md
@@ -39,18 +39,21 @@ Nightly documentation can be found at
|
||||
- Gsk: https://gnome.pages.gitlab.gnome.org/gtk/gsk4/
|
||||
|
||||
Nightly flatpaks of our demos can be installed from the
|
||||
[GNOME Nightly](https://wiki.gnome.org/Apps/Nightly) repository:
|
||||
- `flatpak remote-add --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo`
|
||||
- `flatpak install gnome-nightly org.gtk.Demo4`
|
||||
- `flatpak install gnome-nightly org.gtk.WidgetFactory4`
|
||||
- `flatpak install gnome-nightly org.gtk.IconBrowser4`
|
||||
[GNOME Nightly](https://nightly.gnome.org/) repository:
|
||||
|
||||
```sh
|
||||
flatpak remote-add --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo
|
||||
flatpak install gnome-nightly org.gtk.Demo4
|
||||
flatpak install gnome-nightly org.gtk.WidgetFactory4
|
||||
flatpak install gnome-nightly org.gtk.IconBrowser4
|
||||
```
|
||||
|
||||
Building and installing
|
||||
-----------------------
|
||||
|
||||
In order to build GTK you will need:
|
||||
|
||||
- [a C99 compatible compiler](https://wiki.gnome.org/Projects/GLib/CompilerRequirements)
|
||||
- [a C11 compatible compiler](https://gitlab.gnome.org/GNOME/glib/-/blob/main/docs/toolchain-requirements.md)
|
||||
- [Python 3](https://www.python.org/)
|
||||
- [Meson](http://mesonbuild.com)
|
||||
- [Ninja](https://ninja-build.org)
|
||||
|
@@ -170,6 +170,7 @@ update_paintable (GtkWidget *widget,
|
||||
static GtkWidget *
|
||||
create_cogs (void)
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
GtkWidget *picture;
|
||||
static GskGLShader *cog_shader = NULL;
|
||||
GdkPaintable *paintable;
|
||||
@@ -182,6 +183,7 @@ create_cogs (void)
|
||||
gtk_widget_add_tick_callback (picture, update_paintable, NULL, NULL);
|
||||
|
||||
return picture;
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@@ -20,6 +20,8 @@
|
||||
#include "gtkshadertoy.h"
|
||||
#include "gskshaderpaintable.h"
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
static GtkWidget *demo_window = NULL;
|
||||
|
||||
static void
|
||||
@@ -360,3 +362,5 @@ do_gltransition (GtkWidget *do_widget)
|
||||
|
||||
return demo_window;
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
@@ -22,6 +22,8 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "gskshaderpaintable.h"
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
/**
|
||||
* GskShaderPaintable:
|
||||
*
|
||||
@@ -332,3 +334,5 @@ gsk_shader_paintable_update_time (GskShaderPaintable *self,
|
||||
|
||||
g_bytes_unref (args);
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
@@ -22,6 +22,8 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <gsk/gsk.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_SHADER_PAINTABLE (gsk_shader_paintable_get_type ())
|
||||
@@ -41,3 +43,5 @@ void gsk_shader_paintable_update_time (GskShaderPaintable *self
|
||||
int time_idx,
|
||||
gint64 frame_time);
|
||||
G_END_DECLS
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#include "gtkshaderbin.h"
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
typedef struct {
|
||||
GskGLShader *shader;
|
||||
GtkStateFlags state;
|
||||
@@ -262,3 +264,5 @@ gtk_shader_bin_new (void)
|
||||
|
||||
return GTK_WIDGET (self);
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SHADER_BIN (gtk_shader_bin_get_type ())
|
||||
@@ -18,3 +20,5 @@ void gtk_shader_bin_set_child (GtkShaderBin *self,
|
||||
GtkWidget *gtk_shader_bin_get_child (GtkShaderBin *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#include "gtkshaderstack.h"
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
struct _GtkShaderStack
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
@@ -359,3 +361,5 @@ gtk_shader_stack_set_active (GtkShaderStack *self,
|
||||
self->current = MIN (index, self->children->len);
|
||||
update_child_visible (self);
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SHADER_STACK (gtk_shader_stack_get_type ())
|
||||
@@ -18,3 +20,5 @@ void gtk_shader_stack_set_active (GtkShaderStack *self,
|
||||
int index);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
@@ -936,7 +936,7 @@ search_results_update (GObject *filter_model,
|
||||
char *text;
|
||||
|
||||
if (n_items > 0)
|
||||
text = g_strdup_printf (ngettext ("%ld search result", "%ld search results", n_items), n_items);
|
||||
text = g_strdup_printf (ngettext ("%ld search result", "%ld search results", (long) n_items), (long) n_items);
|
||||
else
|
||||
text = g_strdup (_("No search results"));
|
||||
|
||||
|
@@ -299,7 +299,7 @@ node_editor_application_new (void)
|
||||
|
||||
app = g_object_new (NODE_EDITOR_APPLICATION_TYPE,
|
||||
"application-id", "org.gtk.gtk4.NodeEditor",
|
||||
"flags", G_APPLICATION_HANDLES_OPEN,
|
||||
"flags", G_APPLICATION_HANDLES_OPEN | G_APPLICATION_NON_UNIQUE,
|
||||
NULL);
|
||||
|
||||
g_application_add_main_option (G_APPLICATION (app), "version", 0, 0,G_OPTION_ARG_NONE, "Show program version", NULL);
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<gresource prefix="/org/gtk/gtk4/node-editor">
|
||||
<file preprocess="xml-stripblanks">node-editor-window.ui</file>
|
||||
<file preprocess="xml-stripblanks">help-window.ui</file>
|
||||
<file>node-format.md</file>
|
||||
<file alias='node-format.md'>../../docs/reference/gtk/node-format.md</file>
|
||||
<file alias='icons/apps/org.gtk.gtk4.NodeEditor.svg'>data/scalable/apps/org.gtk.gtk4.NodeEditor.svg</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
@@ -111,3 +111,11 @@ content_images = [
|
||||
]
|
||||
content_base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/docs/reference/gdk/"
|
||||
urlmap_file = "urlmap.js"
|
||||
|
||||
[[object]]
|
||||
name = "DECLARE_INTERNAL_TYPE"
|
||||
hidden = true
|
||||
|
||||
[[object]]
|
||||
pattern = "KEY_*"
|
||||
check_ignore = true
|
||||
|
@@ -29,6 +29,18 @@ if get_option('documentation')
|
||||
install_dir: docs_dir,
|
||||
)
|
||||
|
||||
test('doc-check-gdk',
|
||||
gidocgen,
|
||||
args: [
|
||||
'check',
|
||||
'--config', gdk4_toml,
|
||||
'--add-include-path=@0@'.format(meson.current_build_dir() / '../../../gtk'),
|
||||
gdk_gir[0],
|
||||
],
|
||||
depends: gdk_gir[0],
|
||||
suite: ['docs'],
|
||||
)
|
||||
|
||||
if x11_enabled
|
||||
gdk4x11_toml = configure_file(
|
||||
input: 'gdk4-x11.toml.in',
|
||||
@@ -87,5 +99,17 @@ if get_option('documentation')
|
||||
install: true,
|
||||
install_dir: docs_dir,
|
||||
)
|
||||
|
||||
test('doc-check-gdk-wayland',
|
||||
gidocgen,
|
||||
args: [
|
||||
'check',
|
||||
'--config', gdk4wayland_toml,
|
||||
'--add-include-path=@0@'.format(meson.current_build_dir() / '../../../gtk'),
|
||||
gdk_wayland_gir[0],
|
||||
],
|
||||
depends: gdk_wayland_gir[0],
|
||||
suite: ['docs'],
|
||||
)
|
||||
endif
|
||||
endif
|
||||
|
@@ -66,3 +66,7 @@ content_images = [
|
||||
]
|
||||
content_base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/docs/reference/gsk/"
|
||||
urlmap_file = "urlmap.js"
|
||||
|
||||
[[object]]
|
||||
name = "INCLUDE_WARNING"
|
||||
hidden = true
|
||||
|
@@ -30,4 +30,16 @@ if get_option('documentation')
|
||||
install: true,
|
||||
install_dir: docs_dir,
|
||||
)
|
||||
|
||||
test('doc-check-gsk',
|
||||
gidocgen,
|
||||
args: [
|
||||
'check',
|
||||
'--config', gsk4_toml,
|
||||
'--add-include-path=@0@'.format(meson.current_build_dir() / '../../../gtk'),
|
||||
gsk_gir[0],
|
||||
],
|
||||
depends: gsk_gir[0],
|
||||
suite: ['docs'],
|
||||
)
|
||||
endif
|
||||
|
@@ -140,7 +140,7 @@ Other libraries are maintained separately.
|
||||
file formats. It is available [here](ttps://download.gnome.org/sources/gdk-pixbuf/).
|
||||
- [Pango](http://www.pango.org) is a library for internationalized
|
||||
text handling. It is available [here](https://download.gnome.org/sources/pango/).
|
||||
- [GObject Introspection](https://wiki.gnome.org/Projects/GObjectIntrospection)
|
||||
- [GObject Introspection](https://gitlab.gnome.org/GNOME/gobject-introspection)
|
||||
is a framework for making introspection data available to language
|
||||
bindings. It is available [here](https://download.gnome.org/sources/gobject-introspection/).
|
||||
- The [GNU libiconv](https://www.gnu.org/software/libiconv/) library
|
||||
|
@@ -93,11 +93,12 @@ Colors can be expressed in numerous ways in CSS (see the
|
||||
many (but not all) of these.
|
||||
|
||||
You can use rgb(), rgba(), hsl() with both the legacy or the modern CSS
|
||||
syntax, and calc() can be used as well in color expressions.
|
||||
syntax, and calc() can be used as well in color expressions. hwb(), oklab(),
|
||||
oklch(), color(), color-mix() and relative colors are supported as well.
|
||||
|
||||
### Non-CSS Colors
|
||||
|
||||
GTK extends the CSS syntax with several additional ways to specify colors.
|
||||
GTK extends the CSS syntax with several additional ways to specify colors.
|
||||
|
||||
These extensions are deprecated and should be replaced by the equivalent
|
||||
standard CSS notions.
|
||||
|
@@ -99,16 +99,15 @@ reaches the requested phase. However, in practice most things
|
||||
happen at higher levels:
|
||||
|
||||
- If you are doing an animation, you can use
|
||||
gtk_widget_add_tick_callback() which will cause a regular
|
||||
[method@Gtk.Widget.add_tick_callback] which will cause a regular
|
||||
beating of the clock with a callback in the Update phase
|
||||
until you stop the tick.
|
||||
- If some state changes that causes the size of your widget to
|
||||
change you call gtk_widget_queue_resize() which will request
|
||||
change you call [method@Gtk.Widget.queue_resize] which will request
|
||||
a Layout phase and mark your widget as needing relayout.
|
||||
- If some state changes so you need to redraw some area of
|
||||
your widget you use the normal gtk_widget_queue_draw()
|
||||
set of functions. These will request a Paint phase and
|
||||
mark the region as needing redraw.
|
||||
- If some state changes so you need to redraw your widget you
|
||||
use [method@Gtk.Widget.queue_draw] to request a Paint phase for
|
||||
your widget.
|
||||
|
||||
There are also a lot of implicit triggers of these from the
|
||||
CSS layer (which does animations, resizes and repaints as needed).
|
||||
|
@@ -245,9 +245,6 @@ to connect the "clicked" signal with [method@Gtk.Window.destroy], then the funct
|
||||
would be called on `button` (which would not go well, since the function expects
|
||||
a `GtkWindow` as argument).
|
||||
|
||||
More information about creating buttons can be found
|
||||
[here](https://wiki.gnome.org/HowDoI/Buttons).
|
||||
|
||||
The rest of the code in `example-1.c` is identical to `example-0.c`. The next
|
||||
section will elaborate further on how to add several [class@Gtk.Widget]s to your
|
||||
GTK application.
|
||||
|
97
docs/reference/gtk/gtk4-image-tool.rst
Normal file
97
docs/reference/gtk/gtk4-image-tool.rst
Normal file
@@ -0,0 +1,97 @@
|
||||
.. _gtk4-image-tool(1):
|
||||
|
||||
====================
|
||||
gtk4-image-tool
|
||||
====================
|
||||
|
||||
-----------------------
|
||||
Image Utility
|
||||
-----------------------
|
||||
|
||||
:Version: GTK
|
||||
:Manual section: 1
|
||||
:Manual group: GTK commands
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
| **gtk4-image-tool** <COMMAND> [OPTIONS...] <FILE>...
|
||||
|
|
||||
| **gtk4-image-tool** compare [OPTIONS...] <FILE1> <FILE2>
|
||||
| **gtk4-image-tool** convert [OPTIONS...] <FILE1> <FILE2>
|
||||
| **gtk4-image-tool** info [OPTIONS...] <FILE>
|
||||
| **gtk4-image-tool** relabel [OPTIONS...] <FILE1> <FILE2>
|
||||
| **gtk4-image-tool** show [OPTIONS...] <FILE>...
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
``gtk4-image-tool`` can perform various operations on images.
|
||||
|
||||
COMMANDS
|
||||
--------
|
||||
|
||||
Information
|
||||
^^^^^^^^^^^
|
||||
|
||||
The ``info`` command shows general information about the image, such
|
||||
as its format and color state.
|
||||
|
||||
Showing
|
||||
^^^^^^^
|
||||
|
||||
The ``show`` command displays one or more images, side-by-side.
|
||||
|
||||
``--undecorated``
|
||||
|
||||
Removes window decorations. This is meant for rendering of exactly the image
|
||||
without any titlebar.
|
||||
|
||||
Compare
|
||||
^^^^^^^
|
||||
|
||||
The ``compare`` command compares two images. If any differences are found,
|
||||
the exit code is 1. If the images are identical, it is 0.
|
||||
|
||||
``--output=FILE``
|
||||
|
||||
Save the differences as a png image in ``FILE``.
|
||||
|
||||
``--quiet``
|
||||
|
||||
Don't write results to stdout.
|
||||
|
||||
Conversion
|
||||
^^^^^^^^^^
|
||||
|
||||
The ``convert`` command converts the image to a different format or color state.
|
||||
|
||||
``--format=FORMAT``
|
||||
|
||||
Convert to the given format. The supported formats can be listed
|
||||
with ``--format=list``.
|
||||
|
||||
``--color-state=COLORSTATE``
|
||||
|
||||
Convert to the given color state. The supported color states can be
|
||||
listed with ``--format=list``.
|
||||
|
||||
``--cicp=CICP``
|
||||
|
||||
Convert to a color state that is specified as a cicp tuple. The cicp tuple
|
||||
must be specified as four numbers, separated by /, e.g. 1/13/6/0.
|
||||
|
||||
Relabeling
|
||||
^^^^^^^^^^
|
||||
|
||||
The ``relabel`` command changes the color state of an image without conversion.
|
||||
This can be useful to produce wrong color renderings for diagnostics.
|
||||
|
||||
``--color-state=COLORSTATE``
|
||||
|
||||
Relabel to the given color state. The supported color states can be
|
||||
listed with ``--format=list``.
|
||||
|
||||
``--cicp=CICP``
|
||||
|
||||
Relabel to a color state that is specified as a cicp tuple. The cicp tuple
|
||||
must be specified as four numbers, separated by /, e.g. 1/13/6/0.
|
@@ -18,6 +18,7 @@ SYNOPSIS
|
||||
|
|
||||
| **gtk4-rendernode-tool** benchmark [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** compare [OPTIONS...] <FILE1> <FILE2>
|
||||
| **gtk4-rendernode-tool** extract [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** info [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** render [OPTIONS...] <FILE> [<FILE>]
|
||||
| **gtk4-rendernode-tool** show [OPTIONS...] <FILE>
|
||||
@@ -99,3 +100,15 @@ exit code is 1. If the images are identical, it is 0.
|
||||
``--quiet``
|
||||
|
||||
Don't write results to stdout.
|
||||
|
||||
|
||||
Extract
|
||||
^^^^^^^
|
||||
|
||||
The ``extract`` command saves all the data urls found in a node file to a given
|
||||
directory. The file names for the extracted files are derived from the mimetype
|
||||
of the url.
|
||||
|
||||
``--dir=DIRECTORY``
|
||||
|
||||
Save extracted files in ``DIRECTORY`` (defaults to the current directory).
|
||||
|
@@ -77,6 +77,7 @@ content_files = [
|
||||
"section-tree-widget.md",
|
||||
"migrating-2to4.md",
|
||||
"migrating-3to4.md",
|
||||
"migrating-4to5.md",
|
||||
"broadway.md",
|
||||
"osx.md",
|
||||
"wayland.md",
|
||||
@@ -84,6 +85,7 @@ content_files = [
|
||||
"x11.md",
|
||||
"tools.md",
|
||||
"visual_index.md",
|
||||
"node-format.md",
|
||||
]
|
||||
content_images = [
|
||||
"../images/favicon.svg",
|
||||
@@ -250,3 +252,12 @@ content_images = [
|
||||
]
|
||||
content_base_url = "https://gitlab.gnome.org/GNOME/gtk/-/blob/main/docs/reference/gtk/"
|
||||
urlmap_file = "urlmap.js"
|
||||
|
||||
[[object]]
|
||||
name = "StyleProvider"
|
||||
[[object.signal]]
|
||||
name = "gtk-private-changed"
|
||||
hidden = true
|
||||
|
||||
[check]
|
||||
skip_deprecated = true
|
||||
|
@@ -140,6 +140,11 @@ capture phase, and key bindings locally, during the target phase.
|
||||
Under the hood, all shortcuts are represented as instances of `GtkShortcut`,
|
||||
and they are managed by `GtkShortcutController`.
|
||||
|
||||
Note that GTK does not do anything to map the primary shortcut modifier
|
||||
to <kbd>Command</kbd> on macOS. If you want to let your application to follow
|
||||
macOS user experience conventions, you must create macOS-specific keyboard shortcuts.
|
||||
The <kbd>Command</kbd> is named `Meta` (`GDK_META_MASK`) in GTK.
|
||||
|
||||
## Text input
|
||||
|
||||
When actual text input is needed (i.e. not just keyboard shortcuts),
|
||||
|
@@ -14,6 +14,7 @@ expand_content_md_files = [
|
||||
'running.md',
|
||||
'migrating-2to4.md',
|
||||
'migrating-3to4.md',
|
||||
'migrating-4to5.md',
|
||||
'actions.md',
|
||||
'input-handling.md',
|
||||
'drawing-model.md',
|
||||
@@ -63,6 +64,18 @@ if get_option('documentation')
|
||||
install_dir: docs_dir,
|
||||
install_tag: 'doc',
|
||||
)
|
||||
|
||||
test('doc-check-gtk',
|
||||
gidocgen,
|
||||
args: [
|
||||
'check',
|
||||
'--config', gtk4_toml,
|
||||
'--add-include-path=@0@'.format(meson.current_build_dir() / '../../../gtk'),
|
||||
gtk_gir[0],
|
||||
],
|
||||
depends: gtk_gir[0],
|
||||
suite: ['docs'],
|
||||
)
|
||||
endif
|
||||
|
||||
rst2man = find_program('rst2man', 'rst2man.py', required: get_option('man-pages'))
|
||||
@@ -72,6 +85,7 @@ rst_files = [
|
||||
[ 'gtk4-broadwayd', '1' ],
|
||||
[ 'gtk4-builder-tool', '1' ],
|
||||
[ 'gtk4-encode-symbolic-svg', '1', ],
|
||||
[ 'gtk4-image-tool', '1' ],
|
||||
[ 'gtk4-launch', '1', ],
|
||||
[ 'gtk4-query-settings', '1', ],
|
||||
[ 'gtk4-rendernode-tool', '1' ],
|
||||
|
@@ -451,11 +451,11 @@ hint about how modifiers are expected to be used. It also promoted
|
||||
the use of `<Primary>` instead of `<Control>` to specify accelerators that
|
||||
adapt to platform conventions.
|
||||
|
||||
In GTK 4, the meaning of modifiers has been fixed, and backends are
|
||||
In GTK 4, the meaning of modifiers has been fixed, and applications are
|
||||
expected to map the platform conventions to the existing modifiers.
|
||||
The expected use of modifiers in GTK 4 is:
|
||||
|
||||
`GDK_CONTROL_MASK`
|
||||
`GDK_CONTROL_MASK` (`GDK_META_MASK` on macOS)
|
||||
: Primary accelerators
|
||||
|
||||
`GDK_ALT_MASK`
|
||||
@@ -464,7 +464,7 @@ The expected use of modifiers in GTK 4 is:
|
||||
`GDK_SHIFT_MASK`
|
||||
: Extending selections
|
||||
|
||||
`GDK_CONTROL_MASK`
|
||||
`GDK_CONTROL_MASK` (`GDK_META_MASK` on macOS)
|
||||
: Modifying selections
|
||||
|
||||
`GDK_CONTROL_MASK|GDK_ALT_MASK`
|
||||
@@ -473,9 +473,15 @@ The expected use of modifiers in GTK 4 is:
|
||||
Consequently, `GdkModifierIntent` and related APIs have been removed,
|
||||
and `<Control>` is preferred over `<Primary>` in accelerators.
|
||||
|
||||
In GTK 3 on macOS, the `<Primary>` modifier mapped to the <kbd>Command</kbd> key.
|
||||
In GTK 4, this is no longer the case: `<Primary>` is synonymous to `<Control>`.
|
||||
If you want to make your application to feel native on macOS,
|
||||
you need to add accelerators for macOS that use the `<Meta>` modifier.
|
||||
|
||||
A related change is that GTK 4 no longer supports the use of archaic
|
||||
X11 'real' modifiers with the names Mod1,..., Mod5, and `GDK_MOD1_MASK`
|
||||
has been renamed to `GDK_ALT_MASK`.
|
||||
has been renamed to `GDK_ALT_MASK` and `GDK_MOD2_MASK` has been renamed to
|
||||
`GDK_META_MASK`.
|
||||
|
||||
### Replace `GtkClipboard` with `GdkClipboard`
|
||||
|
||||
|
@@ -58,7 +58,7 @@ use a GtkLabel.
|
||||
If you have a need for custom drawing that fits into the current
|
||||
(dark or light) theme, e.g. for rendering a graph, you can still
|
||||
get the current style foreground color, using
|
||||
[method@Gtk.Widget.get_style_color].
|
||||
[method@Gtk.Widget.get_color].
|
||||
|
||||
## Local stylesheets are going away
|
||||
|
||||
@@ -73,6 +73,103 @@ GTK 5 will no longer provide this functionality. The recommendations
|
||||
is to use a global stylesheet (i.e. gtk_style_context_add_provider_for_display())
|
||||
and rely on style classes to make your CSS apply only where desired.
|
||||
|
||||
## Non-standard CSS extensions are going away
|
||||
|
||||
GTK's CSS machinery has a some non-standard extensions around colors:
|
||||
named colors with \@define-color and color functions: lighter(), darker(),
|
||||
shade(), alpha(), mix().
|
||||
|
||||
GTK now implements equivalent functionality from the CSS specs.
|
||||
|
||||
### \@define-color is going away
|
||||
|
||||
\@define-color should be replaced by custom properties in the :root scope.
|
||||
|
||||
Instead of
|
||||
|
||||
```
|
||||
@define-color fg_color #2e3436
|
||||
|
||||
...
|
||||
|
||||
box {
|
||||
color: @fg_color;
|
||||
}
|
||||
```
|
||||
|
||||
use
|
||||
|
||||
```
|
||||
:root {
|
||||
--fg-color: #2e3436;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
box {
|
||||
color: var(--fg-color);
|
||||
}
|
||||
```
|
||||
|
||||
For more information about custom CSS properties and variables, see the
|
||||
[CSS Custom Properties for Cascading Variables](https://www.w3.org/TR/css-variables-1/)
|
||||
spec.
|
||||
|
||||
### Color expressions are going away
|
||||
|
||||
The color functions can all be replaced by combinations of calc() and color-mix().
|
||||
|
||||
ligher(c) and darker(c) are just shade(c, 1.3) or shade(c, 0.7), respectively, and
|
||||
thus can be handled the same way as shade in the examples below.
|
||||
|
||||
Replace
|
||||
|
||||
```
|
||||
a {
|
||||
color: mix(red, green, 0.8);
|
||||
}
|
||||
|
||||
b {
|
||||
color: alpha(green, 0.6);
|
||||
}
|
||||
|
||||
c {
|
||||
color: shade(red, 1.3);
|
||||
}
|
||||
|
||||
d {
|
||||
color: shade(red, 0.7);
|
||||
}
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
```
|
||||
a {
|
||||
color: color-mix(in srgb, red, green 80%);
|
||||
}
|
||||
|
||||
b {
|
||||
color: rgb(from green, r g b / calc(alpha * 0.6));
|
||||
}
|
||||
|
||||
c {
|
||||
color: hsl(from red, h calc(s * 1.3) calc(l * 1.3));
|
||||
}
|
||||
|
||||
d {
|
||||
color: hsl(from red, h calc(s * 0.7) calc(l * 0.7));
|
||||
}
|
||||
```
|
||||
|
||||
Variations of these replacements are possible.
|
||||
|
||||
Note that GTK has historically computed mix() and shade() values in the SRGB and HSL
|
||||
colorspaces, but using OKLAB instead might yield slightly better results.
|
||||
|
||||
For more information about color-mix(), see the
|
||||
[CSS Color](https://drafts.csswg.org/css-color-5) spec.
|
||||
|
||||
## Chooser interfaces are going away
|
||||
|
||||
The GtkColorChooser, GtkFontChooser, GtkFileChooser and GtkAppChooser
|
||||
|
@@ -1,13 +1,15 @@
|
||||
# The Node file format
|
||||
Title: The Node file format
|
||||
|
||||
GSK render nodes can be serialized and deserialized using APIs such as `gsk_render_node_serialize()` and `gsk_render_node_deserialize()`. The intended use for this is development - primarily the development of GTK - by allowing things such as creating testsuites and benchmarks, exchanging nodes in bug reports. GTK includes the `gtk4-node-editor` application for creating such test files.
|
||||
|
||||
The format is a text format that follows the [CSS syntax rules](https://drafts.csswg.org/css-syntax-3/). In particular, this means that every array of bytes will produce a render node when parsed, as there is a defined error recovery method. For more details on error handling, please refer to the documentation of the parsing APIs.
|
||||
|
||||
The grammar of a node text representation using [the CSS value definition syntax](https://drafts.csswg.org/css-values-3/#value-defs) looks like this:
|
||||
**document**: `<node>\*`
|
||||
**node**: container [ "name" ] { <document> } | `<node-type> [ "name" ] { <property>* }` | "name"
|
||||
**property**: `<property-name>: <node> | <value> ;`
|
||||
|
||||
document: <@-rule>*<node>*
|
||||
@-rule: @cicp "name" { <property>* }
|
||||
node: container [ "name" ] { <document> } | <node-type> [ "name" ] { <property>* } | "name"
|
||||
property: <property-name>: <node> | <value> ;
|
||||
|
||||
Each node has its own `<node-type>` and supports a custom set of properties, each with their own `<property-name>` and syntax. The following paragraphs document each of the nodes and their properties.
|
||||
|
||||
@@ -25,6 +27,45 @@ Nodes can be given a name by adding a string after the `<node-type>` in their de
|
||||
|
||||
Just like nodes, textures can be referenced by name. When defining a named texture, the name has to be placed in front of the URL.
|
||||
|
||||
# Color states
|
||||
|
||||
Color states are represented either by an ident (for builtin ones) or a string
|
||||
(for custom ones):
|
||||
|
||||
color-state: <ident> | <string>
|
||||
|
||||
Custom color states can be defined at the beginning of the document, with an @cicp rule.
|
||||
|
||||
The format for @cicp rules is
|
||||
|
||||
@cicp "name" {
|
||||
...
|
||||
}
|
||||
|
||||
The following properties can be set for custom color states:
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| --------- | ---------------- | -------- | ----------- |
|
||||
| primaries | `<integer>` | 2 | always |
|
||||
| transfer | `<integer>` | 2 | always |
|
||||
| matrix | `<integer>` | 2 | always |
|
||||
| range | `narrow | full` | full | non-default |
|
||||
|
||||
Note that the primaries, transfer and matrix properties always need
|
||||
to be specified, since GTK does not allow creating color state objects
|
||||
with these being set to 2 (== unspecified).
|
||||
|
||||
# Colors
|
||||
|
||||
Colors can be specified with a variation of the modern CSS color syntax:
|
||||
|
||||
color(<color-state> <number> <number> <number> ["/" <number>])
|
||||
|
||||
The traditional syntax for sRGB colors still works as well:
|
||||
|
||||
rgba(<number>, <number>, <number>, <number)
|
||||
rgb(<number, <number>, <number>)
|
||||
|
||||
# Nodes
|
||||
|
||||
### container
|
@@ -7,5 +7,5 @@ on top of the Quartz API.
|
||||
Currently, the macOS port does not use any additional commandline options
|
||||
or environment variables.
|
||||
|
||||
For up-to-date information about the current status of this port, see the
|
||||
[project page](https://wiki.gnome.org/Projects/GTK/OSX).
|
||||
For up-to-date information on building, installation, and bundling, see the
|
||||
[GTK website](https://www.gtk.org/docs/installations/macos).
|
||||
|
@@ -5,10 +5,12 @@ Slug: gtk-running
|
||||
|
||||
GTK inspects a number of environment variables in addition to
|
||||
standard variables like `LANG`, `PATH`, `HOME` or `DISPLAY`; mostly
|
||||
to determine paths to look for certain files. The [X11](#x11-envar),
|
||||
[Wayland](#wayland-envar), [Windows](#win32-envar) and
|
||||
[Broadway](#broadway-envar) GDK backends use some additional
|
||||
environment variables.
|
||||
to determine paths to look for certain files. The
|
||||
[X11](https://docs.gtk.org/gtk4/x11.html#x11-specific-environment-variables),
|
||||
[Wayland](https://docs.gtk.org/gtk4/wayland.html#wayland-specific-environment-variables),
|
||||
[Windows](https://docs.gtk.org/gtk4/windows.html#windows-specific-environment-variables) and
|
||||
[Broadway](https://docs.gtk.org/gtk4/broadway.html#broadway-specific-environment-variables)
|
||||
GDK backends use some additional environment variables.
|
||||
|
||||
Note that environment variables are generally used for debugging
|
||||
purposes. They are not guaranteed to be API stable, and should not
|
||||
@@ -290,8 +292,8 @@ are only available when GTK has been configured with `-Ddebug=true`.
|
||||
`fallback`
|
||||
: Information about fallback usage in renderers
|
||||
|
||||
`glyphcache`
|
||||
: Information about glyph caching
|
||||
`cache`
|
||||
: Information about caching
|
||||
|
||||
`verbose`
|
||||
: Print verbose output while rendering
|
||||
|
@@ -43,7 +43,7 @@ X11 details, in particular the ICCCM and the Extended Window Manager
|
||||
Hints specifications. [freedesktop.org](http://www.freedesktop.org/standards/)
|
||||
has links to many relevant specifications.
|
||||
|
||||
The GDK manual covers [using Xlib in a GTK program](#gdk-X-Window-System-Interaction).
|
||||
The GDK manual covers [using Xlib in a GTK program](https://docs.gtk.org/gdk4/x11.html).
|
||||
|
||||
### Server, client, window manager
|
||||
|
||||
|
@@ -33,9 +33,11 @@ gdk_broadway_cairo_context_dispose (GObject *object)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
cairo_region_t *region)
|
||||
gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
cairo_region_t *region,
|
||||
GdkColorState **out_color_state,
|
||||
GdkMemoryDepth *out_depth)
|
||||
{
|
||||
GdkBroadwayCairoContext *self = GDK_BROADWAY_CAIRO_CONTEXT (draw_context);
|
||||
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
|
||||
@@ -59,6 +61,9 @@ gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_fill (cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
*out_color_state = GDK_COLOR_STATE_SRGB;
|
||||
*out_depth = gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -33,9 +33,11 @@ gdk_broadway_draw_context_dispose (GObject *object)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
cairo_region_t *region)
|
||||
gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
cairo_region_t *region,
|
||||
GdkColorState **out_color_state,
|
||||
GdkMemoryDepth *out_depth)
|
||||
{
|
||||
GdkBroadwayDrawContext *self = GDK_BROADWAY_DRAW_CONTEXT (draw_context);
|
||||
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
|
||||
@@ -52,6 +54,9 @@ gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
|
||||
|
||||
self->nodes = g_array_new (FALSE, FALSE, sizeof(guint32));
|
||||
self->node_textures = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
|
||||
*out_color_state = GDK_COLOR_STATE_SRGB;
|
||||
*out_depth = gdk_color_state_get_depth (GDK_COLOR_STATE_SRGB);
|
||||
}
|
||||
|
||||
static void
|
||||
|
11
gdk/gdk.c
11
gdk/gdk.c
@@ -43,6 +43,14 @@
|
||||
|
||||
#include <fribidi.h>
|
||||
|
||||
/* GTK has a general architectural assumption that gsize is pointer-sized
|
||||
* (equivalent to uintptr_t), making it non-portable to architectures like
|
||||
* CHERI where that isn't true. If a future release relaxes that
|
||||
* assumption, changes will be needed in numerous places.
|
||||
* See also https://gitlab.gnome.org/GNOME/glib/-/issues/2842 for the
|
||||
* equivalent in GLib, which would be a prerequisite. */
|
||||
G_STATIC_ASSERT (sizeof (gsize) == sizeof (void *));
|
||||
G_STATIC_ASSERT (G_ALIGNOF (gsize) == G_ALIGNOF (void *));
|
||||
|
||||
/**
|
||||
* GDK_WINDOWING_X11:
|
||||
@@ -120,6 +128,8 @@ static const GdkDebugKey gdk_debug_keys[] = {
|
||||
{ "dmabuf", GDK_DEBUG_DMABUF, "Information about dmabuf buffers" },
|
||||
{ "offload", GDK_DEBUG_OFFLOAD, "Information about subsurfaces and graphics offload" },
|
||||
|
||||
{ "linear", GDK_DEBUG_LINEAR, "Enable linear rendering" },
|
||||
{ "hdr", GDK_DEBUG_HDR, "Force HDR rendering" },
|
||||
{ "portals", GDK_DEBUG_PORTALS, "Force use of portals" },
|
||||
{ "no-portals", GDK_DEBUG_NO_PORTALS, "Disable use of portals" },
|
||||
{ "force-offload", GDK_DEBUG_FORCE_OFFLOAD, "Force graphics offload for all textures" },
|
||||
@@ -133,7 +143,6 @@ static const GdkDebugKey gdk_debug_keys[] = {
|
||||
{ "gl-glx", GDK_DEBUG_GL_GLX, "Use GLX on X11" },
|
||||
{ "gl-wgl", GDK_DEBUG_GL_WGL, "Use WGL on Windows" },
|
||||
{ "vulkan-disable", GDK_DEBUG_VULKAN_DISABLE, "Disable Vulkan support" },
|
||||
{ "vulkan-validate", GDK_DEBUG_VULKAN_VALIDATE, "Load the Vulkan validation layer" },
|
||||
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings" },
|
||||
{ "high-depth", GDK_DEBUG_HIGH_DEPTH, "Use high bit depth rendering if possible" },
|
||||
{ "no-vsync", GDK_DEBUG_NO_VSYNC, "Repaint instantly (uses 100% CPU with animations)" },
|
||||
|
@@ -29,7 +29,9 @@
|
||||
#include <gdk/gdkapplaunchcontext.h>
|
||||
#include <gdk/gdkcairo.h>
|
||||
#include <gdk/gdkcairocontext.h>
|
||||
#include <gdk/gdkcicpparams.h>
|
||||
#include <gdk/gdkclipboard.h>
|
||||
#include <gdk/gdkcolorstate.h>
|
||||
#include <gdk/gdkconfig.h>
|
||||
#include <gdk/gdkcontentdeserializer.h>
|
||||
#include <gdk/gdkcontentformats.h>
|
||||
@@ -61,6 +63,7 @@
|
||||
#include <gdk/gdkkeys.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <gdk/gdkmemorytexture.h>
|
||||
#include <gdk/gdkmemorytexturebuilder.h>
|
||||
#include <gdk/gdkmonitor.h>
|
||||
#include <gdk/gdkpaintable.h>
|
||||
#include <gdk/gdkpango.h>
|
||||
|
159
gdk/gdkcairoprivate.h
Normal file
159
gdk/gdkcairoprivate.h
Normal file
@@ -0,0 +1,159 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkcolorprivate.h"
|
||||
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytexture.h"
|
||||
|
||||
#include <cairo.h>
|
||||
#include <graphene.h>
|
||||
|
||||
static inline cairo_format_t
|
||||
gdk_cairo_format_for_depth (GdkMemoryDepth depth)
|
||||
{
|
||||
switch (depth)
|
||||
{
|
||||
case GDK_MEMORY_NONE:
|
||||
case GDK_MEMORY_U8:
|
||||
return CAIRO_FORMAT_ARGB32;
|
||||
|
||||
case GDK_MEMORY_U8_SRGB:
|
||||
case GDK_MEMORY_U16:
|
||||
case GDK_MEMORY_FLOAT16:
|
||||
case GDK_MEMORY_FLOAT32:
|
||||
return CAIRO_FORMAT_RGBA128F;
|
||||
|
||||
case GDK_N_DEPTHS:
|
||||
default:
|
||||
g_return_val_if_reached (CAIRO_FORMAT_ARGB32);
|
||||
}
|
||||
}
|
||||
|
||||
static inline GdkMemoryDepth
|
||||
gdk_cairo_depth_for_format (cairo_format_t format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
case CAIRO_FORMAT_RGB16_565:
|
||||
case CAIRO_FORMAT_A1:
|
||||
case CAIRO_FORMAT_A8:
|
||||
return GDK_MEMORY_U8;
|
||||
|
||||
case CAIRO_FORMAT_RGB30:
|
||||
return GDK_MEMORY_U16;
|
||||
|
||||
case CAIRO_FORMAT_RGB96F:
|
||||
case CAIRO_FORMAT_RGBA128F:
|
||||
return GDK_MEMORY_FLOAT32;
|
||||
|
||||
case CAIRO_FORMAT_INVALID:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return GDK_MEMORY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static GdkMemoryFormat
|
||||
gdk_cairo_format_to_memory_format (cairo_format_t format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
return GDK_MEMORY_DEFAULT;
|
||||
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
return GDK_MEMORY_B8G8R8X8;
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
return GDK_MEMORY_X8R8G8B8;
|
||||
#else
|
||||
#error "Unknown byte order for Cairo format"
|
||||
#endif
|
||||
case CAIRO_FORMAT_A8:
|
||||
return GDK_MEMORY_A8;
|
||||
case CAIRO_FORMAT_RGB96F:
|
||||
return GDK_MEMORY_R32G32B32_FLOAT;
|
||||
case CAIRO_FORMAT_RGBA128F:
|
||||
return GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
|
||||
case CAIRO_FORMAT_RGB16_565:
|
||||
case CAIRO_FORMAT_RGB30:
|
||||
case CAIRO_FORMAT_INVALID:
|
||||
case CAIRO_FORMAT_A1:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return GDK_MEMORY_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_cairo_set_source_color (cairo_t *cr,
|
||||
GdkColorState *ccs,
|
||||
const GdkColor *color)
|
||||
{
|
||||
float c[4];
|
||||
gdk_color_to_float (color, ccs, c);
|
||||
cairo_set_source_rgba (cr, c[0], c[1], c[2], c[3]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_cairo_set_source_rgba_ccs (cairo_t *cr,
|
||||
GdkColorState *ccs,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
GdkColor c;
|
||||
gdk_color_init_from_rgba (&c, rgba);
|
||||
gdk_cairo_set_source_color (cr, ccs, &c);
|
||||
gdk_color_finish (&c);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_cairo_pattern_add_color_stop_rgba_ccs (cairo_pattern_t *pattern,
|
||||
GdkColorState *ccs,
|
||||
double offset,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
float color[4];
|
||||
|
||||
gdk_color_state_from_rgba (ccs, rgba, color);
|
||||
cairo_pattern_add_color_stop_rgba (pattern, offset, color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_cairo_rect (cairo_t *cr,
|
||||
const graphene_rect_t *rect)
|
||||
{
|
||||
cairo_rectangle (cr,
|
||||
rect->origin.x, rect->origin.y,
|
||||
rect->size.width, rect->size.height);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_cairo_surface_convert_color_state (cairo_surface_t *surface,
|
||||
GdkColorState *source,
|
||||
GdkColorState *target)
|
||||
{
|
||||
cairo_surface_t *image_surface;
|
||||
|
||||
if (gdk_color_state_equal (source, target))
|
||||
return;
|
||||
|
||||
image_surface = cairo_surface_map_to_image (surface, NULL);
|
||||
|
||||
gdk_memory_convert_color_state (cairo_image_surface_get_data (image_surface),
|
||||
cairo_image_surface_get_stride (image_surface),
|
||||
gdk_cairo_format_to_memory_format (cairo_image_surface_get_format (image_surface)),
|
||||
source,
|
||||
target,
|
||||
cairo_image_surface_get_width (image_surface),
|
||||
cairo_image_surface_get_height (image_surface));
|
||||
|
||||
cairo_surface_mark_dirty (image_surface);
|
||||
cairo_surface_unmap_image (surface, image_surface);
|
||||
/* https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/487 */
|
||||
cairo_surface_mark_dirty (surface);
|
||||
}
|
||||
|
481
gdk/gdkcicpparams.c
Normal file
481
gdk/gdkcicpparams.c
Normal file
@@ -0,0 +1,481 @@
|
||||
/* gdkcicpparams.c
|
||||
*
|
||||
* Copyright 2024 Matthias Clasen
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkcicpparamsprivate.h"
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkenumtypes.h"
|
||||
|
||||
/**
|
||||
* GdkCicpParams:
|
||||
*
|
||||
* The `GdkCicpParams` struct contains the parameters that define
|
||||
* a colorstate according to the ITU-T H.273
|
||||
* [specification](https://www.itu.int/rec/T-REC-H.273/en).
|
||||
*
|
||||
* See the documentation of individual properties for supported values.
|
||||
*
|
||||
* The 'unspecified' value (2) is not treated in any special way, and
|
||||
* must be replaced by a different value before creating a color state.
|
||||
*
|
||||
* `GdkCicpParams` can be used as a builder object to construct a color
|
||||
* state from Cicp data with [method@Gdk.CicpParams.build_color_state].
|
||||
* The function will return an error if the given parameters are not
|
||||
* supported.
|
||||
*
|
||||
* You can obtain a `GdkCicpParams` object from a color state with
|
||||
* [method@Gdk.ColorState.create_cicp_params]. This can be used to
|
||||
* create a variant of a color state, by changing just one of the cicp
|
||||
* parameters, or just to obtain information about the color state.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
|
||||
/* {{{ GObject boilerplate */
|
||||
|
||||
struct _GdkCicpParams
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GdkCicp cicp;
|
||||
};
|
||||
|
||||
struct _GdkCicpParamsClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkCicpParams, gdk_cicp_params, G_TYPE_OBJECT)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_COLOR_PRIMARIES = 1,
|
||||
PROP_TRANSFER_FUNCTION,
|
||||
PROP_MATRIX_COEFFICIENTS,
|
||||
PROP_RANGE,
|
||||
|
||||
N_PROPERTIES,
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPERTIES] = { NULL, };
|
||||
|
||||
static void
|
||||
gdk_cicp_params_init (GdkCicpParams *self)
|
||||
{
|
||||
self->cicp.color_primaries = 2;
|
||||
self->cicp.transfer_function = 2;
|
||||
self->cicp.matrix_coefficients = 2;
|
||||
self->cicp.range = GDK_CICP_RANGE_NARROW;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_cicp_params_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkCicpParams *self = GDK_CICP_PARAMS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_COLOR_PRIMARIES:
|
||||
g_value_set_uint (value, self->cicp.color_primaries);
|
||||
break;
|
||||
|
||||
case PROP_TRANSFER_FUNCTION:
|
||||
g_value_set_uint (value, self->cicp.transfer_function);
|
||||
break;
|
||||
|
||||
case PROP_MATRIX_COEFFICIENTS:
|
||||
g_value_set_uint (value, self->cicp.matrix_coefficients);
|
||||
break;
|
||||
|
||||
case PROP_RANGE:
|
||||
g_value_set_enum (value, self->cicp.range);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_cicp_params_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkCicpParams *self = GDK_CICP_PARAMS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_COLOR_PRIMARIES:
|
||||
gdk_cicp_params_set_color_primaries (self, g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_TRANSFER_FUNCTION:
|
||||
gdk_cicp_params_set_transfer_function (self, g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_MATRIX_COEFFICIENTS:
|
||||
gdk_cicp_params_set_matrix_coefficients (self, g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_RANGE:
|
||||
gdk_cicp_params_set_range (self, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_cicp_params_class_init (GdkCicpParamsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = gdk_cicp_params_get_property;
|
||||
object_class->set_property = gdk_cicp_params_set_property;
|
||||
|
||||
/**
|
||||
* GdkCicpParams:color-primaries:
|
||||
*
|
||||
* The color primaries to use.
|
||||
*
|
||||
* Supported values:
|
||||
*
|
||||
* - 1: BT.709 / sRGB
|
||||
* - 2: unspecified
|
||||
* - 5: PAL
|
||||
* - 6,7: BT.601 / NTSC
|
||||
* - 9: BT.2020
|
||||
* - 12: Display P3
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_COLOR_PRIMARIES] =
|
||||
g_param_spec_uint ("color-primaries", NULL, NULL,
|
||||
0, 255, 2,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkCicpParams:transfer-function:
|
||||
*
|
||||
* The transfer function to use.
|
||||
*
|
||||
* Supported values:
|
||||
*
|
||||
* - 1,6,14,15: BT.709, BT.601, BT.2020
|
||||
* - 2: unspecified
|
||||
* - 4: gamma 2.2
|
||||
* - 5: gamma 2.8
|
||||
* - 8: linear
|
||||
* - 13: sRGB
|
||||
* - 16: BT.2100 PQ
|
||||
* - 18: BT.2100 HLG
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_TRANSFER_FUNCTION] =
|
||||
g_param_spec_uint ("transfer-function", NULL, NULL,
|
||||
0, 255, 2,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkCicpParams:matrix-coefficients:
|
||||
*
|
||||
* The matrix coefficients (for YUV to RGB conversion).
|
||||
*
|
||||
* Supported values:
|
||||
*
|
||||
* - 0: RGB
|
||||
* - 2: unspecified
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_MATRIX_COEFFICIENTS] =
|
||||
g_param_spec_uint ("matrix-coefficients", NULL, NULL,
|
||||
0, 255, 2,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkCicpParams:range:
|
||||
*
|
||||
* Whether the data is using the full range of values.
|
||||
*
|
||||
* The range of the data.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_RANGE] =
|
||||
g_param_spec_enum ("range", NULL, NULL,
|
||||
GDK_TYPE_CICP_RANGE,
|
||||
GDK_CICP_RANGE_NARROW,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
/**
|
||||
* gdk_cicp_params_new:
|
||||
*
|
||||
* Creates a new `GdkCicpParams` object.
|
||||
*
|
||||
* The initial values of the properties are the values for "undefined"
|
||||
* and need to be set before a color state object can be built.
|
||||
*
|
||||
* Returns: (transfer full): a new `GdkCicpParams`
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkCicpParams *
|
||||
gdk_cicp_params_new (void)
|
||||
{
|
||||
return g_object_new (GDK_TYPE_CICP_PARAMS, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cicp_params_get_color_primaries:
|
||||
* @self: a `GdkCicpParams`
|
||||
*
|
||||
* Returns the value of the color-primaries property
|
||||
* of @self.
|
||||
*
|
||||
* Returns: the color-primaries value
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
guint
|
||||
gdk_cicp_params_get_color_primaries (GdkCicpParams *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_CICP_PARAMS (self), 0);
|
||||
|
||||
return self->cicp.color_primaries;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cicp_params_set_color_primaries:
|
||||
* @self: a `GdkCicpParams`
|
||||
* @color_primaries: the new color primaries value
|
||||
*
|
||||
* Sets the color-primaries property of @self.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_cicp_params_set_color_primaries (GdkCicpParams *self,
|
||||
guint color_primaries)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_CICP_PARAMS (self));
|
||||
|
||||
if (self->cicp.color_primaries == color_primaries)
|
||||
return;
|
||||
|
||||
self->cicp.color_primaries = color_primaries;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLOR_PRIMARIES]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cicp_params_get_transfer_function:
|
||||
* @self: a `GdkCicpParams`
|
||||
*
|
||||
* Gets the transfer-function property of @self.
|
||||
*
|
||||
* Returns: the transfer-function value
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
guint
|
||||
gdk_cicp_params_get_transfer_function (GdkCicpParams *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_CICP_PARAMS (self), 0);
|
||||
|
||||
return self->cicp.transfer_function;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cicp_params_set_transfer_function:
|
||||
* @self: a `GdkCicpParams`
|
||||
* @transfer_function: the new transfer-function value
|
||||
*
|
||||
* Sets the transfer-function property of @self.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_cicp_params_set_transfer_function (GdkCicpParams *self,
|
||||
guint transfer_function)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_CICP_PARAMS (self));
|
||||
|
||||
if (self->cicp.transfer_function == transfer_function)
|
||||
return;
|
||||
|
||||
self->cicp.transfer_function = transfer_function;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TRANSFER_FUNCTION]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cicp_params_get_matrix_coefficients:
|
||||
* @self: a `GdkCicpParams`
|
||||
*
|
||||
* Gets the matrix-coefficients property of @self.
|
||||
*
|
||||
* Returns: the matrix-coefficients value
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
guint
|
||||
gdk_cicp_params_get_matrix_coefficients (GdkCicpParams *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_CICP_PARAMS (self), 0);
|
||||
|
||||
return self->cicp.matrix_coefficients;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cicp_params_set_matrix_coefficients:
|
||||
* @self a `GdkCicpParams`
|
||||
* @matrix_coefficients: the new matrix-coefficients value
|
||||
*
|
||||
* Sets the matrix-coefficients property of @self.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_cicp_params_set_matrix_coefficients (GdkCicpParams *self,
|
||||
guint matrix_coefficients)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_CICP_PARAMS (self));
|
||||
|
||||
if (self->cicp.matrix_coefficients == matrix_coefficients)
|
||||
return;
|
||||
|
||||
self->cicp.matrix_coefficients = matrix_coefficients;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MATRIX_COEFFICIENTS]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cicp_params_get_range:
|
||||
* @self: a `GdkCicpParams`
|
||||
*
|
||||
* Gets the range property of @self.
|
||||
*
|
||||
* Returns: the range value
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkCicpRange
|
||||
gdk_cicp_params_get_range (GdkCicpParams *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_CICP_PARAMS (self), GDK_CICP_RANGE_NARROW);
|
||||
|
||||
return self->cicp.range;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cicp_params_set_range:
|
||||
* @self: a `GdkCipParams`
|
||||
* @range: the range value
|
||||
*
|
||||
* Sets the range property of @self
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_cicp_params_set_range (GdkCicpParams *self,
|
||||
GdkCicpRange range)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_CICP_PARAMS (self));
|
||||
|
||||
if (self->cicp.range == range)
|
||||
return;
|
||||
|
||||
self->cicp.range = range;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RANGE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cicp_params_build_color_state:
|
||||
* @self: a `GdkCicpParams`
|
||||
* @error: return location for errors
|
||||
*
|
||||
* Creates a new `GdkColorState` object for the cicp parameters in @self.
|
||||
*
|
||||
* Note that this may fail if the cicp parameters in @self are not
|
||||
* supported by GTK. In that case, `NULL` is returned, and @error is set
|
||||
* with an error message that can be presented to the user.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): A newly allocated `GdkColorState`
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_cicp_params_build_color_state (GdkCicpParams *self,
|
||||
GError **error)
|
||||
{
|
||||
return gdk_color_state_new_for_cicp (gdk_cicp_params_get_cicp (self), error);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Private API */
|
||||
|
||||
/*< private >
|
||||
* gdk_cicp_params_new_for_cicp:
|
||||
* @cicp: a GdkCicp struct
|
||||
*
|
||||
* Create a `GdkCicpParams` from the values in @cicp.
|
||||
*
|
||||
* Returns: (transfer full): a new `GdkCicpParams` object
|
||||
*/
|
||||
GdkCicpParams *
|
||||
gdk_cicp_params_new_for_cicp (const GdkCicp *cicp)
|
||||
{
|
||||
return g_object_new (GDK_TYPE_CICP_PARAMS,
|
||||
"color-primaries", cicp->color_primaries,
|
||||
"transfer-function", cicp->transfer_function,
|
||||
"matrix-coefficients", cicp->matrix_coefficients,
|
||||
"range", cicp->range,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_cicp_params_get_cicp:
|
||||
* @self: a `GdkCicpParams` object
|
||||
*
|
||||
* Gets the `GdkCicp` struct of @self.
|
||||
*
|
||||
* Returns: (transfer none): a `GdkCicp` struct containing
|
||||
* the values of @self
|
||||
*/
|
||||
const GdkCicp *
|
||||
gdk_cicp_params_get_cicp (GdkCicpParams *self)
|
||||
{
|
||||
return &self->cicp;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
90
gdk/gdkcicpparams.h
Normal file
90
gdk/gdkcicpparams.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* gdkcicpparams.h
|
||||
*
|
||||
* Copyright 2024 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GDK_TYPE_CICP_PARAMS (gdk_cicp_params_get_type ())
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GDK_DECLARE_INTERNAL_TYPE (GdkCicpParams, gdk_cicp_params, GDK, CICP_PARAMS, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkCicpParams *gdk_cicp_params_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
guint gdk_cicp_params_get_color_primaries (GdkCicpParams *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_cicp_params_set_color_primaries (GdkCicpParams *self,
|
||||
guint color_primaries);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
guint gdk_cicp_params_get_transfer_function (GdkCicpParams *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_cicp_params_set_transfer_function (GdkCicpParams *self,
|
||||
guint transfer_function);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
guint gdk_cicp_params_get_matrix_coefficients (GdkCicpParams *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_cicp_params_set_matrix_coefficients (GdkCicpParams *self,
|
||||
guint matrix_coefficients);
|
||||
|
||||
/**
|
||||
* GdkCicpRange:
|
||||
* @GDK_CICP_RANGE_NARROW: The values use the range of 16-235 (for Y) and 16-240 for u and v.
|
||||
* @GDK_CICO_RANGE_FULL: The values use the full range.
|
||||
*
|
||||
* The values of this enumeration describe whether image data uses
|
||||
* the full range of 8-bit values.
|
||||
*
|
||||
* In digital broadcasting, it is common to reserve the lowest and
|
||||
* highest values. Typically the allowed values for the narrow range
|
||||
* are 16-235 for Y and 16-240 for u,v (when dealing with YUV data).
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GDK_CICP_RANGE_NARROW,
|
||||
GDK_CICP_RANGE_FULL,
|
||||
} GdkCicpRange;
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkCicpRange gdk_cicp_params_get_range (GdkCicpParams *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_cicp_params_set_range (GdkCicpParams *self,
|
||||
GdkCicpRange range);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_cicp_params_build_color_state (GdkCicpParams *self,
|
||||
GError **error);
|
||||
|
||||
|
||||
G_END_DECLS
|
84
gdk/gdkcicpparamsprivate.h
Normal file
84
gdk/gdkcicpparamsprivate.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkcicpparams.h"
|
||||
|
||||
typedef struct _GdkCicp GdkCicp;
|
||||
|
||||
struct _GdkCicp
|
||||
{
|
||||
guint color_primaries;
|
||||
guint transfer_function;
|
||||
guint matrix_coefficients;
|
||||
GdkCicpRange range;
|
||||
};
|
||||
|
||||
/*< private >
|
||||
* gdk_cicp_equal:
|
||||
* @p1: a `GdkCicp`
|
||||
* @p2: another `GdkCicp`
|
||||
*
|
||||
* Compare two cicp tuples for equality.
|
||||
*
|
||||
* Note that several cicp values are 'functionally equivalent'.
|
||||
* If you are interested in that notion, use gdk_cicp_equivalent().
|
||||
*
|
||||
* Returns: whether @p1 and @p2 are equal
|
||||
*/
|
||||
static inline gboolean
|
||||
gdk_cicp_equal (const GdkCicp *p1,
|
||||
const GdkCicp *p2)
|
||||
{
|
||||
return p1->color_primaries == p2->color_primaries &&
|
||||
p1->transfer_function == p2->transfer_function &&
|
||||
p1->matrix_coefficients == p2->matrix_coefficients &&
|
||||
p1->range == p2->range;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_cicp_normalize (const GdkCicp *orig,
|
||||
GdkCicp *out)
|
||||
{
|
||||
memcpy (out, orig, sizeof (GdkCicp));
|
||||
|
||||
/* ntsc */
|
||||
if (out->color_primaries == 6)
|
||||
out->color_primaries = 5;
|
||||
|
||||
/* bt709 */
|
||||
if (out->transfer_function == 6 ||
|
||||
out->transfer_function == 14 ||
|
||||
out->transfer_function == 15)
|
||||
out->transfer_function = 1;
|
||||
|
||||
/* bt601 */
|
||||
if (out->matrix_coefficients == 6)
|
||||
out->matrix_coefficients = 5;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_cicp_equivalent:
|
||||
* @p1: a `GdkCicp`
|
||||
* @p2: another `GdkCicp`
|
||||
*
|
||||
* Determine whether two cicp tuples are functionally equivalent.
|
||||
*
|
||||
* Returns: whether @p1 and @p2 are functionally equivalent
|
||||
*/
|
||||
static inline gboolean
|
||||
gdk_cicp_equivalent (const GdkCicp *p1,
|
||||
const GdkCicp *p2)
|
||||
{
|
||||
GdkCicp n1, n2;
|
||||
|
||||
if (gdk_cicp_equal (p1, p2))
|
||||
return TRUE;
|
||||
|
||||
gdk_cicp_normalize (p1, &n1);
|
||||
gdk_cicp_normalize (p2, &n2);
|
||||
|
||||
return gdk_cicp_equal (&n1, &n2);
|
||||
}
|
||||
|
||||
const GdkCicp * gdk_cicp_params_get_cicp (GdkCicpParams *params);
|
||||
|
||||
GdkCicpParams * gdk_cicp_params_new_for_cicp (const GdkCicp *cicp);
|
@@ -515,8 +515,8 @@ gdk_clipboard_get_content (GdkClipboard *clipboard)
|
||||
* @clipboard: a `GdkClipboard`
|
||||
* @io_priority: the I/O priority of the request
|
||||
* @cancellable: (nullable): optional `GCancellable` object
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
* @callback: (scope async) (closure user_data): callback to call when the request is satisfied
|
||||
* @user_data:: the data to pass to callback function
|
||||
*
|
||||
* Asynchronously instructs the @clipboard to store its contents remotely.
|
||||
*
|
||||
@@ -630,8 +630,8 @@ gdk_clipboard_read_internal (GdkClipboard *clipboard,
|
||||
* @mime_types: (array zero-terminated=1): a %NULL-terminated array of mime types to choose from
|
||||
* @io_priority: the I/O priority of the request
|
||||
* @cancellable: (nullable): optional `GCancellable` object
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
* @callback: (scope async) (closure user_data): callback to call when the request is satisfied
|
||||
* @user_data: the data to pass to callback function
|
||||
*
|
||||
* Asynchronously requests an input stream to read the @clipboard's
|
||||
* contents from.
|
||||
@@ -823,8 +823,8 @@ gdk_clipboard_read_value_internal (GdkClipboard *clipboard,
|
||||
* @type: a `GType` to read
|
||||
* @io_priority: the I/O priority of the request
|
||||
* @cancellable: (nullable): optional `GCancellable` object
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
* @callback: (scope async) (closure user_data): callback to call when the request is satisfied
|
||||
* @user_data: the data to pass to callback function
|
||||
*
|
||||
* Asynchronously request the @clipboard contents converted to the given
|
||||
* @type.
|
||||
@@ -882,8 +882,8 @@ gdk_clipboard_read_value_finish (GdkClipboard *clipboard,
|
||||
* gdk_clipboard_read_texture_async:
|
||||
* @clipboard: a `GdkClipboard`
|
||||
* @cancellable: (nullable): optional `GCancellable` object, %NULL to ignore.
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
* @callback: (scope async) (closure user_data): callback to call when the request is satisfied
|
||||
* @user_data: the data to pass to callback function
|
||||
*
|
||||
* Asynchronously request the @clipboard contents converted to a `GdkPixbuf`.
|
||||
*
|
||||
@@ -944,8 +944,8 @@ gdk_clipboard_read_texture_finish (GdkClipboard *clipboard,
|
||||
* gdk_clipboard_read_text_async:
|
||||
* @clipboard: a `GdkClipboard`
|
||||
* @cancellable: (nullable): optional `GCancellable` object
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
* @callback: (scope async) (closure user_data): callback to call when the request is satisfied
|
||||
* @user_data: the data to pass to callback function
|
||||
*
|
||||
* Asynchronously request the @clipboard contents converted to a string.
|
||||
*
|
||||
|
301
gdk/gdkcolor.c
Normal file
301
gdk/gdkcolor.c
Normal file
@@ -0,0 +1,301 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* Copyright (C) 2021 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkcolorprivate.h"
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkrgbaprivate.h"
|
||||
|
||||
/*< private >
|
||||
* GdkColor:
|
||||
* @color_state: the color state to interpret the values in
|
||||
* @values: the 3 coordinates that define the color, followed
|
||||
* by the alpha value
|
||||
*
|
||||
* A `GdkColor` represents a color.
|
||||
*
|
||||
* The color state defines the meaning and range of the values.
|
||||
* E.g., the srgb color state has r, g, b components representing
|
||||
* red, green and blue with a range of [0,1], while the oklch color
|
||||
* state has l, c, h components representing luminosity, chromaticity
|
||||
* and hue, with l ranging from 0 to 1 and c from 0 to about 0.4, while
|
||||
* h is interpreted as angle in degrees.
|
||||
*
|
||||
* value[3] is always the alpha value with a range of [0,1].
|
||||
*
|
||||
* The values are also available under the names red, green, blue
|
||||
* and alpha, or r, g, b and a.
|
||||
*/
|
||||
|
||||
/*< private >
|
||||
* gdk_color_init:
|
||||
* @self: the `GdkColor` struct to initialize
|
||||
* @color_state: the color state
|
||||
* @values: the values
|
||||
*
|
||||
* Initializes the `GdkColor` with the given color state
|
||||
* and values.
|
||||
*
|
||||
* Note that this takes a reference on @color_state that
|
||||
* must be freed by calling [function@Gdk.Color.finish]
|
||||
* when the `GdkColor` is no longer needed.
|
||||
*/
|
||||
void
|
||||
(gdk_color_init) (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const float values[4])
|
||||
{
|
||||
_gdk_color_init (self, color_state, values);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_init_copy:
|
||||
* @self: the `GdkColor` struct to initialize
|
||||
* @color: the `GdkColor` to copy
|
||||
*
|
||||
* Initializes the `GdkColor` by copying the contents
|
||||
* of another `GdkColor`.
|
||||
*
|
||||
* Note that this takes a reference on the color state
|
||||
* that must be freed by calling [function@Gdk.Color.finish]
|
||||
* when the `GdkColor` is no longer needed.
|
||||
*/
|
||||
void
|
||||
(gdk_color_init_copy) (GdkColor *self,
|
||||
const GdkColor *color)
|
||||
{
|
||||
_gdk_color_init_copy (self, color);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_init_from_rgba:
|
||||
* @self: the `GdkColor` struct to initialize
|
||||
* @rgba: the `GdkRGBA` to copy
|
||||
*
|
||||
* Initializes the `GdkColor` by copying the contents
|
||||
* of a `GdkRGBA`.
|
||||
*
|
||||
* Note that `GdkRGBA` colors are always in the sRGB
|
||||
* color state.
|
||||
*
|
||||
* Note that this takes a reference on the color state
|
||||
* that must be freed by calling [function@Gdk.Color.finish]
|
||||
* when the `GdkColor` is no longer needed.
|
||||
*/
|
||||
void
|
||||
(gdk_color_init_from_rgba) (GdkColor *self,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
_gdk_color_init_from_rgba (self, rgba);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Drop the reference on the color state of @self.
|
||||
*
|
||||
* After this, @self is empty and can be initialized again
|
||||
* with [function@Gdk.Color.init] and its variants.
|
||||
*/
|
||||
void
|
||||
(gdk_color_finish) (GdkColor *self)
|
||||
{
|
||||
_gdk_color_finish (self);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_equal:
|
||||
* @self: a `GdkColor`
|
||||
* @other: another `GdkColor`
|
||||
*
|
||||
* Compares two `GdkColor` structs for equality.
|
||||
*
|
||||
* Returns: `TRUE` if @self and @other are equal
|
||||
*/
|
||||
gboolean
|
||||
(gdk_color_equal) (const GdkColor *self,
|
||||
const GdkColor *other)
|
||||
{
|
||||
return _gdk_color_equal (self, other);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_is_clear:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Returns whether @self is fully transparent.
|
||||
*
|
||||
* Returns: `TRUE` if @self is transparent
|
||||
*/
|
||||
gboolean
|
||||
(gdk_color_is_clear) (const GdkColor *self)
|
||||
{
|
||||
return _gdk_color_is_clear (self);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_is_opaque:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Returns whether @self is fully opaque.
|
||||
*
|
||||
* Returns: `TRUE` if @self if opaque
|
||||
*/
|
||||
gboolean
|
||||
(gdk_color_is_opaque) (const GdkColor *self)
|
||||
{
|
||||
return _gdk_color_is_opaque (self);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_convert:
|
||||
* @self: the `GdkColor` to store the result in
|
||||
* @color_state: the target color start
|
||||
* @other: the `GdkColor` to convert
|
||||
*
|
||||
* Converts a given `GdkColor` to another color state.
|
||||
*
|
||||
* After the conversion, @self will represent the same
|
||||
* color as @other in @color_state, to the degree possible.
|
||||
*
|
||||
* Different color states have different gamuts of colors
|
||||
* they can represent, and converting a color to a color
|
||||
* state with a smaller gamut may yield an 'out of gamut'
|
||||
* result.
|
||||
*/
|
||||
void
|
||||
(gdk_color_convert) (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkColor *other)
|
||||
{
|
||||
gdk_color_convert (self, color_state, other);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_to_float:
|
||||
* @self: a `GdkColor`
|
||||
* @target: the color state to convert to
|
||||
* @values: the location to store the result in
|
||||
*
|
||||
* Converts a given `GdkColor to another color state
|
||||
* and stores the result in a `float[4]`.
|
||||
*/
|
||||
void
|
||||
(gdk_color_to_float) (const GdkColor *self,
|
||||
GdkColorState *target,
|
||||
float values[4])
|
||||
{
|
||||
gdk_color_to_float (self, target, values);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_from_rgba:
|
||||
* @self: the `GdkColor` to store the result in
|
||||
* @color_state: the target color state
|
||||
* @rgba: the `GdkRGBA` to convert
|
||||
*
|
||||
* Converts a given `GdkRGBA` to the target @color_state.
|
||||
*/
|
||||
void
|
||||
gdk_color_from_rgba (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
GdkColor tmp = {
|
||||
.color_state = GDK_COLOR_STATE_SRGB,
|
||||
.r = rgba->red,
|
||||
.g = rgba->green,
|
||||
.b = rgba->blue,
|
||||
.a = rgba->alpha
|
||||
};
|
||||
|
||||
gdk_color_convert (self, color_state, &tmp);
|
||||
gdk_color_finish (&tmp);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_get_depth:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Returns the preferred depth for the color state of @self.
|
||||
*
|
||||
* Returns: the preferred depth
|
||||
*/
|
||||
GdkMemoryDepth
|
||||
(gdk_color_get_depth) (const GdkColor *self)
|
||||
{
|
||||
return gdk_color_state_get_depth (self->color_state);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_print:
|
||||
* @self: the `GdkColor` to print
|
||||
* @string: the string to print to
|
||||
*
|
||||
* Appends a representation of @self to @string.
|
||||
*
|
||||
* The representation is inspired by CSS3 colors,
|
||||
* but not 100% identical, and looks like this:
|
||||
*
|
||||
* color(NAME R G B / A)
|
||||
*
|
||||
* where `NAME` identifies color state, and
|
||||
* `R`, `G`, `B` and `A` are the components of the color.
|
||||
*
|
||||
* The alpha may be omitted if it is 1.
|
||||
*/
|
||||
void
|
||||
gdk_color_print (const GdkColor *self,
|
||||
GString *string)
|
||||
{
|
||||
if (gdk_color_state_equal (self->color_state, GDK_COLOR_STATE_SRGB))
|
||||
{
|
||||
gdk_rgba_print ((const GdkRGBA *) self->values, string);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_printf (string, "color(%s %g %g %g",
|
||||
gdk_color_state_get_name (self->color_state),
|
||||
self->r, self->g, self->b);
|
||||
if (self->a < 1)
|
||||
g_string_append_printf (string, " / %g", self->a);
|
||||
g_string_append_c (string, ')');
|
||||
}
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_print:
|
||||
* @self: the `GdkColor` to print
|
||||
*
|
||||
* Create a string representation of @self.
|
||||
*
|
||||
* See [method@Gdk.Color.print] for details about
|
||||
* the format.
|
||||
|
||||
* Returns: (transfer full): a newly-allocated string
|
||||
*/
|
||||
char *
|
||||
gdk_color_to_string (const GdkColor *self)
|
||||
{
|
||||
GString *string = g_string_new ("");
|
||||
gdk_color_print (self, string);
|
||||
return g_string_free (string, FALSE);
|
||||
}
|
||||
|
||||
|
224
gdk/gdkcolordefs.h
Normal file
224
gdk/gdkcolordefs.h
Normal file
@@ -0,0 +1,224 @@
|
||||
/* gdkcolordefs.h
|
||||
*
|
||||
* Copyright 2024 Matthias Clasen
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Note that this header is shared between the color state implementation
|
||||
* and tests, and must not include other headers.
|
||||
*/
|
||||
|
||||
static inline float
|
||||
srgb_oetf (float v)
|
||||
{
|
||||
if (v > 0.0031308f)
|
||||
return 1.055f * powf (v, 1.f / 2.4f) - 0.055f;
|
||||
else
|
||||
return 12.92f * v;
|
||||
}
|
||||
|
||||
static inline float
|
||||
srgb_eotf (float v)
|
||||
{
|
||||
if (v >= 0.04045f)
|
||||
return powf (((v + 0.055f) / (1.f + 0.055f)), 2.4f);
|
||||
else
|
||||
return v / 12.92f;
|
||||
}
|
||||
|
||||
static inline float
|
||||
gamma22_oetf (float v)
|
||||
{
|
||||
return powf (v, 1.f / 2.2f);
|
||||
}
|
||||
|
||||
static inline float
|
||||
gamma22_eotf (float v)
|
||||
{
|
||||
return powf (v, 2.2f);
|
||||
}
|
||||
|
||||
static inline float
|
||||
gamma28_oetf (float v)
|
||||
{
|
||||
return powf (v, 1.f / 2.8f);
|
||||
}
|
||||
|
||||
static inline float
|
||||
gamma28_eotf (float v)
|
||||
{
|
||||
return powf (v, 2.8f);
|
||||
}
|
||||
|
||||
static inline float
|
||||
pq_eotf (float v)
|
||||
{
|
||||
float ninv = (1 << 14) / 2610.0;
|
||||
float minv = (1 << 5) / 2523.0;
|
||||
float c1 = 3424.0 / (1 << 12);
|
||||
float c2 = 2413.0 / (1 << 7);
|
||||
float c3 = 2392.0 / (1 << 7);
|
||||
|
||||
float x = powf (MAX ((powf (v, minv) - c1), 0) / (c2 - (c3 * (powf (v, minv)))), ninv);
|
||||
|
||||
return x * 10000 / 203.0;
|
||||
}
|
||||
|
||||
static inline float
|
||||
pq_oetf (float v)
|
||||
{
|
||||
float x = v * 203.0 / 10000.0;
|
||||
float n = 2610.0 / (1 << 14);
|
||||
float m = 2523.0 / (1 << 5);
|
||||
float c1 = 3424.0 / (1 << 12);
|
||||
float c2 = 2413.0 / (1 << 7);
|
||||
float c3 = 2392.0 / (1 << 7);
|
||||
|
||||
return powf (((c1 + (c2 * powf (x, n))) / (1 + (c3 * powf (x, n)))), m);
|
||||
}
|
||||
|
||||
static inline float
|
||||
bt709_eotf (float v)
|
||||
{
|
||||
const float a = 1.099;
|
||||
const float d = 0.0812;
|
||||
|
||||
if (v < d)
|
||||
return v / 4.5f;
|
||||
else
|
||||
return powf ((v + (a - 1)) / a, 1 / 0.45f);
|
||||
}
|
||||
|
||||
static inline float
|
||||
bt709_oetf (float v)
|
||||
{
|
||||
const float a = 1.099;
|
||||
const float b = 0.018;
|
||||
|
||||
if (v < b)
|
||||
return v * 4.5f;
|
||||
else
|
||||
return a * powf (v, 0.45f) - (a - 1);
|
||||
}
|
||||
|
||||
static inline float
|
||||
hlg_eotf (float v)
|
||||
{
|
||||
const float a = 0.17883277;
|
||||
const float b = 0.28466892;
|
||||
const float c = 0.55991073;
|
||||
|
||||
if (v <= 0.5)
|
||||
return (v * v) / 3;
|
||||
else
|
||||
return (expf ((v - c) / a) + b) / 12.0;
|
||||
}
|
||||
|
||||
static inline float
|
||||
hlg_oetf (float v)
|
||||
{
|
||||
const float a = 0.17883277;
|
||||
const float b = 0.28466892;
|
||||
const float c = 0.55991073;
|
||||
|
||||
if (v <= 1/12.0)
|
||||
return sqrtf (3 * v);
|
||||
else
|
||||
return a * logf (12 * v - b) + c;
|
||||
}
|
||||
|
||||
/* See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
|
||||
* for how to derive the abc_to_xyz matrices from chromaticity coordinates.
|
||||
*/
|
||||
|
||||
static const float identity[9] = {
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1,
|
||||
};
|
||||
|
||||
static const float srgb_to_xyz[9] = {
|
||||
0.4124564, 0.3575761, 0.1804375,
|
||||
0.2126729, 0.7151522, 0.0721750,
|
||||
0.0193339, 0.1191920, 0.9503041,
|
||||
};
|
||||
|
||||
static const float xyz_to_srgb[9] = {
|
||||
3.2404542, -1.5371385, -0.4985314,
|
||||
-0.9692660, 1.8760108, 0.0415560,
|
||||
0.0556434, -0.2040259, 1.0572252,
|
||||
};
|
||||
|
||||
static const float rec2020_to_xyz[9] = {
|
||||
0.6369580, 0.1446169, 0.1688810,
|
||||
0.2627002, 0.6779981, 0.0593017,
|
||||
0.0000000, 0.0280727, 1.0609851,
|
||||
};
|
||||
|
||||
static const float xyz_to_rec2020[9] = {
|
||||
1.7166512, -0.3556708, -0.2533663,
|
||||
-0.6666844, 1.6164812, 0.0157685,
|
||||
0.0176399, -0.0427706, 0.9421031,
|
||||
};
|
||||
|
||||
static const float pal_to_xyz[9] = {
|
||||
0.4305538, 0.3415498, 0.1783523,
|
||||
0.2220043, 0.7066548, 0.0713409,
|
||||
0.0201822, 0.1295534, 0.9393222,
|
||||
};
|
||||
|
||||
static const float xyz_to_pal[9] = {
|
||||
3.0633611, -1.3933902, -0.4758237,
|
||||
-0.9692436, 1.8759675, 0.0415551,
|
||||
0.0678610, -0.2287993, 1.0690896,
|
||||
};
|
||||
|
||||
static const float ntsc_to_xyz[9] = {
|
||||
0.3935209, 0.3652581, 0.1916769,
|
||||
0.2123764, 0.7010599, 0.0865638,
|
||||
0.0187391, 0.1119339, 0.9583847,
|
||||
};
|
||||
|
||||
static const float xyz_to_ntsc[9] = {
|
||||
3.5060033, -1.7397907, -0.5440583,
|
||||
-1.0690476, 1.9777789, 0.0351714,
|
||||
0.0563066, -0.1969757, 1.0499523,
|
||||
};
|
||||
|
||||
static const float p3_to_xyz[9] = {
|
||||
0.4865709, 0.2656677, 0.1982173,
|
||||
0.2289746, 0.6917385, 0.0792869,
|
||||
0.0000000, 0.0451134, 1.0439444,
|
||||
};
|
||||
|
||||
static const float xyz_to_p3[9] = {
|
||||
2.4934969, -0.9313836, -0.4027108,
|
||||
-0.8294890, 1.7626641, 0.0236247,
|
||||
0.0358458, -0.0761724, 0.9568845,
|
||||
};
|
||||
|
||||
/* premultiplied matrices for default conversions */
|
||||
|
||||
static const float rec2020_to_srgb[9] = {
|
||||
1.660227, -0.587548, -0.072838,
|
||||
-0.124553, 1.132926, -0.008350,
|
||||
-0.018155, -0.100603, 1.118998,
|
||||
};
|
||||
|
||||
static const float srgb_to_rec2020[9] = {
|
||||
0.627504, 0.329275, 0.043303,
|
||||
0.069108, 0.919519, 0.011360,
|
||||
0.016394, 0.088011, 0.895380,
|
||||
};
|
135
gdk/gdkcolorimpl.h
Normal file
135
gdk/gdkcolorimpl.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* Copyright (C) 2021 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
|
||||
|
||||
#define gdk_color_init(...) _gdk_color_init (__VA_ARGS__)
|
||||
static inline void
|
||||
_gdk_color_init (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const float values[4])
|
||||
{
|
||||
self->color_state = gdk_color_state_ref (color_state);
|
||||
memcpy (self->values, values, sizeof (float) * 4);
|
||||
}
|
||||
|
||||
#define gdk_color_init_copy(self, color) _gdk_color_init_copy ((self), (color))
|
||||
static inline void
|
||||
_gdk_color_init_copy (GdkColor *self,
|
||||
const GdkColor *color)
|
||||
{
|
||||
_gdk_color_init (self, color->color_state, color->values);
|
||||
}
|
||||
|
||||
#define gdk_color_init_from_rgb(self, rgba) _gdk_color_init_from_rgba ((self), (rgba))
|
||||
static inline void
|
||||
_gdk_color_init_from_rgba (GdkColor *self,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
_gdk_color_init (self, GDK_COLOR_STATE_SRGB, (const float *) rgba);
|
||||
}
|
||||
|
||||
#define gdk_color_finish(self) _gdk_color_finish ((self))
|
||||
static inline void
|
||||
_gdk_color_finish (GdkColor *self)
|
||||
{
|
||||
gdk_color_state_unref (self->color_state);
|
||||
self->color_state = NULL;
|
||||
}
|
||||
|
||||
#define gdk_color_get_color_state(self) _gdk_color_get_color_state ((self))
|
||||
static inline GdkColorState *
|
||||
_gdk_color_get_color_state (const GdkColor *self)
|
||||
{
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
#define gdk_color_equal(self, other) _gdk_color_equal ((self), (other))
|
||||
static inline gboolean
|
||||
_gdk_color_equal (const GdkColor *self,
|
||||
const GdkColor *other)
|
||||
{
|
||||
return self->values[0] == other->values[0] &&
|
||||
self->values[1] == other->values[1] &&
|
||||
self->values[2] == other->values[2] &&
|
||||
self->values[3] == other->values[3] &&
|
||||
gdk_color_state_equal (self->color_state, other->color_state);
|
||||
}
|
||||
|
||||
#define gdk_color_is_clear(self) _gdk_color_is_clear ((self))
|
||||
static inline gboolean
|
||||
_gdk_color_is_clear (const GdkColor *self)
|
||||
{
|
||||
return self->alpha < (255.f / 65535.f);
|
||||
}
|
||||
|
||||
#define gdk_color_is_opaque(self) _gdk_color_is_opaque ((self))
|
||||
static inline gboolean
|
||||
_gdk_color_is_opaque (const GdkColor *self)
|
||||
{
|
||||
return self->alpha > (65280.f / 65535.f);
|
||||
}
|
||||
|
||||
#define gdk_color_convert(self, cs, other) _gdk_color_convert ((self), (cs), (other))
|
||||
static inline void
|
||||
_gdk_color_convert (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkColor *other)
|
||||
{
|
||||
if (gdk_color_state_equal (color_state, other->color_state))
|
||||
{
|
||||
gdk_color_init_copy (self, other);
|
||||
return;
|
||||
}
|
||||
|
||||
self->color_state = gdk_color_state_ref (color_state);
|
||||
|
||||
gdk_color_state_convert_color (other->color_state,
|
||||
other->values,
|
||||
self->color_state,
|
||||
self->values);
|
||||
}
|
||||
|
||||
#define gdk_color_to_float(self, cs, values) _gdk_color_to_float ((self), (cs), (values))
|
||||
static inline void
|
||||
_gdk_color_to_float (const GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
float values[4])
|
||||
{
|
||||
if (gdk_color_state_equal (self->color_state, color_state))
|
||||
{
|
||||
memcpy (values, self->values, sizeof (float) * 4);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_color_state_convert_color (self->color_state,
|
||||
self->values,
|
||||
color_state,
|
||||
values);
|
||||
}
|
||||
|
||||
#define gdk_color_get_depth(self) _gdk_color_get_depth ((self))
|
||||
static inline GdkMemoryDepth
|
||||
_gdk_color_get_depth (const GdkColor *self)
|
||||
{
|
||||
return gdk_color_state_get_depth (self->color_state);
|
||||
}
|
||||
|
107
gdk/gdkcolorprivate.h
Normal file
107
gdk/gdkcolorprivate.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* Copyright (C) 2021 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdkcolorstate.h>
|
||||
#include <gdk/gdkrgba.h>
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
|
||||
|
||||
typedef struct _GdkColor GdkColor;
|
||||
|
||||
/* The interpretation of the first 3 components depends on the color state.
|
||||
* values[3] is always alpha.
|
||||
*/
|
||||
struct _GdkColor
|
||||
{
|
||||
GdkColorState *color_state;
|
||||
union {
|
||||
float values[4];
|
||||
struct {
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
};
|
||||
struct {
|
||||
float red;
|
||||
float green;
|
||||
float blue;
|
||||
float alpha;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (GdkColor, r) == G_STRUCT_OFFSET (GdkColor, red));
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (GdkColor, g) == G_STRUCT_OFFSET (GdkColor, green));
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (GdkColor, b) == G_STRUCT_OFFSET (GdkColor, blue));
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (GdkColor, a) == G_STRUCT_OFFSET (GdkColor, alpha));
|
||||
|
||||
/* The committee notes that since all known implementations but one "get it right"
|
||||
* this may well not be a defect at all.
|
||||
* https://open-std.org/JTC1/SC22/WG14/www/docs/n2396.htm#dr_496
|
||||
*/
|
||||
#ifndef _MSC_VER
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (GdkColor, r) == G_STRUCT_OFFSET (GdkColor, values[0]));
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (GdkColor, g) == G_STRUCT_OFFSET (GdkColor, values[1]));
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (GdkColor, b) == G_STRUCT_OFFSET (GdkColor, values[2]));
|
||||
G_STATIC_ASSERT (G_STRUCT_OFFSET (GdkColor, a) == G_STRUCT_OFFSET (GdkColor, values[3]));
|
||||
#endif
|
||||
|
||||
#define GDK_COLOR_SRGB(r,g,b,a) (GdkColor) { \
|
||||
.color_state = GDK_COLOR_STATE_SRGB, \
|
||||
.values = { (r), (g), (b), (a) } \
|
||||
}
|
||||
|
||||
void gdk_color_init (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const float values[4]);
|
||||
void gdk_color_init_copy (GdkColor *self,
|
||||
const GdkColor *color);
|
||||
void gdk_color_init_from_rgba (GdkColor *self,
|
||||
const GdkRGBA *rgba);
|
||||
void gdk_color_finish (GdkColor *self);
|
||||
|
||||
gboolean gdk_color_equal (const GdkColor *color1,
|
||||
const GdkColor *color2);
|
||||
gboolean gdk_color_is_clear (const GdkColor *self);
|
||||
gboolean gdk_color_is_opaque (const GdkColor *self);
|
||||
GdkMemoryDepth gdk_color_get_depth (const GdkColor *self);
|
||||
|
||||
void gdk_color_convert (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkColor *other);
|
||||
|
||||
void gdk_color_to_float (const GdkColor *self,
|
||||
GdkColorState *target,
|
||||
float values[4]);
|
||||
|
||||
void gdk_color_from_rgba (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkRGBA *rgba);
|
||||
|
||||
void gdk_color_print (const GdkColor *self,
|
||||
GString *string);
|
||||
|
||||
char * gdk_color_to_string (const GdkColor *self);
|
||||
|
||||
#include "gdkcolorimpl.h"
|
||||
|
||||
G_END_DECLS
|
774
gdk/gdkcolorstate.c
Normal file
774
gdk/gdkcolorstate.c
Normal file
@@ -0,0 +1,774 @@
|
||||
/* gdkcolorstate.c
|
||||
*
|
||||
* Copyright 2024 Matthias Clasen
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "gdkcolordefs.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
/**
|
||||
* GdkColorState:
|
||||
*
|
||||
* A `GdkColorState` object provides the information to interpret
|
||||
* colors and pixels in a variety of ways.
|
||||
*
|
||||
* They are also known as
|
||||
* [*color spaces*](https://en.wikipedia.org/wiki/Color_space).
|
||||
*
|
||||
* Crucially, GTK knows how to convert colors from one color
|
||||
* state to another.
|
||||
*
|
||||
* `GdkColorState objects are immutable and therefore threadsafe.
|
||||
*
|
||||
* Since 4.16
|
||||
*/
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GdkColorState, gdk_color_state,
|
||||
gdk_color_state_ref, gdk_color_state_unref);
|
||||
|
||||
/* {{{ Public API */
|
||||
|
||||
/**
|
||||
* gdk_color_state_ref:
|
||||
* @self: a `GdkColorState`
|
||||
*
|
||||
* Increase the reference count of @self.
|
||||
*
|
||||
* Returns: the object that was passed in
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
(gdk_color_state_ref) (GdkColorState *self)
|
||||
{
|
||||
return _gdk_color_state_ref (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_unref:
|
||||
* @self:a `GdkColorState`
|
||||
*
|
||||
* Decrease the reference count of @self.
|
||||
*
|
||||
* Unless @self is static, it will be freed
|
||||
* when the reference count reaches zero.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
(gdk_color_state_unref) (GdkColorState *self)
|
||||
{
|
||||
_gdk_color_state_unref (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_get_srgb:
|
||||
*
|
||||
* Returns the color state object representing the sRGB color space.
|
||||
*
|
||||
* This color state uses the primaries defined by BT.709-6 and the transfer function
|
||||
* defined by IEC 61966-2-1.
|
||||
*
|
||||
* It is equivalent to the [Cicp](class.CicpParams.html) tuple 1/13/0/1.
|
||||
*
|
||||
* See e.g. [the CSS Color Module](https://www.w3.org/TR/css-color-4/#predefined-sRGB)
|
||||
* for details about this colorstate.
|
||||
*
|
||||
* Returns: the color state object for sRGB
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_color_state_get_srgb (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_SRGB;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_get_srgb_linear:
|
||||
*
|
||||
* Returns the color state object representing the linearized sRGB color space.
|
||||
*
|
||||
* This color state uses the primaries defined by BT.709-6 and a linear transfer function.
|
||||
*
|
||||
* It is equivalent to the [Cicp](class.CicpParams.html) tuple 1/8/0/1.
|
||||
*
|
||||
* See e.g. [the CSS Color Module](https://www.w3.org/TR/css-color-4/#predefined-sRGB-linear)
|
||||
* for details about this colorstate.
|
||||
*
|
||||
* Returns: the color state object for linearized sRGB
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_color_state_get_srgb_linear (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_SRGB_LINEAR;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_get_rec2100_pq:
|
||||
*
|
||||
* Returns the color state object representing the rec2100-pq color space.
|
||||
*
|
||||
* This color state uses the primaries defined by BT.2020-2 and BT.2100-0 and the transfer
|
||||
* function defined by SMPTE ST 2084 and BT.2100-2.
|
||||
*
|
||||
* It is equivalent to the [Cicp](class.CicpParams.html) tuple 9/16/0/1.
|
||||
*
|
||||
* See e.g. [the CSS HDR Module](https://drafts.csswg.org/css-color-hdr/#valdef-color-rec2100-pq)
|
||||
* for details about this colorstate.
|
||||
*
|
||||
* Returns: the color state object for rec2100-pq
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_color_state_get_rec2100_pq (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_REC2100_PQ;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_get_rec2100_linear:
|
||||
*
|
||||
* Returns the color state object representing the linear rec2100 color space.
|
||||
*
|
||||
* This color state uses the primaries defined by BT.2020-2 and BT.2100-0 and a linear
|
||||
* transfer function.
|
||||
*
|
||||
* It is equivalent to the [Cicp](class.CicpParams.html) tuple 9/8/0/1.
|
||||
*
|
||||
* See e.g. [the CSS HDR Module](https://drafts.csswg.org/css-color-hdr/#valdef-color-rec2100-linear)
|
||||
* for details about this colorstate.
|
||||
*
|
||||
* Returns: the color state object for linearized rec2100
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_color_state_get_rec2100_linear (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_REC2100_LINEAR;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_equal:
|
||||
* @self: a `GdkColorState`
|
||||
* @other: another `GdkColorStatee`
|
||||
*
|
||||
* Compares two `GdkColorStates` for equality.
|
||||
*
|
||||
* Note that this function is not guaranteed to be perfect and two objects
|
||||
* describing the same color state may compare not equal. However, different
|
||||
* color states will never compare equal.
|
||||
*
|
||||
* Returns: %TRUE if the two color states compare equal
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
gboolean
|
||||
(gdk_color_state_equal) (GdkColorState *self,
|
||||
GdkColorState *other)
|
||||
{
|
||||
return _gdk_color_state_equal (self, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_create_cicp_params:
|
||||
* @self: a `GdkColorState`
|
||||
*
|
||||
* Create a [class@Gdk.CicpParams] representing the colorstate.
|
||||
*
|
||||
* It is not guaranteed that every `GdkColorState` can be
|
||||
* represented with Cicp parameters. If that is the case,
|
||||
* this function returns `NULL`.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): A new [class@Gdk.CicpParams]
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkCicpParams *
|
||||
gdk_color_state_create_cicp_params (GdkColorState *self)
|
||||
{
|
||||
const GdkCicp *cicp = gdk_color_state_get_cicp (self);
|
||||
|
||||
if (cicp)
|
||||
return gdk_cicp_params_new_for_cicp (cicp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Conversion functions */
|
||||
|
||||
typedef float (* GdkTransferFunc) (float v);
|
||||
typedef const float GdkColorMatrix[9];
|
||||
|
||||
#define IDENTITY ((float*)0)
|
||||
#define NONE ((GdkTransferFunc)0)
|
||||
|
||||
#define TRANSFORM(name, eotf, matrix, oetf) \
|
||||
static void \
|
||||
name (GdkColorState *self, \
|
||||
float (*values)[4], \
|
||||
gsize n_values) \
|
||||
{ \
|
||||
for (gsize i = 0; i < n_values; i++) \
|
||||
{ \
|
||||
if (eotf != NONE) \
|
||||
{ \
|
||||
values[i][0] = eotf (values[i][0]); \
|
||||
values[i][1] = eotf (values[i][1]); \
|
||||
values[i][2] = eotf (values[i][2]); \
|
||||
} \
|
||||
if (matrix != IDENTITY) \
|
||||
{ \
|
||||
float res[3]; \
|
||||
res[0] = matrix[0] * values[i][0] + matrix[1] * values[i][1] + matrix[2] * values[i][2]; \
|
||||
res[1] = matrix[3] * values[i][0] + matrix[4] * values[i][1] + matrix[5] * values[i][2]; \
|
||||
res[2] = matrix[6] * values[i][0] + matrix[7] * values[i][1] + matrix[8] * values[i][2]; \
|
||||
values[i][0] = res[0]; \
|
||||
values[i][1] = res[1]; \
|
||||
values[i][2] = res[2]; \
|
||||
} \
|
||||
if (oetf != NONE) \
|
||||
{ \
|
||||
values[i][0] = oetf (values[i][0]); \
|
||||
values[i][1] = oetf (values[i][1]); \
|
||||
values[i][2] = oetf (values[i][2]); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
TRANSFORM(gdk_default_srgb_to_srgb_linear, srgb_eotf, IDENTITY, NONE);
|
||||
TRANSFORM(gdk_default_srgb_linear_to_srgb, NONE, IDENTITY, srgb_oetf)
|
||||
TRANSFORM(gdk_default_rec2100_pq_to_rec2100_linear, pq_eotf, IDENTITY, NONE)
|
||||
TRANSFORM(gdk_default_rec2100_linear_to_rec2100_pq, NONE, IDENTITY, pq_oetf)
|
||||
TRANSFORM(gdk_default_srgb_linear_to_rec2100_linear, NONE, srgb_to_rec2020, NONE)
|
||||
TRANSFORM(gdk_default_rec2100_linear_to_srgb_linear, NONE, rec2020_to_srgb, NONE)
|
||||
TRANSFORM(gdk_default_srgb_to_rec2100_linear, srgb_eotf, srgb_to_rec2020, NONE)
|
||||
TRANSFORM(gdk_default_rec2100_pq_to_srgb_linear, pq_eotf, rec2020_to_srgb, NONE)
|
||||
TRANSFORM(gdk_default_srgb_linear_to_rec2100_pq, NONE, srgb_to_rec2020, pq_oetf)
|
||||
TRANSFORM(gdk_default_rec2100_linear_to_srgb, NONE, rec2020_to_srgb, srgb_oetf)
|
||||
TRANSFORM(gdk_default_srgb_to_rec2100_pq, srgb_eotf, srgb_to_rec2020, pq_oetf)
|
||||
TRANSFORM(gdk_default_rec2100_pq_to_srgb, pq_eotf, rec2020_to_srgb, srgb_oetf)
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Default implementation */
|
||||
/* {{{ Vfuncs */
|
||||
|
||||
static gboolean
|
||||
gdk_default_color_state_equal (GdkColorState *self,
|
||||
GdkColorState *other)
|
||||
{
|
||||
return self == other;
|
||||
}
|
||||
|
||||
static const char *
|
||||
gdk_default_color_state_get_name (GdkColorState *color_state)
|
||||
{
|
||||
GdkDefaultColorState *self = (GdkDefaultColorState *) color_state;
|
||||
|
||||
return self->name;
|
||||
}
|
||||
|
||||
static GdkColorState *
|
||||
gdk_default_color_state_get_no_srgb_tf (GdkColorState *color_state)
|
||||
{
|
||||
GdkDefaultColorState *self = (GdkDefaultColorState *) color_state;
|
||||
|
||||
return self->no_srgb;
|
||||
}
|
||||
|
||||
static GdkFloatColorConvert
|
||||
gdk_default_color_state_get_convert_to (GdkColorState *color_state,
|
||||
GdkColorState *target)
|
||||
{
|
||||
GdkDefaultColorState *self = (GdkDefaultColorState *) color_state;
|
||||
|
||||
if (GDK_IS_DEFAULT_COLOR_STATE (target))
|
||||
return self->convert_to[GDK_DEFAULT_COLOR_STATE_ID (target)];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GdkFloatColorConvert
|
||||
gdk_default_color_state_get_convert_from (GdkColorState *color_state,
|
||||
GdkColorState *source)
|
||||
{
|
||||
/* This is ok because the default-to-default conversion functions
|
||||
* don't use the passed colorstate at all.
|
||||
*/
|
||||
return gdk_default_color_state_get_convert_to (source, color_state);
|
||||
}
|
||||
|
||||
static const GdkCicp *
|
||||
gdk_default_color_state_get_cicp (GdkColorState *color_state)
|
||||
{
|
||||
GdkDefaultColorState *self = (GdkDefaultColorState *) color_state;
|
||||
|
||||
return &self->cicp;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
static const
|
||||
GdkColorStateClass GDK_DEFAULT_COLOR_STATE_CLASS = {
|
||||
.free = NULL, /* crash here if this ever happens */
|
||||
.equal = gdk_default_color_state_equal,
|
||||
.get_name = gdk_default_color_state_get_name,
|
||||
.get_no_srgb_tf = gdk_default_color_state_get_no_srgb_tf,
|
||||
.get_convert_to = gdk_default_color_state_get_convert_to,
|
||||
.get_convert_from = gdk_default_color_state_get_convert_from,
|
||||
.get_cicp = gdk_default_color_state_get_cicp,
|
||||
};
|
||||
|
||||
GdkDefaultColorState gdk_default_color_states[] = {
|
||||
[GDK_COLOR_STATE_ID_SRGB] = {
|
||||
.parent = {
|
||||
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
|
||||
.ref_count = 0,
|
||||
.depth = GDK_MEMORY_U8_SRGB,
|
||||
.rendering_color_state = GDK_COLOR_STATE_SRGB_LINEAR,
|
||||
},
|
||||
.name = "srgb",
|
||||
.no_srgb = GDK_COLOR_STATE_SRGB_LINEAR,
|
||||
.convert_to = {
|
||||
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = gdk_default_srgb_to_srgb_linear,
|
||||
[GDK_COLOR_STATE_ID_REC2100_PQ] = gdk_default_srgb_to_rec2100_pq,
|
||||
[GDK_COLOR_STATE_ID_REC2100_LINEAR] = gdk_default_srgb_to_rec2100_linear,
|
||||
},
|
||||
.cicp = { 1, 13, 0, 1 },
|
||||
},
|
||||
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = {
|
||||
.parent = {
|
||||
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
|
||||
.ref_count = 0,
|
||||
.depth = GDK_MEMORY_U8,
|
||||
.rendering_color_state = GDK_COLOR_STATE_SRGB_LINEAR,
|
||||
},
|
||||
.name = "srgb-linear",
|
||||
.no_srgb = NULL,
|
||||
.convert_to = {
|
||||
[GDK_COLOR_STATE_ID_SRGB] = gdk_default_srgb_linear_to_srgb,
|
||||
[GDK_COLOR_STATE_ID_REC2100_PQ] = gdk_default_srgb_linear_to_rec2100_pq,
|
||||
[GDK_COLOR_STATE_ID_REC2100_LINEAR] = gdk_default_srgb_linear_to_rec2100_linear,
|
||||
},
|
||||
.cicp = { 1, 8, 0, 1 },
|
||||
},
|
||||
[GDK_COLOR_STATE_ID_REC2100_PQ] = {
|
||||
.parent = {
|
||||
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
|
||||
.ref_count = 0,
|
||||
.depth = GDK_MEMORY_FLOAT16,
|
||||
.rendering_color_state = GDK_COLOR_STATE_REC2100_LINEAR,
|
||||
},
|
||||
.name = "rec2100-pq",
|
||||
.no_srgb = NULL,
|
||||
.convert_to = {
|
||||
[GDK_COLOR_STATE_ID_SRGB] = gdk_default_rec2100_pq_to_srgb,
|
||||
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = gdk_default_rec2100_pq_to_srgb_linear,
|
||||
[GDK_COLOR_STATE_ID_REC2100_LINEAR] = gdk_default_rec2100_pq_to_rec2100_linear,
|
||||
},
|
||||
.cicp = { 9, 16, 0, 1 },
|
||||
},
|
||||
[GDK_COLOR_STATE_ID_REC2100_LINEAR] = {
|
||||
.parent = {
|
||||
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
|
||||
.ref_count = 0,
|
||||
.depth = GDK_MEMORY_FLOAT16,
|
||||
.rendering_color_state = GDK_COLOR_STATE_REC2100_LINEAR,
|
||||
},
|
||||
.name = "rec2100-linear",
|
||||
.no_srgb = NULL,
|
||||
.convert_to = {
|
||||
[GDK_COLOR_STATE_ID_SRGB] = gdk_default_rec2100_linear_to_srgb,
|
||||
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = gdk_default_rec2100_linear_to_srgb_linear,
|
||||
[GDK_COLOR_STATE_ID_REC2100_PQ] = gdk_default_rec2100_linear_to_rec2100_pq,
|
||||
},
|
||||
.cicp = { 9, 8, 0, 1 },
|
||||
},
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Cicp implementation */
|
||||
|
||||
typedef struct _GdkCicpColorState GdkCicpColorState;
|
||||
struct _GdkCicpColorState
|
||||
{
|
||||
GdkColorState parent;
|
||||
|
||||
GdkColorState *no_srgb;
|
||||
|
||||
const char *name;
|
||||
|
||||
GdkTransferFunc eotf;
|
||||
GdkTransferFunc oetf;
|
||||
|
||||
float *to_srgb;
|
||||
float *to_rec2020;
|
||||
float *from_srgb;
|
||||
float *from_rec2020;
|
||||
|
||||
GdkCicp cicp;
|
||||
};
|
||||
|
||||
/* {{{ Conversion functions */
|
||||
|
||||
#define cicp ((GdkCicpColorState *)self)
|
||||
|
||||
TRANSFORM(gdk_cicp_to_srgb, cicp->eotf, cicp->to_srgb, srgb_oetf)
|
||||
TRANSFORM(gdk_cicp_to_srgb_linear, cicp->eotf, cicp->to_srgb, NONE)
|
||||
TRANSFORM(gdk_cicp_to_rec2100_pq, cicp->eotf, cicp->to_rec2020, pq_oetf)
|
||||
TRANSFORM(gdk_cicp_to_rec2100_linear, cicp->eotf, cicp->to_rec2020, NONE)
|
||||
TRANSFORM(gdk_cicp_from_srgb, srgb_eotf, cicp->from_srgb, cicp->oetf)
|
||||
TRANSFORM(gdk_cicp_from_srgb_linear, NONE, cicp->from_srgb, cicp->oetf)
|
||||
TRANSFORM(gdk_cicp_from_rec2100_pq, pq_eotf, cicp->from_rec2020, cicp->oetf)
|
||||
TRANSFORM(gdk_cicp_from_rec2100_linear, NONE, cicp->from_rec2020, cicp->oetf)
|
||||
|
||||
#undef cicp
|
||||
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
/* {{{ Vfuncs */
|
||||
|
||||
static void
|
||||
gdk_cicp_color_state_free (GdkColorState *cs)
|
||||
{
|
||||
GdkCicpColorState *self = (GdkCicpColorState *) cs;
|
||||
|
||||
if (self->no_srgb)
|
||||
gdk_color_state_unref (self->no_srgb);
|
||||
|
||||
g_free (self->to_srgb);
|
||||
g_free (self->to_rec2020);
|
||||
g_free (self->from_srgb);
|
||||
g_free (self->from_rec2020);
|
||||
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_cicp_color_state_equal (GdkColorState *self,
|
||||
GdkColorState *other)
|
||||
{
|
||||
GdkCicpColorState *cs1 = (GdkCicpColorState *) self;
|
||||
GdkCicpColorState *cs2 = (GdkCicpColorState *) other;
|
||||
|
||||
return gdk_cicp_equal (&cs1->cicp, &cs2->cicp);
|
||||
}
|
||||
|
||||
static const char *
|
||||
gdk_cicp_color_state_get_name (GdkColorState *self)
|
||||
{
|
||||
GdkCicpColorState *cs = (GdkCicpColorState *) self;
|
||||
|
||||
return cs->name;
|
||||
}
|
||||
|
||||
static GdkColorState *
|
||||
gdk_cicp_color_state_get_no_srgb_tf (GdkColorState *self)
|
||||
{
|
||||
GdkCicpColorState *cs = (GdkCicpColorState *) self;
|
||||
|
||||
return cs->no_srgb;
|
||||
}
|
||||
|
||||
static GdkFloatColorConvert
|
||||
gdk_cicp_color_state_get_convert_to (GdkColorState *self,
|
||||
GdkColorState *target)
|
||||
{
|
||||
if (!GDK_IS_DEFAULT_COLOR_STATE (target))
|
||||
return NULL;
|
||||
|
||||
switch (GDK_DEFAULT_COLOR_STATE_ID (target))
|
||||
{
|
||||
case GDK_COLOR_STATE_ID_SRGB:
|
||||
return gdk_cicp_to_srgb;
|
||||
case GDK_COLOR_STATE_ID_SRGB_LINEAR:
|
||||
return gdk_cicp_to_srgb_linear;
|
||||
case GDK_COLOR_STATE_ID_REC2100_PQ:
|
||||
return gdk_cicp_to_rec2100_pq;
|
||||
case GDK_COLOR_STATE_ID_REC2100_LINEAR:
|
||||
return gdk_cicp_to_rec2100_linear;
|
||||
|
||||
case GDK_COLOR_STATE_N_IDS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GdkFloatColorConvert
|
||||
gdk_cicp_color_state_get_convert_from (GdkColorState *self,
|
||||
GdkColorState *source)
|
||||
{
|
||||
if (!GDK_IS_DEFAULT_COLOR_STATE (source))
|
||||
return NULL;
|
||||
|
||||
switch (GDK_DEFAULT_COLOR_STATE_ID (source))
|
||||
{
|
||||
case GDK_COLOR_STATE_ID_SRGB:
|
||||
return gdk_cicp_from_srgb;
|
||||
case GDK_COLOR_STATE_ID_SRGB_LINEAR:
|
||||
return gdk_cicp_from_srgb_linear;
|
||||
case GDK_COLOR_STATE_ID_REC2100_PQ:
|
||||
return gdk_cicp_from_rec2100_pq;
|
||||
case GDK_COLOR_STATE_ID_REC2100_LINEAR:
|
||||
return gdk_cicp_from_rec2100_linear;
|
||||
|
||||
case GDK_COLOR_STATE_N_IDS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const GdkCicp *
|
||||
gdk_cicp_color_state_get_cicp (GdkColorState *color_state)
|
||||
{
|
||||
GdkCicpColorState *self = (GdkCicpColorState *) color_state;
|
||||
|
||||
return &self->cicp;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
static const
|
||||
GdkColorStateClass GDK_CICP_COLOR_STATE_CLASS = {
|
||||
.free = gdk_cicp_color_state_free,
|
||||
.equal = gdk_cicp_color_state_equal,
|
||||
.get_name = gdk_cicp_color_state_get_name,
|
||||
.get_no_srgb_tf = gdk_cicp_color_state_get_no_srgb_tf,
|
||||
.get_convert_to = gdk_cicp_color_state_get_convert_to,
|
||||
.get_convert_from = gdk_cicp_color_state_get_convert_from,
|
||||
.get_cicp = gdk_cicp_color_state_get_cicp,
|
||||
};
|
||||
|
||||
static inline float *
|
||||
multiply (float res[9],
|
||||
const float m1[9],
|
||||
const float m2[9])
|
||||
{
|
||||
#define IDX(i,j) 3*i+j
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (int j = 0; j < 3; j++)
|
||||
res[IDX(i,j)] = m1[IDX(i,0)] * m2[IDX(0,j)]
|
||||
+ m1[IDX(i,1)] * m2[IDX(1,j)]
|
||||
+ m1[IDX(i,2)] * m2[IDX(2,j)];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
gdk_color_state_new_for_cicp (const GdkCicp *cicp,
|
||||
GError **error)
|
||||
{
|
||||
GdkCicpColorState *self;
|
||||
GdkTransferFunc eotf;
|
||||
GdkTransferFunc oetf;
|
||||
gconstpointer to_xyz;
|
||||
gconstpointer from_xyz;
|
||||
|
||||
if (cicp->range == GDK_CICP_RANGE_NARROW || cicp->matrix_coefficients != 0)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("cicp: Narrow range or YUV not supported"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cicp->color_primaries == 2 ||
|
||||
cicp->transfer_function == 2 ||
|
||||
cicp->matrix_coefficients == 2)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("cicp: Unspecified parameters not supported"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (guint i = 0; i < GDK_COLOR_STATE_N_IDS; i++)
|
||||
{
|
||||
if (gdk_cicp_equivalent (cicp, &gdk_default_color_states[i].cicp))
|
||||
return (GdkColorState *) &gdk_default_color_states[i];
|
||||
}
|
||||
|
||||
switch (cicp->transfer_function)
|
||||
{
|
||||
case 1:
|
||||
case 6:
|
||||
case 14:
|
||||
case 15:
|
||||
eotf = bt709_eotf;
|
||||
oetf = bt709_oetf;
|
||||
break;
|
||||
case 4:
|
||||
eotf = gamma22_eotf;
|
||||
oetf = gamma22_oetf;
|
||||
break;
|
||||
case 5:
|
||||
eotf = gamma28_eotf;
|
||||
oetf = gamma28_oetf;
|
||||
break;
|
||||
case 8:
|
||||
eotf = NONE;
|
||||
oetf = NONE;
|
||||
break;
|
||||
case 13:
|
||||
eotf = srgb_eotf;
|
||||
oetf = srgb_oetf;
|
||||
break;
|
||||
case 16:
|
||||
eotf = pq_eotf;
|
||||
oetf = pq_oetf;
|
||||
break;
|
||||
case 18:
|
||||
eotf = hlg_eotf;
|
||||
oetf = hlg_oetf;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("cicp: Transfer function %u not supported"),
|
||||
cicp->transfer_function);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (cicp->color_primaries)
|
||||
{
|
||||
case 1:
|
||||
to_xyz = srgb_to_xyz;
|
||||
from_xyz = xyz_to_srgb;
|
||||
break;
|
||||
case 5:
|
||||
to_xyz = pal_to_xyz;
|
||||
from_xyz = xyz_to_pal;
|
||||
break;
|
||||
case 6:
|
||||
to_xyz = ntsc_to_xyz;
|
||||
from_xyz = xyz_to_ntsc;
|
||||
break;
|
||||
case 9:
|
||||
to_xyz = rec2020_to_xyz;
|
||||
from_xyz = xyz_to_rec2020;
|
||||
break;
|
||||
case 12:
|
||||
to_xyz = p3_to_xyz;
|
||||
from_xyz = xyz_to_p3;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("cicp: Color primaries %u not supported"),
|
||||
cicp->color_primaries);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self = g_new0 (GdkCicpColorState, 1);
|
||||
|
||||
self->parent.klass = &GDK_CICP_COLOR_STATE_CLASS;
|
||||
self->parent.ref_count = 1;
|
||||
|
||||
/* sRGB is special-cased by being a default colorstate */
|
||||
self->parent.rendering_color_state = GDK_COLOR_STATE_REC2100_LINEAR;
|
||||
|
||||
self->parent.depth = GDK_MEMORY_FLOAT16;
|
||||
|
||||
memcpy (&self->cicp, cicp, sizeof (GdkCicp));
|
||||
|
||||
self->eotf = eotf;
|
||||
self->oetf = oetf;
|
||||
|
||||
self->to_srgb = multiply (g_new (float, 9), xyz_to_srgb, to_xyz);
|
||||
self->to_rec2020 = multiply (g_new (float, 9), xyz_to_rec2020, to_xyz);
|
||||
self->from_srgb = multiply (g_new (float, 9), from_xyz, srgb_to_xyz);
|
||||
self->from_rec2020 = multiply (g_new (float, 9), from_xyz, rec2020_to_xyz);
|
||||
|
||||
self->name = g_strdup_printf ("cicp-%u/%u/%u/%u",
|
||||
cicp->color_primaries,
|
||||
cicp->transfer_function,
|
||||
cicp->matrix_coefficients,
|
||||
cicp->range);
|
||||
|
||||
if (cicp->transfer_function == 13)
|
||||
{
|
||||
GdkCicp no_srgb;
|
||||
|
||||
memcpy (&no_srgb, cicp, sizeof (GdkCicp));
|
||||
no_srgb.transfer_function = 8;
|
||||
|
||||
self->no_srgb = gdk_color_state_new_for_cicp (&no_srgb, NULL);
|
||||
}
|
||||
|
||||
return (GdkColorState *) self;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Private API */
|
||||
|
||||
/*<private>
|
||||
* gdk_color_state_get_name:
|
||||
* @self: a colorstate
|
||||
*
|
||||
* Returns the name of @self.
|
||||
*
|
||||
* This is *not* a translated, user-visible string.
|
||||
*
|
||||
* Returns: (transfer none): a name for representing the color state
|
||||
* in diagnostic output
|
||||
*/
|
||||
const char *
|
||||
gdk_color_state_get_name (GdkColorState *self)
|
||||
{
|
||||
return self->klass->get_name (self);
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_color_state_get_no_srgb_tf:
|
||||
* @self: a colorstate
|
||||
*
|
||||
* This function checks if the colorstate uses an sRGB transfer function
|
||||
* as final operation. In that case, it is suitable for use with GL_SRGB
|
||||
* (and the Vulkan equivalents).
|
||||
*
|
||||
* If it is suitable, the colorstate without the transfer function is
|
||||
* returned. Otherwise, this function returns NULL.
|
||||
*
|
||||
* Returns: (transfer none): the colorstate without sRGB transfer function.
|
||||
**/
|
||||
GdkColorState *
|
||||
gdk_color_state_get_no_srgb_tf (GdkColorState *self)
|
||||
{
|
||||
if (!GDK_DEBUG_CHECK (LINEAR))
|
||||
return FALSE;
|
||||
|
||||
return self->klass->get_no_srgb_tf (self);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
62
gdk/gdkcolorstate.h
Normal file
62
gdk/gdkcolorstate.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* gdkcolorstate.h
|
||||
*
|
||||
* Copyright 2024 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_COLOR_STATE (gdk_color_state_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GType gdk_color_state_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_ref (GdkColorState *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_color_state_unref (GdkColorState *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_srgb (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_srgb_linear (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_rec2100_pq (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_rec2100_linear (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gboolean gdk_color_state_equal (GdkColorState *self,
|
||||
GdkColorState *other);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkCicpParams *gdk_color_state_create_cicp_params (GdkColorState *self);
|
||||
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkColorState, gdk_color_state_unref);
|
||||
|
||||
G_END_DECLS
|
220
gdk/gdkcolorstateprivate.h
Normal file
220
gdk/gdkcolorstateprivate.h
Normal file
@@ -0,0 +1,220 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkcolorstate.h"
|
||||
|
||||
#include "gdkcicpparamsprivate.h"
|
||||
#include "gdkdebugprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkrgba.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GDK_COLOR_STATE_ID_SRGB,
|
||||
GDK_COLOR_STATE_ID_SRGB_LINEAR,
|
||||
GDK_COLOR_STATE_ID_REC2100_PQ,
|
||||
GDK_COLOR_STATE_ID_REC2100_LINEAR,
|
||||
|
||||
GDK_COLOR_STATE_N_IDS
|
||||
} GdkColorStateId;
|
||||
|
||||
typedef struct _GdkColorStateClass GdkColorStateClass;
|
||||
|
||||
struct _GdkColorState
|
||||
{
|
||||
const GdkColorStateClass *klass;
|
||||
gatomicrefcount ref_count;
|
||||
|
||||
GdkMemoryDepth depth;
|
||||
GdkColorState *rendering_color_state;
|
||||
};
|
||||
|
||||
/* Note: self may be the source or the target colorstate */
|
||||
typedef void (* GdkFloatColorConvert)(GdkColorState *self,
|
||||
float (*values)[4],
|
||||
gsize n_values);
|
||||
|
||||
struct _GdkColorStateClass
|
||||
{
|
||||
void (* free) (GdkColorState *self);
|
||||
gboolean (* equal) (GdkColorState *self,
|
||||
GdkColorState *other);
|
||||
const char * (* get_name) (GdkColorState *self);
|
||||
GdkColorState * (* get_no_srgb_tf) (GdkColorState *self);
|
||||
GdkFloatColorConvert (* get_convert_to) (GdkColorState *self,
|
||||
GdkColorState *target);
|
||||
GdkFloatColorConvert (* get_convert_from) (GdkColorState *self,
|
||||
GdkColorState *source);
|
||||
const GdkCicp * (* get_cicp) (GdkColorState *self);
|
||||
};
|
||||
|
||||
typedef struct _GdkDefaultColorState GdkDefaultColorState;
|
||||
|
||||
struct _GdkDefaultColorState
|
||||
{
|
||||
GdkColorState parent;
|
||||
|
||||
const char *name;
|
||||
GdkColorState *no_srgb;
|
||||
GdkFloatColorConvert convert_to[GDK_COLOR_STATE_N_IDS];
|
||||
|
||||
GdkCicp cicp;
|
||||
};
|
||||
|
||||
extern GdkDefaultColorState gdk_default_color_states[GDK_COLOR_STATE_N_IDS];
|
||||
|
||||
#define GDK_COLOR_STATE_SRGB ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_SRGB])
|
||||
#define GDK_COLOR_STATE_SRGB_LINEAR ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_SRGB_LINEAR])
|
||||
#define GDK_COLOR_STATE_REC2100_PQ ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_REC2100_PQ])
|
||||
#define GDK_COLOR_STATE_REC2100_LINEAR ((GdkColorState *) &gdk_default_color_states[GDK_COLOR_STATE_ID_REC2100_LINEAR])
|
||||
|
||||
#define GDK_IS_DEFAULT_COLOR_STATE(c) ((GdkDefaultColorState *) (c) >= &gdk_default_color_states[0] && \
|
||||
(GdkDefaultColorState *) (c) < &gdk_default_color_states[GDK_COLOR_STATE_N_IDS])
|
||||
#define GDK_DEFAULT_COLOR_STATE_ID(c) ((GdkColorStateId) (((GdkDefaultColorState *) c) - gdk_default_color_states))
|
||||
|
||||
const char * gdk_color_state_get_name (GdkColorState *color_state);
|
||||
GdkColorState * gdk_color_state_get_no_srgb_tf (GdkColorState *self);
|
||||
|
||||
GdkColorState * gdk_color_state_new_for_cicp (const GdkCicp *cicp,
|
||||
GError **error);
|
||||
|
||||
static inline GdkColorState *
|
||||
gdk_color_state_get_rendering_color_state (GdkColorState *self,
|
||||
gboolean srgb)
|
||||
{
|
||||
if (srgb)
|
||||
{
|
||||
self = gdk_color_state_get_no_srgb_tf (self);
|
||||
g_assert (self);
|
||||
}
|
||||
|
||||
if (GDK_DEBUG_CHECK (HDR))
|
||||
self = GDK_COLOR_STATE_REC2100_PQ;
|
||||
|
||||
if (!GDK_DEBUG_CHECK (LINEAR))
|
||||
return self;
|
||||
|
||||
return self->rendering_color_state;
|
||||
}
|
||||
|
||||
static inline GdkMemoryDepth
|
||||
gdk_color_state_get_depth (GdkColorState *self)
|
||||
{
|
||||
if (!GDK_DEBUG_CHECK (LINEAR) && self->depth == GDK_MEMORY_U8_SRGB)
|
||||
return GDK_MEMORY_U8;
|
||||
|
||||
return self->depth;
|
||||
}
|
||||
|
||||
static inline GdkColorState *
|
||||
gdk_color_state_get_by_id (GdkColorStateId id)
|
||||
{
|
||||
return (GdkColorState *) &gdk_default_color_states[id];
|
||||
}
|
||||
|
||||
#define gdk_color_state_ref(self) _gdk_color_state_ref (self)
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_ref (GdkColorState *self)
|
||||
{
|
||||
if (GDK_IS_DEFAULT_COLOR_STATE (self))
|
||||
return self;
|
||||
|
||||
g_atomic_ref_count_inc (&self->ref_count);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#define gdk_color_state_unref(self) _gdk_color_state_unref (self)
|
||||
static inline void
|
||||
_gdk_color_state_unref (GdkColorState *self)
|
||||
{
|
||||
if (GDK_IS_DEFAULT_COLOR_STATE (self))
|
||||
return;
|
||||
|
||||
if (g_atomic_ref_count_dec (&self->ref_count))
|
||||
self->klass->free (self);
|
||||
}
|
||||
|
||||
#define gdk_color_state_equal(a,b) _gdk_color_state_equal ((a), (b))
|
||||
static inline gboolean
|
||||
_gdk_color_state_equal (GdkColorState *self,
|
||||
GdkColorState *other)
|
||||
{
|
||||
if (self == other)
|
||||
return TRUE;
|
||||
|
||||
if (self->klass != other->klass)
|
||||
return FALSE;
|
||||
|
||||
return self->klass->equal (self, other);
|
||||
}
|
||||
|
||||
/* Note: the functions returned from this expect the source
|
||||
* color state to be passed as self
|
||||
*/
|
||||
static inline GdkFloatColorConvert
|
||||
gdk_color_state_get_convert_to (GdkColorState *self,
|
||||
GdkColorState *target)
|
||||
{
|
||||
return self->klass->get_convert_to (self, target);
|
||||
}
|
||||
|
||||
/* Note: the functions returned from this expect the target
|
||||
* color state to be passed as self
|
||||
*/
|
||||
static inline GdkFloatColorConvert
|
||||
gdk_color_state_get_convert_from (GdkColorState *self,
|
||||
GdkColorState *source)
|
||||
{
|
||||
return self->klass->get_convert_from (self, source);
|
||||
}
|
||||
|
||||
static inline const GdkCicp *
|
||||
gdk_color_state_get_cicp (GdkColorState *self)
|
||||
{
|
||||
return self->klass->get_cicp (self);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_color_state_convert_color (GdkColorState *src_cs,
|
||||
const float src[4],
|
||||
GdkColorState *dest_cs,
|
||||
float dest[4])
|
||||
{
|
||||
GdkFloatColorConvert convert = NULL;
|
||||
GdkFloatColorConvert convert2 = NULL;
|
||||
|
||||
memcpy (dest, src, sizeof (float) * 4);
|
||||
|
||||
if (gdk_color_state_equal (src_cs, dest_cs))
|
||||
return;
|
||||
|
||||
convert = gdk_color_state_get_convert_to (src_cs, dest_cs);
|
||||
|
||||
if (!convert)
|
||||
convert2 = gdk_color_state_get_convert_from (dest_cs, src_cs);
|
||||
|
||||
if (!convert && !convert2)
|
||||
{
|
||||
GdkColorState *connection = GDK_COLOR_STATE_REC2100_LINEAR;
|
||||
convert = gdk_color_state_get_convert_to (src_cs, connection);
|
||||
convert2 = gdk_color_state_get_convert_from (dest_cs, connection);
|
||||
}
|
||||
|
||||
if (convert)
|
||||
convert (src_cs, (float(*)[4]) dest, 1);
|
||||
|
||||
if (convert2)
|
||||
convert2 (dest_cs, (float(*)[4]) dest, 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_color_state_from_rgba (GdkColorState *self,
|
||||
const GdkRGBA *rgba,
|
||||
float out_color[4])
|
||||
{
|
||||
gdk_color_state_convert_color (GDK_COLOR_STATE_SRGB,
|
||||
(const float *) rgba,
|
||||
self,
|
||||
out_color);
|
||||
}
|
||||
|
@@ -533,8 +533,8 @@ deserialize_not_found (GdkContentDeserializer *deserializer)
|
||||
* @type: the GType to deserialize from
|
||||
* @io_priority: the I/O priority of the operation
|
||||
* @cancellable: (nullable): optional `GCancellable` object
|
||||
* @callback: (scope async): callback to call when the operation is done
|
||||
* @user_data: (closure): data to pass to the callback function
|
||||
* @callback: (scope async) (closure user_data): callback to call when the operation is done
|
||||
* @user_data: data to pass to the callback function
|
||||
*
|
||||
* Read content from the given input stream and deserialize it, asynchronously.
|
||||
*
|
||||
|
@@ -273,8 +273,8 @@ gdk_content_provider_content_changed (GdkContentProvider *provider)
|
||||
* @stream: the `GOutputStream` to write to
|
||||
* @io_priority: I/O priority of the request.
|
||||
* @cancellable: (nullable): optional `GCancellable` object, %NULL to ignore.
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
* @callback: (scope async) (closure user_data): callback to call when the request is satisfied
|
||||
* @user_data: the data to pass to callback function
|
||||
*
|
||||
* Asynchronously writes the contents of @provider to @stream in the given
|
||||
* @mime_type.
|
||||
|
@@ -539,8 +539,8 @@ serialize_not_found (GdkContentSerializer *serializer)
|
||||
* @value: the content to serialize
|
||||
* @io_priority: the I/O priority of the operation
|
||||
* @cancellable: (nullable): optional `GCancellable` object
|
||||
* @callback: (scope async): callback to call when the operation is done
|
||||
* @user_data: (closure): data to pass to the callback function
|
||||
* @callback: (scope async) (closure): callback to call when the operation is done
|
||||
* @user_data: data to pass to the callback function
|
||||
*
|
||||
* Serialize content and write it to the given output stream, asynchronously.
|
||||
*
|
||||
|
@@ -40,20 +40,21 @@ typedef enum {
|
||||
GDK_DEBUG_OFFLOAD = 1 << 12,
|
||||
|
||||
/* flags below are influencing behavior */
|
||||
GDK_DEBUG_PORTALS = 1 << 14,
|
||||
GDK_DEBUG_NO_PORTALS = 1 << 15,
|
||||
GDK_DEBUG_GL_DISABLE = 1 << 16,
|
||||
GDK_DEBUG_GL_NO_FRACTIONAL= 1 << 17,
|
||||
GDK_DEBUG_FORCE_OFFLOAD = 1 << 18,
|
||||
GDK_DEBUG_GL_DISABLE_GL = 1 << 19,
|
||||
GDK_DEBUG_GL_DISABLE_GLES = 1 << 20,
|
||||
GDK_DEBUG_GL_PREFER_GL = 1 << 21,
|
||||
GDK_DEBUG_GL_DEBUG = 1 << 22,
|
||||
GDK_DEBUG_GL_EGL = 1 << 23,
|
||||
GDK_DEBUG_GL_GLX = 1 << 24,
|
||||
GDK_DEBUG_GL_WGL = 1 << 25,
|
||||
GDK_DEBUG_VULKAN_DISABLE = 1 << 26,
|
||||
GDK_DEBUG_VULKAN_VALIDATE = 1 << 27,
|
||||
GDK_DEBUG_LINEAR = 1 << 13,
|
||||
GDK_DEBUG_HDR = 1 << 14,
|
||||
GDK_DEBUG_PORTALS = 1 << 15,
|
||||
GDK_DEBUG_NO_PORTALS = 1 << 16,
|
||||
GDK_DEBUG_GL_DISABLE = 1 << 17,
|
||||
GDK_DEBUG_GL_NO_FRACTIONAL= 1 << 18,
|
||||
GDK_DEBUG_FORCE_OFFLOAD = 1 << 19,
|
||||
GDK_DEBUG_GL_DISABLE_GL = 1 << 20,
|
||||
GDK_DEBUG_GL_DISABLE_GLES = 1 << 21,
|
||||
GDK_DEBUG_GL_PREFER_GL = 1 << 22,
|
||||
GDK_DEBUG_GL_DEBUG = 1 << 23,
|
||||
GDK_DEBUG_GL_EGL = 1 << 24,
|
||||
GDK_DEBUG_GL_GLX = 1 << 25,
|
||||
GDK_DEBUG_GL_WGL = 1 << 26,
|
||||
GDK_DEBUG_VULKAN_DISABLE = 1 << 27,
|
||||
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 28,
|
||||
GDK_DEBUG_HIGH_DEPTH = 1 << 29,
|
||||
GDK_DEBUG_NO_VSYNC = 1 << 30,
|
||||
|
82
gdk/gdkdihedral.c
Normal file
82
gdk/gdkdihedral.c
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkdihedralprivate.h"
|
||||
|
||||
void
|
||||
gdk_dihedral_get_mat2 (GdkDihedral transform,
|
||||
float *xx,
|
||||
float *xy,
|
||||
float *yx,
|
||||
float *yy)
|
||||
{
|
||||
const float mat[8][2][2] = {
|
||||
[GDK_DIHEDRAL_NORMAL] = {
|
||||
{ 1.0, 0.0 },
|
||||
{ 0.0, 1.0 }
|
||||
},
|
||||
[GDK_DIHEDRAL_90] = {
|
||||
{ 0.0, 1.0 },
|
||||
{ -1.0, 0.0 }
|
||||
},
|
||||
[GDK_DIHEDRAL_180] = {
|
||||
{ -1.0, 0.0 },
|
||||
{ 0.0, -1.0 }
|
||||
},
|
||||
[GDK_DIHEDRAL_270] = {
|
||||
{ 0.0, -1.0 },
|
||||
{ 1.0, 0.0 }
|
||||
},
|
||||
[GDK_DIHEDRAL_FLIPPED] = {
|
||||
{ -1.0, 0.0 },
|
||||
{ 0.0, 1.0 }
|
||||
},
|
||||
[GDK_DIHEDRAL_FLIPPED_90] = {
|
||||
{ 0.0, -1.0 },
|
||||
{ -1.0, 0.0 }
|
||||
},
|
||||
[GDK_DIHEDRAL_FLIPPED_180] = {
|
||||
{ 1.0, 0.0 },
|
||||
{ 0.0, -1.0 }
|
||||
},
|
||||
[GDK_DIHEDRAL_FLIPPED_270] = {
|
||||
{ 0.0, 1.0 },
|
||||
{ 1.0, 0.0 }
|
||||
},
|
||||
};
|
||||
|
||||
*xx = mat[transform][0][0];
|
||||
*xy = mat[transform][1][0];
|
||||
*yx = mat[transform][0][1];
|
||||
*yy = mat[transform][1][1];
|
||||
}
|
||||
|
||||
GdkDihedral
|
||||
gdk_dihedral_combine (GdkDihedral first,
|
||||
GdkDihedral second)
|
||||
{
|
||||
return ((first & 4) ^ (second & 4)) |
|
||||
((((first & 3) * (((second & 4) >> 1) + 1)) + second) & 3);
|
||||
}
|
||||
|
||||
GdkDihedral
|
||||
gdk_dihedral_invert (GdkDihedral self)
|
||||
{
|
||||
return ((4 - self) * (((self & 4) >> 1) + 1) & 3) | (self & 4);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_dihedral_swaps_xy (GdkDihedral self)
|
||||
{
|
||||
return (self & 1) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
const char *
|
||||
gdk_dihedral_get_name (GdkDihedral self)
|
||||
{
|
||||
const char *name[] = {
|
||||
"normal", "90", "180", "270", "flipped", "flipped-90", "flipped-180", "flipped-270"
|
||||
};
|
||||
|
||||
return name[self];
|
||||
}
|
49
gdk/gdkdihedralprivate.h
Normal file
49
gdk/gdkdihedralprivate.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2024 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GDK_DIHEDRAL_NORMAL,
|
||||
GDK_DIHEDRAL_90,
|
||||
GDK_DIHEDRAL_180,
|
||||
GDK_DIHEDRAL_270,
|
||||
GDK_DIHEDRAL_FLIPPED,
|
||||
GDK_DIHEDRAL_FLIPPED_90,
|
||||
GDK_DIHEDRAL_FLIPPED_180,
|
||||
GDK_DIHEDRAL_FLIPPED_270,
|
||||
} GdkDihedral;
|
||||
|
||||
void gdk_dihedral_get_mat2 (GdkDihedral transform,
|
||||
float *xx,
|
||||
float *xy,
|
||||
float *yx,
|
||||
float *yy);
|
||||
|
||||
GdkDihedral gdk_dihedral_combine (GdkDihedral first,
|
||||
GdkDihedral second);
|
||||
GdkDihedral gdk_dihedral_invert (GdkDihedral self);
|
||||
gboolean gdk_dihedral_swaps_xy (GdkDihedral self);
|
||||
|
||||
const char * gdk_dihedral_get_name (GdkDihedral self);
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -1570,19 +1570,27 @@ describe_egl_config (EGLDisplay egl_display,
|
||||
}
|
||||
|
||||
gpointer
|
||||
gdk_display_get_egl_config (GdkDisplay *self)
|
||||
gdk_display_get_egl_config (GdkDisplay *self,
|
||||
GdkMemoryDepth depth)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
|
||||
return priv->egl_config;
|
||||
}
|
||||
switch (depth)
|
||||
{
|
||||
case GDK_MEMORY_NONE:
|
||||
case GDK_MEMORY_U8:
|
||||
case GDK_MEMORY_U8_SRGB:
|
||||
return priv->egl_config;
|
||||
|
||||
gpointer
|
||||
gdk_display_get_egl_config_high_depth (GdkDisplay *self)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
case GDK_MEMORY_U16:
|
||||
case GDK_MEMORY_FLOAT16:
|
||||
case GDK_MEMORY_FLOAT32:
|
||||
return priv->egl_config_high_depth;
|
||||
|
||||
return priv->egl_config_high_depth;
|
||||
case GDK_N_DEPTHS:
|
||||
default:
|
||||
g_return_val_if_reached (priv->egl_config);
|
||||
}
|
||||
}
|
||||
|
||||
static EGLDisplay
|
||||
@@ -1874,6 +1882,8 @@ gdk_display_init_egl (GdkDisplay *self,
|
||||
epoxy_has_egl_extension (priv->egl_display, "EGL_EXT_image_dma_buf_import_modifiers");
|
||||
self->have_egl_dma_buf_export =
|
||||
epoxy_has_egl_extension (priv->egl_display, "EGL_MESA_image_dma_buf_export");
|
||||
self->have_egl_gl_colorspace =
|
||||
epoxy_has_egl_extension (priv->egl_display, "EGL_KHR_gl_colorspace");
|
||||
|
||||
if (self->have_egl_no_config_context)
|
||||
priv->egl_config_high_depth = gdk_display_create_egl_config (self,
|
||||
|
@@ -18,15 +18,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdksurface.h"
|
||||
|
||||
#include "gdkcursor.h"
|
||||
#include "gdkmonitor.h"
|
||||
#include "gdkdebugprivate.h"
|
||||
#include "gdksurfaceprivate.h"
|
||||
#include "gdkkeysprivate.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdmabufprivate.h"
|
||||
#include "gdkdmabufdownloaderprivate.h"
|
||||
#include "gdkdmabufprivate.h"
|
||||
#include "gdkkeysprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmonitor.h"
|
||||
#include "gdksurfaceprivate.h"
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
@@ -44,12 +45,9 @@ typedef struct _GdkDisplayClass GdkDisplayClass;
|
||||
typedef enum {
|
||||
GDK_VULKAN_FEATURE_DMABUF = 1 << 0,
|
||||
GDK_VULKAN_FEATURE_YCBCR = 1 << 1,
|
||||
GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING = 1 << 2,
|
||||
GDK_VULKAN_FEATURE_DYNAMIC_INDEXING = 1 << 3,
|
||||
GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING = 1 << 4,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT = 1 << 5,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT = 1 << 6,
|
||||
GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT = 1 << 7,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT = 1 << 2,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT = 1 << 3,
|
||||
GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT = 1 << 4,
|
||||
} GdkVulkanFeatures;
|
||||
|
||||
/* Tracks information about the device grab on this display */
|
||||
@@ -130,6 +128,7 @@ struct _GdkDisplay
|
||||
guint have_egl_pixel_format_float : 1;
|
||||
guint have_egl_dma_buf_import : 1;
|
||||
guint have_egl_dma_buf_export : 1;
|
||||
guint have_egl_gl_colorspace : 1;
|
||||
|
||||
GdkDmabufFormats *dmabuf_formats;
|
||||
GdkDmabufDownloader *dmabuf_downloaders[4];
|
||||
@@ -247,9 +246,8 @@ gboolean gdk_display_init_egl (GdkDisplay *display
|
||||
gboolean allow_any,
|
||||
GError **error);
|
||||
gpointer gdk_display_get_egl_display (GdkDisplay *display);
|
||||
gpointer gdk_display_get_egl_config (GdkDisplay *display);
|
||||
gpointer gdk_display_get_egl_config_high_depth
|
||||
(GdkDisplay *display);
|
||||
gpointer gdk_display_get_egl_config (GdkDisplay *display,
|
||||
GdkMemoryDepth depth);
|
||||
|
||||
void gdk_display_set_rgba (GdkDisplay *display,
|
||||
gboolean rgba);
|
||||
|
155
gdk/gdkdmabuf.c
155
gdk/gdkdmabuf.c
@@ -71,7 +71,7 @@ download_memcpy (guchar *dst_data,
|
||||
bpp = gdk_memory_format_bytes_per_pixel (dst_format);
|
||||
src_stride = dmabuf->planes[0].stride;
|
||||
src_data = src_datas[0] + dmabuf->planes[0].offset;
|
||||
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + (height - 1) * dst_stride + width * bpp);
|
||||
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + gdk_memory_format_min_buffer_size (dst_format, dst_stride, width, height));
|
||||
|
||||
if (dst_stride == src_stride)
|
||||
memcpy (dst_data, src_data, (height - 1) * dst_stride + width * bpp);
|
||||
@@ -241,6 +241,108 @@ download_nv12 (guchar *dst_data,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
get_uv_values16 (const YUVCoefficients *coeffs,
|
||||
guint16 u,
|
||||
guint16 v,
|
||||
gint64 *out_r,
|
||||
gint64 *out_g,
|
||||
gint64 *out_b)
|
||||
{
|
||||
gint64 u2 = (gint64) u - 32767;
|
||||
gint64 v2 = (gint64) v - 32767;
|
||||
*out_r = coeffs->v_to_r * v2;
|
||||
*out_g = coeffs->u_to_g * u2 + coeffs->v_to_g * v2;
|
||||
*out_b = coeffs->u_to_b * u2;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_rgb_values16 (guint16 rgb[3],
|
||||
guint16 y,
|
||||
gint64 r,
|
||||
gint64 g,
|
||||
gint64 b)
|
||||
{
|
||||
gint64 y2 = (gint64) y * 65536;
|
||||
|
||||
rgb[0] = CLAMP ((y2 + r) >> 16, 0, 65535);
|
||||
rgb[1] = CLAMP ((y2 + g) >> 16, 0, 65535);
|
||||
rgb[2] = CLAMP ((y2 + b) >> 16, 0, 65535);
|
||||
}
|
||||
|
||||
static void
|
||||
download_p010 (guchar *dst,
|
||||
gsize dst_stride,
|
||||
GdkMemoryFormat dst_format,
|
||||
gsize width,
|
||||
gsize height,
|
||||
const GdkDmabuf *dmabuf,
|
||||
const guchar *src_data[GDK_DMABUF_MAX_PLANES],
|
||||
gsize sizes[GDK_DMABUF_MAX_PLANES])
|
||||
{
|
||||
const guint16 *y_data, *uv_data;
|
||||
guint16 *dst_data;
|
||||
gsize x, y, y_stride, uv_stride;
|
||||
gsize U, V, X_SUB, Y_SUB;
|
||||
guint16 SIZE, MASK;
|
||||
|
||||
switch (dmabuf->fourcc)
|
||||
{
|
||||
case DRM_FORMAT_P010:
|
||||
U = 0; V = 1; X_SUB = 2; Y_SUB = 2;
|
||||
SIZE = 10;
|
||||
break;
|
||||
case DRM_FORMAT_P012:
|
||||
U = 0; V = 1; X_SUB = 2; Y_SUB = 2;
|
||||
SIZE = 12;
|
||||
break;
|
||||
case DRM_FORMAT_P016:
|
||||
U = 0; V = 1; X_SUB = 2; Y_SUB = 2;
|
||||
SIZE = 16;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return;
|
||||
}
|
||||
MASK = 0xFFFF << (16 - SIZE);
|
||||
|
||||
y_stride = dmabuf->planes[0].stride / 2;
|
||||
y_data = (const guint16 *) (src_data[0] + dmabuf->planes[0].offset);
|
||||
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + height * dmabuf->planes[0].stride);
|
||||
uv_stride = dmabuf->planes[1].stride / 2;
|
||||
uv_data = (const guint16 *) (src_data[1] + dmabuf->planes[1].offset);
|
||||
g_return_if_fail (sizes[1] >= dmabuf->planes[1].offset + (height + Y_SUB - 1) / Y_SUB * dmabuf->planes[1].stride);
|
||||
dst_data = (guint16 *) dst;
|
||||
dst_stride /= 2;
|
||||
|
||||
for (y = 0; y < height; y += Y_SUB)
|
||||
{
|
||||
for (x = 0; x < width; x += X_SUB)
|
||||
{
|
||||
gint64 r, g, b;
|
||||
gsize xs, ys;
|
||||
guint16 u, v;
|
||||
|
||||
u = uv_data[x / X_SUB * 2 + U];
|
||||
u = (u & MASK) | (u >> SIZE);
|
||||
v = uv_data[x / X_SUB * 2 + V];
|
||||
v = (v & MASK) | (v >> SIZE);
|
||||
get_uv_values16 (&itu601_narrow, u, v, &r, &g, &b);
|
||||
|
||||
for (ys = 0; ys < Y_SUB && y + ys < height; ys++)
|
||||
for (xs = 0; xs < X_SUB && x + xs < width; xs++)
|
||||
{
|
||||
guint16 y_ = y_data[x + xs + y_stride * ys];
|
||||
y_ = (y_ & MASK) | (y_ >> SIZE);
|
||||
set_rgb_values16 (&dst_data[3 * (x + xs) + dst_stride * ys], y_, r, g, b);
|
||||
}
|
||||
}
|
||||
dst_data += Y_SUB * dst_stride;
|
||||
y_data += Y_SUB * y_stride;
|
||||
uv_data += uv_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
download_yuv_3 (guchar *dst_data,
|
||||
gsize dst_stride,
|
||||
@@ -1673,7 +1775,7 @@ static const GdkDrmFormatInfo supported_formats[] = {
|
||||
.download = NULL,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
.vk = {
|
||||
.format = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
|
||||
.format = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
|
||||
.swizzle = VULKAN_DEFAULT_SWIZZLE,
|
||||
},
|
||||
#endif
|
||||
@@ -1682,10 +1784,10 @@ static const GdkDrmFormatInfo supported_formats[] = {
|
||||
.fourcc = DRM_FORMAT_P010,
|
||||
.memory_format = GDK_MEMORY_R16G16B16,
|
||||
.is_yuv = TRUE,
|
||||
.download = NULL,
|
||||
.download = download_p010,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
.vk = {
|
||||
.format = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
|
||||
.format = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
|
||||
.swizzle = VULKAN_DEFAULT_SWIZZLE,
|
||||
},
|
||||
#endif
|
||||
@@ -1694,10 +1796,10 @@ static const GdkDrmFormatInfo supported_formats[] = {
|
||||
.fourcc = DRM_FORMAT_P012,
|
||||
.memory_format = GDK_MEMORY_R16G16B16,
|
||||
.is_yuv = TRUE,
|
||||
.download = NULL,
|
||||
.download = download_p010,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
.vk = {
|
||||
.format = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
|
||||
.format = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
|
||||
.swizzle = VULKAN_DEFAULT_SWIZZLE,
|
||||
},
|
||||
#endif
|
||||
@@ -1706,10 +1808,10 @@ static const GdkDrmFormatInfo supported_formats[] = {
|
||||
.fourcc = DRM_FORMAT_P016,
|
||||
.memory_format = GDK_MEMORY_R16G16B16,
|
||||
.is_yuv = TRUE,
|
||||
.download = NULL,
|
||||
.download = download_p010,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
.vk = {
|
||||
.format = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
|
||||
.format = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
|
||||
.swizzle = VULKAN_DEFAULT_SWIZZLE,
|
||||
},
|
||||
#endif
|
||||
@@ -2028,8 +2130,8 @@ gdk_dmabuf_do_download_mmap (GdkTexture *texture,
|
||||
if (gdk_dmabuf_ioctl (dmabuf->planes[i].fd, DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_START|DMA_BUF_SYNC_READ }) < 0)
|
||||
g_warning ("Failed to sync dmabuf: %s", g_strerror (errno));
|
||||
|
||||
src_data[i] = mmap (NULL, sizes[i], PROT_READ, MAP_SHARED, dmabuf->planes[i].fd, dmabuf->planes[i].offset);
|
||||
if (src_data[i] == NULL)
|
||||
src_data[i] = mmap (NULL, sizes[i], PROT_READ, MAP_SHARED, dmabuf->planes[i].fd, 0);
|
||||
if (src_data[i] == NULL || src_data[i] == MAP_FAILED)
|
||||
{
|
||||
g_warning ("Failed to mmap dmabuf: %s", g_strerror (errno));
|
||||
goto out;
|
||||
@@ -2062,13 +2164,21 @@ out:
|
||||
void
|
||||
gdk_dmabuf_download_mmap (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkMemoryFormat src_format = gdk_texture_get_format (texture);
|
||||
GdkColorState *src_color_state = gdk_texture_get_color_state (texture);
|
||||
|
||||
if (format == src_format)
|
||||
gdk_dmabuf_do_download_mmap (texture, data, stride);
|
||||
{
|
||||
gdk_dmabuf_do_download_mmap (texture, data, stride);
|
||||
gdk_memory_convert_color_state (data, stride, format,
|
||||
src_color_state, color_state,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int width, height;
|
||||
@@ -2083,8 +2193,8 @@ gdk_dmabuf_download_mmap (GdkTexture *texture,
|
||||
|
||||
gdk_dmabuf_do_download_mmap (texture, src_data, src_stride);
|
||||
|
||||
gdk_memory_convert (data, stride, format,
|
||||
src_data, src_stride, src_format,
|
||||
gdk_memory_convert (data, stride, format, color_state,
|
||||
src_data, src_stride, src_format, src_color_state,
|
||||
width, height);
|
||||
|
||||
g_free (src_data);
|
||||
@@ -2361,7 +2471,7 @@ gdk_dmabuf_is_disjoint (const GdkDmabuf *dmabuf)
|
||||
{
|
||||
struct stat plane_stat;
|
||||
|
||||
if (fstat (dmabuf->planes[0].fd, &plane_stat) != 0)
|
||||
if (fstat (dmabuf->planes[i].fd, &plane_stat) != 0)
|
||||
return TRUE;
|
||||
|
||||
if (first_stat.st_ino != plane_stat.st_ino)
|
||||
@@ -2372,3 +2482,20 @@ gdk_dmabuf_is_disjoint (const GdkDmabuf *dmabuf)
|
||||
}
|
||||
|
||||
#endif /* HAVE_DMABUF */
|
||||
|
||||
void
|
||||
gdk_dmabuf_close_fds (GdkDmabuf *dmabuf)
|
||||
{
|
||||
guint i, j;
|
||||
|
||||
for (i = 0; i < dmabuf->n_planes; i++)
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
if (dmabuf->planes[i].fd == dmabuf->planes[j].fd)
|
||||
break;
|
||||
}
|
||||
if (i == j)
|
||||
g_close (dmabuf->planes[i].fd, NULL);
|
||||
}
|
||||
}
|
||||
|
@@ -35,6 +35,7 @@ void
|
||||
gdk_dmabuf_downloader_download (GdkDmabufDownloader *self,
|
||||
GdkDmabufTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -43,6 +44,6 @@ gdk_dmabuf_downloader_download (GdkDmabufDownloader *self,
|
||||
g_return_if_fail (GDK_IS_DMABUF_DOWNLOADER (self));
|
||||
|
||||
iface = GDK_DMABUF_DOWNLOADER_GET_IFACE (self);
|
||||
iface->download (self, texture, format, data, stride);
|
||||
iface->download (self, texture, format, color_state, data, stride);
|
||||
}
|
||||
|
||||
|
@@ -20,6 +20,7 @@ struct _GdkDmabufDownloaderInterface
|
||||
void (* download) (GdkDmabufDownloader *downloader,
|
||||
GdkDmabufTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
};
|
||||
@@ -31,6 +32,7 @@ gboolean gdk_dmabuf_downloader_supports (GdkDmabufDownlo
|
||||
void gdk_dmabuf_downloader_download (GdkDmabufDownloader *downloader,
|
||||
GdkDmabufTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
|
||||
|
@@ -207,7 +207,8 @@ gdk_dmabuf_formats_new (GdkDmabufFormat *formats,
|
||||
self->n_formats = n_formats;
|
||||
self->formats = g_new (GdkDmabufFormat, n_formats);
|
||||
|
||||
memcpy (self->formats, formats, n_formats * sizeof (GdkDmabufFormat));
|
||||
if (n_formats != 0)
|
||||
memcpy (self->formats, formats, n_formats * sizeof (GdkDmabufFormat));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@@ -55,4 +55,6 @@ GDK_AVAILABLE_IN_4_14
|
||||
gboolean gdk_dmabuf_formats_equal (const GdkDmabufFormats *formats1,
|
||||
const GdkDmabufFormats *formats2);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GdkDmabufFormats, gdk_dmabuf_formats_unref);
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -10,6 +10,10 @@
|
||||
((__u32)(c) << 16) | ((__u32)(d) << 24))
|
||||
#endif
|
||||
|
||||
#ifndef DRM_FORMAT_INVALID
|
||||
#define DRM_FORMAT_INVALID 0
|
||||
#endif
|
||||
|
||||
#ifndef DRM_FORMAT_C1
|
||||
#define DRM_FORMAT_C1 fourcc_code('C', '1', ' ', ' ')
|
||||
#endif
|
||||
|
@@ -22,15 +22,17 @@ struct _GdkDmabuf
|
||||
} planes[GDK_DMABUF_MAX_PLANES];
|
||||
};
|
||||
|
||||
void gdk_dmabuf_close_fds (GdkDmabuf *dmabuf);
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
|
||||
GdkDmabufFormats * gdk_dmabuf_get_mmap_formats (void) G_GNUC_CONST;
|
||||
void gdk_dmabuf_download_mmap (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
|
||||
|
||||
int gdk_dmabuf_ioctl (int fd,
|
||||
unsigned long request,
|
||||
void *arg);
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkdmabufdownloaderprivate.h"
|
||||
#include "gdkdmabufformatsbuilderprivate.h"
|
||||
@@ -96,6 +97,7 @@ struct _Download
|
||||
{
|
||||
GdkDmabufTexture *texture;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
volatile int spinlock;
|
||||
@@ -109,6 +111,7 @@ gdk_dmabuf_texture_invoke_callback (gpointer data)
|
||||
gdk_dmabuf_downloader_download (download->texture->downloader,
|
||||
download->texture,
|
||||
download->format,
|
||||
download->color_state,
|
||||
download->data,
|
||||
download->stride);
|
||||
|
||||
@@ -120,16 +123,17 @@ gdk_dmabuf_texture_invoke_callback (gpointer data)
|
||||
static void
|
||||
gdk_dmabuf_texture_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkDmabufTexture *self = GDK_DMABUF_TEXTURE (texture);
|
||||
Download download = { self, format, data, stride, 0 };
|
||||
Download download = { self, format, color_state, data, stride, 0 };
|
||||
|
||||
if (self->downloader == NULL)
|
||||
{
|
||||
#ifdef HAVE_DMABUF
|
||||
gdk_dmabuf_download_mmap (texture, format, data, stride);
|
||||
gdk_dmabuf_download_mmap (texture, format, color_state, data, stride);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -178,6 +182,7 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
|
||||
GdkTexture *update_texture;
|
||||
GdkDisplay *display;
|
||||
GdkDmabuf dmabuf;
|
||||
GdkColorState *color_state;
|
||||
GError *local_error = NULL;
|
||||
int width, height;
|
||||
gboolean premultiplied;
|
||||
@@ -197,9 +202,24 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
|
||||
|
||||
gdk_display_init_dmabuf (display);
|
||||
|
||||
color_state = gdk_dmabuf_texture_builder_get_color_state (builder);
|
||||
if (color_state == NULL)
|
||||
{
|
||||
gboolean is_yuv;
|
||||
|
||||
if (gdk_dmabuf_fourcc_is_yuv (dmabuf.fourcc, &is_yuv) && is_yuv)
|
||||
{
|
||||
g_warning_once ("FIXME: Implement the proper colorstate for YUV dmabufs");
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
}
|
||||
else
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
}
|
||||
|
||||
self = g_object_new (GDK_TYPE_DMABUF_TEXTURE,
|
||||
"width", width,
|
||||
"height", height,
|
||||
"color-state", color_state,
|
||||
NULL);
|
||||
|
||||
g_set_object (&self->display, display);
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include "gdkdebugprivate.h"
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkdmabuftexturebuilderprivate.h"
|
||||
|
||||
@@ -41,6 +42,8 @@ struct _GdkDmabufTextureBuilder
|
||||
|
||||
GdkDmabuf dmabuf;
|
||||
|
||||
GdkColorState *color_state;
|
||||
|
||||
GdkTexture *update_texture;
|
||||
cairo_region_t *update_region;
|
||||
};
|
||||
@@ -124,6 +127,7 @@ enum
|
||||
PROP_MODIFIER,
|
||||
PROP_PREMULTIPLIED,
|
||||
PROP_N_PLANES,
|
||||
PROP_COLOR_STATE,
|
||||
PROP_UPDATE_REGION,
|
||||
PROP_UPDATE_TEXTURE,
|
||||
|
||||
@@ -141,6 +145,7 @@ gdk_dmabuf_texture_builder_dispose (GObject *object)
|
||||
|
||||
g_clear_object (&self->update_texture);
|
||||
g_clear_pointer (&self->update_region, cairo_region_destroy);
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_dmabuf_texture_builder_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -183,6 +188,10 @@ gdk_dmabuf_texture_builder_get_property (GObject *object,
|
||||
g_value_set_uint (value, self->dmabuf.n_planes);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
g_value_set_boxed (value, self->color_state);
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
g_value_set_boxed (value, self->update_region);
|
||||
break;
|
||||
@@ -235,6 +244,10 @@ gdk_dmabuf_texture_builder_set_property (GObject *object,
|
||||
gdk_dmabuf_texture_builder_set_n_planes (self, g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
gdk_dmabuf_texture_builder_set_color_state (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
gdk_dmabuf_texture_builder_set_update_region (self, g_value_get_boxed (value));
|
||||
break;
|
||||
@@ -347,6 +360,18 @@ gdk_dmabuf_texture_builder_class_init (GdkDmabufTextureBuilderClass *klass)
|
||||
1, GDK_DMABUF_MAX_PLANES, 1,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:color-state:
|
||||
*
|
||||
* The color state of the texture.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_COLOR_STATE] =
|
||||
g_param_spec_boxed ("color-state", NULL, NULL,
|
||||
GDK_TYPE_COLOR_STATE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:update-region: (attributes org.gtk.Property.get=gdk_dmabuf_texture_builder_get_update_region org.gtk.Property.set=gdk_dmabuf_texture_builder_set_update_region)
|
||||
*
|
||||
@@ -383,6 +408,8 @@ gdk_dmabuf_texture_builder_init (GdkDmabufTextureBuilder *self)
|
||||
|
||||
for (int i = 0; i < GDK_DMABUF_MAX_PLANES; i++)
|
||||
self->dmabuf.planes[i].fd = -1;
|
||||
|
||||
self->color_state = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -843,6 +870,55 @@ gdk_dmabuf_texture_builder_set_offset (GdkDmabufTextureBuilder *self,
|
||||
self->dmabuf.planes[plane].offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_color_state: (attributes org.gtk.Method.get_property=color-state)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
*
|
||||
* Gets the color state previously set via gdk_dmabuf_texture_builder_set_color_state().
|
||||
*
|
||||
* Returns: (nullable): the color state
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_dmabuf_texture_builder_get_color_state (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_color_state: (attributes org.gtk.Method.set_property=color-state)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @color_state: (nullable): a `GdkColorState` or `NULL` to unset the colorstate.
|
||||
*
|
||||
* Sets the color state for the texture.
|
||||
*
|
||||
* By default, the colorstate is `NULL`. In that case, GTK will choose the
|
||||
* correct colorstate based on the format.
|
||||
* If you don't know what colorstates are, this is probably the right thing.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_color_state (GdkDmabufTextureBuilder *self,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->color_state == color_state ||
|
||||
(self->color_state != NULL && color_state != NULL && gdk_color_state_equal (self->color_state, color_state)))
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
self->color_state = color_state;
|
||||
if (color_state)
|
||||
gdk_color_state_ref (color_state);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLOR_STATE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_update_texture: (attributes org.gtk.Method.get_property=update-texture)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
|
@@ -100,6 +100,12 @@ void gdk_dmabuf_texture_builder_set_offset (GdkDmabufT
|
||||
unsigned int plane,
|
||||
unsigned int offset);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_dmabuf_texture_builder_get_color_state (GdkDmabufTextureBuilder *self);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_dmabuf_texture_builder_set_color_state (GdkDmabufTextureBuilder *self,
|
||||
GdkColorState *color_state);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GdkTexture * gdk_dmabuf_texture_builder_get_update_texture (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
|
@@ -48,6 +48,8 @@ struct _GdkDrawContextPrivate {
|
||||
GdkSurface *surface;
|
||||
|
||||
cairo_region_t *frame_region;
|
||||
GdkColorState *color_state;
|
||||
GdkMemoryDepth depth;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -201,8 +203,12 @@ static guint pixels_counter;
|
||||
static void
|
||||
gdk_draw_context_init (GdkDrawContext *self)
|
||||
{
|
||||
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (self);
|
||||
|
||||
if (pixels_counter == 0)
|
||||
pixels_counter = gdk_profiler_define_int_counter ("frame pixels", "Pixels drawn per frame");
|
||||
|
||||
priv->depth = GDK_N_DEPTHS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,7 +384,15 @@ gdk_draw_context_begin_frame_full (GdkDrawContext *context,
|
||||
priv->frame_region = cairo_region_copy (region);
|
||||
priv->surface->paint_context = g_object_ref (context);
|
||||
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, depth, priv->frame_region);
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context,
|
||||
depth,
|
||||
priv->frame_region,
|
||||
&priv->color_state,
|
||||
&priv->depth);
|
||||
|
||||
/* the callback is meant to set them */
|
||||
g_assert (priv->color_state != NULL);
|
||||
g_assert (priv->depth < GDK_N_DEPTHS);
|
||||
|
||||
cairo_region_intersect_rectangle (priv->frame_region,
|
||||
&(cairo_rectangle_int_t) {
|
||||
@@ -449,8 +463,10 @@ gdk_draw_context_end_frame (GdkDrawContext *context)
|
||||
|
||||
gdk_profiler_set_int_counter (pixels_counter, region_get_pixels (priv->frame_region));
|
||||
|
||||
g_clear_pointer (&priv->color_state, gdk_color_state_unref);
|
||||
g_clear_pointer (&priv->frame_region, cairo_region_destroy);
|
||||
g_clear_object (&priv->surface->paint_context);
|
||||
priv->depth = GDK_N_DEPTHS;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,6 +494,38 @@ gdk_draw_context_get_frame_region (GdkDrawContext *context)
|
||||
return priv->frame_region;
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_draw_context_get_color_state:
|
||||
* @self: a `GdkDrawContext`
|
||||
*
|
||||
* Gets the target color state while rendering. If no rendering is going on, %NULL is returned.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the target color state
|
||||
**/
|
||||
GdkColorState *
|
||||
gdk_draw_context_get_color_state (GdkDrawContext *self)
|
||||
{
|
||||
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (self);
|
||||
|
||||
return priv->color_state;
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_draw_context_get_depth:
|
||||
* @self: a `GdkDrawContext`
|
||||
*
|
||||
* Gets the target depth while rendering. If no rendering is going on, the return value is undefined.
|
||||
*
|
||||
* Returns: the target depth
|
||||
**/
|
||||
GdkMemoryDepth
|
||||
gdk_draw_context_get_depth (GdkDrawContext *self)
|
||||
{
|
||||
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (self);
|
||||
|
||||
return priv->depth;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_draw_context_empty_frame (GdkDrawContext *context)
|
||||
{
|
||||
|
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "gdkdrawcontext.h"
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -43,7 +44,9 @@ struct _GdkDrawContextClass
|
||||
|
||||
void (* begin_frame) (GdkDrawContext *context,
|
||||
GdkMemoryDepth depth,
|
||||
cairo_region_t *update_area);
|
||||
cairo_region_t *update_area,
|
||||
GdkColorState **out_color_state,
|
||||
GdkMemoryDepth *out_depth);
|
||||
void (* end_frame) (GdkDrawContext *context,
|
||||
cairo_region_t *painted);
|
||||
void (* empty_frame) (GdkDrawContext *context);
|
||||
@@ -58,6 +61,9 @@ void gdk_draw_context_begin_frame_full (GdkDrawContext
|
||||
|
||||
void gdk_draw_context_empty_frame (GdkDrawContext *context);
|
||||
|
||||
GdkColorState * gdk_draw_context_get_color_state (GdkDrawContext *self);
|
||||
GdkMemoryDepth gdk_draw_context_get_depth (GdkDrawContext *self);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -651,9 +651,9 @@ gdk_drop_read_internal (GdkDrop *self,
|
||||
* pointer to an array of mime types
|
||||
* @io_priority: the I/O priority for the read operation
|
||||
* @cancellable: (nullable): optional `GCancellable` object
|
||||
* @callback: (scope async): a `GAsyncReadyCallback` to call when
|
||||
* @callback: (scope async) (closure user_data): a `GAsyncReadyCallback` to call when
|
||||
* the request is satisfied
|
||||
* @user_data: (closure): the data to pass to @callback
|
||||
* @user_data: the data to pass to @callback
|
||||
*
|
||||
* Asynchronously read the dropped data from a `GdkDrop`
|
||||
* in a format that complies with one of the mime types.
|
||||
@@ -843,8 +843,8 @@ gdk_drop_read_value_internal (GdkDrop *self,
|
||||
* @type: a `GType` to read
|
||||
* @io_priority: the I/O priority of the request.
|
||||
* @cancellable: (nullable): optional `GCancellable` object, %NULL to ignore.
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
* @callback: (scope async) (closure user_data): callback to call when the request is satisfied
|
||||
* @user_data: the data to pass to callback function
|
||||
*
|
||||
* Asynchronously request the drag operation's contents converted
|
||||
* to the given @type.
|
||||
|
@@ -98,9 +98,9 @@ typedef enum
|
||||
* @GDK_BUTTON3_MASK: the third mouse button.
|
||||
* @GDK_BUTTON4_MASK: the fourth mouse button.
|
||||
* @GDK_BUTTON5_MASK: the fifth mouse button.
|
||||
* @GDK_SUPER_MASK: the Super modifier
|
||||
* @GDK_HYPER_MASK: the Hyper modifier
|
||||
* @GDK_META_MASK: the Meta modifier
|
||||
* @GDK_SUPER_MASK: the Super modifier.
|
||||
* @GDK_HYPER_MASK: the Hyper modifier.
|
||||
* @GDK_META_MASK: the Meta modifier. Maps to Command on macOS.
|
||||
*
|
||||
* Flags to indicate the state of modifier keys and mouse buttons
|
||||
* in events.
|
||||
|
@@ -329,7 +329,7 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
|
||||
if (display->have_egl_no_config_context)
|
||||
egl_config = NULL;
|
||||
else
|
||||
egl_config = gdk_display_get_egl_config (display);
|
||||
egl_config = gdk_display_get_egl_config (display, GDK_MEMORY_U8);
|
||||
|
||||
if (debug_bit)
|
||||
flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
||||
@@ -609,24 +609,38 @@ gdk_gl_context_get_scale (GdkGLContext *self)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
cairo_region_t *region)
|
||||
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
cairo_region_t *region,
|
||||
GdkColorState **out_color_state,
|
||||
GdkMemoryDepth *out_depth)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
G_GNUC_UNUSED GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
GdkSurface *surface;
|
||||
GdkSurface *surface = gdk_draw_context_get_surface (draw_context);
|
||||
GdkColorState *color_state;
|
||||
cairo_region_t *damage;
|
||||
double scale;
|
||||
int ww, wh;
|
||||
int i;
|
||||
|
||||
surface = gdk_draw_context_get_surface (draw_context);
|
||||
color_state = gdk_surface_get_color_state (surface);
|
||||
scale = gdk_gl_context_get_scale (context);
|
||||
|
||||
depth = gdk_memory_depth_merge (depth, gdk_color_state_get_depth (color_state));
|
||||
|
||||
g_assert (depth != GDK_MEMORY_U8_SRGB || gdk_color_state_get_no_srgb_tf (color_state) != NULL);
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
if (priv->egl_context)
|
||||
gdk_surface_ensure_egl_surface (surface, depth != GDK_MEMORY_U8);
|
||||
*out_depth = gdk_surface_ensure_egl_surface (surface, depth);
|
||||
else
|
||||
*out_depth = GDK_MEMORY_U8;
|
||||
|
||||
*out_color_state = color_state;
|
||||
#else
|
||||
*out_color_state = gdk_color_state_get_srgb ();
|
||||
*out_depth = GDK_MEMORY_U8;
|
||||
#endif
|
||||
|
||||
damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
@@ -136,6 +137,7 @@ typedef struct _Download Download;
|
||||
struct _Download
|
||||
{
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
};
|
||||
@@ -151,7 +153,7 @@ gdk_gl_texture_find_format (GdkGLContext *context,
|
||||
|
||||
for (format = 0; format < GDK_MEMORY_N_FORMATS; format++)
|
||||
{
|
||||
GLint q_internal_format;
|
||||
GLint q_internal_format, q_internal_srgb_format;
|
||||
GLenum q_format, q_type;
|
||||
GLint q_swizzle[4];
|
||||
|
||||
@@ -164,6 +166,7 @@ gdk_gl_texture_find_format (GdkGLContext *context,
|
||||
gdk_memory_format_gl_format (format,
|
||||
gdk_gl_context_get_use_es (context),
|
||||
&q_internal_format,
|
||||
&q_internal_srgb_format,
|
||||
&q_format,
|
||||
&q_type,
|
||||
q_swizzle);
|
||||
@@ -187,7 +190,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
GdkMemoryFormat format;
|
||||
gsize expected_stride;
|
||||
Download *download = download_;
|
||||
GLint gl_internal_format;
|
||||
GLint gl_internal_format, gl_internal_srgb_format;
|
||||
GLenum gl_format, gl_type;
|
||||
GLint gl_swizzle[4];
|
||||
|
||||
@@ -199,7 +202,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
{
|
||||
gdk_memory_format_gl_format (format,
|
||||
gdk_gl_context_get_use_es (context),
|
||||
&gl_internal_format,
|
||||
&gl_internal_format, &gl_internal_srgb_format,
|
||||
&gl_format, &gl_type, gl_swizzle);
|
||||
if (download->stride == expected_stride &&
|
||||
download->format == format)
|
||||
@@ -209,6 +212,14 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
gl_format,
|
||||
gl_type,
|
||||
download->data);
|
||||
|
||||
gdk_memory_convert_color_state (download->data,
|
||||
download->stride,
|
||||
download->format,
|
||||
download->color_state,
|
||||
texture->color_state,
|
||||
texture->width,
|
||||
texture->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -225,14 +236,15 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
gdk_memory_convert (download->data,
|
||||
download->stride,
|
||||
download->format,
|
||||
download->color_state,
|
||||
pixels,
|
||||
stride,
|
||||
format,
|
||||
texture->color_state,
|
||||
texture->width,
|
||||
texture->height);
|
||||
|
||||
g_free (pixels);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -256,25 +268,25 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
actual_format = gdk_memory_depth_get_format (gdk_memory_format_get_depth (format));
|
||||
actual_format = gdk_memory_depth_get_format (gdk_memory_format_get_depth (format, FALSE));
|
||||
if (gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
actual_format = gdk_memory_format_get_straight (actual_format);
|
||||
|
||||
gdk_memory_format_gl_format (actual_format,
|
||||
gdk_gl_context_get_use_es (context),
|
||||
&gl_internal_format,
|
||||
&gl_internal_format, &gl_internal_srgb_format,
|
||||
&gl_read_format, &gl_read_type, gl_swizzle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
actual_format = gdk_memory_depth_get_format (gdk_memory_format_get_depth (format));
|
||||
actual_format = gdk_memory_depth_get_format (gdk_memory_format_get_depth (format, FALSE));
|
||||
if (gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
actual_format = gdk_memory_format_get_straight (actual_format);
|
||||
|
||||
gdk_memory_format_gl_format (actual_format,
|
||||
gdk_gl_context_get_use_es (context),
|
||||
&gl_internal_format,
|
||||
&gl_internal_format, &gl_internal_srgb_format,
|
||||
&gl_read_format, &gl_read_type, gl_swizzle);
|
||||
}
|
||||
|
||||
@@ -286,6 +298,14 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
gl_read_format,
|
||||
gl_read_type,
|
||||
download->data);
|
||||
|
||||
gdk_memory_convert_color_state (download->data,
|
||||
download->stride,
|
||||
download->format,
|
||||
download->color_state,
|
||||
texture->color_state,
|
||||
texture->width,
|
||||
texture->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -377,9 +397,11 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
gdk_memory_convert (download->data,
|
||||
download->stride,
|
||||
download->format,
|
||||
download->color_state,
|
||||
pixels,
|
||||
stride,
|
||||
actual_format,
|
||||
texture->color_state,
|
||||
texture->width,
|
||||
texture->height);
|
||||
|
||||
@@ -393,6 +415,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
static void
|
||||
gdk_gl_texture_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -401,11 +424,12 @@ gdk_gl_texture_download (GdkTexture *texture,
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
gdk_texture_do_download (self->saved, format, data, stride);
|
||||
gdk_texture_do_download (self->saved, format, color_state, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
download.format = format;
|
||||
download.color_state = color_state;
|
||||
download.data = data;
|
||||
download.stride = stride;
|
||||
|
||||
@@ -471,8 +495,7 @@ gdk_gl_texture_release (GdkGLTexture *self)
|
||||
g_return_if_fail (self->saved == NULL);
|
||||
|
||||
texture = GDK_TEXTURE (self);
|
||||
self->saved = GDK_TEXTURE (gdk_memory_texture_from_texture (texture,
|
||||
gdk_texture_get_format (texture)));
|
||||
self->saved = GDK_TEXTURE (gdk_memory_texture_from_texture (texture));
|
||||
|
||||
drop_gl_resources (self);
|
||||
}
|
||||
@@ -488,6 +511,7 @@ gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder,
|
||||
self = g_object_new (GDK_TYPE_GL_TEXTURE,
|
||||
"width", gdk_gl_texture_builder_get_width (builder),
|
||||
"height", gdk_gl_texture_builder_get_height (builder),
|
||||
"color-state", gdk_gl_texture_builder_get_color_state (builder),
|
||||
NULL);
|
||||
|
||||
self->context = g_object_ref (gdk_gl_texture_builder_get_context (builder));
|
||||
@@ -682,6 +706,7 @@ gdk_gl_texture_new (GdkGLContext *context,
|
||||
self = g_object_new (GDK_TYPE_GL_TEXTURE,
|
||||
"width", width,
|
||||
"height", height,
|
||||
"color-state", GDK_COLOR_STATE_SRGB,
|
||||
NULL);
|
||||
|
||||
self->context = g_object_ref (context);
|
||||
|
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkglcontext.h"
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
@@ -38,6 +39,7 @@ struct _GdkGLTextureBuilder
|
||||
GdkMemoryFormat format;
|
||||
gboolean has_mipmap;
|
||||
gpointer sync;
|
||||
GdkColorState *color_state;
|
||||
|
||||
GdkTexture *update_texture;
|
||||
cairo_region_t *update_region;
|
||||
@@ -75,6 +77,7 @@ enum
|
||||
PROP_HEIGHT,
|
||||
PROP_ID,
|
||||
PROP_SYNC,
|
||||
PROP_COLOR_STATE,
|
||||
PROP_UPDATE_REGION,
|
||||
PROP_UPDATE_TEXTURE,
|
||||
PROP_WIDTH,
|
||||
@@ -95,6 +98,7 @@ gdk_gl_texture_builder_dispose (GObject *object)
|
||||
|
||||
g_clear_object (&self->update_texture);
|
||||
g_clear_pointer (&self->update_region, cairo_region_destroy);
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_gl_texture_builder_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -133,6 +137,10 @@ gdk_gl_texture_builder_get_property (GObject *object,
|
||||
g_value_set_pointer (value, self->sync);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
g_value_set_boxed (value, self->color_state);
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
g_value_set_boxed (value, self->update_region);
|
||||
break;
|
||||
@@ -185,6 +193,10 @@ gdk_gl_texture_builder_set_property (GObject *object,
|
||||
gdk_gl_texture_builder_set_sync (self, g_value_get_pointer (value));
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
gdk_gl_texture_builder_set_color_state (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
gdk_gl_texture_builder_set_update_region (self, g_value_get_boxed (value));
|
||||
break;
|
||||
@@ -286,6 +298,18 @@ gdk_gl_texture_builder_class_init (GdkGLTextureBuilderClass *klass)
|
||||
g_param_spec_pointer ("sync", NULL, NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkGLTextureBuilder:color-state:
|
||||
*
|
||||
* The color state of the texture.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_COLOR_STATE] =
|
||||
g_param_spec_boxed ("color-state", NULL, NULL,
|
||||
GDK_TYPE_COLOR_STATE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkGLTextureBuilder:update-region: (attributes org.gtk.Property.get=gdk_gl_texture_builder_get_update_region org.gtk.Property.set=gdk_gl_texture_builder_set_update_region)
|
||||
*
|
||||
@@ -329,6 +353,7 @@ static void
|
||||
gdk_gl_texture_builder_init (GdkGLTextureBuilder *self)
|
||||
{
|
||||
self->format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
self->color_state = gdk_color_state_ref (gdk_color_state_get_srgb ());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,7 +393,7 @@ gdk_gl_texture_builder_get_context (GdkGLTextureBuilder *self)
|
||||
/**
|
||||
* gdk_gl_texture_builder_set_context: (attributes org.gtk.Method.set_property=context)
|
||||
* @self: a `GdkGLTextureBuilder`
|
||||
* @context: (nullable): The context the texture beongs to or %NULL to unset
|
||||
* @context: (nullable): The context the texture belongs to or %NULL to unset
|
||||
*
|
||||
* Sets the context to be used for the texture. This is the context that owns
|
||||
* the texture.
|
||||
@@ -616,6 +641,51 @@ gdk_gl_texture_builder_set_sync (GdkGLTextureBuilder *self,
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SYNC]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_texture_builder_get_color_state: (attributes org.gtk.Method.get_property=color-state)
|
||||
* @self: a `GdkGLTextureBuilder`
|
||||
*
|
||||
* Gets the color state previously set via gdk_gl_texture_builder_set_color_state().
|
||||
*
|
||||
* Returns: the color state
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_gl_texture_builder_get_color_state (GdkGLTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_texture_builder_set_color_state: (attributes org.gtk.Method.set_property=color-state)
|
||||
* @self: a `GdkGLTextureBuilder`
|
||||
* @color_state: a `GdkColorState`
|
||||
*
|
||||
* Sets the color state for the texture.
|
||||
*
|
||||
* By default, the sRGB colorstate is used. If you don't know what
|
||||
* colorstates are, this is probably the right thing.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_gl_texture_builder_set_color_state (GdkGLTextureBuilder *self,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (color_state != NULL);
|
||||
|
||||
if (gdk_color_state_equal (self->color_state, color_state))
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
self->color_state = gdk_color_state_ref (color_state);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLOR_STATE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_texture_builder_get_format: (attributes org.gtk.Method.get_property=format)
|
||||
* @self: a `GdkGLTextureBuilder`
|
||||
|
@@ -76,6 +76,12 @@ GDK_AVAILABLE_IN_4_12
|
||||
void gdk_gl_texture_builder_set_sync (GdkGLTextureBuilder *self,
|
||||
gpointer sync);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_gl_texture_builder_get_color_state (GdkGLTextureBuilder *self);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_gl_texture_builder_set_color_state (GdkGLTextureBuilder *self,
|
||||
GdkColorState *color_state);
|
||||
|
||||
GDK_AVAILABLE_IN_4_12
|
||||
GdkTexture * gdk_gl_texture_builder_get_update_texture (GdkGLTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_12
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -37,26 +37,40 @@ typedef enum {
|
||||
} GdkMemoryAlpha;
|
||||
|
||||
typedef enum {
|
||||
GDK_MEMORY_NONE,
|
||||
GDK_MEMORY_U8,
|
||||
GDK_MEMORY_U8_SRGB,
|
||||
GDK_MEMORY_U16,
|
||||
GDK_MEMORY_FLOAT16,
|
||||
GDK_MEMORY_FLOAT32
|
||||
GDK_MEMORY_FLOAT32,
|
||||
|
||||
GDK_N_DEPTHS
|
||||
} GdkMemoryDepth;
|
||||
|
||||
#define GDK_MEMORY_DEPTH_BITS 3
|
||||
|
||||
gsize gdk_memory_format_alignment (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
GdkMemoryAlpha gdk_memory_format_alpha (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
GdkMemoryFormat gdk_memory_format_get_premultiplied (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
GdkMemoryFormat gdk_memory_format_get_straight (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
const GdkMemoryFormat * gdk_memory_format_get_fallbacks (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
GdkMemoryDepth gdk_memory_format_get_depth (GdkMemoryFormat format) G_GNUC_CONST;
|
||||
GdkMemoryDepth gdk_memory_format_get_depth (GdkMemoryFormat format,
|
||||
gboolean srgb) G_GNUC_CONST;
|
||||
gsize gdk_memory_format_min_buffer_size (GdkMemoryFormat format,
|
||||
gsize stride,
|
||||
gsize width,
|
||||
gsize height) G_GNUC_CONST;
|
||||
gboolean gdk_memory_depth_is_srgb (GdkMemoryDepth depth) G_GNUC_CONST;
|
||||
GdkMemoryDepth gdk_memory_depth_merge (GdkMemoryDepth depth1,
|
||||
GdkMemoryDepth depth2) G_GNUC_CONST;
|
||||
GdkMemoryFormat gdk_memory_depth_get_format (GdkMemoryDepth depth) G_GNUC_CONST;
|
||||
GdkMemoryFormat gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth) G_GNUC_CONST;
|
||||
const char * gdk_memory_depth_get_name (GdkMemoryDepth depth);
|
||||
void gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
GLint *out_internal_format,
|
||||
GLint *out_internal_srgb_format,
|
||||
GLenum *out_format,
|
||||
GLenum *out_type,
|
||||
GLint out_swizzle[4]);
|
||||
@@ -64,25 +78,36 @@ gboolean gdk_memory_format_gl_rgba_format (GdkMemoryFormat
|
||||
gboolean gles,
|
||||
GdkMemoryFormat *out_actual_format,
|
||||
GLint *out_internal_format,
|
||||
GLint *out_internal_srgb_format,
|
||||
GLenum *out_format,
|
||||
GLenum *out_type,
|
||||
GLint out_swizzle[4]);
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
VkFormat gdk_memory_format_vk_format (GdkMemoryFormat format,
|
||||
VkComponentMapping *out_swizzle);
|
||||
VkFormat gdk_memory_format_vk_srgb_format (GdkMemoryFormat format);
|
||||
VkFormat gdk_memory_format_vk_rgba_format (GdkMemoryFormat format,
|
||||
GdkMemoryFormat *out_rgba_format,
|
||||
VkComponentMapping *out_swizzle);
|
||||
#endif
|
||||
guint32 gdk_memory_format_get_dmabuf_fourcc (GdkMemoryFormat format);
|
||||
|
||||
const char * gdk_memory_format_get_name (GdkMemoryFormat format);
|
||||
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
GdkColorState *src_cs,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
GdkColorState *dest_cs,
|
||||
gsize width,
|
||||
gsize height);
|
||||
void gdk_memory_convert_color_state (guchar *data,
|
||||
gsize stride,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *src_color_state,
|
||||
GdkColorState *dest_color_state,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
|
@@ -21,8 +21,8 @@
|
||||
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gsk/gl/fp16private.h"
|
||||
|
||||
/**
|
||||
* GdkMemoryTexture:
|
||||
@@ -58,6 +58,7 @@ gdk_memory_texture_dispose (GObject *object)
|
||||
static void
|
||||
gdk_memory_texture_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -65,9 +66,11 @@ gdk_memory_texture_download (GdkTexture *texture,
|
||||
|
||||
gdk_memory_convert (data, stride,
|
||||
format,
|
||||
color_state,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
texture->format,
|
||||
texture->color_state,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
@@ -123,6 +126,46 @@ gdk_memory_sanitize (GBytes *bytes,
|
||||
return g_bytes_new_take (copy, copy_stride * height);
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gdk_memory_texture_new_from_builder (GdkMemoryTextureBuilder *builder)
|
||||
{
|
||||
GdkMemoryTexture *self;
|
||||
GdkTexture *texture, *update_texture;
|
||||
|
||||
self = g_object_new (GDK_TYPE_MEMORY_TEXTURE,
|
||||
"width", gdk_memory_texture_builder_get_width (builder),
|
||||
"height", gdk_memory_texture_builder_get_height (builder),
|
||||
"color-state", gdk_memory_texture_builder_get_color_state (builder),
|
||||
NULL);
|
||||
texture = GDK_TEXTURE (self);
|
||||
|
||||
texture->format = gdk_memory_texture_builder_get_format (builder);
|
||||
self->bytes = gdk_memory_sanitize (g_bytes_ref (gdk_memory_texture_builder_get_bytes (builder)),
|
||||
texture->width,
|
||||
texture->height,
|
||||
texture->format,
|
||||
gdk_memory_texture_builder_get_stride (builder),
|
||||
&self->stride);
|
||||
|
||||
update_texture = gdk_memory_texture_builder_get_update_texture (builder);
|
||||
if (update_texture)
|
||||
{
|
||||
cairo_region_t *update_region = gdk_memory_texture_builder_get_update_region (builder);
|
||||
if (update_region)
|
||||
{
|
||||
update_region = cairo_region_copy (update_region);
|
||||
cairo_region_intersect_rectangle (update_region,
|
||||
&(cairo_rectangle_int_t) {
|
||||
0, 0,
|
||||
update_texture->width, update_texture->height
|
||||
});
|
||||
gdk_texture_set_diff (GDK_TEXTURE (self), update_texture, update_region);
|
||||
}
|
||||
}
|
||||
|
||||
return GDK_TEXTURE (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_new:
|
||||
* @width: the width of the texture
|
||||
@@ -152,13 +195,14 @@ gdk_memory_texture_new (int width,
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (stride >= width * gdk_memory_format_bytes_per_pixel (format), NULL);
|
||||
/* needs to be this complex to support subtexture of the bottom right part */
|
||||
g_return_val_if_fail (g_bytes_get_size (bytes) >= stride * (height - 1) + width * gdk_memory_format_bytes_per_pixel (format), NULL);
|
||||
g_return_val_if_fail (g_bytes_get_size (bytes) >= gdk_memory_format_min_buffer_size (format, stride, width, height), NULL);
|
||||
|
||||
bytes = gdk_memory_sanitize (bytes, width, height, format, stride, &stride);
|
||||
|
||||
self = g_object_new (GDK_TYPE_MEMORY_TEXTURE,
|
||||
"width", width,
|
||||
"height", height,
|
||||
"color-state", GDK_COLOR_STATE_SRGB,
|
||||
NULL);
|
||||
|
||||
GDK_TEXTURE (self)->format = format;
|
||||
@@ -176,7 +220,7 @@ gdk_memory_texture_new_subtexture (GdkMemoryTexture *source,
|
||||
int height)
|
||||
{
|
||||
GdkTexture *texture, *result;
|
||||
gsize bpp, offset, size;
|
||||
gsize offset, size;
|
||||
GBytes *bytes;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE (source), NULL);
|
||||
@@ -186,9 +230,8 @@ gdk_memory_texture_new_subtexture (GdkMemoryTexture *source,
|
||||
g_return_val_if_fail (height > 0 && y + height <= GDK_TEXTURE (source)->height, NULL);
|
||||
|
||||
texture = GDK_TEXTURE (source);
|
||||
bpp = gdk_memory_format_bytes_per_pixel (texture->format);
|
||||
offset = y * source->stride + x * bpp;
|
||||
size = source->stride * (height - 1) + width * bpp;
|
||||
offset = y * source->stride + x * gdk_memory_format_bytes_per_pixel (texture->format);
|
||||
size = gdk_memory_format_min_buffer_size (texture->format, source->stride, width, height);
|
||||
bytes = g_bytes_new_from_bytes (source->bytes, offset, size);
|
||||
|
||||
result = gdk_memory_texture_new (width,
|
||||
@@ -202,8 +245,7 @@ gdk_memory_texture_new_subtexture (GdkMemoryTexture *source,
|
||||
}
|
||||
|
||||
GdkMemoryTexture *
|
||||
gdk_memory_texture_from_texture (GdkTexture *texture,
|
||||
GdkMemoryFormat format)
|
||||
gdk_memory_texture_from_texture (GdkTexture *texture)
|
||||
{
|
||||
GdkTexture *result;
|
||||
GBytes *bytes;
|
||||
@@ -213,21 +255,16 @@ gdk_memory_texture_from_texture (GdkTexture *texture,
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
if (GDK_IS_MEMORY_TEXTURE (texture))
|
||||
{
|
||||
GdkMemoryTexture *memtex = GDK_MEMORY_TEXTURE (texture);
|
||||
return g_object_ref (GDK_MEMORY_TEXTURE (texture));
|
||||
|
||||
if (gdk_texture_get_format (texture) == format)
|
||||
return g_object_ref (memtex);
|
||||
}
|
||||
|
||||
stride = texture->width * gdk_memory_format_bytes_per_pixel (format);
|
||||
stride = texture->width * gdk_memory_format_bytes_per_pixel (texture->format);
|
||||
data = g_malloc_n (stride, texture->height);
|
||||
|
||||
gdk_texture_do_download (texture, format, data, stride);
|
||||
gdk_texture_do_download (texture, texture->format, texture->color_state, data, stride);
|
||||
bytes = g_bytes_new_take (data, stride * texture->height);
|
||||
result = gdk_memory_texture_new (texture->width,
|
||||
texture->height,
|
||||
format,
|
||||
texture->format,
|
||||
bytes,
|
||||
stride);
|
||||
g_bytes_unref (bytes);
|
||||
|
729
gdk/gdkmemorytexturebuilder.c
Normal file
729
gdk/gdkmemorytexturebuilder.c
Normal file
@@ -0,0 +1,729 @@
|
||||
/*
|
||||
* Copyright © 2024 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkmemorytexturebuilder.h"
|
||||
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
|
||||
struct _GdkMemoryTextureBuilder
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GBytes *bytes;
|
||||
gsize stride;
|
||||
int width;
|
||||
int height;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
|
||||
GdkTexture *update_texture;
|
||||
cairo_region_t *update_region;
|
||||
};
|
||||
|
||||
struct _GdkMemoryTextureBuilderClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/**
|
||||
* GdkMemoryTextureBuilder:
|
||||
*
|
||||
* `GdkMemoryTextureBuilder` is a builder used to construct [class@Gdk.Texture] objects
|
||||
* from system memory provided via [struct@GLib.Bytes].
|
||||
*
|
||||
* The operation is quite simple: Create a texture builder, set all the necessary
|
||||
* properties - keep in mind that the properties [property@Gdk.MemoryTextureBuilder:bytes],
|
||||
* [property@Gdk.MemoryTextureBuilder:stride], [property@Gdk.MemoryTextureBuilder:width],
|
||||
* and [property@Gdk.MemoryTextureBuilder:height] are mandatory - and then call
|
||||
* [method@Gdk.MemoryTextureBuilder.build] to create the new texture.
|
||||
*
|
||||
* `GdkMemoryTextureBuilder` can be used for quick one-shot construction of
|
||||
* textures as well as kept around and reused to construct multiple textures.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_BYTES,
|
||||
PROP_COLOR_STATE,
|
||||
PROP_FORMAT,
|
||||
PROP_HEIGHT,
|
||||
PROP_STRIDE,
|
||||
PROP_UPDATE_REGION,
|
||||
PROP_UPDATE_TEXTURE,
|
||||
PROP_WIDTH,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkMemoryTextureBuilder, gdk_memory_texture_builder, G_TYPE_OBJECT)
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gdk_memory_texture_builder_dispose (GObject *object)
|
||||
{
|
||||
GdkMemoryTextureBuilder *self = GDK_MEMORY_TEXTURE_BUILDER (object);
|
||||
|
||||
g_clear_pointer (&self->bytes, g_bytes_unref);
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
|
||||
g_clear_object (&self->update_texture);
|
||||
g_clear_pointer (&self->update_region, cairo_region_destroy);
|
||||
|
||||
G_OBJECT_CLASS (gdk_memory_texture_builder_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_builder_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkMemoryTextureBuilder *self = GDK_MEMORY_TEXTURE_BUILDER (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_BYTES:
|
||||
g_value_set_boxed (value, self->bytes);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
g_value_set_boxed (value, self->color_state);
|
||||
break;
|
||||
|
||||
case PROP_FORMAT:
|
||||
g_value_set_enum (value, self->format);
|
||||
break;
|
||||
|
||||
case PROP_HEIGHT:
|
||||
g_value_set_int (value, self->height);
|
||||
break;
|
||||
|
||||
case PROP_STRIDE:
|
||||
g_value_set_uint64 (value, self->stride);
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
g_value_set_boxed (value, self->update_region);
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_TEXTURE:
|
||||
g_value_set_object (value, self->update_texture);
|
||||
break;
|
||||
|
||||
case PROP_WIDTH:
|
||||
g_value_set_int (value, self->width);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_builder_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkMemoryTextureBuilder *self = GDK_MEMORY_TEXTURE_BUILDER (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_BYTES:
|
||||
gdk_memory_texture_builder_set_bytes (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
gdk_memory_texture_builder_set_color_state (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_FORMAT:
|
||||
gdk_memory_texture_builder_set_format (self, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_HEIGHT:
|
||||
gdk_memory_texture_builder_set_height (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_STRIDE:
|
||||
gdk_memory_texture_builder_set_stride (self, g_value_get_uint64 (value));
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
gdk_memory_texture_builder_set_update_region (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_TEXTURE:
|
||||
gdk_memory_texture_builder_set_update_texture (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_WIDTH:
|
||||
gdk_memory_texture_builder_set_width (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_builder_class_init (GdkMemoryTextureBuilderClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = gdk_memory_texture_builder_dispose;
|
||||
gobject_class->get_property = gdk_memory_texture_builder_get_property;
|
||||
gobject_class->set_property = gdk_memory_texture_builder_set_property;
|
||||
|
||||
/**
|
||||
* GdkMemoryTextureBuilder:bytes:
|
||||
*
|
||||
* The bytes holding the data.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_BYTES] =
|
||||
g_param_spec_boxed ("bytes", NULL, NULL,
|
||||
G_TYPE_BYTES,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkMemoryTextureBuilder:color-state:
|
||||
*
|
||||
* The colorstate describing the data.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_COLOR_STATE] =
|
||||
g_param_spec_boxed ("color-state", NULL, NULL,
|
||||
GDK_TYPE_COLOR_STATE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkMemoryTextureBuilder:format:
|
||||
*
|
||||
* The format of the data.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_FORMAT] =
|
||||
g_param_spec_enum ("format", NULL, NULL,
|
||||
GDK_TYPE_MEMORY_FORMAT,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkMemoryTextureBuilder:height:
|
||||
*
|
||||
* The height of the texture.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_HEIGHT] =
|
||||
g_param_spec_int ("height", NULL, NULL,
|
||||
G_MININT, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkMemoryTextureBuilder:stride:
|
||||
*
|
||||
* The rowstride of the texture.
|
||||
*
|
||||
* The rowstride is the number of bytes between the first pixel
|
||||
* in a row of image data, and the first pixel in the next row.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_STRIDE] =
|
||||
g_param_spec_uint64 ("stride", NULL, NULL,
|
||||
0, G_MAXUINT64, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkMemoryTextureBuilder:update-region:
|
||||
*
|
||||
* The update region for [property@Gdk.MemoryTextureBuilder:update-texture].
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_UPDATE_REGION] =
|
||||
g_param_spec_boxed ("update-region", NULL, NULL,
|
||||
CAIRO_GOBJECT_TYPE_REGION,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkMemoryTextureBuilder:update-texture:
|
||||
*
|
||||
* The texture [property@Gdk.MemoryTextureBuilder:update-region] is an update for.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_UPDATE_TEXTURE] =
|
||||
g_param_spec_object ("update-texture", NULL, NULL,
|
||||
GDK_TYPE_TEXTURE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkMemoryTextureBuilder:width:
|
||||
*
|
||||
* The width of the texture.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_WIDTH] =
|
||||
g_param_spec_int ("width", NULL, NULL,
|
||||
G_MININT, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_builder_init (GdkMemoryTextureBuilder *self)
|
||||
{
|
||||
self->format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
self->color_state = gdk_color_state_ref (gdk_color_state_get_srgb ());
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_new: (constructor):
|
||||
*
|
||||
* Creates a new texture builder.
|
||||
*
|
||||
* Returns: the new `GdkTextureBuilder`
|
||||
*
|
||||
* Since: 4.16
|
||||
**/
|
||||
GdkMemoryTextureBuilder *
|
||||
gdk_memory_texture_builder_new (void)
|
||||
{
|
||||
return g_object_new (GDK_TYPE_MEMORY_TEXTURE_BUILDER, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_get_bytes:
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
*
|
||||
* Gets the bytes previously set via gdk_memory_texture_builder_set_bytes()
|
||||
* or %NULL if none was set.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): The bytes
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GBytes *
|
||||
gdk_memory_texture_builder_get_bytes (GdkMemoryTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_set_bytes: (attributes org.gtk.Method.set_property=bytes)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
* @bytes: (nullable): The bytes the texture shows or %NULL to unset
|
||||
*
|
||||
* Sets the data to be shown but the texture.
|
||||
*
|
||||
* The bytes must be set before calling [method@Gdk.MemoryTextureBuilder.build].
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_memory_texture_builder_set_bytes (GdkMemoryTextureBuilder *self,
|
||||
GBytes *bytes)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (bytes != NULL);
|
||||
|
||||
if (self->bytes == bytes)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->bytes, g_bytes_unref);
|
||||
self->bytes = bytes;
|
||||
if (bytes)
|
||||
g_bytes_ref (bytes);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BYTES]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_get_color_state: (attributes org.gtk.Method.get_property=color-state)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
*
|
||||
* Gets the colorstate previously set via gdk_memory_texture_builder_set_color_state().
|
||||
*
|
||||
* Returns: (transfer none): The colorstate
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_memory_texture_builder_get_color_state (GdkMemoryTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_set_color_state: (attributes org.gtk.Method.set_property=color-state)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
* @color_state: (nullable): The colorstate describing the data
|
||||
*
|
||||
* Sets the colorstate describing the data.
|
||||
*
|
||||
* By default, the sRGB colorstate is used. If you don't know
|
||||
* what colorstates are, this is probably the right thing.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_memory_texture_builder_set_color_state (GdkMemoryTextureBuilder *self,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (color_state != NULL);
|
||||
|
||||
if (self->color_state == color_state)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
self->color_state = color_state;
|
||||
if (color_state)
|
||||
gdk_color_state_ref (color_state);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLOR_STATE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_get_height: (attributes org.gtk.Method.get_property=height)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
*
|
||||
* Gets the height previously set via gdk_memory_texture_builder_set_height()
|
||||
* or 0 if the height wasn't set.
|
||||
*
|
||||
* Returns: The height
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
int
|
||||
gdk_memory_texture_builder_get_height (GdkMemoryTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self), 0);
|
||||
|
||||
return self->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_set_height: (attributes org.gtk.Method.set_property=height)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
* @height: The texture's height or 0 to unset
|
||||
*
|
||||
* Sets the height of the texture.
|
||||
*
|
||||
* The height must be set before calling [method@Gdk.MemoryTextureBuilder.build].
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_memory_texture_builder_set_height (GdkMemoryTextureBuilder *self,
|
||||
int height)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->height == height)
|
||||
return;
|
||||
|
||||
self->height = height;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HEIGHT]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_get_width: (attributes org.gtk.Method.get_property=width)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
*
|
||||
* Gets the width previously set via gdk_memory_texture_builder_set_width()
|
||||
* or 0 if the width wasn't set.
|
||||
*
|
||||
* Returns: The width
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
int
|
||||
gdk_memory_texture_builder_get_width (GdkMemoryTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self), 0);
|
||||
|
||||
return self->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_set_width: (attributes org.gtk.Method.set_property=width)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
* @width: The texture's width or 0 to unset
|
||||
*
|
||||
* Sets the width of the texture.
|
||||
*
|
||||
* The width must be set before calling [method@Gdk.MemoryTextureBuilder.build].
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_memory_texture_builder_set_width (GdkMemoryTextureBuilder *self,
|
||||
int width)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->width == width)
|
||||
return;
|
||||
|
||||
self->width = width;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WIDTH]);
|
||||
}
|
||||
|
||||
/* gdk_memory_texture_builder_get_stride: (attributes org.gtk.Method.get_property=stride) */
|
||||
/**
|
||||
* gdk_memory_texture_builder_get_stride:
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
*
|
||||
* Gets the stride previously set via gdk_memory_texture_builder_set_stride().
|
||||
*
|
||||
* Returns: the stride
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
gsize
|
||||
gdk_memory_texture_builder_get_stride (GdkMemoryTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self), 0);
|
||||
|
||||
return self->stride;
|
||||
}
|
||||
|
||||
/* gdk_memory_texture_builder_set_stride: (attributes org.gtk.Method.set_property=stride) */
|
||||
/**
|
||||
* gdk_memory_texture_builder_set_stride:
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
* @stride: the stride or 0 to unset
|
||||
*
|
||||
* Sets the rowstride of the bytes used.
|
||||
*
|
||||
* The rowstride must be set before calling [method@Gdk.MemoryTextureBuilder.build].
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_memory_texture_builder_set_stride (GdkMemoryTextureBuilder *self,
|
||||
gsize stride)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->stride == stride)
|
||||
return;
|
||||
|
||||
self->stride = stride;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STRIDE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_get_format: (attributes org.gtk.Method.get_property=format)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
*
|
||||
* Gets the format previously set via gdk_memory_texture_builder_set_format().
|
||||
*
|
||||
* Returns: The format
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkMemoryFormat
|
||||
gdk_memory_texture_builder_get_format (GdkMemoryTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self), GDK_MEMORY_R8G8B8A8_PREMULTIPLIED);
|
||||
|
||||
return self->format;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_set_format: (attributes org.gtk.Method.set_property=format)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
* @format: The texture's format
|
||||
*
|
||||
* Sets the format of the bytes.
|
||||
*
|
||||
* The default is `GDK_MEMORY_R8G8B8A8_PREMULTIPLIED`.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_memory_texture_builder_set_format (GdkMemoryTextureBuilder *self,
|
||||
GdkMemoryFormat format)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->format == format)
|
||||
return;
|
||||
|
||||
self->format = format;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FORMAT]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_get_update_texture: (attributes org.gtk.Method.get_property=update-texture)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
*
|
||||
* Gets the texture previously set via gdk_memory_texture_builder_set_update_texture()
|
||||
* or %NULL if none was set.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): The update texture
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_memory_texture_builder_get_update_texture (GdkMemoryTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->update_texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_set_update_texture: (attributes org.gtk.Method.set_property=update-texture)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
* @texture: (nullable): the texture to update
|
||||
*
|
||||
* Sets the texture to be updated by this texture.
|
||||
*
|
||||
* See [method@Gdk.MemoryTextureBuilder.set_update_region] for an explanation.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_memory_texture_builder_set_update_texture (GdkMemoryTextureBuilder *self,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (texture == NULL || GDK_IS_TEXTURE (texture));
|
||||
|
||||
if (!g_set_object (&self->update_texture, texture))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_TEXTURE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_get_update_region: (attributes org.gtk.Method.get_property=update-region)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
*
|
||||
* Gets the region previously set via gdk_memory_texture_builder_set_update_region()
|
||||
* or %NULL if none was set.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): The update region
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
cairo_region_t *
|
||||
gdk_memory_texture_builder_get_update_region (GdkMemoryTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->update_region;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_set_update_region: (attributes org.gtk.Method.set_property=update-region)
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
* @region: (nullable): the region to update
|
||||
*
|
||||
* Sets the region to be updated by this texture.
|
||||
*
|
||||
* Together with [property@Gdk.MemoryTextureBuilder:update-texture],
|
||||
* this describes an update of a previous texture.
|
||||
*
|
||||
* When rendering animations of large textures, it is possible that
|
||||
* consecutive textures are only updating contents in parts of the texture.
|
||||
* It is then possible to describe this update via these two properties,
|
||||
* so that GTK can avoid rerendering parts that did not change.
|
||||
*
|
||||
* An example would be a screen recording where only the mouse pointer moves.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_memory_texture_builder_set_update_region (GdkMemoryTextureBuilder *self,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self));
|
||||
|
||||
if (self->update_region == region)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->update_region, cairo_region_destroy);
|
||||
|
||||
if (region)
|
||||
self->update_region = cairo_region_reference (region);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_REGION]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_builder_build:
|
||||
* @self: a `GdkMemoryTextureBuilder`
|
||||
*
|
||||
* Builds a new `GdkTexture` with the values set up in the builder.
|
||||
*
|
||||
* Note that it is a programming error to call this function if any mandatory
|
||||
* property has not been set.
|
||||
*
|
||||
* It is possible to call this function multiple times to create multiple textures,
|
||||
* possibly with changing properties in between.
|
||||
*
|
||||
* Returns: (transfer full): a newly built `GdkTexture`
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_memory_texture_builder_build (GdkMemoryTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE_BUILDER (self), NULL);
|
||||
g_return_val_if_fail (self->width > 0, NULL);
|
||||
g_return_val_if_fail (self->height > 0, NULL);
|
||||
g_return_val_if_fail (self->bytes != NULL, NULL);
|
||||
g_return_val_if_fail (self->stride >= self->width * gdk_memory_format_bytes_per_pixel (self->format), NULL);
|
||||
/* needs to be this complex to support subtexture of the bottom right part */
|
||||
g_return_val_if_fail (g_bytes_get_size (self->bytes) >= gdk_memory_format_min_buffer_size (self->format, self->stride, self->width, self->height), NULL);
|
||||
|
||||
return gdk_memory_texture_new_from_builder (self);
|
||||
}
|
89
gdk/gdkmemorytexturebuilder.h
Normal file
89
gdk/gdkmemorytexturebuilder.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright © 2024 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_MEMORY_TEXTURE_BUILDER (gdk_memory_texture_builder_get_type ())
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GDK_DECLARE_INTERNAL_TYPE (GdkMemoryTextureBuilder, gdk_memory_texture_builder, GDK, MEMORY_TEXTURE_BUILDER, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkMemoryTextureBuilder * gdk_memory_texture_builder_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GBytes * gdk_memory_texture_builder_get_bytes (GdkMemoryTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_memory_texture_builder_set_bytes (GdkMemoryTextureBuilder *self,
|
||||
GBytes *bytes);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gsize gdk_memory_texture_builder_get_stride (GdkMemoryTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_memory_texture_builder_set_stride (GdkMemoryTextureBuilder *self,
|
||||
gsize stride);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
int gdk_memory_texture_builder_get_width (GdkMemoryTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_memory_texture_builder_set_width (GdkMemoryTextureBuilder *self,
|
||||
int width);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
int gdk_memory_texture_builder_get_height (GdkMemoryTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_memory_texture_builder_set_height (GdkMemoryTextureBuilder *self,
|
||||
int height);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkMemoryFormat gdk_memory_texture_builder_get_format (GdkMemoryTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_memory_texture_builder_set_format (GdkMemoryTextureBuilder *self,
|
||||
GdkMemoryFormat format);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_memory_texture_builder_get_color_state (GdkMemoryTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_memory_texture_builder_set_color_state (GdkMemoryTextureBuilder *self,
|
||||
GdkColorState *color_state);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkTexture * gdk_memory_texture_builder_get_update_texture (GdkMemoryTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_memory_texture_builder_set_update_texture (GdkMemoryTextureBuilder *self,
|
||||
GdkTexture *texture);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
cairo_region_t * gdk_memory_texture_builder_get_update_region (GdkMemoryTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_memory_texture_builder_set_update_region (GdkMemoryTextureBuilder *self,
|
||||
cairo_region_t *region);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkTexture * gdk_memory_texture_builder_build (GdkMemoryTextureBuilder *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "gdkmemorytexture.h"
|
||||
|
||||
#include "gdkmemorytexturebuilder.h"
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -28,14 +29,15 @@ G_BEGIN_DECLS
|
||||
#define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8
|
||||
#define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
|
||||
|
||||
GdkMemoryTexture * gdk_memory_texture_from_texture (GdkTexture *texture,
|
||||
GdkMemoryFormat format);
|
||||
GdkMemoryTexture * gdk_memory_texture_from_texture (GdkTexture *texture);
|
||||
GdkTexture * gdk_memory_texture_new_subtexture (GdkMemoryTexture *texture,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
GdkTexture * gdk_memory_texture_new_from_builder (GdkMemoryTextureBuilder *builder);
|
||||
|
||||
GBytes * gdk_memory_texture_get_bytes (GdkMemoryTexture *self,
|
||||
gsize *out_stride);
|
||||
|
||||
|
@@ -109,7 +109,7 @@ gdk_popup_default_init (GdkPopupInterface *iface)
|
||||
*
|
||||
* Present @popup after having processed the `GdkPopupLayout` rules.
|
||||
*
|
||||
* If the popup was previously now showing, it will be showed,
|
||||
* If the popup was previously not showing, it will be shown,
|
||||
* otherwise it will change position according to @layout.
|
||||
*
|
||||
* After calling this function, the result should be handled in response
|
||||
|
@@ -29,11 +29,14 @@ gdk_subsurface_init (GdkSubsurface *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void remove_subsurface (GdkSubsurface *subsurface);
|
||||
|
||||
static void
|
||||
gdk_subsurface_finalize (GObject *object)
|
||||
{
|
||||
GdkSubsurface *subsurface = GDK_SUBSURFACE (object);
|
||||
|
||||
remove_subsurface (subsurface);
|
||||
g_ptr_array_remove (subsurface->parent->subsurfaces, subsurface);
|
||||
g_clear_object (&subsurface->parent);
|
||||
|
||||
@@ -144,7 +147,7 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *source,
|
||||
const graphene_rect_t *dest,
|
||||
GdkTextureTransform transform,
|
||||
GdkDihedral transform,
|
||||
const graphene_rect_t *background,
|
||||
gboolean above,
|
||||
GdkSubsurface *sibling)
|
||||
@@ -156,8 +159,8 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
|
||||
g_return_val_if_fail (source != NULL &&
|
||||
gsk_rect_contains_rect (&GRAPHENE_RECT_INIT (0, 0,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture)),
|
||||
gdk_dihedral_swaps_xy (transform) ? gdk_texture_get_height (texture) : gdk_texture_get_width (texture),
|
||||
gdk_dihedral_swaps_xy (transform) ? gdk_texture_get_width (texture) : gdk_texture_get_height (texture)),
|
||||
source), FALSE);
|
||||
g_return_val_if_fail (dest != NULL, FALSE);
|
||||
g_return_val_if_fail (sibling != subsurface, FALSE);
|
||||
@@ -320,10 +323,10 @@ gdk_subsurface_get_sibling (GdkSubsurface *subsurface,
|
||||
*
|
||||
* Returns: the transform
|
||||
*/
|
||||
GdkTextureTransform
|
||||
GdkDihedral
|
||||
gdk_subsurface_get_transform (GdkSubsurface *subsurface)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), GDK_TEXTURE_TRANSFORM_NORMAL);
|
||||
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), GDK_DIHEDRAL_NORMAL);
|
||||
|
||||
return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_transform (subsurface);
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkdihedralprivate.h"
|
||||
#include "gdksurface.h"
|
||||
#include <graphene.h>
|
||||
|
||||
@@ -47,17 +48,6 @@ struct _GdkSubsurface
|
||||
GdkSubsurface *sibling_below;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GDK_TEXTURE_TRANSFORM_NORMAL,
|
||||
GDK_TEXTURE_TRANSFORM_90,
|
||||
GDK_TEXTURE_TRANSFORM_180,
|
||||
GDK_TEXTURE_TRANSFORM_270,
|
||||
GDK_TEXTURE_TRANSFORM_FLIPPED,
|
||||
GDK_TEXTURE_TRANSFORM_FLIPPED_90,
|
||||
GDK_TEXTURE_TRANSFORM_FLIPPED_180,
|
||||
GDK_TEXTURE_TRANSFORM_FLIPPED_270,
|
||||
} GdkTextureTransform;
|
||||
|
||||
struct _GdkSubsurfaceClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
@@ -66,7 +56,7 @@ struct _GdkSubsurfaceClass
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *source,
|
||||
const graphene_rect_t *dest,
|
||||
GdkTextureTransform transform,
|
||||
GdkDihedral transform,
|
||||
const graphene_rect_t *bg,
|
||||
gboolean above,
|
||||
GdkSubsurface *sibling);
|
||||
@@ -76,7 +66,7 @@ struct _GdkSubsurfaceClass
|
||||
graphene_rect_t *rect);
|
||||
void (* get_texture_rect) (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *rect);
|
||||
GdkTextureTransform
|
||||
GdkDihedral
|
||||
(* get_transform) (GdkSubsurface *subsurface);
|
||||
gboolean (* get_background_rect) (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *rect);
|
||||
@@ -90,7 +80,7 @@ gboolean gdk_subsurface_attach (GdkSubsurface *subsu
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *source,
|
||||
const graphene_rect_t *dest,
|
||||
GdkTextureTransform transform,
|
||||
GdkDihedral transform,
|
||||
const graphene_rect_t *background,
|
||||
gboolean above,
|
||||
GdkSubsurface *sibling);
|
||||
@@ -103,7 +93,7 @@ void gdk_subsurface_get_texture_rect (GdkSubsurface *subsu
|
||||
gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface);
|
||||
GdkSubsurface * gdk_subsurface_get_sibling (GdkSubsurface *subsurface,
|
||||
gboolean above);
|
||||
GdkTextureTransform
|
||||
GdkDihedral
|
||||
gdk_subsurface_get_transform (GdkSubsurface *subsurface);
|
||||
gboolean gdk_subsurface_get_background_rect (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *rect);
|
||||
|
@@ -72,10 +72,12 @@ struct _GdkSurfacePrivate
|
||||
gpointer egl_native_window;
|
||||
#ifdef HAVE_EGL
|
||||
EGLSurface egl_surface;
|
||||
gboolean egl_surface_high_depth;
|
||||
GdkMemoryDepth egl_surface_depth;
|
||||
#endif
|
||||
|
||||
gpointer widget;
|
||||
|
||||
GdkColorState *color_state;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -475,6 +477,8 @@ gdk_surface_event_marshallerv (GClosure *closure,
|
||||
static void
|
||||
gdk_surface_init (GdkSurface *surface)
|
||||
{
|
||||
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (surface);
|
||||
|
||||
/* 0-initialization is good for all other fields. */
|
||||
|
||||
surface->state = 0;
|
||||
@@ -488,6 +492,8 @@ gdk_surface_init (GdkSurface *surface)
|
||||
NULL, g_object_unref);
|
||||
|
||||
surface->subsurfaces = g_ptr_array_new ();
|
||||
|
||||
priv->color_state = gdk_color_state_ref (gdk_color_state_get_srgb ());
|
||||
}
|
||||
|
||||
static double
|
||||
@@ -745,6 +751,7 @@ static void
|
||||
gdk_surface_finalize (GObject *object)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (object);
|
||||
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (surface);
|
||||
|
||||
g_clear_handle_id (&surface->request_motion_id, g_source_remove);
|
||||
|
||||
@@ -773,6 +780,8 @@ gdk_surface_finalize (GObject *object)
|
||||
|
||||
g_ptr_array_unref (surface->subsurfaces);
|
||||
|
||||
g_clear_pointer (&priv->color_state, gdk_color_state_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_surface_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@@ -1123,8 +1132,10 @@ gdk_surface_set_egl_native_window (GdkSurface *self,
|
||||
|
||||
if (priv->egl_surface != NULL)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (self);
|
||||
|
||||
gdk_gl_context_clear_current_if_surface (self);
|
||||
eglDestroySurface (gdk_surface_get_display (self), priv->egl_surface);
|
||||
eglDestroySurface (gdk_display_get_egl_display (display), priv->egl_surface);
|
||||
priv->egl_surface = NULL;
|
||||
}
|
||||
|
||||
@@ -1139,18 +1150,18 @@ gdk_surface_get_egl_surface (GdkSurface *self)
|
||||
return priv->egl_surface;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_surface_ensure_egl_surface (GdkSurface *self,
|
||||
gboolean high_depth)
|
||||
GdkMemoryDepth
|
||||
gdk_surface_ensure_egl_surface (GdkSurface *self,
|
||||
GdkMemoryDepth depth)
|
||||
{
|
||||
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
|
||||
GdkDisplay *display = gdk_surface_get_display (self);
|
||||
|
||||
g_return_if_fail (priv->egl_native_window != NULL);
|
||||
g_return_val_if_fail (priv->egl_native_window != NULL, depth);
|
||||
|
||||
if (priv->egl_surface_high_depth != high_depth &&
|
||||
if (priv->egl_surface_depth != depth &&
|
||||
priv->egl_surface != NULL &&
|
||||
gdk_display_get_egl_config_high_depth (display) != gdk_display_get_egl_config (display))
|
||||
gdk_display_get_egl_config (display, priv->egl_surface_depth) != gdk_display_get_egl_config (display, depth))
|
||||
{
|
||||
gdk_gl_context_clear_current_if_surface (self);
|
||||
eglDestroySurface (gdk_display_get_egl_display (display), priv->egl_surface);
|
||||
@@ -1159,16 +1170,45 @@ gdk_surface_ensure_egl_surface (GdkSurface *self,
|
||||
|
||||
if (priv->egl_surface == NULL)
|
||||
{
|
||||
EGLint attribs[4];
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
if (depth == GDK_MEMORY_U8_SRGB && display->have_egl_gl_colorspace)
|
||||
{
|
||||
attribs[i++] = EGL_GL_COLORSPACE_KHR;
|
||||
attribs[i++] = EGL_GL_COLORSPACE_SRGB_KHR;
|
||||
self->is_srgb = TRUE;
|
||||
}
|
||||
g_assert (i < G_N_ELEMENTS (attribs));
|
||||
attribs[i++] = EGL_NONE;
|
||||
|
||||
priv->egl_surface = eglCreateWindowSurface (gdk_display_get_egl_display (display),
|
||||
high_depth ? gdk_display_get_egl_config_high_depth (display)
|
||||
: gdk_display_get_egl_config (display),
|
||||
gdk_display_get_egl_config (display, depth),
|
||||
(EGLNativeWindowType) priv->egl_native_window,
|
||||
NULL);
|
||||
priv->egl_surface_high_depth = high_depth;
|
||||
attribs);
|
||||
if (priv->egl_surface == EGL_NO_SURFACE)
|
||||
{
|
||||
/* just assume the error is no srgb support and try again without */
|
||||
self->is_srgb = FALSE;
|
||||
priv->egl_surface = eglCreateWindowSurface (gdk_display_get_egl_display (display),
|
||||
gdk_display_get_egl_config (display, depth),
|
||||
(EGLNativeWindowType) priv->egl_native_window,
|
||||
NULL);
|
||||
}
|
||||
priv->egl_surface_depth = depth;
|
||||
}
|
||||
|
||||
return priv->egl_surface_depth;
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_surface_get_gl_is_srgb (GdkSurface *self)
|
||||
{
|
||||
return self->is_srgb;
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_surface_get_paint_gl_context (GdkSurface *surface,
|
||||
GError **error)
|
||||
@@ -3076,3 +3116,26 @@ gdk_surface_get_subsurface (GdkSurface *surface,
|
||||
{
|
||||
return g_ptr_array_index (surface->subsurfaces, idx);
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
gdk_surface_get_color_state (GdkSurface *surface)
|
||||
{
|
||||
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (surface);
|
||||
|
||||
return priv->color_state;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_surface_set_color_state (GdkSurface *surface,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (surface);
|
||||
|
||||
if (gdk_color_state_equal (priv->color_state, color_state))
|
||||
return;
|
||||
|
||||
gdk_color_state_unref (priv->color_state);
|
||||
priv->color_state = gdk_color_state_ref (color_state);
|
||||
|
||||
gdk_surface_invalidate_rect (surface, NULL);
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdksurface.h"
|
||||
#include "gdktoplevel.h"
|
||||
#include <graphene.h>
|
||||
@@ -70,6 +71,7 @@ struct _GdkSurface
|
||||
guint shortcuts_inhibited : 1;
|
||||
guint request_motion : 1;
|
||||
guint has_pointer : 1;
|
||||
guint is_srgb : 1;
|
||||
|
||||
guint request_motion_id;
|
||||
|
||||
@@ -298,10 +300,12 @@ void gdk_surface_set_frame_clock (GdkSurface
|
||||
GdkFrameClock *clock);
|
||||
void gdk_surface_set_egl_native_window (GdkSurface *self,
|
||||
gpointer native_window);
|
||||
void gdk_surface_ensure_egl_surface (GdkSurface *self,
|
||||
gboolean hdr);
|
||||
GdkMemoryDepth gdk_surface_ensure_egl_surface (GdkSurface *self,
|
||||
GdkMemoryDepth depth);
|
||||
gpointer /*EGLSurface*/ gdk_surface_get_egl_surface (GdkSurface *self);
|
||||
|
||||
gboolean gdk_surface_get_gl_is_srgb (GdkSurface *self);
|
||||
|
||||
void gdk_surface_set_widget (GdkSurface *self,
|
||||
gpointer widget);
|
||||
gpointer gdk_surface_get_widget (GdkSurface *self);
|
||||
@@ -339,12 +343,6 @@ void gdk_surface_queue_state_change (GdkSurface *surface,
|
||||
|
||||
void gdk_surface_apply_state_change (GdkSurface *surface);
|
||||
|
||||
void gdk_surface_emit_size_changed (GdkSurface *surface,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void gdk_surface_request_compute_size (GdkSurface *surface);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_surface_request_motion (GdkSurface *surface);
|
||||
|
||||
@@ -355,4 +353,8 @@ gsize gdk_surface_get_n_subsurfaces (GdkSurface *surface);
|
||||
GdkSubsurface * gdk_surface_get_subsurface (GdkSurface *surface,
|
||||
gsize idx);
|
||||
|
||||
GdkColorState * gdk_surface_get_color_state (GdkSurface *surface);
|
||||
void gdk_surface_set_color_state (GdkSurface *surface,
|
||||
GdkColorState *color_state);
|
||||
|
||||
G_END_DECLS
|
||||
|
158
gdk/gdktexture.c
158
gdk/gdktexture.c
@@ -40,11 +40,14 @@
|
||||
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gdkcairoprivate.h"
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkpaintable.h"
|
||||
#include "gdksnapshot.h"
|
||||
#include "gdktexturedownloaderprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <graphene.h>
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
#include "loaders/gdktiffprivate.h"
|
||||
@@ -69,6 +72,7 @@ enum {
|
||||
PROP_0,
|
||||
PROP_WIDTH,
|
||||
PROP_HEIGHT,
|
||||
PROP_COLOR_STATE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
@@ -258,6 +262,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkTexture, gdk_texture, G_TYPE_OBJECT,
|
||||
static void
|
||||
gdk_texture_default_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -282,6 +287,11 @@ gdk_texture_set_property (GObject *gobject,
|
||||
self->height = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
self->color_state = g_value_dup_boxed (value);
|
||||
g_assert (self->color_state);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@@ -306,6 +316,10 @@ gdk_texture_get_property (GObject *gobject,
|
||||
g_value_set_int (value, self->height);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
g_value_set_boxed (value, self->color_state);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@@ -347,6 +361,16 @@ gdk_texture_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (gdk_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_finalize (GObject *object)
|
||||
{
|
||||
GdkTexture *self = GDK_TEXTURE (object);
|
||||
|
||||
gdk_color_state_unref (self->color_state);
|
||||
|
||||
G_OBJECT_CLASS (gdk_texture_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_class_init (GdkTextureClass *klass)
|
||||
{
|
||||
@@ -357,6 +381,7 @@ gdk_texture_class_init (GdkTextureClass *klass)
|
||||
gobject_class->set_property = gdk_texture_set_property;
|
||||
gobject_class->get_property = gdk_texture_get_property;
|
||||
gobject_class->dispose = gdk_texture_dispose;
|
||||
gobject_class->finalize = gdk_texture_finalize;
|
||||
|
||||
/**
|
||||
* GdkTexture:width: (attributes org.gtk.Property.get=gdk_texture_get_width)
|
||||
@@ -388,21 +413,70 @@ gdk_texture_class_init (GdkTextureClass *klass)
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkTexture:color-state: (attributes org.gtk.Property.get=gdk_texture_get_color_state)
|
||||
*
|
||||
* The color state of the texture.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_COLOR_STATE] =
|
||||
g_param_spec_boxed ("color-state", NULL, NULL,
|
||||
GDK_TYPE_COLOR_STATE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_init (GdkTexture *self)
|
||||
{
|
||||
self->color_state = gdk_color_state_get_srgb ();
|
||||
}
|
||||
|
||||
/**
|
||||
static GdkMemoryFormat
|
||||
cairo_format_to_memory_format (cairo_format_t format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
return GDK_MEMORY_DEFAULT;
|
||||
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
return GDK_MEMORY_B8G8R8X8;
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
return GDK_MEMORY_X8R8G8B8;
|
||||
#else
|
||||
#error "Unknown byte order for Cairo format"
|
||||
#endif
|
||||
case CAIRO_FORMAT_A8:
|
||||
return GDK_MEMORY_A8;
|
||||
case CAIRO_FORMAT_RGB96F:
|
||||
return GDK_MEMORY_R32G32B32_FLOAT;
|
||||
case CAIRO_FORMAT_RGBA128F:
|
||||
return GDK_MEMORY_R32G32B32A32_FLOAT;
|
||||
|
||||
case CAIRO_FORMAT_RGB16_565:
|
||||
case CAIRO_FORMAT_RGB30:
|
||||
case CAIRO_FORMAT_INVALID:
|
||||
case CAIRO_FORMAT_A1:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return GDK_MEMORY_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_texture_new_for_surface:
|
||||
* @surface: a cairo image surface
|
||||
*
|
||||
* Creates a new texture object representing the surface.
|
||||
*
|
||||
* The @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`.
|
||||
* The @surface must be an image surface with a format supperted by GTK.
|
||||
*
|
||||
* The newly created texture will acquire a reference on the @surface.
|
||||
*
|
||||
@@ -426,7 +500,7 @@ gdk_texture_new_for_surface (cairo_surface_t *surface)
|
||||
|
||||
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
GDK_MEMORY_DEFAULT,
|
||||
cairo_format_to_memory_format (cairo_image_surface_get_format (surface)),
|
||||
bytes,
|
||||
cairo_image_surface_get_stride (surface));
|
||||
|
||||
@@ -727,13 +801,32 @@ gdk_texture_get_height (GdkTexture *texture)
|
||||
return texture->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_get_color_state: (attributes org.gtk.Method.get_property=color-state)
|
||||
* @self: a `GdkTexture`
|
||||
*
|
||||
* Returns the color state associated with the texture.
|
||||
*
|
||||
* Returns: (transfer none): the color state of the `GdkTexture`
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_texture_get_color_state (GdkTexture *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (self), NULL);
|
||||
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_texture_do_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, data, stride);
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, color_state, data, stride);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -829,22 +922,46 @@ gdk_texture_set_diff (GdkTexture *self,
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
gdk_texture_download_surface (GdkTexture *texture)
|
||||
gdk_texture_download_surface (GdkTexture *texture,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
GdkMemoryDepth depth;
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t surface_status;
|
||||
cairo_format_t surface_format;
|
||||
GdkTextureDownloader downloader;
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
depth = gdk_texture_get_depth (texture);
|
||||
#if 0
|
||||
/* disabled for performance reasons. Enjoy living with some banding. */
|
||||
if (!gdk_color_state_equal (texture->color_state, color_state))
|
||||
depth = gdk_memory_depth_merge (depth, gdk_color_state_get_depth (color_state));
|
||||
#else
|
||||
if (depth == GDK_MEMORY_U8_SRGB)
|
||||
depth = GDK_MEMORY_U8;
|
||||
#endif
|
||||
|
||||
surface_format = gdk_cairo_format_for_depth (depth);
|
||||
surface = cairo_image_surface_create (surface_format,
|
||||
texture->width, texture->height);
|
||||
|
||||
surface_status = cairo_surface_status (surface);
|
||||
if (surface_status != CAIRO_STATUS_SUCCESS)
|
||||
g_warning ("%s: surface error: %s", __FUNCTION__,
|
||||
cairo_status_to_string (surface_status));
|
||||
{
|
||||
g_warning ("%s: surface error: %s", __FUNCTION__,
|
||||
cairo_status_to_string (surface_status));
|
||||
return surface;
|
||||
}
|
||||
|
||||
gdk_texture_downloader_init (&downloader, texture);
|
||||
gdk_texture_downloader_set_format (&downloader,
|
||||
gdk_cairo_format_to_memory_format (surface_format));
|
||||
gdk_texture_downloader_set_color_state (&downloader, color_state);
|
||||
gdk_texture_downloader_download_into (&downloader,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
gdk_texture_downloader_finish (&downloader);
|
||||
|
||||
gdk_texture_download (texture,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
return surface;
|
||||
@@ -891,6 +1008,7 @@ gdk_texture_download (GdkTexture *texture,
|
||||
|
||||
gdk_texture_do_download (texture,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
GDK_COLOR_STATE_SRGB,
|
||||
data,
|
||||
stride);
|
||||
}
|
||||
@@ -921,6 +1039,13 @@ gdk_texture_get_format (GdkTexture *self)
|
||||
return self->format;
|
||||
}
|
||||
|
||||
GdkMemoryDepth
|
||||
gdk_texture_get_depth (GdkTexture *self)
|
||||
{
|
||||
return gdk_memory_format_get_depth (self->format,
|
||||
gdk_color_state_get_no_srgb_tf (self->color_state) != NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_texture_set_render_data (GdkTexture *self,
|
||||
gpointer key,
|
||||
@@ -939,6 +1064,14 @@ gdk_texture_set_render_data (GdkTexture *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_texture_steal_render_data (GdkTexture *self)
|
||||
{
|
||||
self->render_key = NULL;
|
||||
self->render_data = NULL;
|
||||
self->render_notify = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_texture_clear_render_data (GdkTexture *self)
|
||||
{
|
||||
@@ -1086,3 +1219,4 @@ gdk_texture_save_to_tiff_bytes (GdkTexture *texture)
|
||||
|
||||
return gdk_save_tiff (texture);
|
||||
}
|
||||
|
||||
|
@@ -83,6 +83,9 @@ int gdk_texture_get_height (GdkTexture
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GdkMemoryFormat gdk_texture_get_format (GdkTexture *self) G_GNUC_PURE;
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_texture_get_color_state (GdkTexture *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
|
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "gdktexturedownloaderprivate.h"
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdktextureprivate.h"
|
||||
@@ -51,12 +52,14 @@ gdk_texture_downloader_init (GdkTextureDownloader *self,
|
||||
{
|
||||
self->texture = g_object_ref (texture);
|
||||
self->format = GDK_MEMORY_DEFAULT;
|
||||
self->color_state = gdk_color_state_ref (GDK_COLOR_STATE_SRGB);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_texture_downloader_finish (GdkTextureDownloader *self)
|
||||
{
|
||||
g_object_unref (self->texture);
|
||||
gdk_color_state_unref (self->color_state);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,6 +68,9 @@ gdk_texture_downloader_finish (GdkTextureDownloader *self)
|
||||
*
|
||||
* Creates a new texture downloader for @texture.
|
||||
*
|
||||
* By default, the downloader will convert the data to
|
||||
* the default memory format, and to the sRGB color state.
|
||||
*
|
||||
* Returns: A new texture downloader
|
||||
*
|
||||
* Since: 4.10
|
||||
@@ -199,6 +205,45 @@ gdk_texture_downloader_get_format (const GdkTextureDownloader *self)
|
||||
return self->format;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_downloader_set_color_state:
|
||||
* @self: a texture downloader
|
||||
* @color_state: the color state to use
|
||||
*
|
||||
* Sets the color state the downloader will convert the data to.
|
||||
*
|
||||
* By default, the sRGB colorstate returned by [func@ColorState.get_srgb]
|
||||
* is used.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_texture_downloader_set_color_state (GdkTextureDownloader *self,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
if (self->color_state == color_state)
|
||||
return;
|
||||
|
||||
gdk_color_state_unref (self->color_state);
|
||||
self->color_state = gdk_color_state_ref (color_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_downloader_get_color_state:
|
||||
* @self: a texture downloader
|
||||
*
|
||||
* Gets the color state that the data will be downloaded in.
|
||||
*
|
||||
* Returns: The color state of the download
|
||||
*
|
||||
* Since: 4.16
|
||||
**/
|
||||
GdkColorState *
|
||||
gdk_texture_downloader_get_color_state (const GdkTextureDownloader *self)
|
||||
{
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_downloader_download_into:
|
||||
* @self: a texture downloader
|
||||
@@ -219,7 +264,7 @@ gdk_texture_downloader_download_into (const GdkTextureDownloader *self,
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (stride >= gdk_texture_get_width (self->texture) * gdk_memory_format_bytes_per_pixel (self->format));
|
||||
|
||||
gdk_texture_do_download (self->texture, self->format, data, stride);
|
||||
gdk_texture_do_download (self->texture, self->format, self->color_state, data, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,7 +295,8 @@ gdk_texture_downloader_download_bytes (const GdkTextureDownloader *self,
|
||||
g_return_val_if_fail (out_stride != NULL, NULL);
|
||||
|
||||
if (GDK_IS_MEMORY_TEXTURE (self->texture) &&
|
||||
gdk_texture_get_format (self->texture) == self->format)
|
||||
gdk_texture_get_format (self->texture) == self->format &&
|
||||
gdk_color_state_equal (gdk_texture_get_color_state (self->texture), self->color_state))
|
||||
{
|
||||
GdkMemoryTexture *memtex = GDK_MEMORY_TEXTURE (self->texture);
|
||||
|
||||
@@ -260,7 +306,7 @@ gdk_texture_downloader_download_bytes (const GdkTextureDownloader *self,
|
||||
stride = self->texture->width * gdk_memory_format_bytes_per_pixel (self->format);
|
||||
data = g_malloc_n (stride, self->texture->height);
|
||||
|
||||
gdk_texture_do_download (self->texture, self->format, data, stride);
|
||||
gdk_texture_do_download (self->texture, self->format, self->color_state, data, stride);
|
||||
|
||||
*out_stride = stride;
|
||||
return g_bytes_new_take (data, stride * self->texture->height);
|
||||
|
@@ -30,7 +30,7 @@ G_BEGIN_DECLS
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GType gdk_texture_downloader_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GdkTextureDownloader * gdk_texture_downloader_new (GdkTexture *texture);
|
||||
GdkTextureDownloader * gdk_texture_downloader_new (GdkTexture *texture);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GdkTextureDownloader * gdk_texture_downloader_copy (const GdkTextureDownloader *self);
|
||||
@@ -48,6 +48,11 @@ void gdk_texture_downloader_set_format (GdkTextureDownl
|
||||
GdkMemoryFormat format);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GdkMemoryFormat gdk_texture_downloader_get_format (const GdkTextureDownloader *self);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_texture_downloader_set_color_state (GdkTextureDownloader *self,
|
||||
GdkColorState *color_state);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_texture_downloader_get_color_state (const GdkTextureDownloader *self);
|
||||
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
|
@@ -28,6 +28,7 @@ struct _GdkTextureDownloader
|
||||
/*< private >*/
|
||||
GdkTexture *texture;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
};
|
||||
|
||||
void gdk_texture_downloader_init (GdkTextureDownloader *self,
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include "gdktexture.h"
|
||||
|
||||
#include "gdkenums.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -25,6 +26,7 @@ struct _GdkTexture
|
||||
GdkMemoryFormat format;
|
||||
int width;
|
||||
int height;
|
||||
GdkColorState *color_state;
|
||||
|
||||
gpointer render_key;
|
||||
gpointer render_data;
|
||||
@@ -46,6 +48,7 @@ struct _GdkTextureClass {
|
||||
/* mandatory: Download in the given format into data */
|
||||
void (* download) (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
};
|
||||
@@ -53,10 +56,14 @@ struct _GdkTextureClass {
|
||||
gboolean gdk_texture_can_load (GBytes *bytes);
|
||||
|
||||
GdkTexture * gdk_texture_new_for_surface (cairo_surface_t *surface);
|
||||
cairo_surface_t * gdk_texture_download_surface (GdkTexture *texture);
|
||||
cairo_surface_t * gdk_texture_download_surface (GdkTexture *texture,
|
||||
GdkColorState *color_state);
|
||||
|
||||
GdkMemoryDepth gdk_texture_get_depth (GdkTexture *self);
|
||||
|
||||
void gdk_texture_do_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
void gdk_texture_diff (GdkTexture *self,
|
||||
@@ -71,6 +78,7 @@ gboolean gdk_texture_set_render_data (GdkTexture
|
||||
gpointer key,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
void gdk_texture_steal_render_data (GdkTexture *self);
|
||||
void gdk_texture_clear_render_data (GdkTexture *self);
|
||||
gpointer gdk_texture_get_render_data (GdkTexture *self,
|
||||
gpointer key);
|
||||
|
@@ -745,6 +745,10 @@ gdk_toplevel_begin_move (GdkToplevel *toplevel,
|
||||
* @toplevel: a `GdkToplevel`
|
||||
* @gesture: a `GdkTitlebarGesture`
|
||||
*
|
||||
* Performs a title bar gesture.
|
||||
*
|
||||
* Returns: whether the gesture was performed
|
||||
*
|
||||
* Since: 4.4
|
||||
*/
|
||||
gboolean
|
||||
|
@@ -74,6 +74,8 @@ typedef cairo_rectangle_int_t GdkRectangle;
|
||||
|
||||
/* Forward declarations of commonly used types */
|
||||
typedef struct _GdkRGBA GdkRGBA;
|
||||
typedef struct _GdkCicpParams GdkCicpParams;
|
||||
typedef struct _GdkColorState GdkColorState;
|
||||
typedef struct _GdkContentFormats GdkContentFormats;
|
||||
typedef struct _GdkContentProvider GdkContentProvider;
|
||||
typedef struct _GdkCursor GdkCursor;
|
||||
@@ -99,7 +101,7 @@ typedef struct _GdkVulkanContext GdkVulkanContext;
|
||||
typedef struct _GdkDmabufFormats GdkDmabufFormats;
|
||||
typedef struct _GdkDmabufTexture GdkDmabufTexture;
|
||||
|
||||
/*
|
||||
/*<private>
|
||||
* GDK_DECLARE_INTERNAL_TYPE:
|
||||
* @ModuleObjName: The name of the new type, in camel case (like GtkWidget)
|
||||
* @module_obj_name: The name of the new type in lowercase, with words
|
||||
|
@@ -30,16 +30,14 @@
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdkmemorytexture.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
static const GdkDebugKey gsk_vulkan_feature_keys[] = {
|
||||
{ "dmabuf", GDK_VULKAN_FEATURE_DMABUF, "Never import Dmabufs" },
|
||||
{ "ycbcr", GDK_VULKAN_FEATURE_YCBCR, "Do not support Ycbcr textures" },
|
||||
{ "descriptor-indexing", GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING, "Force slow descriptor set layout codepath" },
|
||||
{ "dynamic-indexing", GDK_VULKAN_FEATURE_DYNAMIC_INDEXING, "Hardcode small number of buffer and texture arrays" },
|
||||
{ "nonuniform-indexing", GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING, "Split draw calls to ensure uniform texture accesses" },
|
||||
{ "ycbcr", GDK_VULKAN_FEATURE_YCBCR, "Do not support Ycbcr textures (also disables dmabufs)" },
|
||||
{ "semaphore-export", GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT, "Disable sync of exported dmabufs" },
|
||||
{ "semaphore-import", GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT, "Disable sync of imported dmabufs" },
|
||||
{ "incremental-present", GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT, "Do not send damage regions" },
|
||||
@@ -71,16 +69,16 @@ struct _GdkVulkanContextPrivate {
|
||||
struct {
|
||||
VkSurfaceFormatKHR vk_format;
|
||||
GdkMemoryFormat gdk_format;
|
||||
} formats[4];
|
||||
GdkMemoryDepth current_format;
|
||||
GdkMemoryFormat offscreen_formats[4];
|
||||
} formats[GDK_N_DEPTHS];
|
||||
GdkMemoryDepth current_depth;
|
||||
|
||||
VkSwapchainKHR swapchain;
|
||||
VkSemaphore draw_semaphore;
|
||||
|
||||
guint n_images;
|
||||
VkImage *images;
|
||||
cairo_region_t **regions;
|
||||
|
||||
VkSemaphore draw_semaphore;
|
||||
#endif
|
||||
|
||||
guint32 draw_index;
|
||||
@@ -367,14 +365,6 @@ gdk_vulkan_context_dispose (GObject *gobject)
|
||||
|
||||
device = gdk_vulkan_context_get_device (context);
|
||||
|
||||
if (priv->draw_semaphore != VK_NULL_HANDLE)
|
||||
{
|
||||
vkDestroySemaphore (device,
|
||||
priv->draw_semaphore,
|
||||
NULL);
|
||||
priv->draw_semaphore = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (priv->swapchain != VK_NULL_HANDLE)
|
||||
{
|
||||
vkDestroySwapchainKHR (device,
|
||||
@@ -473,8 +463,8 @@ gdk_vulkan_context_check_swapchain (GdkVulkanContext *context,
|
||||
.minImageCount = CLAMP (4,
|
||||
capabilities.minImageCount,
|
||||
capabilities.maxImageCount ? capabilities.maxImageCount : G_MAXUINT32),
|
||||
.imageFormat = priv->formats[priv->current_format].vk_format.format,
|
||||
.imageColorSpace = priv->formats[priv->current_format].vk_format.colorSpace,
|
||||
.imageFormat = priv->formats[priv->current_depth].vk_format.format,
|
||||
.imageColorSpace = priv->formats[priv->current_depth].vk_format.colorSpace,
|
||||
.imageExtent = capabilities.currentExtent,
|
||||
.imageArrayLayers = 1,
|
||||
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
@@ -592,23 +582,6 @@ physical_device_check_features (VkPhysicalDevice device)
|
||||
|
||||
features = 0;
|
||||
|
||||
if (v10_features.features.shaderUniformBufferArrayDynamicIndexing &&
|
||||
v10_features.features.shaderSampledImageArrayDynamicIndexing)
|
||||
features |= GDK_VULKAN_FEATURE_DYNAMIC_INDEXING;
|
||||
|
||||
if (v12_features.descriptorIndexing &&
|
||||
v12_features.descriptorBindingPartiallyBound &&
|
||||
v12_features.descriptorBindingVariableDescriptorCount &&
|
||||
v12_features.descriptorBindingSampledImageUpdateAfterBind &&
|
||||
v12_features.descriptorBindingStorageBufferUpdateAfterBind)
|
||||
features |= GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING;
|
||||
else if (physical_device_supports_extension (device, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME))
|
||||
features |= GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING;
|
||||
|
||||
if (v12_features.shaderSampledImageArrayNonUniformIndexing &&
|
||||
v12_features.shaderStorageBufferArrayNonUniformIndexing)
|
||||
features |= GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING;
|
||||
|
||||
if (ycbcr_features.samplerYcbcrConversion ||
|
||||
physical_device_supports_extension (device, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME))
|
||||
features |= GDK_VULKAN_FEATURE_YCBCR;
|
||||
@@ -634,59 +607,79 @@ physical_device_check_features (VkPhysicalDevice device)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
cairo_region_t *region)
|
||||
gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
cairo_region_t *region,
|
||||
GdkColorState **out_color_state,
|
||||
GdkMemoryDepth *out_depth)
|
||||
{
|
||||
GdkVulkanContext *context = GDK_VULKAN_CONTEXT (draw_context);
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
GdkSurface *surface = gdk_draw_context_get_surface (draw_context);
|
||||
GdkColorState *color_state;
|
||||
VkResult acquire_result;
|
||||
guint i;
|
||||
|
||||
if (depth != priv->current_format)
|
||||
g_assert (priv->draw_semaphore != VK_NULL_HANDLE);
|
||||
|
||||
color_state = gdk_surface_get_color_state (surface);
|
||||
depth = gdk_memory_depth_merge (depth, gdk_color_state_get_depth (color_state));
|
||||
|
||||
g_assert (depth != GDK_MEMORY_U8_SRGB || gdk_color_state_get_no_srgb_tf (color_state) != NULL);
|
||||
|
||||
if (depth != priv->current_depth && depth != GDK_MEMORY_NONE)
|
||||
{
|
||||
if (priv->formats[depth].gdk_format != priv->formats[priv->current_format].gdk_format)
|
||||
if (priv->formats[depth].vk_format.format != priv->formats[priv->current_depth].vk_format.format ||
|
||||
priv->formats[depth].vk_format.colorSpace != priv->formats[priv->current_depth].vk_format.colorSpace)
|
||||
{
|
||||
GdkMemoryDepth old_depth = priv->current_depth;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->current_depth = depth;
|
||||
if (!gdk_vulkan_context_check_swapchain (context, &error))
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
priv->current_depth = old_depth;
|
||||
}
|
||||
}
|
||||
priv->current_format = depth;
|
||||
}
|
||||
for (i = 0; i < priv->n_images; i++)
|
||||
{
|
||||
cairo_region_union (priv->regions[i], region);
|
||||
}
|
||||
|
||||
acquire_next_image:
|
||||
acquire_result = GDK_VK_CHECK (vkAcquireNextImageKHR, gdk_vulkan_context_get_device (context),
|
||||
priv->swapchain,
|
||||
UINT64_MAX,
|
||||
priv->draw_semaphore,
|
||||
VK_NULL_HANDLE,
|
||||
&priv->draw_index);
|
||||
if ((acquire_result == VK_ERROR_OUT_OF_DATE_KHR) ||
|
||||
(acquire_result == VK_SUBOPTIMAL_KHR))
|
||||
while (TRUE)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
GDK_DEBUG (VULKAN, "Recreating the swapchain");
|
||||
|
||||
if (!gdk_vulkan_context_check_swapchain (context, &error))
|
||||
acquire_result = GDK_VK_CHECK (vkAcquireNextImageKHR, gdk_vulkan_context_get_device (context),
|
||||
priv->swapchain,
|
||||
UINT64_MAX,
|
||||
priv->draw_semaphore,
|
||||
VK_NULL_HANDLE,
|
||||
&priv->draw_index);
|
||||
if ((acquire_result == VK_ERROR_OUT_OF_DATE_KHR) ||
|
||||
(acquire_result == VK_SUBOPTIMAL_KHR))
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
GDK_DEBUG (VULKAN, "Recreating the swapchain");
|
||||
|
||||
if (gdk_vulkan_context_check_swapchain (context, &error))
|
||||
continue;
|
||||
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
goto acquire_next_image;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
priv->draw_semaphore = VK_NULL_HANDLE;
|
||||
|
||||
cairo_region_union (region, priv->regions[priv->draw_index]);
|
||||
|
||||
*out_color_state = color_state;
|
||||
*out_depth = priv->current_depth;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -732,10 +725,8 @@ gdk_vulkan_context_end_frame (GdkDrawContext *draw_context,
|
||||
GDK_VK_CHECK (vkQueuePresentKHR, gdk_vulkan_context_get_queue (context),
|
||||
&(VkPresentInfoKHR) {
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = (VkSemaphore[]) {
|
||||
priv->draw_semaphore
|
||||
},
|
||||
.waitSemaphoreCount = 0,
|
||||
.pWaitSemaphores = NULL,
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = (VkSwapchainKHR[]) {
|
||||
priv->swapchain
|
||||
@@ -824,11 +815,6 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
if (!priv->vulkan_ref)
|
||||
return FALSE;
|
||||
|
||||
priv->offscreen_formats[GDK_MEMORY_U8] = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
priv->offscreen_formats[GDK_MEMORY_U16] = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
priv->offscreen_formats[GDK_MEMORY_FLOAT16] = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
priv->offscreen_formats[GDK_MEMORY_FLOAT32] = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
|
||||
if (surface == NULL)
|
||||
{
|
||||
for (i = 0; i < G_N_ELEMENTS (priv->formats); i++)
|
||||
@@ -884,7 +870,6 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
{
|
||||
priv->formats[GDK_MEMORY_U8].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_U8].gdk_format = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
priv->offscreen_formats[GDK_MEMORY_U8] = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
};
|
||||
break;
|
||||
|
||||
@@ -896,6 +881,22 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||
if (priv->formats[GDK_MEMORY_U8_SRGB].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
priv->formats[GDK_MEMORY_U8_SRGB].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_U8_SRGB].gdk_format = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R8G8B8A8_SRGB:
|
||||
if (priv->formats[GDK_MEMORY_U8_SRGB].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
priv->formats[GDK_MEMORY_U8_SRGB].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_U8_SRGB].gdk_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_FORMAT_R16G16B16A16_UNORM:
|
||||
priv->formats[GDK_MEMORY_U16].vk_format = formats[i];
|
||||
priv->formats[GDK_MEMORY_U16].gdk_format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
@@ -939,17 +940,11 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
priv->formats[GDK_MEMORY_FLOAT16] = priv->formats[GDK_MEMORY_FLOAT32];
|
||||
if (priv->formats[GDK_MEMORY_U16].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
priv->formats[GDK_MEMORY_U16] = priv->formats[GDK_MEMORY_FLOAT32];
|
||||
priv->formats[GDK_MEMORY_NONE] = priv->formats[GDK_MEMORY_U8];
|
||||
|
||||
if (!gdk_vulkan_context_check_swapchain (context, error))
|
||||
goto out_surface;
|
||||
|
||||
GDK_VK_CHECK (vkCreateSemaphore, gdk_vulkan_context_get_device (context),
|
||||
&(VkSemaphoreCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||
},
|
||||
NULL,
|
||||
&priv->draw_semaphore);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -961,15 +956,6 @@ out_surface:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GdkMemoryFormat
|
||||
gdk_vulkan_context_get_offscreen_format (GdkVulkanContext *context,
|
||||
GdkMemoryDepth depth)
|
||||
{
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
|
||||
return priv->offscreen_formats[depth];
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_vulkan_context_initable_init (GInitableIface *iface)
|
||||
{
|
||||
@@ -1178,7 +1164,7 @@ gdk_vulkan_save_pipeline_cache (GdkDisplay *display)
|
||||
|
||||
file = gdk_vulkan_get_pipeline_cache_file (display);
|
||||
|
||||
GDK_DEBUG (VULKAN, "Saving pipeline cache of size %lu to %s", size, g_file_peek_path (file));
|
||||
GDK_DEBUG (VULKAN, "Saving pipeline cache of size %" G_GSIZE_FORMAT " to %s", size, g_file_peek_path (file));
|
||||
|
||||
if (!g_file_replace_contents (file,
|
||||
data,
|
||||
@@ -1272,7 +1258,7 @@ gdk_display_create_pipeline_cache (GdkDisplay *display)
|
||||
}
|
||||
else
|
||||
{
|
||||
GDK_DEBUG (VULKAN, "Loading pipeline cache (%lu bytes)", display->vk_pipeline_cache_size);
|
||||
GDK_DEBUG (VULKAN, "Loading pipeline cache (%" G_GSIZE_FORMAT " bytes)", display->vk_pipeline_cache_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1291,9 +1277,18 @@ gdk_vulkan_context_get_image_format (GdkVulkanContext *context)
|
||||
|
||||
g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), VK_FORMAT_UNDEFINED);
|
||||
|
||||
return priv->formats[priv->current_format].vk_format.format;
|
||||
return priv->formats[priv->current_depth].vk_format.format;
|
||||
}
|
||||
|
||||
GdkMemoryFormat
|
||||
gdk_vulkan_context_get_memory_format (GdkVulkanContext *context)
|
||||
{
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), GDK_MEMORY_DEFAULT);
|
||||
|
||||
return priv->formats[priv->current_depth].gdk_format;
|
||||
}
|
||||
/**
|
||||
* gdk_vulkan_context_get_n_images:
|
||||
* @context: a `GdkVulkanContext`
|
||||
@@ -1356,26 +1351,28 @@ gdk_vulkan_context_get_draw_index (GdkVulkanContext *context)
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_vulkan_context_get_draw_semaphore:
|
||||
* gdk_vulkan_context_set_draw_semaphore:
|
||||
* @context: a `GdkVulkanContext`
|
||||
* @semaphore: a `VkSemaphore`
|
||||
*
|
||||
* Gets the Vulkan semaphore that protects access to the image that is
|
||||
* currently being drawn.
|
||||
* Sets the Vulkan semaphore that will be used in the immediately following
|
||||
* gdk_draw_context_begin_frame() call.
|
||||
* This is essentially an extra argument for that call, but without extending the
|
||||
* arguments of that generic function with Vulkan-specific things.
|
||||
*
|
||||
* This function can only be used between [method@Gdk.DrawContext.begin_frame]
|
||||
* and [method@Gdk.DrawContext.end_frame] calls.
|
||||
*
|
||||
* Returns: (transfer none): the VkSemaphore
|
||||
* This function must be called or begin_frame() will abort.
|
||||
*/
|
||||
VkSemaphore
|
||||
gdk_vulkan_context_get_draw_semaphore (GdkVulkanContext *context)
|
||||
void
|
||||
gdk_vulkan_context_set_draw_semaphore (GdkVulkanContext *context,
|
||||
VkSemaphore semaphore)
|
||||
{
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), VK_NULL_HANDLE);
|
||||
g_return_val_if_fail (gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context)), VK_NULL_HANDLE);
|
||||
g_return_if_fail (GDK_IS_VULKAN_CONTEXT (context));
|
||||
g_return_if_fail (!gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context)));
|
||||
g_return_if_fail (priv->draw_semaphore == VK_NULL_HANDLE);
|
||||
|
||||
return priv->draw_semaphore;
|
||||
priv->draw_semaphore = semaphore;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1410,6 +1407,8 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
skip_features = gdk_parse_debug_var ("GDK_VULKAN_DISABLE",
|
||||
gsk_vulkan_feature_keys,
|
||||
G_N_ELEMENTS (gsk_vulkan_feature_keys));
|
||||
if (skip_features & GDK_VULKAN_FEATURE_YCBCR)
|
||||
skip_features |= GDK_VULKAN_FEATURE_DMABUF;
|
||||
|
||||
override = g_getenv ("GDK_VULKAN_DEVICE");
|
||||
list_devices = FALSE;
|
||||
@@ -1510,8 +1509,6 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
|
||||
device_extensions = g_ptr_array_new ();
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
if (features & GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING)
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
if (features & GDK_VULKAN_FEATURE_YCBCR)
|
||||
{
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
|
||||
@@ -1554,16 +1551,6 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
.pNext = &(VkPhysicalDeviceVulkan11Features) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
|
||||
.samplerYcbcrConversion = ENABLE_IF (GDK_VULKAN_FEATURE_YCBCR),
|
||||
.pNext = &(VkPhysicalDeviceVulkan12Features) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||
.shaderSampledImageArrayNonUniformIndexing = ENABLE_IF (GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING),
|
||||
.shaderStorageBufferArrayNonUniformIndexing = ENABLE_IF (GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING),
|
||||
.descriptorIndexing = ENABLE_IF (GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING),
|
||||
.descriptorBindingPartiallyBound = ENABLE_IF (GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING),
|
||||
.descriptorBindingVariableDescriptorCount = ENABLE_IF (GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING),
|
||||
.descriptorBindingSampledImageUpdateAfterBind = ENABLE_IF (GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING),
|
||||
.descriptorBindingStorageBufferUpdateAfterBind = ENABLE_IF (GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING),
|
||||
}
|
||||
}
|
||||
},
|
||||
NULL,
|
||||
@@ -1635,8 +1622,7 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
|
||||
uint32_t i;
|
||||
GPtrArray *used_extensions;
|
||||
GPtrArray *used_layers;
|
||||
gboolean validate = FALSE, have_debug_report = FALSE;
|
||||
gboolean have_debug_report = FALSE;
|
||||
VkResult res;
|
||||
|
||||
if (gdk_display_get_debug_flags (display) & GDK_DEBUG_VULKAN_DISABLE)
|
||||
@@ -1685,43 +1671,6 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
g_ptr_array_add (used_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
uint32_t n_layers;
|
||||
GDK_VK_CHECK (vkEnumerateInstanceLayerProperties, &n_layers, NULL);
|
||||
VkLayerProperties *layers = g_newa (VkLayerProperties, n_layers);
|
||||
GDK_VK_CHECK (vkEnumerateInstanceLayerProperties, &n_layers, layers);
|
||||
|
||||
used_layers = g_ptr_array_new ();
|
||||
|
||||
for (i = 0; i < n_layers; i++)
|
||||
{
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (display, VULKAN))
|
||||
g_print ("Layer available: %s v%u.%u.%u (%s)\n",
|
||||
layers[i].layerName,
|
||||
VK_VERSION_MAJOR (layers[i].specVersion),
|
||||
VK_VERSION_MINOR (layers[i].specVersion),
|
||||
VK_VERSION_PATCH (layers[i].specVersion),
|
||||
layers[i].description);
|
||||
if (gdk_display_get_debug_flags (display) & GDK_DEBUG_VULKAN_VALIDATE)
|
||||
{
|
||||
const char *validation_layer_names[] = {
|
||||
"VK_LAYER_LUNARG_standard_validation",
|
||||
"VK_LAYER_KHRONOS_validation",
|
||||
NULL,
|
||||
};
|
||||
|
||||
if (g_strv_contains (validation_layer_names, layers[i].layerName))
|
||||
{
|
||||
g_ptr_array_add (used_layers, layers[i].layerName);
|
||||
validate = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((gdk_display_get_debug_flags (display) & GDK_DEBUG_VULKAN_VALIDATE) && !validate)
|
||||
{
|
||||
g_warning ("Vulkan validation layers were requested, but not found. Running without.");
|
||||
}
|
||||
|
||||
res = GDK_VK_CHECK (vkCreateInstance, &(VkInstanceCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
@@ -1735,14 +1684,13 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
.engineVersion = VK_MAKE_VERSION (GDK_MAJOR_VERSION, GDK_MINOR_VERSION, GDK_MICRO_VERSION),
|
||||
.apiVersion = VK_API_VERSION_1_3
|
||||
},
|
||||
.enabledLayerCount = used_layers->len,
|
||||
.ppEnabledLayerNames = (const char * const *) used_layers->pdata,
|
||||
.enabledLayerCount = 0,
|
||||
.ppEnabledLayerNames = NULL,
|
||||
.enabledExtensionCount = used_extensions->len,
|
||||
.ppEnabledExtensionNames = (const char * const *) used_extensions->pdata,
|
||||
},
|
||||
NULL,
|
||||
&display->vk_instance);
|
||||
g_ptr_array_free (used_layers, TRUE);
|
||||
g_ptr_array_free (used_extensions, TRUE);
|
||||
|
||||
if (res != VK_SUCCESS)
|
||||
|
@@ -94,14 +94,14 @@ VkDevice gdk_vulkan_context_get_device (GdkVulk
|
||||
VkQueue gdk_vulkan_context_get_queue (GdkVulkanContext *context);
|
||||
uint32_t gdk_vulkan_context_get_queue_family_index (GdkVulkanContext *context);
|
||||
VkFormat gdk_vulkan_context_get_image_format (GdkVulkanContext *context);
|
||||
GdkMemoryFormat gdk_vulkan_context_get_memory_format (GdkVulkanContext *context);
|
||||
uint32_t gdk_vulkan_context_get_n_images (GdkVulkanContext *context);
|
||||
VkImage gdk_vulkan_context_get_image (GdkVulkanContext *context,
|
||||
guint id);
|
||||
uint32_t gdk_vulkan_context_get_draw_index (GdkVulkanContext *context);
|
||||
VkSemaphore gdk_vulkan_context_get_draw_semaphore (GdkVulkanContext *context);
|
||||
|
||||
GdkMemoryFormat gdk_vulkan_context_get_offscreen_format (GdkVulkanContext *context,
|
||||
GdkMemoryDepth depth);
|
||||
void gdk_vulkan_context_set_draw_semaphore (GdkVulkanContext *context,
|
||||
VkSemaphore semaphore);
|
||||
|
||||
#else /* !GDK_RENDERING_VULKAN */
|
||||
|
||||
|
@@ -24,6 +24,8 @@
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gdktexture.h"
|
||||
#include "gdktexturedownloaderprivate.h"
|
||||
#include "gdkmemorytexturebuilder.h"
|
||||
#include "gdkcolorstateprivate.h"
|
||||
|
||||
#include "gdkprofilerprivate.h"
|
||||
|
||||
@@ -76,31 +78,6 @@ output_message_handler (j_common_ptr cinfo)
|
||||
/* }}} */
|
||||
/* {{{ Format conversion */
|
||||
|
||||
static void
|
||||
convert_grayscale_to_rgb (guchar *data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
gsize x, y;
|
||||
guchar *dest, *src;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = data + width;
|
||||
dest = data + 3 * width;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
dest -= 3;
|
||||
src -= 1;
|
||||
dest[0] = *src;
|
||||
dest[1] = *src;
|
||||
dest[2] = *src;
|
||||
}
|
||||
data += stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
convert_cmyk_to_rgba (guchar *data,
|
||||
int width,
|
||||
@@ -131,7 +108,7 @@ convert_cmyk_to_rgba (guchar *data,
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
GdkTexture *
|
||||
@@ -144,8 +121,10 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
unsigned char *data = NULL;
|
||||
unsigned char *row[1];
|
||||
GBytes *bytes;
|
||||
GdkMemoryTextureBuilder *builder;
|
||||
GdkTexture *texture;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
G_GNUC_UNUSED guint64 before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
info.err = jpeg_std_error (&jerr.pub);
|
||||
@@ -175,9 +154,15 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
width = info.output_width;
|
||||
height = info.output_height;
|
||||
|
||||
color_state = GDK_COLOR_STATE_SRGB;
|
||||
|
||||
switch ((int)info.out_color_space)
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
stride = width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
format = GDK_MEMORY_G8;
|
||||
break;
|
||||
case JCS_RGB:
|
||||
stride = 3 * width;
|
||||
data = g_try_malloc_n (stride, height);
|
||||
@@ -211,34 +196,31 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
jpeg_read_scanlines (&info, row, 1);
|
||||
}
|
||||
|
||||
switch ((int)info.out_color_space)
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
convert_grayscale_to_rgb (data, width, height, stride);
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
break;
|
||||
case JCS_RGB:
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
convert_cmyk_to_rgba (data, width, height, stride);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
if (info.out_color_space == JCS_CMYK)
|
||||
convert_cmyk_to_rgba (data, width, height, stride);
|
||||
|
||||
jpeg_finish_decompress (&info);
|
||||
jpeg_destroy_decompress (&info);
|
||||
|
||||
bytes = g_bytes_new_take (data, stride * height);
|
||||
|
||||
texture = gdk_memory_texture_new (width, height,
|
||||
format,
|
||||
bytes, stride);
|
||||
builder = gdk_memory_texture_builder_new ();
|
||||
|
||||
gdk_memory_texture_builder_set_bytes (builder, bytes);
|
||||
gdk_memory_texture_builder_set_stride (builder, stride);
|
||||
gdk_memory_texture_builder_set_width (builder, width);
|
||||
gdk_memory_texture_builder_set_height (builder, height);
|
||||
gdk_memory_texture_builder_set_format (builder, format);
|
||||
gdk_memory_texture_builder_set_color_state (builder, color_state);
|
||||
|
||||
texture = gdk_memory_texture_builder_build (builder);
|
||||
|
||||
gdk_color_state_unref (color_state);
|
||||
g_object_unref (builder);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
gdk_profiler_end_mark (before, "Load jpeg", NULL);
|
||||
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
@@ -292,6 +274,7 @@ gdk_save_jpeg (GdkTexture *texture)
|
||||
|
||||
gdk_texture_downloader_init (&downloader, texture);
|
||||
gdk_texture_downloader_set_format (&downloader, GDK_MEMORY_R8G8B8);
|
||||
gdk_texture_downloader_set_color_state (&downloader, GDK_COLOR_STATE_SRGB);
|
||||
texbytes = gdk_texture_downloader_download_bytes (&downloader, &texstride);
|
||||
gdk_texture_downloader_finish (&downloader);
|
||||
texdata = g_bytes_get_data (texbytes, NULL);
|
||||
|
@@ -20,11 +20,13 @@
|
||||
#include "gdkpngprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytexture.h"
|
||||
#include "gdkmemorytexturebuilder.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdktexturedownloaderprivate.h"
|
||||
#include "gsk/gl/fp16private.h"
|
||||
|
||||
#include <png.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -126,6 +128,141 @@ png_simple_warning_callback (png_structp png,
|
||||
{
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Color profile handling */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gboolean cicp_chunk_read;
|
||||
int color_primaries;
|
||||
int transfer_function;
|
||||
int matrix_coefficients;
|
||||
int range;
|
||||
} CICPData;
|
||||
|
||||
static int
|
||||
png_read_chunk_func (png_structp png,
|
||||
png_unknown_chunkp chunk)
|
||||
{
|
||||
if (strcmp ((char *) chunk->name, "cICP") == 0 &&
|
||||
chunk->size == 4)
|
||||
{
|
||||
CICPData *cicp = png_get_user_chunk_ptr (png);
|
||||
|
||||
cicp->cicp_chunk_read = TRUE;
|
||||
|
||||
cicp->color_primaries = chunk->data[0];
|
||||
cicp->transfer_function = chunk->data[1];
|
||||
cicp->matrix_coefficients = chunk->data[2];
|
||||
cicp->range = chunk->data[3];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GdkColorState *
|
||||
gdk_png_get_color_state_from_cicp (const CICPData *data,
|
||||
GError **error)
|
||||
{
|
||||
GdkCicp cicp;
|
||||
|
||||
cicp.color_primaries = data->color_primaries;
|
||||
cicp.transfer_function = data->transfer_function;
|
||||
cicp.matrix_coefficients= data->matrix_coefficients;
|
||||
cicp.range = data->range;
|
||||
|
||||
return gdk_color_state_new_for_cicp (&cicp, error);
|
||||
}
|
||||
|
||||
static GdkColorState *
|
||||
gdk_png_get_color_state (png_struct *png,
|
||||
png_info *info,
|
||||
GError **error)
|
||||
{
|
||||
GdkColorState *color_state;
|
||||
CICPData *cicp;
|
||||
int intent;
|
||||
|
||||
cicp = png_get_user_chunk_ptr (png);
|
||||
|
||||
if (cicp->cicp_chunk_read)
|
||||
{
|
||||
GError *local_error = NULL;
|
||||
|
||||
color_state = gdk_png_get_color_state_from_cicp (cicp, &local_error);
|
||||
if (color_state)
|
||||
{
|
||||
g_debug ("Color state from cICP data: %s", gdk_color_state_get_name (color_state));
|
||||
return color_state;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_UNSUPPORTED_CONTENT,
|
||||
local_error->message);
|
||||
g_error_free (local_error);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (png_get_iCCP (png, info, &name, NULL, &icc_data, &icc_len))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
if (png_get_sRGB (png, info, &intent))
|
||||
return gdk_color_state_ref (GDK_COLOR_STATE_SRGB);
|
||||
|
||||
/* If neither of those is valid, the result is sRGB */
|
||||
if (!png_get_valid (png, info, PNG_INFO_gAMA) &&
|
||||
!png_get_valid (png, info, PNG_INFO_cHRM))
|
||||
return GDK_COLOR_STATE_SRGB;
|
||||
|
||||
g_debug ("Failed to find color state, assuming SRGB");
|
||||
|
||||
return GDK_COLOR_STATE_SRGB;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_png_set_color_state (png_struct *png,
|
||||
png_info *info,
|
||||
GdkColorState *color_state,
|
||||
png_byte *chunk_data)
|
||||
{
|
||||
const GdkCicp *cicp;
|
||||
|
||||
cicp = gdk_color_state_get_cicp (color_state);
|
||||
|
||||
if (cicp)
|
||||
{
|
||||
png_unknown_chunk chunk = {
|
||||
.name = { 'c', 'I', 'C', 'P', '\0' },
|
||||
.data = chunk_data,
|
||||
.size = 4,
|
||||
.location = PNG_HAVE_IHDR,
|
||||
};
|
||||
|
||||
chunk_data[0] = (png_byte) cicp->color_primaries;
|
||||
chunk_data[1] = (png_byte) cicp->transfer_function;
|
||||
chunk_data[2] = (png_byte) 0; /* png only supports this */
|
||||
chunk_data[3] = (png_byte) cicp->range;
|
||||
|
||||
png_set_unknown_chunks (png, info, &chunk, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unsupported color state. Fall back to sRGB */
|
||||
gdk_color_state_unref (color_state);
|
||||
color_state = gdk_color_state_ref (gdk_color_state_get_srgb ());
|
||||
}
|
||||
|
||||
/* For good measure, we add an sRGB chunk too */
|
||||
if (gdk_color_state_equal (color_state, GDK_COLOR_STATE_SRGB))
|
||||
png_set_sRGB (png, info, PNG_sRGB_INTENT_PERCEPTUAL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
@@ -143,12 +280,16 @@ gdk_load_png (GBytes *bytes,
|
||||
gsize i, stride;
|
||||
int depth, color_type;
|
||||
int interlace;
|
||||
GdkMemoryTextureBuilder *builder;
|
||||
GdkMemoryFormat format;
|
||||
guchar *buffer = NULL;
|
||||
guchar **row_pointers = NULL;
|
||||
GBytes *out_bytes;
|
||||
GdkColorState *color_state;
|
||||
GdkTexture *texture;
|
||||
int bpp;
|
||||
CICPData cicp = { FALSE, };
|
||||
|
||||
G_GNUC_UNUSED gint64 before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
io.data = (guchar *)g_bytes_get_data (bytes, &io.size);
|
||||
@@ -169,6 +310,7 @@ gdk_load_png (GBytes *bytes,
|
||||
g_error ("Out of memory");
|
||||
|
||||
png_set_read_fn (png, &io, png_read_func);
|
||||
png_set_read_user_chunk_fn (png, &cicp, png_read_chunk_func);
|
||||
|
||||
if (sigsetjmp (png_jmpbuf (png), 1))
|
||||
{
|
||||
@@ -266,6 +408,10 @@ gdk_load_png (GBytes *bytes,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
color_state = gdk_png_get_color_state (png, info, error);
|
||||
if (color_state == NULL)
|
||||
return NULL;
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
if (!g_size_checked_mul (&stride, width, bpp) ||
|
||||
!g_size_checked_add (&stride, stride, (8 - stride % 8) % 8))
|
||||
@@ -281,6 +427,7 @@ gdk_load_png (GBytes *bytes,
|
||||
|
||||
if (!buffer || !row_pointers)
|
||||
{
|
||||
gdk_color_state_unref (color_state);
|
||||
g_free (buffer);
|
||||
g_free (row_pointers);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
@@ -297,8 +444,17 @@ gdk_load_png (GBytes *bytes,
|
||||
png_read_end (png, info);
|
||||
|
||||
out_bytes = g_bytes_new_take (buffer, height * stride);
|
||||
texture = gdk_memory_texture_new (width, height, format, out_bytes, stride);
|
||||
builder = gdk_memory_texture_builder_new ();
|
||||
gdk_memory_texture_builder_set_format (builder, format);
|
||||
gdk_memory_texture_builder_set_color_state (builder, color_state);
|
||||
gdk_memory_texture_builder_set_width (builder, width);
|
||||
gdk_memory_texture_builder_set_height (builder, height);
|
||||
gdk_memory_texture_builder_set_bytes (builder, out_bytes);
|
||||
gdk_memory_texture_builder_set_stride (builder, stride);
|
||||
texture = gdk_memory_texture_builder_build (builder);
|
||||
g_object_unref (builder);
|
||||
g_bytes_unref (out_bytes);
|
||||
gdk_color_state_unref (color_state);
|
||||
|
||||
if (options && png_get_text (png, info, &text, &num_texts))
|
||||
{
|
||||
@@ -337,11 +493,14 @@ gdk_save_png (GdkTexture *texture)
|
||||
GBytes *bytes;
|
||||
gsize stride;
|
||||
const guchar *data;
|
||||
GdkColorState *color_state;
|
||||
int png_format;
|
||||
int depth;
|
||||
png_byte chunk_data[4];
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
color_state = gdk_texture_get_color_state (texture);
|
||||
format = gdk_texture_get_format (texture);
|
||||
|
||||
switch (format)
|
||||
@@ -436,6 +595,8 @@ gdk_save_png (GdkTexture *texture)
|
||||
/* 2^31-1 is the maximum size for PNG files */
|
||||
png_set_user_limits (png, (1u << 31) - 1, (1u << 31) - 1);
|
||||
|
||||
png_set_keep_unknown_chunks (png, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0);
|
||||
|
||||
info = png_create_info_struct (png);
|
||||
if (!info)
|
||||
{
|
||||
@@ -443,15 +604,13 @@ gdk_save_png (GdkTexture *texture)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gdk_texture_downloader_init (&downloader, texture);
|
||||
gdk_texture_downloader_set_format (&downloader, format);
|
||||
bytes = gdk_texture_downloader_download_bytes (&downloader, &stride);
|
||||
gdk_texture_downloader_finish (&downloader);
|
||||
data = g_bytes_get_data (bytes, NULL);
|
||||
gdk_color_state_ref (color_state);
|
||||
bytes = NULL;
|
||||
|
||||
if (sigsetjmp (png_jmpbuf (png), 1))
|
||||
{
|
||||
g_bytes_unref (bytes);
|
||||
gdk_color_state_unref (color_state);
|
||||
g_clear_pointer (&bytes, g_bytes_unref);
|
||||
g_free (io.data);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
return NULL;
|
||||
@@ -465,12 +624,20 @@ gdk_save_png (GdkTexture *texture)
|
||||
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
gdk_png_set_color_state (png, info, color_state, chunk_data);
|
||||
|
||||
png_write_info (png, info);
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
png_set_swap (png);
|
||||
#endif
|
||||
|
||||
gdk_texture_downloader_init (&downloader, texture);
|
||||
gdk_texture_downloader_set_format (&downloader, format);
|
||||
bytes = gdk_texture_downloader_download_bytes (&downloader, &stride);
|
||||
gdk_texture_downloader_finish (&downloader);
|
||||
data = g_bytes_get_data (bytes, NULL);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
png_write_row (png, data + y * stride);
|
||||
|
||||
@@ -478,6 +645,7 @@ gdk_save_png (GdkTexture *texture)
|
||||
|
||||
png_destroy_write_struct (&png, &info);
|
||||
|
||||
gdk_color_state_unref (color_state);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return g_bytes_new_take (io.data, io.size);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user