Compare commits
545 Commits
temp-geome
...
temp-geome
Author | SHA1 | Date | |
---|---|---|---|
c8698e6657 | |||
b517b9f646 | |||
3d7021b4ec | |||
b129a0b397 | |||
5f27a5fff7 | |||
b801db1181 | |||
b5840f9b5b | |||
![]() |
beb6399ae5 | ||
![]() |
15868b1ff4 | ||
7b524d9b71 | |||
a13314a03f | |||
cbdddc5648 | |||
51568030e9 | |||
27da305a40 | |||
67b352f9c5 | |||
8cdb99d51c | |||
3a8347f823 | |||
6570159929 | |||
1f778dbefc | |||
4b9ff3cd42 | |||
2e99a74df9 | |||
879b89e967 | |||
0469f2392f | |||
55bffa82da | |||
de6c6501f0 | |||
de05e261ec | |||
379f116a2a | |||
f7fbb518c8 | |||
d6212f67a9 | |||
ef7fcaf8e6 | |||
6e4b9f5836 | |||
c9f12b21e2 | |||
35db01325f | |||
8f4d991594 | |||
a50a51eef0 | |||
276790cbfa | |||
7dd7849ddd | |||
7561e3dad0 | |||
354ecc2f1e | |||
157081069d | |||
befb9d99f8 | |||
b964f73e7d | |||
eed9ac5b6e | |||
e291432f5f | |||
635b4db162 | |||
![]() |
a6f275cad3 | ||
82c17082ba | |||
071799d4fc | |||
61b22d27c8 | |||
5cc8e7ab53 | |||
2c916c97ac | |||
0f427f4eb1 | |||
58e58310b7 | |||
a8f37763ca | |||
dbc054bb88 | |||
abb07a38b8 | |||
c88c331384 | |||
![]() |
187e217b5a | ||
fa1868ae97 | |||
c3b641613c | |||
0732a9f1b2 | |||
87833f8f95 | |||
b35ba22d84 | |||
c6e6a9046e | |||
ee8b284d11 | |||
![]() |
c317f111c1 | ||
2fcd3f0296 | |||
1917d0345e | |||
ebfad93039 | |||
3a48147b8a | |||
0b15353baa | |||
f3eecfe386 | |||
026de343e3 | |||
f8d219dfd4 | |||
6ff0d59967 | |||
feaf309de7 | |||
f4e3b1e573 | |||
e3bdb189a7 | |||
ab063db34d | |||
3f1111b2a8 | |||
ad9fd47d7b | |||
01234b430b | |||
956c539e59 | |||
d3a792431e | |||
53ba9f01e2 | |||
1725bfc3cb | |||
6a3bd04e42 | |||
8af2c87f7e | |||
cd39e3dec1 | |||
338be95874 | |||
9ac56bad4c | |||
67ee87a6e9 | |||
53e1442ac2 | |||
e1d6219731 | |||
dc3b7602ee | |||
d086570c7a | |||
4947aa29db | |||
d443dcc733 | |||
6f158f834d | |||
445d506ac9 | |||
![]() |
b11a463e4f | ||
b665ad8621 | |||
41af27c582 | |||
47473bee34 | |||
b9ccfb89ce | |||
ce64cfd6ed | |||
3cf39c09bf | |||
4246898ad3 | |||
2851602052 | |||
4968a0bdf9 | |||
![]() |
f383cad329 | ||
002d563bbb | |||
4d91808710 | |||
4044c29069 | |||
54d651c344 | |||
19df0e3cfd | |||
b2510b9e20 | |||
feb6fd632f | |||
a1c3e45100 | |||
b45cee1aaf | |||
5df6b4004c | |||
5f71b1edd5 | |||
80083ac773 | |||
0cd34967c0 | |||
6afafc46f6 | |||
2d75b39b64 | |||
eee3529eaf | |||
859b3ff346 | |||
bce482f476 | |||
d9b1592c88 | |||
3462b4c7ae | |||
2d60c496a2 | |||
513f566b40 | |||
b5e5fbcfc8 | |||
3da25dc625 | |||
f3c5a84bb9 | |||
033641aa74 | |||
f9aea19d98 | |||
d52b7dbe26 | |||
3e6f2c7a99 | |||
f7022fc73f | |||
8a048593ca | |||
b6030711a2 | |||
638c16f410 | |||
682a74e090 | |||
aee04d4960 | |||
4c19fe4707 | |||
4998ceebfc | |||
408726000a | |||
![]() |
e0f2f07d1e | ||
![]() |
6d73d98fb6 | ||
03a83b4eb5 | |||
![]() |
ea4309925f | ||
a9d5c8f97f | |||
847b66e81d | |||
b8cf8e0bc2 | |||
80bc819d50 | |||
adefdbc9df | |||
7c68147709 | |||
060d668ae6 | |||
6c1fdd52c1 | |||
3caafd24a9 | |||
c4958bc540 | |||
2e8d7fa7ee | |||
253c5d25f7 | |||
c290ac2ab1 | |||
af4167441b | |||
50a4b9d502 | |||
5f0d4fef91 | |||
68b06208d2 | |||
f3c88f8ba5 | |||
![]() |
e178a273fa | ||
94c4a9995e | |||
4b673ebb99 | |||
577d6d3f87 | |||
ed4222258e | |||
7c1bb239be | |||
56db09e2fd | |||
1388e9de8a | |||
a971409d5a | |||
ccd5f80550 | |||
8ff6322152 | |||
6db290641e | |||
286bd87445 | |||
eb85de027c | |||
78693d524c | |||
e7003bc965 | |||
c73be23e17 | |||
845f4cebad | |||
d03b26edbd | |||
a1cc7042a7 | |||
247abdbf41 | |||
b37093de7b | |||
45d59e0df5 | |||
0cebe554d1 | |||
af3d7123c9 | |||
3953b82030 | |||
88aa056d1a | |||
b66600b9f3 | |||
b406b6717f | |||
94084b2d3c | |||
00fc110d3f | |||
1c0a490d0e | |||
c3fa7b7e4f | |||
4b36c5b1a7 | |||
3385c04598 | |||
9fed00341e | |||
![]() |
ed4b2ba75a | ||
2209321f78 | |||
be8a201a16 | |||
0b0c7ca017 | |||
c8e331f450 | |||
4891da8ae2 | |||
1a5fa2b319 | |||
143a81ccce | |||
c29afa5156 | |||
732e8c723e | |||
![]() |
6bb980b0f4 | ||
8e84938dd0 | |||
a4f840e15b | |||
fcc844f8fb | |||
![]() |
b3f0dc2907 | ||
71997921c4 | |||
0c75a98561 | |||
![]() |
174ed69c1b | ||
7c8b9c7a9a | |||
62906cdbea | |||
7f570a7174 | |||
9cd2e80d5d | |||
462bd81399 | |||
819152527f | |||
89e2b441ed | |||
ae34808114 | |||
fdad77d73d | |||
0a361eb5ec | |||
2ba804d7b7 | |||
5dc0fd08a7 | |||
2053e1f533 | |||
4ae06b6123 | |||
013fc69ea8 | |||
3bf98d1cec | |||
9ce49af32e | |||
1f251b7a27 | |||
61fdc45034 | |||
bf7f918a0e | |||
fe0fa7cec6 | |||
![]() |
4a540b9b48 | ||
fcbb20286a | |||
d08e925ef1 | |||
bcff0ef9ca | |||
2e5671a959 | |||
aadd355028 | |||
3de6fe0b3e | |||
e9b4de43d8 | |||
90b0fb135f | |||
8a1860bd9a | |||
6bef255904 | |||
8083527f90 | |||
1d2eb461b5 | |||
![]() |
b84707df17 | ||
ada47c4772 | |||
748475b943 | |||
b21db5e698 | |||
![]() |
5add6f2ed9 | ||
c9dc55301c | |||
a19c9e9351 | |||
![]() |
2db09f67a4 | ||
03544ed54f | |||
54a03d4247 | |||
84adc23941 | |||
2b343c74d5 | |||
1e468f57b1 | |||
2ee7d5282d | |||
d9c3a223cc | |||
0f68e5c30a | |||
5181bc46b3 | |||
452590571c | |||
ab38223047 | |||
f731bce6cd | |||
4c3bb60d0f | |||
9ff4e0068f | |||
84e98ba182 | |||
8e58f93215 | |||
aab4794512 | |||
952d6663e0 | |||
7b0c8097a7 | |||
b313525c1b | |||
d75e45d10c | |||
bd87ba90e6 | |||
![]() |
7bc5246156 | ||
2f9dbe9e7c | |||
f6c5af3d47 | |||
c8fcea0c33 | |||
20ece8736f | |||
![]() |
b4adb85933 | ||
605ce623be | |||
![]() |
7b30a3e98d | ||
![]() |
7b76a160a4 | ||
0eb9351296 | |||
![]() |
2330cec2c6 | ||
fe22635bf6 | |||
c0367b19e2 | |||
4adbe31e2f | |||
1fb2eaf1c5 | |||
2f280d4b92 | |||
e9c8ae767a | |||
![]() |
7fc220517f | ||
![]() |
28617bb167 | ||
84f025c6fd | |||
![]() |
066f5a4469 | ||
![]() |
d07cc5e680 | ||
![]() |
162cf8e81d | ||
![]() |
fd5c94c48a | ||
![]() |
2724d08cf5 | ||
![]() |
461ba4438f | ||
d581c1b304 | |||
e8a4bddef4 | |||
fbd889ec28 | |||
509e0c5b76 | |||
45f32b43fc | |||
7b62a54230 | |||
![]() |
53c98e45cf | ||
bcefce33f2 | |||
9df1e0cad5 | |||
aa0bd29546 | |||
1a72ee4cbe | |||
e4ef8cbf7e | |||
5fa6cdb77a | |||
5304c6ed7d | |||
b669fd376a | |||
4d4608363c | |||
7141eb75ef | |||
12bf0af064 | |||
b282a065f1 | |||
![]() |
4f81b4b4ce | ||
9c393bab47 | |||
a3226bdf3e | |||
3ec74ee230 | |||
![]() |
d96e9de9de | ||
93fd07e19c | |||
5f19646d7e | |||
675677ec67 | |||
539095ca40 | |||
![]() |
df2a19eac7 | ||
2856f3b583 | |||
965bd53e02 | |||
05f15645ec | |||
cb0cab48ef | |||
029fb002dd | |||
4443c4082e | |||
bda8887e0c | |||
5575aba025 | |||
25d8ce16b5 | |||
59553d47c0 | |||
84af1eaa92 | |||
059f19d821 | |||
0f156a2436 | |||
f42a501c61 | |||
d8b8b4d7e2 | |||
14f3b2cdad | |||
f546b0800b | |||
92ae3ff84c | |||
5954b351f0 | |||
33c4eefabb | |||
![]() |
6e999e08ab | ||
ec98bb318b | |||
3a7ab62eac | |||
1f55e12206 | |||
ea3895558d | |||
![]() |
e4c6da29b2 | ||
4ced8900f5 | |||
f087a225dc | |||
dd98f6b55c | |||
b18a214ecb | |||
d7c812f15b | |||
3ba16afa1e | |||
8c3f4f7edf | |||
307f8c8e76 | |||
8bd09b1d77 | |||
21ac9d9cff | |||
f29a738e23 | |||
c18ff180e3 | |||
4aae988163 | |||
22ee056c3a | |||
f5a2d93224 | |||
a31bd2609f | |||
![]() |
2e19649bb9 | ||
7124c66340 | |||
![]() |
259b9c73d0 | ||
08b0de45f3 | |||
![]() |
2246d456aa | ||
9553ba1373 | |||
a2ebbeb836 | |||
5b014911a5 | |||
23fd576cf8 | |||
43464c94f4 | |||
322a614497 | |||
340c535dbf | |||
088ea59b7e | |||
cac9828ae3 | |||
9e9d45ae16 | |||
89d0cc3a0c | |||
e54a4b355e | |||
933c2cffd6 | |||
ed1fc9d96b | |||
496045fc30 | |||
f651cc6c4e | |||
0efb627bbd | |||
1b07b7a068 | |||
bd75d9f44c | |||
4602874a04 | |||
3a8c57afd5 | |||
0abce91940 | |||
2e46a8c864 | |||
ef5a362a5b | |||
a6715213c3 | |||
482465e18a | |||
b0ec1d2747 | |||
1ef33be2d4 | |||
d2aee304e8 | |||
6e56b42faa | |||
1c6e338d59 | |||
7313b243f2 | |||
1182c26978 | |||
8cbff7093d | |||
0fcc063fd9 | |||
1949643ee5 | |||
7bf9d2c580 | |||
4a9c5c60b7 | |||
0e285fa23c | |||
214a78a46f | |||
f87f8532c3 | |||
3da0b52c97 | |||
785a518ebe | |||
2bf56f7fbb | |||
93a865dde7 | |||
72d2355af5 | |||
dfac5a63bd | |||
c87327ddeb | |||
7ca5ba14b5 | |||
51bf1680bd | |||
91d3a54869 | |||
ee0000b8bb | |||
7f1d1b03ad | |||
abee9a85d4 | |||
![]() |
223016a408 | ||
6e6a1838ea | |||
1d3ffc93ec | |||
e517aaa136 | |||
8b8c3c34dd | |||
4f6cab176a | |||
98876d46ef | |||
7ef2b760dc | |||
c27b7df563 | |||
a496af8680 | |||
54ce344bc7 | |||
dbfde0fe70 | |||
8e43ef5f31 | |||
edaaa2afdd | |||
d2dc452333 | |||
2cd1bc3aa7 | |||
1a912462f4 | |||
bcf9c73cbc | |||
3c9c557580 | |||
c7fee64dea | |||
ca3891e83b | |||
a5114bfb85 | |||
022f8b552d | |||
14508ef100 | |||
bfaf09b5bc | |||
c2fa36999f | |||
5b8cd24863 | |||
![]() |
00073651d4 | ||
eb030204f1 | |||
![]() |
56005ef499 | ||
b6d6d8a1aa | |||
91ecc53994 | |||
0037e08b06 | |||
b6b20c4d92 | |||
![]() |
d486ee2dbd | ||
9ba6b64efa | |||
e4ca6b93ad | |||
77d7cae266 | |||
f4e0a19d4f | |||
053082e9d8 | |||
![]() |
ddd4b2b785 | ||
e5a1cadb2f | |||
c18675b12c | |||
64fc0e34e6 | |||
dba3fb9e09 | |||
3e695a27cd | |||
a1063fc6c2 | |||
b414322f26 | |||
899eefd1bb | |||
72607feb91 | |||
870bcf6e1a | |||
8b78510fc4 | |||
e0bc5c4087 | |||
1fd653dd82 | |||
d9aae38bc8 | |||
efad9bcdda | |||
b5d7fb813f | |||
bb16f96973 | |||
7197017ea9 | |||
ed6fd01ba9 | |||
826bed4349 | |||
797f6e1483 | |||
e011e4ce76 | |||
92f8a6ac21 | |||
7b8d812277 | |||
2ae4e860f6 | |||
2ef192a55b | |||
a51f8f94d5 | |||
17f72be3cb | |||
2a868d277e | |||
b60a72eaab | |||
2dcb6782e0 | |||
4d64de2853 | |||
5af7225816 | |||
925df8ef26 | |||
2ee575fc1f | |||
1f55786791 | |||
a9dfde7b49 | |||
0ea0ccc4ff | |||
81366b7d2c | |||
dc960a81d1 | |||
4f8edc8e7f | |||
b8ae30e9e3 | |||
ae28ceb9d8 | |||
05b685989b | |||
7654203cc8 | |||
2489f72d79 | |||
730a46e87d | |||
f944121700 | |||
21de669141 | |||
5b176b66da | |||
a55b73417f | |||
ea6d099082 | |||
34f99bc6be | |||
83dab8bf98 | |||
4cc8f09843 | |||
3e2e8f437c | |||
7e5df11cac | |||
0d756bd4be | |||
dedf834884 |
@@ -265,4 +265,5 @@ ForEachMacros:
|
|||||||
- VECTOR_SET_SLOT_PROBING_BEGIN
|
- VECTOR_SET_SLOT_PROBING_BEGIN
|
||||||
|
|
||||||
StatementMacros:
|
StatementMacros:
|
||||||
|
- PyObject_HEAD
|
||||||
- PyObject_VAR_HEAD
|
- PyObject_VAR_HEAD
|
||||||
|
@@ -836,7 +836,7 @@ if(WITH_PYTHON)
|
|||||||
# because UNIX will search for the old Python paths which may not exist.
|
# because UNIX will search for the old Python paths which may not exist.
|
||||||
# giving errors about missing paths before this case is met.
|
# giving errors about missing paths before this case is met.
|
||||||
if(DEFINED PYTHON_VERSION AND "${PYTHON_VERSION}" VERSION_LESS "3.9")
|
if(DEFINED PYTHON_VERSION AND "${PYTHON_VERSION}" VERSION_LESS "3.9")
|
||||||
message(FATAL_ERROR "At least Python 3.9 is required to build")
|
message(FATAL_ERROR "At least Python 3.9 is required to build, but found Python ${PYTHON_VERSION}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/scripts/addons")
|
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/scripts/addons")
|
||||||
|
@@ -43,6 +43,12 @@ endif()
|
|||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(EMBREE_BUILD_DIR ${BUILD_MODE}/)
|
set(EMBREE_BUILD_DIR ${BUILD_MODE}/)
|
||||||
|
if(BUILD_MODE STREQUAL Debug)
|
||||||
|
list(APPEND EMBREE_EXTRA_ARGS
|
||||||
|
-DEMBREE_TBBMALLOC_LIBRARY_NAME=tbbmalloc_debug
|
||||||
|
-DEMBREE_TBB_LIBRARY_NAME=tbb_debug
|
||||||
|
)
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
set(EMBREE_BUILD_DIR)
|
set(EMBREE_BUILD_DIR)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -22,6 +22,7 @@ if(WIN32)
|
|||||||
-DTBB_BUILD_TBBMALLOC_PROXY=On
|
-DTBB_BUILD_TBBMALLOC_PROXY=On
|
||||||
-DTBB_BUILD_STATIC=Off
|
-DTBB_BUILD_STATIC=Off
|
||||||
-DTBB_BUILD_TESTS=Off
|
-DTBB_BUILD_TESTS=Off
|
||||||
|
-DCMAKE_DEBUG_POSTFIX=_debug
|
||||||
)
|
)
|
||||||
set(TBB_LIBRARY tbb)
|
set(TBB_LIBRARY tbb)
|
||||||
set(TBB_STATIC_LIBRARY Off)
|
set(TBB_STATIC_LIBRARY Off)
|
||||||
@@ -55,17 +56,17 @@ if(WIN32)
|
|||||||
ExternalProject_Add_Step(external_tbb after_install
|
ExternalProject_Add_Step(external_tbb after_install
|
||||||
# findtbb.cmake in some deps *NEEDS* to find tbb_debug.lib even if they are not going to use it
|
# findtbb.cmake in some deps *NEEDS* to find tbb_debug.lib even if they are not going to use it
|
||||||
# to make that test pass, we place a copy with the right name in the lib folder.
|
# to make that test pass, we place a copy with the right name in the lib folder.
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.lib ${HARVEST_TARGET}/tbb/lib/tbb_debug.lib
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.lib ${LIBDIR}/tbb/lib/tbb_debug.lib
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_debug.lib
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.lib ${LIBDIR}/tbb/lib/tbbmalloc_debug.lib
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.dll ${HARVEST_TARGET}/tbb/lib/tbb_debug.dll
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbb.dll ${LIBDIR}/tbb/bin/tbb_debug.dll
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.dll ${HARVEST_TARGET}/tbb/lib/tbbmalloc_debug.dll
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbbmalloc.dll ${LIBDIR}/tbb/bin/tbbmalloc_debug.dll
|
||||||
# Normal collection of build artifacts
|
# Normal collection of build artifacts
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.lib ${HARVEST_TARGET}/tbb/lib/tbb.lib
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.lib ${HARVEST_TARGET}/tbb/lib/tbb.lib
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.dll ${HARVEST_TARGET}/tbb/lib/tbb.dll
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbb.dll ${HARVEST_TARGET}/tbb/bin/tbb.dll
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc.lib
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc.lib
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.dll ${HARVEST_TARGET}/tbb/lib/tbbmalloc.dll
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbbmalloc.dll ${HARVEST_TARGET}/tbb/bin/tbbmalloc.dll
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_proxy.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_proxy.lib
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_proxy.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_proxy.lib
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_proxy.dll ${HARVEST_TARGET}/tbb/lib/tbbmalloc_proxy.dll
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbbmalloc_proxy.dll ${HARVEST_TARGET}/tbb/bin/tbbmalloc_proxy.dll
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/tbb/include/ ${HARVEST_TARGET}/tbb/include/
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/tbb/include/ ${HARVEST_TARGET}/tbb/include/
|
||||||
DEPENDEES install
|
DEPENDEES install
|
||||||
)
|
)
|
||||||
@@ -76,11 +77,12 @@ if(WIN32)
|
|||||||
# to make that test pass, we place a copy with the right name in the lib folder.
|
# to make that test pass, we place a copy with the right name in the lib folder.
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_debug.lib ${LIBDIR}/tbb/lib/tbb.lib
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_debug.lib ${LIBDIR}/tbb/lib/tbb.lib
|
||||||
# Normal collection of build artifacts
|
# Normal collection of build artifacts
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_debug.lib ${HARVEST_TARGET}/tbb/lib/debug/tbb_debug.lib
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_debug.lib ${HARVEST_TARGET}/tbb/lib/tbb_debug.lib
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb_debug.dll ${HARVEST_TARGET}/tbb/lib/debug/tbb_debug.dll
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbb_debug.dll ${HARVEST_TARGET}/tbb/bin/tbb_debug.dll
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_proxy.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_proxy_debug.lib
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_debug.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_debug.lib
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.dll ${HARVEST_TARGET}/tbb/lib/debug/tbbmalloc.dll
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_proxy_debug.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_proxy_debug.lib
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc_proxy.dll ${HARVEST_TARGET}/tbb/lib/debug/tbbmalloc_proxy.dll
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbbmalloc_debug.dll ${HARVEST_TARGET}/tbb/bin/tbbmalloc_debug.dll
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/bin/tbbmalloc_proxy_debug.dll ${HARVEST_TARGET}/tbb/bin/tbbmalloc_proxy_debug.dll
|
||||||
DEPENDEES install
|
DEPENDEES install
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -432,9 +432,9 @@ set(USD_HASH 1dd1e2092d085ed393c1f7c450a4155a)
|
|||||||
set(USD_HASH_TYPE MD5)
|
set(USD_HASH_TYPE MD5)
|
||||||
set(USD_FILE usd-v${USD_VERSION}.tar.gz)
|
set(USD_FILE usd-v${USD_VERSION}.tar.gz)
|
||||||
|
|
||||||
set(OIDN_VERSION 1.3.0)
|
set(OIDN_VERSION 1.4.0)
|
||||||
set(OIDN_URI https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.src.tar.gz)
|
set(OIDN_URI https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.src.tar.gz)
|
||||||
set(OIDN_HASH 301a5a0958d375a942014df0679b9270)
|
set(OIDN_HASH 421824019becc5b664a22a2b98332bc5)
|
||||||
set(OIDN_HASH_TYPE MD5)
|
set(OIDN_HASH_TYPE MD5)
|
||||||
set(OIDN_FILE oidn-${OIDN_VERSION}.src.tar.gz)
|
set(OIDN_FILE oidn-${OIDN_VERSION}.src.tar.gz)
|
||||||
|
|
||||||
|
@@ -553,10 +553,10 @@ EMBREE_FORCE_BUILD=false
|
|||||||
EMBREE_FORCE_REBUILD=false
|
EMBREE_FORCE_REBUILD=false
|
||||||
EMBREE_SKIP=false
|
EMBREE_SKIP=false
|
||||||
|
|
||||||
OIDN_VERSION="1.3.0"
|
OIDN_VERSION="1.4.0"
|
||||||
OIDN_VERSION_SHORT="1.3"
|
OIDN_VERSION_SHORT="1.4"
|
||||||
OIDN_VERSION_MIN="1.3.0"
|
OIDN_VERSION_MIN="1.4.0"
|
||||||
OIDN_VERSION_MAX="1.4"
|
OIDN_VERSION_MAX="1.5"
|
||||||
OIDN_FORCE_BUILD=false
|
OIDN_FORCE_BUILD=false
|
||||||
OIDN_FORCE_REBUILD=false
|
OIDN_FORCE_REBUILD=false
|
||||||
OIDN_SKIP=false
|
OIDN_SKIP=false
|
||||||
@@ -565,7 +565,7 @@ ISPC_VERSION="1.14.1"
|
|||||||
|
|
||||||
FFMPEG_VERSION="4.4"
|
FFMPEG_VERSION="4.4"
|
||||||
FFMPEG_VERSION_SHORT="4.4"
|
FFMPEG_VERSION_SHORT="4.4"
|
||||||
FFMPEG_VERSION_MIN="4.4"
|
FFMPEG_VERSION_MIN="3.0"
|
||||||
FFMPEG_VERSION_MAX="5.0"
|
FFMPEG_VERSION_MAX="5.0"
|
||||||
FFMPEG_FORCE_BUILD=false
|
FFMPEG_FORCE_BUILD=false
|
||||||
FFMPEG_FORCE_REBUILD=false
|
FFMPEG_FORCE_REBUILD=false
|
||||||
|
@@ -1,33 +1,3 @@
|
|||||||
diff -Naur oidn-1.3.0/cmake/FindTBB.cmake external_openimagedenoise/cmake/FindTBB.cmake
|
|
||||||
--- oidn-1.3.0/cmake/FindTBB.cmake 2021-02-04 16:20:26 -0700
|
|
||||||
+++ external_openimagedenoise/cmake/FindTBB.cmake 2021-02-12 09:35:53 -0700
|
|
||||||
@@ -332,20 +332,22 @@
|
|
||||||
${TBB_ROOT}/lib/${TBB_ARCH}/${TBB_VCVER}
|
|
||||||
${TBB_ROOT}/lib
|
|
||||||
)
|
|
||||||
-
|
|
||||||
# On Windows, also search the DLL so that the client may install it.
|
|
||||||
file(GLOB DLL_NAMES
|
|
||||||
${TBB_ROOT}/bin/${TBB_ARCH}/${TBB_VCVER}/${LIB_NAME}.dll
|
|
||||||
${TBB_ROOT}/bin/${LIB_NAME}.dll
|
|
||||||
+ ${TBB_ROOT}/lib/${LIB_NAME}.dll
|
|
||||||
${TBB_ROOT}/redist/${TBB_ARCH}/${TBB_VCVER}/${LIB_NAME}.dll
|
|
||||||
${TBB_ROOT}/redist/${TBB_ARCH}/${TBB_VCVER}/${LIB_NAME_GLOB1}.dll
|
|
||||||
${TBB_ROOT}/redist/${TBB_ARCH}/${TBB_VCVER}/${LIB_NAME_GLOB2}.dll
|
|
||||||
${TBB_ROOT}/../redist/${TBB_ARCH}/tbb/${TBB_VCVER}/${LIB_NAME}.dll
|
|
||||||
${TBB_ROOT}/../redist/${TBB_ARCH}_win/tbb/${TBB_VCVER}/${LIB_NAME}.dll
|
|
||||||
)
|
|
||||||
- list(GET DLL_NAMES 0 DLL_NAME)
|
|
||||||
- get_filename_component(${BIN_DIR_VAR} "${DLL_NAME}" DIRECTORY)
|
|
||||||
- set(${DLL_VAR} "${DLL_NAME}" CACHE PATH "${COMPONENT_NAME} ${BUILD_CONFIG} dll path")
|
|
||||||
+ if (DLL_NAMES)
|
|
||||||
+ list(GET DLL_NAMES 0 DLL_NAME)
|
|
||||||
+ get_filename_component(${BIN_DIR_VAR} "${DLL_NAME}" DIRECTORY)
|
|
||||||
+ set(${DLL_VAR} "${DLL_NAME}" CACHE PATH "${COMPONENT_NAME} ${BUILD_CONFIG} dll path")
|
|
||||||
+ endif()
|
|
||||||
elseif(APPLE)
|
|
||||||
set(LIB_PATHS ${TBB_ROOT}/lib)
|
|
||||||
else()
|
|
||||||
--- external_openimagedenoise/cmake/oidn_ispc.cmake 2021-02-15 17:29:34.000000000 +0100
|
--- external_openimagedenoise/cmake/oidn_ispc.cmake 2021-02-15 17:29:34.000000000 +0100
|
||||||
+++ external_openimagedenoise/cmake/oidn_ispc.cmake2 2021-02-15 17:29:28.000000000 +0100
|
+++ external_openimagedenoise/cmake/oidn_ispc.cmake2 2021-02-15 17:29:28.000000000 +0100
|
||||||
@@ -98,7 +98,7 @@
|
@@ -98,7 +98,7 @@
|
||||||
|
@@ -20,8 +20,24 @@ if(NOT CLANG_ROOT_DIR AND NOT $ENV{CLANG_ROOT_DIR} STREQUAL "")
|
|||||||
set(CLANG_ROOT_DIR $ENV{CLANG_ROOT_DIR})
|
set(CLANG_ROOT_DIR $ENV{CLANG_ROOT_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT LLVM_ROOT_DIR)
|
||||||
|
if(DEFINED LLVM_VERSION)
|
||||||
|
message(running llvm-config-${LLVM_VERSION})
|
||||||
|
find_program(LLVM_CONFIG llvm-config-${LLVM_VERSION})
|
||||||
|
endif()
|
||||||
|
if(NOT LLVM_CONFIG)
|
||||||
|
find_program(LLVM_CONFIG llvm-config)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(COMMAND ${LLVM_CONFIG} --prefix
|
||||||
|
OUTPUT_VARIABLE LLVM_ROOT_DIR
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
set(LLVM_ROOT_DIR ${LLVM_ROOT_DIR} CACHE PATH "Path to the LLVM installation")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(_CLANG_SEARCH_DIRS
|
set(_CLANG_SEARCH_DIRS
|
||||||
${CLANG_ROOT_DIR}
|
${CLANG_ROOT_DIR}
|
||||||
|
${LLVM_ROOT_DIR}
|
||||||
/opt/lib/clang
|
/opt/lib/clang
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -472,8 +472,7 @@ if(NOT GFLAGS_FOUND)
|
|||||||
gflags_report_not_found(
|
gflags_report_not_found(
|
||||||
"Could not find gflags include directory, set GFLAGS_INCLUDE_DIR "
|
"Could not find gflags include directory, set GFLAGS_INCLUDE_DIR "
|
||||||
"to directory containing gflags/gflags.h")
|
"to directory containing gflags/gflags.h")
|
||||||
endif(NOT GFLAGS_INCLUDE_DIR OR
|
endif()
|
||||||
NOT EXISTS ${GFLAGS_INCLUDE_DIR})
|
|
||||||
|
|
||||||
find_library(GFLAGS_LIBRARY NAMES gflags
|
find_library(GFLAGS_LIBRARY NAMES gflags
|
||||||
PATHS ${GFLAGS_LIBRARY_DIR_HINTS}
|
PATHS ${GFLAGS_LIBRARY_DIR_HINTS}
|
||||||
@@ -484,8 +483,7 @@ if(NOT GFLAGS_FOUND)
|
|||||||
gflags_report_not_found(
|
gflags_report_not_found(
|
||||||
"Could not find gflags library, set GFLAGS_LIBRARY "
|
"Could not find gflags library, set GFLAGS_LIBRARY "
|
||||||
"to full path to libgflags.")
|
"to full path to libgflags.")
|
||||||
endif(NOT GFLAGS_LIBRARY OR
|
endif()
|
||||||
NOT EXISTS ${GFLAGS_LIBRARY})
|
|
||||||
|
|
||||||
# gflags typically requires a threading library (which is OS dependent), note
|
# gflags typically requires a threading library (which is OS dependent), note
|
||||||
# that this defines the CMAKE_THREAD_LIBS_INIT variable. If we are able to
|
# that this defines the CMAKE_THREAD_LIBS_INIT variable. If we are able to
|
||||||
@@ -560,8 +558,7 @@ if(NOT GFLAGS_FOUND)
|
|||||||
gflags_report_not_found(
|
gflags_report_not_found(
|
||||||
"Caller defined GFLAGS_INCLUDE_DIR:"
|
"Caller defined GFLAGS_INCLUDE_DIR:"
|
||||||
" ${GFLAGS_INCLUDE_DIR} does not contain gflags/gflags.h header.")
|
" ${GFLAGS_INCLUDE_DIR} does not contain gflags/gflags.h header.")
|
||||||
endif(GFLAGS_INCLUDE_DIR AND
|
endif()
|
||||||
NOT EXISTS ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
|
|
||||||
# TODO: This regex for gflags library is pretty primitive, we use lowercase
|
# TODO: This regex for gflags library is pretty primitive, we use lowercase
|
||||||
# for comparison to handle Windows using CamelCase library names, could
|
# for comparison to handle Windows using CamelCase library names, could
|
||||||
# this check be better?
|
# this check be better?
|
||||||
@@ -571,8 +568,7 @@ if(NOT GFLAGS_FOUND)
|
|||||||
gflags_report_not_found(
|
gflags_report_not_found(
|
||||||
"Caller defined GFLAGS_LIBRARY: "
|
"Caller defined GFLAGS_LIBRARY: "
|
||||||
"${GFLAGS_LIBRARY} does not match gflags.")
|
"${GFLAGS_LIBRARY} does not match gflags.")
|
||||||
endif(GFLAGS_LIBRARY AND
|
endif()
|
||||||
NOT "${LOWERCASE_GFLAGS_LIBRARY}" MATCHES ".*gflags[^/]*")
|
|
||||||
|
|
||||||
gflags_reset_find_library_prefix()
|
gflags_reset_find_library_prefix()
|
||||||
|
|
||||||
|
@@ -40,7 +40,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(NanoVDB DEFAULT_MSG
|
|||||||
|
|
||||||
IF(NANOVDB_FOUND)
|
IF(NANOVDB_FOUND)
|
||||||
SET(NANOVDB_INCLUDE_DIRS ${NANOVDB_INCLUDE_DIR})
|
SET(NANOVDB_INCLUDE_DIRS ${NANOVDB_INCLUDE_DIR})
|
||||||
ENDIF(NANOVDB_FOUND)
|
ENDIF()
|
||||||
|
|
||||||
MARK_AS_ADVANCED(
|
MARK_AS_ADVANCED(
|
||||||
NANOVDB_INCLUDE_DIR
|
NANOVDB_INCLUDE_DIR
|
||||||
|
@@ -46,7 +46,7 @@ SET(_opencollada_FIND_COMPONENTS
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Fedora openCOLLADA package links these statically
|
# Fedora openCOLLADA package links these statically
|
||||||
# note that order is important here ot it wont link
|
# note that order is important here or it won't link
|
||||||
SET(_opencollada_FIND_STATIC_COMPONENTS
|
SET(_opencollada_FIND_STATIC_COMPONENTS
|
||||||
buffer
|
buffer
|
||||||
ftoa
|
ftoa
|
||||||
|
@@ -44,7 +44,7 @@ SET(PYTHON_LINKFLAGS "-Xlinker -export-dynamic" CACHE STRING "Linker flags for p
|
|||||||
MARK_AS_ADVANCED(PYTHON_LINKFLAGS)
|
MARK_AS_ADVANCED(PYTHON_LINKFLAGS)
|
||||||
|
|
||||||
|
|
||||||
# if the user passes these defines as args, we dont want to overwrite
|
# if the user passes these defines as args, we don't want to overwrite
|
||||||
SET(_IS_INC_DEF OFF)
|
SET(_IS_INC_DEF OFF)
|
||||||
SET(_IS_INC_CONF_DEF OFF)
|
SET(_IS_INC_CONF_DEF OFF)
|
||||||
SET(_IS_LIB_DEF OFF)
|
SET(_IS_LIB_DEF OFF)
|
||||||
@@ -143,7 +143,7 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_
|
|||||||
SET(_PYTHON_ABI_FLAGS "${_CURRENT_ABI_FLAGS}")
|
SET(_PYTHON_ABI_FLAGS "${_CURRENT_ABI_FLAGS}")
|
||||||
break()
|
break()
|
||||||
ELSE()
|
ELSE()
|
||||||
# ensure we dont find values from 2 different ABI versions
|
# ensure we don't find values from 2 different ABI versions
|
||||||
IF(NOT _IS_INC_DEF)
|
IF(NOT _IS_INC_DEF)
|
||||||
UNSET(PYTHON_INCLUDE_DIR CACHE)
|
UNSET(PYTHON_INCLUDE_DIR CACHE)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
@@ -40,7 +40,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(sse2neon DEFAULT_MSG
|
|||||||
|
|
||||||
IF(SSE2NEON_FOUND)
|
IF(SSE2NEON_FOUND)
|
||||||
SET(SSE2NEON_INCLUDE_DIRS ${SSE2NEON_INCLUDE_DIR})
|
SET(SSE2NEON_INCLUDE_DIRS ${SSE2NEON_INCLUDE_DIR})
|
||||||
ENDIF(SSE2NEON_FOUND)
|
ENDIF()
|
||||||
|
|
||||||
MARK_AS_ADVANCED(
|
MARK_AS_ADVANCED(
|
||||||
SSE2NEON_INCLUDE_DIR
|
SSE2NEON_INCLUDE_DIR
|
||||||
|
@@ -305,7 +305,7 @@ def file_check_arg_sizes(tu):
|
|||||||
for i, node_child in enumerate(children):
|
for i, node_child in enumerate(children):
|
||||||
children = list(node_child.get_children())
|
children = list(node_child.get_children())
|
||||||
|
|
||||||
# skip if we dont have an index...
|
# skip if we don't have an index...
|
||||||
size_def = args_size_definition.get(i, -1)
|
size_def = args_size_definition.get(i, -1)
|
||||||
|
|
||||||
if size_def == -1:
|
if size_def == -1:
|
||||||
@@ -354,7 +354,7 @@ def file_check_arg_sizes(tu):
|
|||||||
filepath # always the same but useful when running threaded
|
filepath # always the same but useful when running threaded
|
||||||
))
|
))
|
||||||
|
|
||||||
# we dont really care what we are looking at, just scan entire file for
|
# we don't really care what we are looking at, just scan entire file for
|
||||||
# function calls.
|
# function calls.
|
||||||
|
|
||||||
def recursive_func_call_check(node):
|
def recursive_func_call_check(node):
|
||||||
|
@@ -596,14 +596,6 @@ function(SETUP_LIBDIRS)
|
|||||||
link_directories(${GMP_LIBPATH})
|
link_directories(${GMP_LIBPATH})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_GHOST_WAYLAND)
|
|
||||||
link_directories(
|
|
||||||
${wayland-client_LIBRARY_DIRS}
|
|
||||||
${wayland-egl_LIBRARY_DIRS}
|
|
||||||
${xkbcommon_LIBRARY_DIRS}
|
|
||||||
${wayland-cursor_LIBRARY_DIRS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WIN32 AND NOT UNIX)
|
if(WIN32 AND NOT UNIX)
|
||||||
link_directories(${PTHREADS_LIBPATH})
|
link_directories(${PTHREADS_LIBPATH})
|
||||||
endif()
|
endif()
|
||||||
@@ -702,7 +694,7 @@ macro(message_first_run)
|
|||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
# when we have warnings as errors applied globally this
|
# when we have warnings as errors applied globally this
|
||||||
# needs to be removed for some external libs which we dont maintain.
|
# needs to be removed for some external libs which we don't maintain.
|
||||||
|
|
||||||
# utility macro
|
# utility macro
|
||||||
macro(remove_cc_flag
|
macro(remove_cc_flag
|
||||||
@@ -802,7 +794,7 @@ macro(remove_extra_strict_flags)
|
|||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
# note, we can only append flags on a single file so we need to negate the options.
|
# note, we can only append flags on a single file so we need to negate the options.
|
||||||
# at the moment we cant shut up ffmpeg deprecations, so use this, but will
|
# at the moment we can't shut up ffmpeg deprecations, so use this, but will
|
||||||
# probably add more removals here.
|
# probably add more removals here.
|
||||||
macro(remove_strict_c_flags_file
|
macro(remove_strict_c_flags_file
|
||||||
filenames)
|
filenames)
|
||||||
@@ -971,14 +963,6 @@ macro(blender_project_hack_post)
|
|||||||
unset(_reset_standard_cflags_rel)
|
unset(_reset_standard_cflags_rel)
|
||||||
unset(_reset_standard_cxxflags_rel)
|
unset(_reset_standard_cxxflags_rel)
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# workaround for omission in cmake 2.8.4's GNU.cmake, fixed in 2.8.5
|
|
||||||
if(CMAKE_COMPILER_IS_GNUCC)
|
|
||||||
if(NOT DARWIN)
|
|
||||||
set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
# pair of macros to allow libraries to be specify files to install, but to
|
# pair of macros to allow libraries to be specify files to install, but to
|
||||||
|
@@ -388,6 +388,10 @@ endif()
|
|||||||
|
|
||||||
if(WITH_TBB)
|
if(WITH_TBB)
|
||||||
find_package(TBB)
|
find_package(TBB)
|
||||||
|
if(NOT TBB_FOUND)
|
||||||
|
message(WARNING "TBB not found, disabling WITH_TBB")
|
||||||
|
set(WITH_TBB OFF)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_POTRACE)
|
if(WITH_POTRACE)
|
||||||
|
@@ -457,6 +457,10 @@ endif()
|
|||||||
|
|
||||||
if(WITH_TBB)
|
if(WITH_TBB)
|
||||||
find_package_wrapper(TBB)
|
find_package_wrapper(TBB)
|
||||||
|
if(NOT TBB_FOUND)
|
||||||
|
message(WARNING "TBB not found, disabling WITH_TBB")
|
||||||
|
set(WITH_TBB OFF)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_XR_OPENXR)
|
if(WITH_XR_OPENXR)
|
||||||
@@ -575,17 +579,17 @@ if(WITH_GHOST_WAYLAND)
|
|||||||
pkg_check_modules(wayland-scanner REQUIRED wayland-scanner)
|
pkg_check_modules(wayland-scanner REQUIRED wayland-scanner)
|
||||||
pkg_check_modules(xkbcommon REQUIRED xkbcommon)
|
pkg_check_modules(xkbcommon REQUIRED xkbcommon)
|
||||||
pkg_check_modules(wayland-cursor REQUIRED wayland-cursor)
|
pkg_check_modules(wayland-cursor REQUIRED wayland-cursor)
|
||||||
|
pkg_check_modules(dbus REQUIRED dbus-1)
|
||||||
|
|
||||||
set(WITH_GL_EGL ON)
|
set(WITH_GL_EGL ON)
|
||||||
|
|
||||||
if(WITH_GHOST_WAYLAND)
|
list(APPEND PLATFORM_LINKLIBS
|
||||||
list(APPEND PLATFORM_LINKLIBS
|
${wayland-client_LINK_LIBRARIES}
|
||||||
${wayland-client_LIBRARIES}
|
${wayland-egl_LINK_LIBRARIES}
|
||||||
${wayland-egl_LIBRARIES}
|
${xkbcommon_LINK_LIBRARIES}
|
||||||
${xkbcommon_LIBRARIES}
|
${wayland-cursor_LINK_LIBRARIES}
|
||||||
${wayland-cursor_LIBRARIES}
|
${dbus_LINK_LIBRARIES}
|
||||||
)
|
)
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_GHOST_X11)
|
if(WITH_GHOST_X11)
|
||||||
|
@@ -261,8 +261,10 @@ if(NOT DEFINED LIBDIR)
|
|||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "32 bit compiler detected, blender no longer provides pre-build libraries for 32 bit windows, please set the LIBDIR cmake variable to your own library folder")
|
message(FATAL_ERROR "32 bit compiler detected, blender no longer provides pre-build libraries for 32 bit windows, please set the LIBDIR cmake variable to your own library folder")
|
||||||
endif()
|
endif()
|
||||||
# Can be 1910..1912
|
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30130)
|
||||||
if(MSVC_VERSION GREATER 1919)
|
message(STATUS "Visual Studio 2022 detected.")
|
||||||
|
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
||||||
|
elseif(MSVC_VERSION GREATER 1919)
|
||||||
message(STATUS "Visual Studio 2019 detected.")
|
message(STATUS "Visual Studio 2019 detected.")
|
||||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
||||||
elseif(MSVC_VERSION GREATER 1909)
|
elseif(MSVC_VERSION GREATER 1909)
|
||||||
@@ -548,7 +550,6 @@ if(WITH_OPENIMAGEIO)
|
|||||||
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
|
set(OPENIMAGEIO_LIBRARIES ${OIIO_OPTIMIZED} ${OIIO_DEBUG})
|
||||||
|
|
||||||
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
|
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
|
||||||
set(OPENCOLORIO_DEFINITIONS "-DDOpenColorIO_SKIP_IMPORTS")
|
|
||||||
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
|
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
|
||||||
add_definitions(-DOIIO_STATIC_DEFINE)
|
add_definitions(-DOIIO_STATIC_DEFINE)
|
||||||
add_definitions(-DOIIO_NO_SSE=1)
|
add_definitions(-DOIIO_NO_SSE=1)
|
||||||
@@ -594,7 +595,7 @@ if(WITH_OPENCOLORIO)
|
|||||||
debug ${OPENCOLORIO_LIBPATH}/libexpatdMD.lib
|
debug ${OPENCOLORIO_LIBPATH}/libexpatdMD.lib
|
||||||
debug ${OPENCOLORIO_LIBPATH}/pystring_d.lib
|
debug ${OPENCOLORIO_LIBPATH}/pystring_d.lib
|
||||||
)
|
)
|
||||||
set(OPENCOLORIO_DEFINITIONS)
|
set(OPENCOLORIO_DEFINITIONS "-DOpenColorIO_SKIP_IMPORTS")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_OPENVDB)
|
if(WITH_OPENVDB)
|
||||||
@@ -675,10 +676,11 @@ if(WITH_SYSTEM_AUDASPACE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_TBB)
|
if(WITH_TBB)
|
||||||
set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/debug/tbb_debug.lib)
|
set(TBB_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbb.lib debug ${LIBDIR}/tbb/lib/tbb_debug.lib)
|
||||||
set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
|
set(TBB_INCLUDE_DIR ${LIBDIR}/tbb/include)
|
||||||
set(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
|
set(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
|
||||||
if(WITH_TBB_MALLOC_PROXY)
|
if(WITH_TBB_MALLOC_PROXY)
|
||||||
|
set(TBB_MALLOC_LIBRARIES optimized ${LIBDIR}/tbb/lib/tbbmalloc.lib debug ${LIBDIR}/tbb/lib/tbbmalloc_debug.lib)
|
||||||
add_definitions(-DWITH_TBB_MALLOC)
|
add_definitions(-DWITH_TBB_MALLOC)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
@@ -15,6 +15,15 @@ if(WITH_WINDOWS_BUNDLE_CRT)
|
|||||||
|
|
||||||
include(InstallRequiredSystemLibraries)
|
include(InstallRequiredSystemLibraries)
|
||||||
|
|
||||||
|
# ucrtbase(d).dll cannot be in the manifest, due to the way windows 10 handles
|
||||||
|
# redirects for this dll, for details see T88813.
|
||||||
|
foreach(lib ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS})
|
||||||
|
string(FIND ${lib} "ucrtbase" pos)
|
||||||
|
if(NOT pos EQUAL -1)
|
||||||
|
list(REMOVE_ITEM CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS ${lib})
|
||||||
|
install(FILES ${lib} DESTINATION . COMPONENT Libraries)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
# Install the CRT to the blender.crt Sub folder.
|
# Install the CRT to the blender.crt Sub folder.
|
||||||
install(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION ./blender.crt COMPONENT Libraries)
|
install(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION ./blender.crt COMPONENT Libraries)
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
{ "path": "source/tools", "branch": "master", "commit_id": "HEAD" }
|
{ "path": "source/tools", "branch": "master", "commit_id": "HEAD" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"svn":
|
"svn":
|
||||||
{
|
{
|
||||||
"tests": { "path": "lib/tests", "branch": "trunk", "commit_id": "HEAD" },
|
"tests": { "path": "lib/tests", "branch": "trunk", "commit_id": "HEAD" },
|
||||||
"libraries":
|
"libraries":
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
"cmake":
|
"cmake":
|
||||||
{
|
{
|
||||||
"default":
|
"default":
|
||||||
{
|
{
|
||||||
"version": "any",
|
"version": "any",
|
||||||
"overrides":
|
"overrides":
|
||||||
{
|
{
|
||||||
@@ -58,28 +58,28 @@
|
|||||||
{
|
{
|
||||||
"overrides":
|
"overrides":
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"darwin-arm64":
|
"darwin-arm64":
|
||||||
{
|
{
|
||||||
"overrides":
|
"overrides":
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"linux-x86_64":
|
"linux-x86_64":
|
||||||
{
|
{
|
||||||
"overrides":
|
"overrides":
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"windows-amd64":
|
"windows-amd64":
|
||||||
{
|
{
|
||||||
"overrides":
|
"overrides":
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,9 @@ if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
|||||||
call "%~dp0\detect_msvc2019.cmd"
|
call "%~dp0\detect_msvc2019.cmd"
|
||||||
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
||||||
|
|
||||||
|
call "%~dp0\detect_msvc2022.cmd"
|
||||||
|
if %ERRORLEVEL% EQU 0 goto DetectionComplete
|
||||||
|
|
||||||
echo Compiler Detection failed. Use verbose switch for more information.
|
echo Compiler Detection failed. Use verbose switch for more information.
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc15
|
if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc15
|
||||||
if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
|
if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
|
||||||
|
if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
|
||||||
|
|
||||||
set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
|
set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
|
||||||
set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
|
set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
|
||||||
|
@@ -19,10 +19,10 @@ if "%WITH_PYDEBUG%"=="1" (
|
|||||||
set PYDEBUG_CMAKE_ARGS=-DWINDOWS_PYTHON_DEBUG=On
|
set PYDEBUG_CMAKE_ARGS=-DWINDOWS_PYTHON_DEBUG=On
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%BUILD_VS_YEAR%"=="2019" (
|
if "%BUILD_VS_YEAR%"=="2017" (
|
||||||
set BUILD_PLATFORM_SELECT=-A %MSBUILD_PLATFORM%
|
|
||||||
) else (
|
|
||||||
set BUILD_GENERATOR_POST=%WINDOWS_ARCH%
|
set BUILD_GENERATOR_POST=%WINDOWS_ARCH%
|
||||||
|
) else (
|
||||||
|
set BUILD_PLATFORM_SELECT=-A %MSBUILD_PLATFORM%
|
||||||
)
|
)
|
||||||
|
|
||||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%BUILD_GENERATOR_POST%" %BUILD_PLATFORM_SELECT% %TESTS_CMAKE_ARGS% %CLANG_CMAKE_ARGS% %ASAN_CMAKE_ARGS% %PYDEBUG_CMAKE_ARGS%
|
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%BUILD_GENERATOR_POST%" %BUILD_PLATFORM_SELECT% %TESTS_CMAKE_ARGS% %CLANG_CMAKE_ARGS% %ASAN_CMAKE_ARGS% %PYDEBUG_CMAKE_ARGS%
|
||||||
|
3
build_files/windows/detect_msvc2022.cmd
Normal file
3
build_files/windows/detect_msvc2022.cmd
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
set BUILD_VS_VER=17
|
||||||
|
set BUILD_VS_YEAR=2022
|
||||||
|
call "%~dp0\detect_msvc_vswhere.cmd"
|
@@ -66,6 +66,14 @@ if NOT "%1" == "" (
|
|||||||
) else if "%1" == "2019b" (
|
) else if "%1" == "2019b" (
|
||||||
set BUILD_VS_YEAR=2019
|
set BUILD_VS_YEAR=2019
|
||||||
set VSWHERE_ARGS=-products Microsoft.VisualStudio.Product.BuildTools
|
set VSWHERE_ARGS=-products Microsoft.VisualStudio.Product.BuildTools
|
||||||
|
) else if "%1" == "2022" (
|
||||||
|
set BUILD_VS_YEAR=2022
|
||||||
|
) else if "%1" == "2022pre" (
|
||||||
|
set BUILD_VS_YEAR=2022
|
||||||
|
set VSWHERE_ARGS=-prerelease
|
||||||
|
) else if "%1" == "2022b" (
|
||||||
|
set BUILD_VS_YEAR=2022
|
||||||
|
set VSWHERE_ARGS=-products Microsoft.VisualStudio.Product.BuildTools
|
||||||
) else if "%1" == "packagename" (
|
) else if "%1" == "packagename" (
|
||||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
|
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
|
||||||
shift /1
|
shift /1
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Doxyfile 1.8.16
|
# Doxyfile 1.9.1
|
||||||
|
|
||||||
# This file describes the settings to be used by the documentation system
|
# This file describes the settings to be used by the documentation system
|
||||||
# doxygen (www.doxygen.org) for a project.
|
# doxygen (www.doxygen.org) for a project.
|
||||||
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = "V3.0"
|
PROJECT_NUMBER = V3.0
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
@@ -227,6 +227,14 @@ QT_AUTOBRIEF = NO
|
|||||||
|
|
||||||
MULTILINE_CPP_IS_BRIEF = NO
|
MULTILINE_CPP_IS_BRIEF = NO
|
||||||
|
|
||||||
|
# By default Python docstrings are displayed as preformatted text and doxygen's
|
||||||
|
# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
|
||||||
|
# doxygen's special commands can be used and the contents of the docstring
|
||||||
|
# documentation blocks is shown as doxygen documentation.
|
||||||
|
# The default value is: YES.
|
||||||
|
|
||||||
|
PYTHON_DOCSTRING = YES
|
||||||
|
|
||||||
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
|
||||||
# documentation from any documented member that it re-implements.
|
# documentation from any documented member that it re-implements.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
@@ -263,12 +271,6 @@ TAB_SIZE = 4
|
|||||||
|
|
||||||
ALIASES =
|
ALIASES =
|
||||||
|
|
||||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
|
||||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
|
||||||
# will allow you to use the command class in the itcl::class meaning.
|
|
||||||
|
|
||||||
TCL_SUBST =
|
|
||||||
|
|
||||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||||
# only. Doxygen will then generate output that is more tailored for C. For
|
# only. Doxygen will then generate output that is more tailored for C. For
|
||||||
# instance, some of the names that are used will be different. The list of all
|
# instance, some of the names that are used will be different. The list of all
|
||||||
@@ -309,19 +311,22 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
|||||||
# parses. With this tag you can assign which parser to use for a given
|
# parses. With this tag you can assign which parser to use for a given
|
||||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
|
||||||
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
|
# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
|
||||||
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
|
||||||
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
|
||||||
# tries to guess whether the code is fixed or free formatted code, this is the
|
# tries to guess whether the code is fixed or free formatted code, this is the
|
||||||
# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
|
# default for Fortran type files). For instance to make doxygen treat .inc files
|
||||||
# .inc files as Fortran files (default is PHP), and .f files as C (default is
|
# as Fortran files (default is PHP), and .f files as C (default is Fortran),
|
||||||
# Fortran), use: inc=Fortran f=C.
|
# use: inc=Fortran f=C.
|
||||||
#
|
#
|
||||||
# Note: For files without extension you can use no_extension as a placeholder.
|
# Note: For files without extension you can use no_extension as a placeholder.
|
||||||
#
|
#
|
||||||
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
|
||||||
# the files are not read by doxygen.
|
# the files are not read by doxygen. When specifying no_extension you should add
|
||||||
|
# * to the FILE_PATTERNS.
|
||||||
|
#
|
||||||
|
# Note see also the list of default file extension mappings.
|
||||||
|
|
||||||
EXTENSION_MAPPING =
|
EXTENSION_MAPPING =
|
||||||
|
|
||||||
@@ -455,6 +460,19 @@ TYPEDEF_HIDES_STRUCT = NO
|
|||||||
|
|
||||||
LOOKUP_CACHE_SIZE = 3
|
LOOKUP_CACHE_SIZE = 3
|
||||||
|
|
||||||
|
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
|
||||||
|
# during processing. When set to 0 doxygen will based this on the number of
|
||||||
|
# cores available in the system. You can set it explicitly to a value larger
|
||||||
|
# than 0 to get more control over the balance between CPU load and processing
|
||||||
|
# speed. At this moment only the input processing can be done using multiple
|
||||||
|
# threads. Since this is still an experimental feature the default is set to 1,
|
||||||
|
# which efficively disables parallel processing. Please report any issues you
|
||||||
|
# encounter. Generating dot graphs in parallel is controlled by the
|
||||||
|
# DOT_NUM_THREADS setting.
|
||||||
|
# Minimum value: 0, maximum value: 32, default value: 1.
|
||||||
|
|
||||||
|
NUM_PROC_THREADS = 1
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Build related configuration options
|
# Build related configuration options
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@@ -518,6 +536,13 @@ EXTRACT_LOCAL_METHODS = NO
|
|||||||
|
|
||||||
EXTRACT_ANON_NSPACES = NO
|
EXTRACT_ANON_NSPACES = NO
|
||||||
|
|
||||||
|
# If this flag is set to YES, the name of an unnamed parameter in a declaration
|
||||||
|
# will be determined by the corresponding definition. By default unnamed
|
||||||
|
# parameters remain unnamed in the output.
|
||||||
|
# The default value is: YES.
|
||||||
|
|
||||||
|
RESOLVE_UNNAMED_PARAMS = YES
|
||||||
|
|
||||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
|
||||||
# undocumented members inside documented classes or files. If set to NO these
|
# undocumented members inside documented classes or files. If set to NO these
|
||||||
# members will be included in the various overviews, but no documentation
|
# members will be included in the various overviews, but no documentation
|
||||||
@@ -535,8 +560,8 @@ HIDE_UNDOC_MEMBERS = NO
|
|||||||
HIDE_UNDOC_CLASSES = NO
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
|
||||||
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
|
||||||
# (class|struct|union) declarations. If set to NO, these declarations will be
|
# declarations. If set to NO, these declarations will be included in the
|
||||||
# included in the documentation.
|
# documentation.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
HIDE_FRIEND_COMPOUNDS = NO
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
@@ -555,11 +580,18 @@ HIDE_IN_BODY_DOCS = NO
|
|||||||
|
|
||||||
INTERNAL_DOCS = YES
|
INTERNAL_DOCS = YES
|
||||||
|
|
||||||
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
|
# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
|
||||||
# names in lower-case letters. If set to YES, upper-case letters are also
|
# able to match the capabilities of the underlying filesystem. In case the
|
||||||
# allowed. This is useful if you have classes or files whose names only differ
|
# filesystem is case sensitive (i.e. it supports files in the same directory
|
||||||
# in case and if your file system supports case sensitive file names. Windows
|
# whose names only differ in casing), the option must be set to YES to properly
|
||||||
# (including Cygwin) ands Mac users are advised to set this option to NO.
|
# deal with such files in case they appear in the input. For filesystems that
|
||||||
|
# are not case sensitive the option should be be set to NO to properly deal with
|
||||||
|
# output files written for symbols that only differ in casing, such as for two
|
||||||
|
# classes, one named CLASS and the other named Class, and to also support
|
||||||
|
# references to files without having to specify the exact matching casing. On
|
||||||
|
# Windows (including Cygwin) and MacOS, users should typically set this option
|
||||||
|
# to NO, whereas on Linux or other Unix flavors it should typically be set to
|
||||||
|
# YES.
|
||||||
# The default value is: system dependent.
|
# The default value is: system dependent.
|
||||||
|
|
||||||
CASE_SENSE_NAMES = YES
|
CASE_SENSE_NAMES = YES
|
||||||
@@ -798,7 +830,10 @@ WARN_IF_DOC_ERROR = YES
|
|||||||
WARN_NO_PARAMDOC = NO
|
WARN_NO_PARAMDOC = NO
|
||||||
|
|
||||||
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
|
||||||
# a warning is encountered.
|
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
|
||||||
|
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
|
||||||
|
# at the end of the doxygen process doxygen will return with a non-zero status.
|
||||||
|
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
WARN_AS_ERROR = NO
|
WARN_AS_ERROR = NO
|
||||||
@@ -840,8 +875,8 @@ INPUT = doxygen.main.h \
|
|||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
|
||||||
# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
|
# documentation (see:
|
||||||
# possible encodings.
|
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
|
||||||
# The default value is: UTF-8.
|
# The default value is: UTF-8.
|
||||||
|
|
||||||
INPUT_ENCODING = UTF-8
|
INPUT_ENCODING = UTF-8
|
||||||
@@ -854,11 +889,15 @@ INPUT_ENCODING = UTF-8
|
|||||||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||||
# read by doxygen.
|
# read by doxygen.
|
||||||
#
|
#
|
||||||
|
# Note the list of default checked file patterns might differ from the list of
|
||||||
|
# default file extension mappings.
|
||||||
|
#
|
||||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||||
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
|
||||||
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
|
||||||
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
|
||||||
|
# *.ucf, *.qsf and *.ice.
|
||||||
|
|
||||||
FILE_PATTERNS =
|
FILE_PATTERNS =
|
||||||
|
|
||||||
@@ -1086,13 +1125,6 @@ VERBATIM_HEADERS = YES
|
|||||||
|
|
||||||
ALPHABETICAL_INDEX = YES
|
ALPHABETICAL_INDEX = YES
|
||||||
|
|
||||||
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
|
||||||
# which the alphabetical index list will be split.
|
|
||||||
# Minimum value: 1, maximum value: 20, default value: 5.
|
|
||||||
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
|
|
||||||
|
|
||||||
COLS_IN_ALPHA_INDEX = 5
|
|
||||||
|
|
||||||
# In case all classes in a project start with a common prefix, all classes will
|
# In case all classes in a project start with a common prefix, all classes will
|
||||||
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
|
||||||
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
# can be used to specify a prefix (or a list of prefixes) that should be ignored
|
||||||
@@ -1231,9 +1263,9 @@ HTML_TIMESTAMP = YES
|
|||||||
|
|
||||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
||||||
# documentation will contain a main index with vertical navigation menus that
|
# documentation will contain a main index with vertical navigation menus that
|
||||||
# are dynamically created via Javascript. If disabled, the navigation index will
|
# are dynamically created via JavaScript. If disabled, the navigation index will
|
||||||
# consists of multiple levels of tabs that are statically embedded in every HTML
|
# consists of multiple levels of tabs that are statically embedded in every HTML
|
||||||
# page. Disable this option to support browsers that do not have Javascript,
|
# page. Disable this option to support browsers that do not have JavaScript,
|
||||||
# like the Qt help browser.
|
# like the Qt help browser.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
@@ -1263,10 +1295,11 @@ HTML_INDEX_NUM_ENTRIES = 100
|
|||||||
|
|
||||||
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
|
||||||
# generated that can be used as input for Apple's Xcode 3 integrated development
|
# generated that can be used as input for Apple's Xcode 3 integrated development
|
||||||
# environment (see: https://developer.apple.com/xcode/), introduced with OSX
|
# environment (see:
|
||||||
# 10.5 (Leopard). To create a documentation set, doxygen will generate a
|
# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
|
||||||
# Makefile in the HTML output directory. Running make will produce the docset in
|
# create a documentation set, doxygen will generate a Makefile in the HTML
|
||||||
# that directory and running make install will install the docset in
|
# output directory. Running make will produce the docset in that directory and
|
||||||
|
# running make install will install the docset in
|
||||||
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
|
||||||
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
|
||||||
# genXcode/_index.html for more information.
|
# genXcode/_index.html for more information.
|
||||||
@@ -1308,8 +1341,8 @@ DOCSET_PUBLISHER_NAME = Publisher
|
|||||||
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
|
||||||
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
|
||||||
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
|
||||||
# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
|
# (see:
|
||||||
# Windows.
|
# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
|
||||||
#
|
#
|
||||||
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
# The HTML Help Workshop contains a compiler that can convert all HTML output
|
||||||
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
|
||||||
@@ -1339,7 +1372,7 @@ CHM_FILE = blender.chm
|
|||||||
HHC_LOCATION = "C:/Program Files (x86)/HTML Help Workshop/hhc.exe"
|
HHC_LOCATION = "C:/Program Files (x86)/HTML Help Workshop/hhc.exe"
|
||||||
|
|
||||||
# The GENERATE_CHI flag controls if a separate .chi index file is generated
|
# The GENERATE_CHI flag controls if a separate .chi index file is generated
|
||||||
# (YES) or that it should be included in the master .chm file (NO).
|
# (YES) or that it should be included in the main .chm file (NO).
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||||
|
|
||||||
@@ -1384,7 +1417,8 @@ QCH_FILE =
|
|||||||
|
|
||||||
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
|
||||||
# Project output. For more information please see Qt Help Project / Namespace
|
# Project output. For more information please see Qt Help Project / Namespace
|
||||||
# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
# (see:
|
||||||
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
|
||||||
# The default value is: org.doxygen.Project.
|
# The default value is: org.doxygen.Project.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
@@ -1392,8 +1426,8 @@ QHP_NAMESPACE = org.doxygen.Project
|
|||||||
|
|
||||||
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
|
||||||
# Help Project output. For more information please see Qt Help Project / Virtual
|
# Help Project output. For more information please see Qt Help Project / Virtual
|
||||||
# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
|
# Folders (see:
|
||||||
# folders).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
|
||||||
# The default value is: doc.
|
# The default value is: doc.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
@@ -1401,16 +1435,16 @@ QHP_VIRTUAL_FOLDER = doc
|
|||||||
|
|
||||||
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
|
||||||
# filter to add. For more information please see Qt Help Project / Custom
|
# filter to add. For more information please see Qt Help Project / Custom
|
||||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
# Filters (see:
|
||||||
# filters).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHP_CUST_FILTER_NAME =
|
QHP_CUST_FILTER_NAME =
|
||||||
|
|
||||||
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
|
||||||
# custom filter to add. For more information please see Qt Help Project / Custom
|
# custom filter to add. For more information please see Qt Help Project / Custom
|
||||||
# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
|
# Filters (see:
|
||||||
# filters).
|
# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHP_CUST_FILTER_ATTRS =
|
QHP_CUST_FILTER_ATTRS =
|
||||||
@@ -1422,9 +1456,9 @@ QHP_CUST_FILTER_ATTRS =
|
|||||||
|
|
||||||
QHP_SECT_FILTER_ATTRS =
|
QHP_SECT_FILTER_ATTRS =
|
||||||
|
|
||||||
# The QHG_LOCATION tag can be used to specify the location of Qt's
|
# The QHG_LOCATION tag can be used to specify the location (absolute path
|
||||||
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
|
# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
|
||||||
# generated .qhp file.
|
# run qhelpgenerator on the generated .qhp file.
|
||||||
# This tag requires that the tag GENERATE_QHP is set to YES.
|
# This tag requires that the tag GENERATE_QHP is set to YES.
|
||||||
|
|
||||||
QHG_LOCATION =
|
QHG_LOCATION =
|
||||||
@@ -1501,6 +1535,17 @@ TREEVIEW_WIDTH = 246
|
|||||||
|
|
||||||
EXT_LINKS_IN_WINDOW = NO
|
EXT_LINKS_IN_WINDOW = NO
|
||||||
|
|
||||||
|
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
|
||||||
|
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
|
||||||
|
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
|
||||||
|
# the HTML output. These images will generally look nicer at scaled resolutions.
|
||||||
|
# Possible values are: png (the default) and svg (looks nicer but requires the
|
||||||
|
# pdf2svg or inkscape tool).
|
||||||
|
# The default value is: png.
|
||||||
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
|
HTML_FORMULA_FORMAT = png
|
||||||
|
|
||||||
# Use this tag to change the font size of LaTeX formulas included as images in
|
# Use this tag to change the font size of LaTeX formulas included as images in
|
||||||
# the HTML documentation. When you change the font size after a successful
|
# the HTML documentation. When you change the font size after a successful
|
||||||
# doxygen run you need to manually remove any form_*.png images from the HTML
|
# doxygen run you need to manually remove any form_*.png images from the HTML
|
||||||
@@ -1521,8 +1566,14 @@ FORMULA_FONTSIZE = 10
|
|||||||
|
|
||||||
FORMULA_TRANSPARENT = YES
|
FORMULA_TRANSPARENT = YES
|
||||||
|
|
||||||
|
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
|
||||||
|
# to create new LaTeX commands to be used in formulas as building blocks. See
|
||||||
|
# the section "Including formulas" for details.
|
||||||
|
|
||||||
|
FORMULA_MACROFILE =
|
||||||
|
|
||||||
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
|
||||||
# https://www.mathjax.org) which uses client side Javascript for the rendering
|
# https://www.mathjax.org) which uses client side JavaScript for the rendering
|
||||||
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
|
||||||
# installed or if you want to formulas look prettier in the HTML output. When
|
# installed or if you want to formulas look prettier in the HTML output. When
|
||||||
# enabled you may also need to install MathJax separately and configure the path
|
# enabled you may also need to install MathJax separately and configure the path
|
||||||
@@ -1534,7 +1585,7 @@ USE_MATHJAX = NO
|
|||||||
|
|
||||||
# When MathJax is enabled you can set the default output format to be used for
|
# When MathJax is enabled you can set the default output format to be used for
|
||||||
# the MathJax output. See the MathJax site (see:
|
# the MathJax output. See the MathJax site (see:
|
||||||
# http://docs.mathjax.org/en/latest/output.html) for more details.
|
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
|
||||||
# Possible values are: HTML-CSS (which is slower, but has the best
|
# Possible values are: HTML-CSS (which is slower, but has the best
|
||||||
# compatibility), NativeMML (i.e. MathML) and SVG.
|
# compatibility), NativeMML (i.e. MathML) and SVG.
|
||||||
# The default value is: HTML-CSS.
|
# The default value is: HTML-CSS.
|
||||||
@@ -1550,7 +1601,7 @@ MATHJAX_FORMAT = HTML-CSS
|
|||||||
# Content Delivery Network so you can quickly see the result without installing
|
# Content Delivery Network so you can quickly see the result without installing
|
||||||
# MathJax. However, it is strongly recommended to install a local copy of
|
# MathJax. However, it is strongly recommended to install a local copy of
|
||||||
# MathJax from https://www.mathjax.org before deployment.
|
# MathJax from https://www.mathjax.org before deployment.
|
||||||
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
|
# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
|
||||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
|
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
|
||||||
@@ -1564,7 +1615,8 @@ MATHJAX_EXTENSIONS =
|
|||||||
|
|
||||||
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
||||||
# of code that will be used on startup of the MathJax code. See the MathJax site
|
# of code that will be used on startup of the MathJax code. See the MathJax site
|
||||||
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
|
# (see:
|
||||||
|
# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
|
||||||
# example see the documentation.
|
# example see the documentation.
|
||||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||||
|
|
||||||
@@ -1592,7 +1644,7 @@ MATHJAX_CODEFILE =
|
|||||||
SEARCHENGINE = NO
|
SEARCHENGINE = NO
|
||||||
|
|
||||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||||
# implemented using a web server instead of a web client using Javascript. There
|
# implemented using a web server instead of a web client using JavaScript. There
|
||||||
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||||
# setting. When disabled, doxygen will generate a PHP script for searching and
|
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||||
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||||
@@ -1611,7 +1663,8 @@ SERVER_BASED_SEARCH = NO
|
|||||||
#
|
#
|
||||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||||
# (doxysearch.cgi) which are based on the open source search engine library
|
# (doxysearch.cgi) which are based on the open source search engine library
|
||||||
# Xapian (see: https://xapian.org/).
|
# Xapian (see:
|
||||||
|
# https://xapian.org/).
|
||||||
#
|
#
|
||||||
# See the section "External Indexing and Searching" for details.
|
# See the section "External Indexing and Searching" for details.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
@@ -1624,8 +1677,9 @@ EXTERNAL_SEARCH = NO
|
|||||||
#
|
#
|
||||||
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
# Doxygen ships with an example indexer (doxyindexer) and search engine
|
||||||
# (doxysearch.cgi) which are based on the open source search engine library
|
# (doxysearch.cgi) which are based on the open source search engine library
|
||||||
# Xapian (see: https://xapian.org/). See the section "External Indexing and
|
# Xapian (see:
|
||||||
# Searching" for details.
|
# https://xapian.org/). See the section "External Indexing and Searching" for
|
||||||
|
# details.
|
||||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||||
|
|
||||||
SEARCHENGINE_URL =
|
SEARCHENGINE_URL =
|
||||||
@@ -1789,9 +1843,11 @@ LATEX_EXTRA_FILES =
|
|||||||
|
|
||||||
PDF_HYPERLINKS = NO
|
PDF_HYPERLINKS = NO
|
||||||
|
|
||||||
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
|
||||||
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
|
# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
|
||||||
# higher quality PDF documentation.
|
# files. Set this option to YES, to get a higher quality PDF documentation.
|
||||||
|
#
|
||||||
|
# See also section LATEX_CMD_NAME for selecting the engine.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
@@ -2126,7 +2182,8 @@ INCLUDE_FILE_PATTERNS =
|
|||||||
# recursively expanded use the := operator instead of the = operator.
|
# recursively expanded use the := operator instead of the = operator.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||||
|
|
||||||
PREDEFINED = BUILD_DATE
|
PREDEFINED = BUILD_DATE \
|
||||||
|
DOXYGEN=1
|
||||||
|
|
||||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||||
# tag can be used to specify a list of macro names that should be expanded. The
|
# tag can be used to specify a list of macro names that should be expanded. The
|
||||||
@@ -2303,10 +2360,32 @@ UML_LOOK = YES
|
|||||||
# but if the number exceeds 15, the total amount of fields shown is limited to
|
# but if the number exceeds 15, the total amount of fields shown is limited to
|
||||||
# 10.
|
# 10.
|
||||||
# Minimum value: 0, maximum value: 100, default value: 10.
|
# Minimum value: 0, maximum value: 100, default value: 10.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag UML_LOOK is set to YES.
|
||||||
|
|
||||||
UML_LIMIT_NUM_FIELDS = 10
|
UML_LIMIT_NUM_FIELDS = 10
|
||||||
|
|
||||||
|
# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
|
||||||
|
# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
|
||||||
|
# tag is set to YES, doxygen will add type and arguments for attributes and
|
||||||
|
# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
|
||||||
|
# will not generate fields with class member information in the UML graphs. The
|
||||||
|
# class diagrams will look similar to the default class diagrams but using UML
|
||||||
|
# notation for the relationships.
|
||||||
|
# Possible values are: NO, YES and NONE.
|
||||||
|
# The default value is: NO.
|
||||||
|
# This tag requires that the tag UML_LOOK is set to YES.
|
||||||
|
|
||||||
|
DOT_UML_DETAILS = NO
|
||||||
|
|
||||||
|
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
|
||||||
|
# to display on a single line. If the actual line length exceeds this threshold
|
||||||
|
# significantly it will wrapped across multiple lines. Some heuristics are apply
|
||||||
|
# to avoid ugly line breaks.
|
||||||
|
# Minimum value: 0, maximum value: 1000, default value: 17.
|
||||||
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
|
DOT_WRAP_THRESHOLD = 17
|
||||||
|
|
||||||
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
|
||||||
# collaboration graphs will show the relations between templates and their
|
# collaboration graphs will show the relations between templates and their
|
||||||
# instances.
|
# instances.
|
||||||
@@ -2496,9 +2575,11 @@ DOT_MULTI_TARGETS = YES
|
|||||||
|
|
||||||
GENERATE_LEGEND = YES
|
GENERATE_LEGEND = YES
|
||||||
|
|
||||||
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
|
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
|
||||||
# files that are used to generate the various graphs.
|
# files that are used to generate the various graphs.
|
||||||
|
#
|
||||||
|
# Note: This setting is not only used for dot files but also for msc and
|
||||||
|
# plantuml temporary files.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
|
||||||
|
|
||||||
DOT_CLEANUP = YES
|
DOT_CLEANUP = YES
|
||||||
|
@@ -29,7 +29,7 @@ with offscreen.bind():
|
|||||||
amount = 10
|
amount = 10
|
||||||
for i in range(-amount, amount + 1):
|
for i in range(-amount, amount + 1):
|
||||||
x_pos = i / amount
|
x_pos = i / amount
|
||||||
draw_circle_2d((x_pos, 0.0), (1, 1, 1, 1), 0.5, 200)
|
draw_circle_2d((x_pos, 0.0), (1, 1, 1, 1), 0.5, segments=200)
|
||||||
|
|
||||||
|
|
||||||
# Drawing the generated texture in 3D space
|
# Drawing the generated texture in 3D space
|
||||||
|
@@ -34,7 +34,9 @@ with offscreen.bind():
|
|||||||
for i in range(RING_AMOUNT):
|
for i in range(RING_AMOUNT):
|
||||||
draw_circle_2d(
|
draw_circle_2d(
|
||||||
(random.uniform(-1, 1), random.uniform(-1, 1)),
|
(random.uniform(-1, 1), random.uniform(-1, 1)),
|
||||||
(1, 1, 1, 1), random.uniform(0.1, 1), 20)
|
(1, 1, 1, 1), random.uniform(0.1, 1),
|
||||||
|
segments=20,
|
||||||
|
)
|
||||||
|
|
||||||
buffer = fb.read_color(0, 0, WIDTH, HEIGHT, 4, 0, 'UBYTE')
|
buffer = fb.read_color(0, 0, WIDTH, HEIGHT, 4, 0, 'UBYTE')
|
||||||
|
|
||||||
|
@@ -1,2 +1,13 @@
|
|||||||
Sphinx==3.5.3
|
sphinx==3.5.4
|
||||||
|
|
||||||
|
# Sphinx dependencies that are important
|
||||||
|
Jinja2==2.11.3
|
||||||
|
Pygments==2.9.0
|
||||||
|
docutils==0.16
|
||||||
|
snowballstemmer==2.1.0
|
||||||
|
babel==2.9.1
|
||||||
|
requests==2.25.1
|
||||||
|
|
||||||
|
# Only needed to match the theme used for the official documentation.
|
||||||
|
# Without this theme, the default theme will be used.
|
||||||
sphinx_rtd_theme==0.5.2
|
sphinx_rtd_theme==0.5.2
|
||||||
|
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
@@ -1,3 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
#define MANTA_GIT_VERSION "commit 9c505cd22e289b98c9aa717efba8ef3201c7e458"
|
#define MANTA_GIT_VERSION "commit 8fbebe02459b7f72575872c20961f7cb757db408"
|
||||||
|
13
extern/mantaflow/preprocessed/kernel.h
vendored
13
extern/mantaflow/preprocessed/kernel.h
vendored
@@ -71,6 +71,19 @@ class ParticleBase;
|
|||||||
for (int j = bnd; j < (grid).getSizeY() - bnd; ++j) \
|
for (int j = bnd; j < (grid).getSizeY() - bnd; ++j) \
|
||||||
for (int i = bnd; i < (grid).getSizeX() - bnd; ++i)
|
for (int i = bnd; i < (grid).getSizeX() - bnd; ++i)
|
||||||
|
|
||||||
|
#define FOR_NEIGHBORS_BND(grid, radius, bnd) \
|
||||||
|
for (int zj = ((grid).is3D() ? std::max(bnd, k - radius) : 0); \
|
||||||
|
zj <= ((grid).is3D() ? std::min(k + radius, (grid).getSizeZ() - 1 - bnd) : 0); \
|
||||||
|
zj++) \
|
||||||
|
for (int yj = std::max(bnd, j - radius); \
|
||||||
|
yj <= std::min(j + radius, (grid).getSizeY() - 1 - bnd); \
|
||||||
|
yj++) \
|
||||||
|
for (int xj = std::max(bnd, i - radius); \
|
||||||
|
xj <= std::min(i + radius, (grid).getSizeX() - 1 - bnd); \
|
||||||
|
xj++)
|
||||||
|
|
||||||
|
#define FOR_NEIGHBORS(grid, radius) FOR_NEIGHBORS_BND(grid, radius, 0)
|
||||||
|
|
||||||
//! Basic data structure for kernel data, initialized based on kernel type (e.g. single, idx, etc).
|
//! Basic data structure for kernel data, initialized based on kernel type (e.g. single, idx, etc).
|
||||||
struct KernelBase {
|
struct KernelBase {
|
||||||
int maxX, maxY, maxZ, minZ, maxT, minT;
|
int maxX, maxY, maxZ, minZ, maxT, minT;
|
||||||
|
92
extern/mantaflow/preprocessed/plugin/flip.cpp
vendored
92
extern/mantaflow/preprocessed/plugin/flip.cpp
vendored
@@ -822,33 +822,29 @@ struct ComputeUnionLevelsetPindex : public KernelBase {
|
|||||||
{
|
{
|
||||||
const Vec3 gridPos = Vec3(i, j, k) + Vec3(0.5); // shifted by half cell
|
const Vec3 gridPos = Vec3(i, j, k) + Vec3(0.5); // shifted by half cell
|
||||||
Real phiv = radius * 1.0; // outside
|
Real phiv = radius * 1.0; // outside
|
||||||
|
const int r = int(radius) + 1;
|
||||||
|
|
||||||
int r = int(radius) + 1;
|
FOR_NEIGHBORS(phi, r)
|
||||||
int rZ = phi.is3D() ? r : 0;
|
{
|
||||||
for (int zj = k - rZ; zj <= k + rZ; zj++)
|
|
||||||
for (int yj = j - r; yj <= j + r; yj++)
|
|
||||||
for (int xj = i - r; xj <= i + r; xj++) {
|
|
||||||
if (!phi.isInBounds(Vec3i(xj, yj, zj)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// note, for the particle indices in indexSys the access is periodic (ie, dont skip for
|
// note, for the particle indices in indexSys the access is periodic (ie, dont skip for eg
|
||||||
// eg inBounds(sx,10,10)
|
// inBounds(sx,10,10)
|
||||||
IndexInt isysIdxS = index.index(xj, yj, zj);
|
IndexInt isysIdxS = index.index(xj, yj, zj);
|
||||||
IndexInt pStart = index(isysIdxS), pEnd = 0;
|
IndexInt pStart = index(isysIdxS), pEnd = 0;
|
||||||
if (phi.isInBounds(isysIdxS + 1))
|
if (phi.isInBounds(isysIdxS + 1))
|
||||||
pEnd = index(isysIdxS + 1);
|
pEnd = index(isysIdxS + 1);
|
||||||
else
|
else
|
||||||
pEnd = indexSys.size();
|
pEnd = indexSys.size();
|
||||||
|
|
||||||
// now loop over particles in cell
|
// now loop over particles in cell
|
||||||
for (IndexInt p = pStart; p < pEnd; ++p) {
|
for (IndexInt p = pStart; p < pEnd; ++p) {
|
||||||
const int psrc = indexSys[p].sourceIndex;
|
const int psrc = indexSys[p].sourceIndex;
|
||||||
if (ptype && ((*ptype)[psrc] & exclude))
|
if (ptype && ((*ptype)[psrc] & exclude))
|
||||||
continue;
|
continue;
|
||||||
const Vec3 pos = parts[psrc].pos;
|
const Vec3 pos = parts[psrc].pos;
|
||||||
phiv = std::min(phiv, fabs(norm(gridPos - pos)) - radius);
|
phiv = std::min(phiv, fabs(norm(gridPos - pos)) - radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
phi(i, j, k) = phiv;
|
phi(i, j, k) = phiv;
|
||||||
}
|
}
|
||||||
inline const Grid<int> &getArg0()
|
inline const Grid<int> &getArg0()
|
||||||
@@ -1026,39 +1022,35 @@ struct ComputeAveragedLevelsetWeight : public KernelBase {
|
|||||||
|
|
||||||
// loop over neighborhood, similar to ComputeUnionLevelsetPindex
|
// loop over neighborhood, similar to ComputeUnionLevelsetPindex
|
||||||
const Real sradiusInv = 1. / (4. * radius * radius);
|
const Real sradiusInv = 1. / (4. * radius * radius);
|
||||||
int r = int(1. * radius) + 1;
|
const int r = int(radius) + 1;
|
||||||
int rZ = phi.is3D() ? r : 0;
|
|
||||||
// accumulators
|
// accumulators
|
||||||
Real wacc = 0.;
|
Real wacc = 0.;
|
||||||
Vec3 pacc = Vec3(0.);
|
Vec3 pacc = Vec3(0.);
|
||||||
Real racc = 0.;
|
Real racc = 0.;
|
||||||
|
|
||||||
for (int zj = k - rZ; zj <= k + rZ; zj++)
|
FOR_NEIGHBORS(phi, r)
|
||||||
for (int yj = j - r; yj <= j + r; yj++)
|
{
|
||||||
for (int xj = i - r; xj <= i + r; xj++) {
|
|
||||||
if (!phi.isInBounds(Vec3i(xj, yj, zj)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
IndexInt isysIdxS = index.index(xj, yj, zj);
|
IndexInt isysIdxS = index.index(xj, yj, zj);
|
||||||
IndexInt pStart = index(isysIdxS), pEnd = 0;
|
IndexInt pStart = index(isysIdxS), pEnd = 0;
|
||||||
if (phi.isInBounds(isysIdxS + 1))
|
if (phi.isInBounds(isysIdxS + 1))
|
||||||
pEnd = index(isysIdxS + 1);
|
pEnd = index(isysIdxS + 1);
|
||||||
else
|
else
|
||||||
pEnd = indexSys.size();
|
pEnd = indexSys.size();
|
||||||
for (IndexInt p = pStart; p < pEnd; ++p) {
|
for (IndexInt p = pStart; p < pEnd; ++p) {
|
||||||
IndexInt psrc = indexSys[p].sourceIndex;
|
IndexInt psrc = indexSys[p].sourceIndex;
|
||||||
if (ptype && ((*ptype)[psrc] & exclude))
|
if (ptype && ((*ptype)[psrc] & exclude))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Vec3 pos = parts[psrc].pos;
|
Vec3 pos = parts[psrc].pos;
|
||||||
Real s = normSquare(gridPos - pos) * sradiusInv;
|
Real s = normSquare(gridPos - pos) * sradiusInv;
|
||||||
// Real w = std::max(0., cubed(1.-s) );
|
// Real w = std::max(0., cubed(1.-s) );
|
||||||
Real w = std::max(0., (1. - s)); // a bit smoother
|
Real w = std::max(0., (1. - s)); // a bit smoother
|
||||||
wacc += w;
|
wacc += w;
|
||||||
racc += radius * w;
|
racc += radius * w;
|
||||||
pacc += pos * w;
|
pacc += pos * w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wacc > VECTOR_EPSILON) {
|
if (wacc > VECTOR_EPSILON) {
|
||||||
racc /= wacc;
|
racc /= wacc;
|
||||||
|
@@ -234,10 +234,10 @@ void subdivideMesh(
|
|||||||
normalize(ne2);
|
normalize(ne2);
|
||||||
|
|
||||||
// Real thisArea = sqrMag(cross(-e2,e0));
|
// Real thisArea = sqrMag(cross(-e2,e0));
|
||||||
// small angle approximation says sin(x) = arcsin(x) = x,
|
// small angle approximation says sin(x) = arcsin(x) = x,
|
||||||
// arccos(x) = pi/2 - arcsin(x),
|
// arccos(x) = pi/2 - arcsin(x),
|
||||||
// cos(x) = dot(A,B),
|
// cos(x) = dot(A,B),
|
||||||
// so angle is approximately 1 - dot(A,B).
|
// so angle is approximately 1 - dot(A,B).
|
||||||
Real angle[3];
|
Real angle[3];
|
||||||
angle[0] = 1.0 - dot(ne0, -ne2);
|
angle[0] = 1.0 - dot(ne0, -ne2);
|
||||||
angle[1] = 1.0 - dot(ne1, -ne0);
|
angle[1] = 1.0 - dot(ne1, -ne0);
|
||||||
|
@@ -2287,10 +2287,9 @@ struct knFlipComputePotentialTrappedAir : public KernelBase {
|
|||||||
const Vec3 &vj = scaleFromManta * v.getCentered(x, y, z);
|
const Vec3 &vj = scaleFromManta * v.getCentered(x, y, z);
|
||||||
const Vec3 xij = xi - xj;
|
const Vec3 xij = xi - xj;
|
||||||
const Vec3 vij = vi - vj;
|
const Vec3 vij = vi - vj;
|
||||||
Real h = !pot.is3D() ?
|
Real h = !pot.is3D() ? 1.414 * radius :
|
||||||
1.414 * radius :
|
1.732 * radius; // estimate sqrt(2)*radius resp. sqrt(3)*radius
|
||||||
1.732 * radius; // estimate sqrt(2)*radius resp. sqrt(3)*radius for h, due
|
// for h, due to squared resp. cubic neighbor area
|
||||||
// to squared resp. cubic neighbor area
|
|
||||||
vdiff += norm(vij) * (1 - dot(getNormalized(vij), getNormalized(xij))) *
|
vdiff += norm(vij) * (1 - dot(getNormalized(vij), getNormalized(xij))) *
|
||||||
(1 - norm(xij) / h);
|
(1 - norm(xij) / h);
|
||||||
}
|
}
|
||||||
|
@@ -79,15 +79,15 @@ typedef struct CLG_IDFilter {
|
|||||||
} CLG_IDFilter;
|
} CLG_IDFilter;
|
||||||
|
|
||||||
typedef struct CLogContext {
|
typedef struct CLogContext {
|
||||||
/** Single linked list of types. */
|
/** Single linked list of types. */
|
||||||
CLG_LogType *types;
|
CLG_LogType *types;
|
||||||
/** Single linked list of references. */
|
/** Single linked list of references. */
|
||||||
CLG_LogRef *refs;
|
CLG_LogRef *refs;
|
||||||
#ifdef WITH_CLOG_PTHREADS
|
#ifdef WITH_CLOG_PTHREADS
|
||||||
pthread_mutex_t types_lock;
|
pthread_mutex_t types_lock;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* exclude, include filters. */
|
/* exclude, include filters. */
|
||||||
CLG_IDFilter *filters[2];
|
CLG_IDFilter *filters[2];
|
||||||
bool use_color;
|
bool use_color;
|
||||||
bool use_basename;
|
bool use_basename;
|
||||||
|
@@ -132,7 +132,7 @@ def init():
|
|||||||
_workaround_buggy_drivers()
|
_workaround_buggy_drivers()
|
||||||
|
|
||||||
path = os.path.dirname(__file__)
|
path = os.path.dirname(__file__)
|
||||||
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', '')))
|
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', path='')))
|
||||||
|
|
||||||
_cycles.init(path, user_path, bpy.app.background)
|
_cycles.init(path, user_path, bpy.app.background)
|
||||||
_parse_command_line()
|
_parse_command_line()
|
||||||
|
@@ -34,12 +34,17 @@ void BlenderSync::sync_light(BL::Object &b_parent,
|
|||||||
bool *use_portal)
|
bool *use_portal)
|
||||||
{
|
{
|
||||||
/* test if we need to sync */
|
/* test if we need to sync */
|
||||||
Light *light;
|
|
||||||
ObjectKey key(b_parent, persistent_id, b_ob_instance, false);
|
ObjectKey key(b_parent, persistent_id, b_ob_instance, false);
|
||||||
BL::Light b_light(b_ob.data());
|
BL::Light b_light(b_ob.data());
|
||||||
|
|
||||||
|
Light *light = light_map.find(key);
|
||||||
|
|
||||||
|
/* Check if the transform was modified, in case a linked collection is moved we do not get a
|
||||||
|
* specific depsgraph update (T88515). This also mimics the behavior for Objects. */
|
||||||
|
const bool tfm_updated = (light && light->get_tfm() != tfm);
|
||||||
|
|
||||||
/* Update if either object or light data changed. */
|
/* Update if either object or light data changed. */
|
||||||
if (!light_map.add_or_update(&light, b_ob, b_parent, key)) {
|
if (!light_map.add_or_update(&light, b_ob, b_parent, key) && !tfm_updated) {
|
||||||
Shader *shader;
|
Shader *shader;
|
||||||
if (!shader_map.add_or_update(&shader, b_light)) {
|
if (!shader_map.add_or_update(&shader, b_light)) {
|
||||||
if (light->get_is_portal())
|
if (light->get_is_portal())
|
||||||
|
@@ -289,11 +289,10 @@ static PyObject *render_func(PyObject * /*self*/, PyObject *args)
|
|||||||
RNA_pointer_create(NULL, &RNA_Depsgraph, (ID *)PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
|
RNA_pointer_create(NULL, &RNA_Depsgraph, (ID *)PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
|
||||||
BL::Depsgraph b_depsgraph(depsgraphptr);
|
BL::Depsgraph b_depsgraph(depsgraphptr);
|
||||||
|
|
||||||
/* Allow Blender to execute other Python scripts, and isolate TBB tasks so we
|
/* Allow Blender to execute other Python scripts. */
|
||||||
* don't get deadlocks with Blender threads accessing shared data like images. */
|
|
||||||
python_thread_state_save(&session->python_thread_state);
|
python_thread_state_save(&session->python_thread_state);
|
||||||
|
|
||||||
tbb::this_task_arena::isolate([&] { session->render(b_depsgraph); });
|
session->render(b_depsgraph);
|
||||||
|
|
||||||
python_thread_state_restore(&session->python_thread_state);
|
python_thread_state_restore(&session->python_thread_state);
|
||||||
|
|
||||||
@@ -330,8 +329,7 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
|
|||||||
|
|
||||||
python_thread_state_save(&session->python_thread_state);
|
python_thread_state_save(&session->python_thread_state);
|
||||||
|
|
||||||
tbb::this_task_arena::isolate(
|
session->bake(b_depsgraph, b_object, pass_type, pass_filter, width, height);
|
||||||
[&] { session->bake(b_depsgraph, b_object, pass_type, pass_filter, width, height); });
|
|
||||||
|
|
||||||
python_thread_state_restore(&session->python_thread_state);
|
python_thread_state_restore(&session->python_thread_state);
|
||||||
|
|
||||||
@@ -377,7 +375,7 @@ static PyObject *reset_func(PyObject * /*self*/, PyObject *args)
|
|||||||
|
|
||||||
python_thread_state_save(&session->python_thread_state);
|
python_thread_state_save(&session->python_thread_state);
|
||||||
|
|
||||||
tbb::this_task_arena::isolate([&] { session->reset_session(b_data, b_depsgraph); });
|
session->reset_session(b_data, b_depsgraph);
|
||||||
|
|
||||||
python_thread_state_restore(&session->python_thread_state);
|
python_thread_state_restore(&session->python_thread_state);
|
||||||
|
|
||||||
@@ -399,7 +397,7 @@ static PyObject *sync_func(PyObject * /*self*/, PyObject *args)
|
|||||||
|
|
||||||
python_thread_state_save(&session->python_thread_state);
|
python_thread_state_save(&session->python_thread_state);
|
||||||
|
|
||||||
tbb::this_task_arena::isolate([&] { session->synchronize(b_depsgraph); });
|
session->synchronize(b_depsgraph);
|
||||||
|
|
||||||
python_thread_state_restore(&session->python_thread_state);
|
python_thread_state_restore(&session->python_thread_state);
|
||||||
|
|
||||||
|
@@ -181,7 +181,7 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
|
|||||||
/* record intersection */
|
/* record intersection */
|
||||||
ctx->local_isect->hits[hit_idx] = current_isect;
|
ctx->local_isect->hits[hit_idx] = current_isect;
|
||||||
ctx->local_isect->Ng[hit_idx] = normalize(make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z));
|
ctx->local_isect->Ng[hit_idx] = normalize(make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z));
|
||||||
/* This tells Embree to continue tracing .*/
|
/* This tells Embree to continue tracing. */
|
||||||
*args->valid = 0;
|
*args->valid = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -297,7 +297,7 @@ struct BVHSpatialBin {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct BVHSpatialStorage {
|
struct BVHSpatialStorage {
|
||||||
/* Accumulated bounds when sweeping from right to left. */
|
/* Accumulated bounds when sweeping from right to left. */
|
||||||
vector<BoundBox> right_bounds;
|
vector<BoundBox> right_bounds;
|
||||||
|
|
||||||
/* Bins used for histogram when selecting best split plane. */
|
/* Bins used for histogram when selecting best split plane. */
|
||||||
|
@@ -1196,16 +1196,18 @@ class OptiXDevice : public CUDADevice {
|
|||||||
|
|
||||||
const CUDAContextScope scope(cuContext);
|
const CUDAContextScope scope(cuContext);
|
||||||
|
|
||||||
|
const bool use_fast_trace_bvh = (bvh->params.bvh_type == SceneParams::BVH_STATIC);
|
||||||
|
|
||||||
// Compute memory usage
|
// Compute memory usage
|
||||||
OptixAccelBufferSizes sizes = {};
|
OptixAccelBufferSizes sizes = {};
|
||||||
OptixAccelBuildOptions options = {};
|
OptixAccelBuildOptions options = {};
|
||||||
options.operation = operation;
|
options.operation = operation;
|
||||||
if (background) {
|
if (use_fast_trace_bvh) {
|
||||||
// Prefer best performance and lowest memory consumption in background
|
VLOG(2) << "Using fast to trace OptiX BVH";
|
||||||
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE | OPTIX_BUILD_FLAG_ALLOW_COMPACTION;
|
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE | OPTIX_BUILD_FLAG_ALLOW_COMPACTION;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Prefer fast updates in viewport
|
VLOG(2) << "Using fast to update OptiX BVH";
|
||||||
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD | OPTIX_BUILD_FLAG_ALLOW_UPDATE;
|
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD | OPTIX_BUILD_FLAG_ALLOW_UPDATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1253,15 +1255,16 @@ class OptiXDevice : public CUDADevice {
|
|||||||
out_data.device_pointer,
|
out_data.device_pointer,
|
||||||
sizes.outputSizeInBytes,
|
sizes.outputSizeInBytes,
|
||||||
&out_handle,
|
&out_handle,
|
||||||
background ? &compacted_size_prop : NULL,
|
use_fast_trace_bvh ? &compacted_size_prop : NULL,
|
||||||
background ? 1 : 0));
|
use_fast_trace_bvh ? 1 : 0));
|
||||||
bvh->traversable_handle = static_cast<uint64_t>(out_handle);
|
bvh->traversable_handle = static_cast<uint64_t>(out_handle);
|
||||||
|
|
||||||
// Wait for all operations to finish
|
// Wait for all operations to finish
|
||||||
check_result_cuda_ret(cuStreamSynchronize(NULL));
|
check_result_cuda_ret(cuStreamSynchronize(NULL));
|
||||||
|
|
||||||
// Compact acceleration structure to save memory (do not do this in viewport for faster builds)
|
// Compact acceleration structure to save memory (only if using fast trace as the
|
||||||
if (background) {
|
// OPTIX_BUILD_FLAG_ALLOW_COMPACTION flag is only set in this case).
|
||||||
|
if (use_fast_trace_bvh) {
|
||||||
uint64_t compacted_size = sizes.outputSizeInBytes;
|
uint64_t compacted_size = sizes.outputSizeInBytes;
|
||||||
check_result_cuda_ret(
|
check_result_cuda_ret(
|
||||||
cuMemcpyDtoH(&compacted_size, compacted_size_prop.result, sizeof(compacted_size)));
|
cuMemcpyDtoH(&compacted_size, compacted_size_prop.result, sizeof(compacted_size)));
|
||||||
@@ -1306,6 +1309,8 @@ class OptiXDevice : public CUDADevice {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool use_fast_trace_bvh = (bvh->params.bvh_type == SceneParams::BVH_STATIC);
|
||||||
|
|
||||||
free_bvh_memory_delayed();
|
free_bvh_memory_delayed();
|
||||||
|
|
||||||
BVHOptiX *const bvh_optix = static_cast<BVHOptiX *>(bvh);
|
BVHOptiX *const bvh_optix = static_cast<BVHOptiX *>(bvh);
|
||||||
@@ -1315,10 +1320,10 @@ class OptiXDevice : public CUDADevice {
|
|||||||
if (!bvh->params.top_level) {
|
if (!bvh->params.top_level) {
|
||||||
assert(bvh->objects.size() == 1 && bvh->geometry.size() == 1);
|
assert(bvh->objects.size() == 1 && bvh->geometry.size() == 1);
|
||||||
|
|
||||||
// Refit is only possible in viewport for now (because AS is built with
|
|
||||||
// OPTIX_BUILD_FLAG_ALLOW_UPDATE only there, see above)
|
|
||||||
OptixBuildOperation operation = OPTIX_BUILD_OPERATION_BUILD;
|
OptixBuildOperation operation = OPTIX_BUILD_OPERATION_BUILD;
|
||||||
if (refit && !background) {
|
/* Refit is only possible when using fast to trace BVH (because AS is built with
|
||||||
|
* OPTIX_BUILD_FLAG_ALLOW_UPDATE only there, see above). */
|
||||||
|
if (refit && !use_fast_trace_bvh) {
|
||||||
assert(bvh_optix->traversable_handle != 0);
|
assert(bvh_optix->traversable_handle != 0);
|
||||||
operation = OPTIX_BUILD_OPERATION_UPDATE;
|
operation = OPTIX_BUILD_OPERATION_UPDATE;
|
||||||
}
|
}
|
||||||
|
@@ -65,7 +65,7 @@ class DenoiseParams {
|
|||||||
/* Viewport start sample. */
|
/* Viewport start sample. */
|
||||||
int start_sample;
|
int start_sample;
|
||||||
|
|
||||||
/** Native Denoiser **/
|
/** Native Denoiser. */
|
||||||
|
|
||||||
/* Pixel radius for neighboring pixels to take into account. */
|
/* Pixel radius for neighboring pixels to take into account. */
|
||||||
int radius;
|
int radius;
|
||||||
@@ -81,7 +81,7 @@ class DenoiseParams {
|
|||||||
/* Clamp the input to the range of +-1e8. Should be enough for any legitimate data. */
|
/* Clamp the input to the range of +-1e8. Should be enough for any legitimate data. */
|
||||||
bool clamp_input;
|
bool clamp_input;
|
||||||
|
|
||||||
/** OIDN/Optix Denoiser **/
|
/** OIDN/Optix Denoiser. */
|
||||||
|
|
||||||
/* Passes handed over to the OIDN/OptiX denoiser (default to color + albedo). */
|
/* Passes handed over to the OIDN/OptiX denoiser (default to color + albedo). */
|
||||||
DenoiserInput input_passes;
|
DenoiserInput input_passes;
|
||||||
|
@@ -116,7 +116,7 @@ CCL_NAMESPACE_BEGIN
|
|||||||
# endif
|
# endif
|
||||||
# endif /* __SHADOW_RECORD_ALL__ */
|
# endif /* __SHADOW_RECORD_ALL__ */
|
||||||
|
|
||||||
/* Record all intersections - Volume BVH traversal */
|
/* Record all intersections - Volume BVH traversal. */
|
||||||
|
|
||||||
# if defined(__VOLUME_RECORD_ALL__)
|
# if defined(__VOLUME_RECORD_ALL__)
|
||||||
# define BVH_FUNCTION_NAME bvh_intersect_volume_all
|
# define BVH_FUNCTION_NAME bvh_intersect_volume_all
|
||||||
|
@@ -61,8 +61,8 @@ ccl_device_forceinline float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderCl
|
|||||||
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
|
const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
|
||||||
float3 N = bsdf->N;
|
float3 N = bsdf->N;
|
||||||
|
|
||||||
float NdotI = dot(N, I); /* in Cycles/OSL convention I is omega_out */
|
float NdotI = dot(N, I); /* in Cycles/OSL convention I is omega_out */
|
||||||
float NdotO = dot(N, omega_in); /* and consequently we use for O omaga_in ;) */
|
float NdotO = dot(N, omega_in); /* and consequently we use for O omaga_in ;) */
|
||||||
|
|
||||||
float out = 0.0f;
|
float out = 0.0f;
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
/* normal on triangle */
|
/* Normal on triangle. */
|
||||||
ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
|
ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
|
||||||
{
|
{
|
||||||
/* load triangle vertices */
|
/* load triangle vertices */
|
||||||
@@ -40,7 +40,7 @@ ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* point and normal on triangle */
|
/* Point and normal on triangle. */
|
||||||
ccl_device_inline void triangle_point_normal(
|
ccl_device_inline void triangle_point_normal(
|
||||||
KernelGlobals *kg, int object, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
|
KernelGlobals *kg, int object, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
|
||||||
{
|
{
|
||||||
|
@@ -64,7 +64,7 @@ typedef struct KernelGlobals {
|
|||||||
OSLThreadData *osl_tdata;
|
OSLThreadData *osl_tdata;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* **** Run-time data **** */
|
/* **** Run-time data **** */
|
||||||
|
|
||||||
/* Heap-allocated storage for transparent shadows intersections. */
|
/* Heap-allocated storage for transparent shadows intersections. */
|
||||||
Intersection *transparent_shadow_intersections;
|
Intersection *transparent_shadow_intersections;
|
||||||
|
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
/* Spherical coordinates <-> Cartesian direction */
|
/* Spherical coordinates <-> Cartesian direction. */
|
||||||
|
|
||||||
ccl_device float2 direction_to_spherical(float3 dir)
|
ccl_device float2 direction_to_spherical(float3 dir)
|
||||||
{
|
{
|
||||||
|
@@ -79,7 +79,7 @@ ccl_device void enqueue_ray_index_local(
|
|||||||
{
|
{
|
||||||
int lidx = ccl_local_id(1) * ccl_local_size(0) + ccl_local_id(0);
|
int lidx = ccl_local_id(1) * ccl_local_size(0) + ccl_local_id(0);
|
||||||
|
|
||||||
/* Get local queue id .*/
|
/* Get local queue id. */
|
||||||
unsigned int lqidx;
|
unsigned int lqidx;
|
||||||
if (enqueue_flag) {
|
if (enqueue_flag) {
|
||||||
lqidx = atomic_fetch_and_inc_uint32(local_queue_atomics);
|
lqidx = atomic_fetch_and_inc_uint32(local_queue_atomics);
|
||||||
|
@@ -302,7 +302,7 @@ enum PathRayFlag {
|
|||||||
PATH_RAY_DIFFUSE_ANCESTOR = (1 << 15),
|
PATH_RAY_DIFFUSE_ANCESTOR = (1 << 15),
|
||||||
/* Single pass has been written. */
|
/* Single pass has been written. */
|
||||||
PATH_RAY_SINGLE_PASS_DONE = (1 << 16),
|
PATH_RAY_SINGLE_PASS_DONE = (1 << 16),
|
||||||
/* Ray is behind a shadow catcher .*/
|
/* Ray is behind a shadow catcher. */
|
||||||
PATH_RAY_SHADOW_CATCHER = (1 << 17),
|
PATH_RAY_SHADOW_CATCHER = (1 << 17),
|
||||||
/* Store shadow data for shadow catcher or denoising. */
|
/* Store shadow data for shadow catcher or denoising. */
|
||||||
PATH_RAY_STORE_SHADOW_INFO = (1 << 18),
|
PATH_RAY_STORE_SHADOW_INFO = (1 << 18),
|
||||||
|
@@ -317,4 +317,4 @@ class OSLRenderServices : public OSL::RendererServices {
|
|||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
#endif /* __OSL_SERVICES_H__ */
|
#endif /* __OSL_SERVICES_H__ */
|
||||||
|
@@ -52,6 +52,9 @@ shader node_vector_math(string math_type = "add",
|
|||||||
else if (math_type == "faceforward") {
|
else if (math_type == "faceforward") {
|
||||||
Vector = compatible_faceforward(Vector1, Vector2, Vector3);
|
Vector = compatible_faceforward(Vector1, Vector2, Vector3);
|
||||||
}
|
}
|
||||||
|
else if (math_type == "multiply_add") {
|
||||||
|
Vector = Vector1 * Vector2 + Vector3;
|
||||||
|
}
|
||||||
else if (math_type == "dot_product") {
|
else if (math_type == "dot_product") {
|
||||||
Value = dot(Vector1, Vector2);
|
Value = dot(Vector1, Vector2);
|
||||||
}
|
}
|
||||||
|
@@ -803,7 +803,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
|
|||||||
float melanin_redness = stack_load_float_default(
|
float melanin_redness = stack_load_float_default(
|
||||||
stack, melanin_redness_ofs, data_node2.w);
|
stack, melanin_redness_ofs, data_node2.w);
|
||||||
|
|
||||||
/* Randomize melanin. */
|
/* Randomize melanin. */
|
||||||
float random_color = stack_load_float_default(stack, random_color_ofs, data_node3.z);
|
float random_color = stack_load_float_default(stack, random_color_ofs, data_node3.z);
|
||||||
random_color = clamp(random_color, 0.0f, 1.0f);
|
random_color = clamp(random_color, 0.0f, 1.0f);
|
||||||
float factor_random_color = 1.0f + 2.0f * (random - 0.5f) * random_color;
|
float factor_random_color = 1.0f + 2.0f * (random - 0.5f) * random_color;
|
||||||
|
@@ -220,11 +220,13 @@ ccl_device void svm_node_hair_info(
|
|||||||
stack_store_float(stack, out_offset, data);
|
stack_store_float(stack, out_offset, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*case NODE_INFO_CURVE_FADE: {
|
# if 0
|
||||||
|
case NODE_INFO_CURVE_FADE: {
|
||||||
data = sd->curve_transparency;
|
data = sd->curve_transparency;
|
||||||
stack_store_float(stack, out_offset, data);
|
stack_store_float(stack, out_offset, data);
|
||||||
break;
|
break;
|
||||||
}*/
|
}
|
||||||
|
# endif
|
||||||
case NODE_INFO_CURVE_TANGENT_NORMAL: {
|
case NODE_INFO_CURVE_TANGENT_NORMAL: {
|
||||||
data3 = curve_tangent_normal(kg, sd);
|
data3 = curve_tangent_normal(kg, sd);
|
||||||
stack_store_float3(stack, out_offset, data3);
|
stack_store_float3(stack, out_offset, data3);
|
||||||
|
@@ -58,7 +58,8 @@ ccl_device void svm_node_vector_math(KernelGlobals *kg,
|
|||||||
float3 vector;
|
float3 vector;
|
||||||
|
|
||||||
/* 3 Vector Operators */
|
/* 3 Vector Operators */
|
||||||
if (type == NODE_VECTOR_MATH_WRAP || type == NODE_VECTOR_MATH_FACEFORWARD) {
|
if (type == NODE_VECTOR_MATH_WRAP || type == NODE_VECTOR_MATH_FACEFORWARD ||
|
||||||
|
type == NODE_VECTOR_MATH_MULTIPLY_ADD) {
|
||||||
uint4 extra_node = read_node(kg, offset);
|
uint4 extra_node = read_node(kg, offset);
|
||||||
c = stack_load_float3(stack, extra_node.x);
|
c = stack_load_float3(stack, extra_node.x);
|
||||||
}
|
}
|
||||||
|
@@ -52,6 +52,9 @@ ccl_device void svm_vector_math(float *value,
|
|||||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||||
*vector = faceforward(a, b, c);
|
*vector = faceforward(a, b, c);
|
||||||
break;
|
break;
|
||||||
|
case NODE_VECTOR_MATH_MULTIPLY_ADD:
|
||||||
|
*vector = a * b + c;
|
||||||
|
break;
|
||||||
case NODE_VECTOR_MATH_DOT_PRODUCT:
|
case NODE_VECTOR_MATH_DOT_PRODUCT:
|
||||||
*value = dot(a, b);
|
*value = dot(a, b);
|
||||||
break;
|
break;
|
||||||
|
@@ -341,6 +341,7 @@ typedef enum NodeVectorMathType {
|
|||||||
NODE_VECTOR_MATH_TANGENT,
|
NODE_VECTOR_MATH_TANGENT,
|
||||||
NODE_VECTOR_MATH_REFRACT,
|
NODE_VECTOR_MATH_REFRACT,
|
||||||
NODE_VECTOR_MATH_FACEFORWARD,
|
NODE_VECTOR_MATH_FACEFORWARD,
|
||||||
|
NODE_VECTOR_MATH_MULTIPLY_ADD,
|
||||||
} NodeVectorMathType;
|
} NodeVectorMathType;
|
||||||
|
|
||||||
typedef enum NodeClampType {
|
typedef enum NodeClampType {
|
||||||
|
@@ -333,7 +333,7 @@ static M44d get_interpolated_matrix_for_time(const MatrixSampleMap &samples, chr
|
|||||||
|
|
||||||
chrono_t t = (time - prev_time) / (next_time - prev_time);
|
chrono_t t = (time - prev_time) / (next_time - prev_time);
|
||||||
|
|
||||||
/* ensure rotation around the shortest angle */
|
/* Ensure rotation around the shortest angle. */
|
||||||
if ((prev_rotation ^ next_rotation) < 0) {
|
if ((prev_rotation ^ next_rotation) < 0) {
|
||||||
next_rotation = -next_rotation;
|
next_rotation = -next_rotation;
|
||||||
}
|
}
|
||||||
|
@@ -736,13 +736,14 @@ static void process_uvs(CachedData &cache,
|
|||||||
const IV2fGeomParam::Sample &sample,
|
const IV2fGeomParam::Sample &sample,
|
||||||
double time)
|
double time)
|
||||||
{
|
{
|
||||||
if (scope != kFacevaryingScope) {
|
if (scope != kFacevaryingScope && scope != kVaryingScope && scope != kVertexScope) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const array<int> *uv_loops = cache.uv_loops.data_for_time_no_check(time).get_data_or_null();
|
const array<int> *uv_loops = cache.uv_loops.data_for_time_no_check(time).get_data_or_null();
|
||||||
|
|
||||||
if (!uv_loops) {
|
/* It's ok to not have loop indices, as long as the scope is not face-varying. */
|
||||||
|
if (!uv_loops && scope == kFacevaryingScope) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -766,9 +767,27 @@ static void process_uvs(CachedData &cache,
|
|||||||
const uint32_t *indices = sample.getIndices()->get();
|
const uint32_t *indices = sample.getIndices()->get();
|
||||||
const V2f *values = sample.getVals()->get();
|
const V2f *values = sample.getVals()->get();
|
||||||
|
|
||||||
for (const int uv_loop_index : *uv_loops) {
|
if (scope == kFacevaryingScope) {
|
||||||
const uint32_t index = indices[uv_loop_index];
|
for (const int uv_loop_index : *uv_loops) {
|
||||||
*data_float2++ = make_float2(values[index][0], values[index][1]);
|
const uint32_t index = indices[uv_loop_index];
|
||||||
|
*data_float2++ = make_float2(values[index][0], values[index][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (scope == kVaryingScope || scope == kVertexScope) {
|
||||||
|
if (triangles) {
|
||||||
|
for (size_t i = 0; i < triangles->size(); i++) {
|
||||||
|
const int3 t = (*triangles)[i];
|
||||||
|
*data_float2++ = make_float2(values[t.x][0], values[t.x][1]);
|
||||||
|
*data_float2++ = make_float2(values[t.y][0], values[t.y][1]);
|
||||||
|
*data_float2++ = make_float2(values[t.z][0], values[t.z][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (corners) {
|
||||||
|
for (size_t i = 0; i < corners->size(); i++) {
|
||||||
|
const int c = (*corners)[i];
|
||||||
|
*data_float2++ = make_float2(values[c][0], values[c][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attribute.data.add_data(data, time);
|
attribute.data.add_data(data, time);
|
||||||
|
@@ -4425,12 +4425,12 @@ void HairInfoNode::compile(SVMCompiler &compiler)
|
|||||||
if (!out->links.empty()) {
|
if (!out->links.empty()) {
|
||||||
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out));
|
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out));
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
/*out = output("Fade");
|
out = output("Fade");
|
||||||
if(!out->links.empty()) {
|
if(!out->links.empty()) {
|
||||||
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out));
|
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out));
|
||||||
}*/
|
}
|
||||||
|
#endif
|
||||||
out = output("Random");
|
out = output("Random");
|
||||||
if (!out->links.empty()) {
|
if (!out->links.empty()) {
|
||||||
int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
|
int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
|
||||||
@@ -6093,6 +6093,7 @@ NODE_DEFINE(VectorMathNode)
|
|||||||
type_enum.insert("reflect", NODE_VECTOR_MATH_REFLECT);
|
type_enum.insert("reflect", NODE_VECTOR_MATH_REFLECT);
|
||||||
type_enum.insert("refract", NODE_VECTOR_MATH_REFRACT);
|
type_enum.insert("refract", NODE_VECTOR_MATH_REFRACT);
|
||||||
type_enum.insert("faceforward", NODE_VECTOR_MATH_FACEFORWARD);
|
type_enum.insert("faceforward", NODE_VECTOR_MATH_FACEFORWARD);
|
||||||
|
type_enum.insert("multiply_add", NODE_VECTOR_MATH_MULTIPLY_ADD);
|
||||||
|
|
||||||
type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
|
type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
|
||||||
|
|
||||||
@@ -6165,7 +6166,8 @@ void VectorMathNode::compile(SVMCompiler &compiler)
|
|||||||
int vector_stack_offset = compiler.stack_assign_if_linked(vector_out);
|
int vector_stack_offset = compiler.stack_assign_if_linked(vector_out);
|
||||||
|
|
||||||
/* 3 Vector Operators */
|
/* 3 Vector Operators */
|
||||||
if (math_type == NODE_VECTOR_MATH_WRAP || math_type == NODE_VECTOR_MATH_FACEFORWARD) {
|
if (math_type == NODE_VECTOR_MATH_WRAP || math_type == NODE_VECTOR_MATH_FACEFORWARD ||
|
||||||
|
math_type == NODE_VECTOR_MATH_MULTIPLY_ADD) {
|
||||||
ShaderInput *vector3_in = input("Vector3");
|
ShaderInput *vector3_in = input("Vector3");
|
||||||
int vector3_stack_offset = compiler.stack_assign(vector3_in);
|
int vector3_stack_offset = compiler.stack_assign(vector3_in);
|
||||||
compiler.add_node(
|
compiler.add_node(
|
||||||
|
@@ -195,4 +195,4 @@ class OSLCompiler {
|
|||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
#endif /* __OSL_H__ */
|
#endif /* __OSL_H__ */
|
||||||
|
@@ -1252,7 +1252,7 @@ bool Session::update_progressive_refine(bool cancel)
|
|||||||
double current_time = time_dt();
|
double current_time = time_dt();
|
||||||
|
|
||||||
if (current_time - last_update_time < params.progressive_update_timeout) {
|
if (current_time - last_update_time < params.progressive_update_timeout) {
|
||||||
/* if last sample was processed, we need to write buffers anyway */
|
/* If last sample was processed, we need to write buffers anyway. */
|
||||||
if (!write && sample != 1)
|
if (!write && sample != 1)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
if(WITH_GTESTS)
|
if(WITH_GTESTS)
|
||||||
Include(GTestTesting)
|
Include(GTestTesting)
|
||||||
|
|
||||||
# Otherwise we get warnings here that we cant fix in external projects
|
# Otherwise we get warnings here that we can't fix in external projects
|
||||||
remove_strict_flags()
|
remove_strict_flags()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@@ -223,12 +223,14 @@ ccl_device_inline ssef fastpow24(const ssef &arg)
|
|||||||
ssef x = fastpow<0x3F4CCCCD, 0x4F55A7FB>(arg); // error max = 0.17 avg = 0.0018 |avg| = 0.05
|
ssef x = fastpow<0x3F4CCCCD, 0x4F55A7FB>(arg); // error max = 0.17 avg = 0.0018 |avg| = 0.05
|
||||||
ssef arg2 = arg * arg;
|
ssef arg2 = arg * arg;
|
||||||
ssef arg4 = arg2 * arg2;
|
ssef arg4 = arg2 * arg2;
|
||||||
x = improve_5throot_solution(x,
|
|
||||||
arg4); /* error max = 0.018 avg = 0.0031 |avg| = 0.0031 */
|
/* error max = 0.018 avg = 0.0031 |avg| = 0.0031 */
|
||||||
x = improve_5throot_solution(x,
|
x = improve_5throot_solution(x, arg4);
|
||||||
arg4); /* error max = 0.00021 avg = 1.6e-05 |avg| = 1.6e-05 */
|
/* error max = 0.00021 avg = 1.6e-05 |avg| = 1.6e-05 */
|
||||||
x = improve_5throot_solution(x,
|
x = improve_5throot_solution(x, arg4);
|
||||||
arg4); /* error max = 6.1e-07 avg = 5.2e-08 |avg| = 1.1e-07 */
|
/* error max = 6.1e-07 avg = 5.2e-08 |avg| = 1.1e-07 */
|
||||||
|
x = improve_5throot_solution(x, arg4);
|
||||||
|
|
||||||
return x * (x * x);
|
return x * (x * x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -129,7 +129,7 @@ class DebugFlags {
|
|||||||
DEVICE_NONE,
|
DEVICE_NONE,
|
||||||
/* All OpenCL devices will be used. */
|
/* All OpenCL devices will be used. */
|
||||||
DEVICE_ALL,
|
DEVICE_ALL,
|
||||||
/* Default system OpenCL device will be used. */
|
/* Default system OpenCL device will be used. */
|
||||||
DEVICE_DEFAULT,
|
DEVICE_DEFAULT,
|
||||||
/* Host processor will be used. */
|
/* Host processor will be used. */
|
||||||
DEVICE_CPU,
|
DEVICE_CPU,
|
||||||
|
@@ -282,8 +282,8 @@ static CPUCapabilities &system_cpu_capabilities()
|
|||||||
/* actual opcode for xgetbv */
|
/* actual opcode for xgetbv */
|
||||||
__asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(xcr_feature_mask), "=d"(edx) : "c"(0));
|
__asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(xcr_feature_mask), "=d"(edx) : "c"(0));
|
||||||
# elif defined(_MSC_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
|
# elif defined(_MSC_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
|
||||||
xcr_feature_mask = (uint32_t)_xgetbv(
|
/* Minimum VS2010 SP1 compiler is required. */
|
||||||
_XCR_XFEATURE_ENABLED_MASK); /* min VS2010 SP1 compiler is required */
|
xcr_feature_mask = (uint32_t)_xgetbv(_XCR_XFEATURE_ENABLED_MASK);
|
||||||
# else
|
# else
|
||||||
xcr_feature_mask = 0;
|
xcr_feature_mask = 0;
|
||||||
# endif
|
# endif
|
||||||
|
@@ -88,7 +88,7 @@ class TaskScheduler {
|
|||||||
|
|
||||||
/* Approximate number of threads that will work on task, which may be lower
|
/* Approximate number of threads that will work on task, which may be lower
|
||||||
* or higher than the actual number of threads. Use as little as possible and
|
* or higher than the actual number of threads. Use as little as possible and
|
||||||
* leave splitting up tasks to the scheduler.. */
|
* leave splitting up tasks to the scheduler. */
|
||||||
static int num_threads();
|
static int num_threads();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@@ -93,42 +93,23 @@ void my_guess_pkt_duration(AVFormatContext *s, AVStream *st, AVPacket *pkt)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
FFMPEG_INLINE
|
FFMPEG_INLINE
|
||||||
void my_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
|
int64_t timestamp_from_pts_or_dts(int64_t pts, int64_t dts)
|
||||||
{
|
{
|
||||||
int i;
|
/* Some videos do not have any pts values, use dts instead in those cases if
|
||||||
|
* possible. Usually when this happens dts can act as pts because as all frames
|
||||||
for (i = 0; i < s->nb_streams; i++) {
|
* should then be presented in their decoded in order. IE pts == dts. */
|
||||||
AVStream *st = s->streams[i];
|
|
||||||
|
|
||||||
st->cur_dts = av_rescale(timestamp,
|
|
||||||
st->time_base.den * (int64_t)ref_st->time_base.num,
|
|
||||||
st->time_base.num * (int64_t)ref_st->time_base.den);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FFMPEG_INLINE
|
|
||||||
void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
|
|
||||||
{
|
|
||||||
my_update_cur_dts(s, ref_st, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
FFMPEG_INLINE
|
|
||||||
int64_t av_get_pts_from_frame(AVFormatContext *avctx, AVFrame *picture)
|
|
||||||
{
|
|
||||||
int64_t pts;
|
|
||||||
pts = picture->pts;
|
|
||||||
|
|
||||||
if (pts == AV_NOPTS_VALUE) {
|
if (pts == AV_NOPTS_VALUE) {
|
||||||
pts = picture->pkt_dts;
|
return dts;
|
||||||
}
|
}
|
||||||
if (pts == AV_NOPTS_VALUE) {
|
|
||||||
pts = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)avctx;
|
|
||||||
return pts;
|
return pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FFMPEG_INLINE
|
||||||
|
int64_t av_get_pts_from_frame(AVFrame *picture)
|
||||||
|
{
|
||||||
|
return timestamp_from_pts_or_dts(picture->pts, picture->pkt_dts);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Deinterlace code block
|
/** \name Deinterlace code block
|
||||||
*
|
*
|
||||||
|
@@ -282,6 +282,7 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||||||
${wayland-egl_INCLUDE_DIRS}
|
${wayland-egl_INCLUDE_DIRS}
|
||||||
${xkbcommon_INCLUDE_DIRS}
|
${xkbcommon_INCLUDE_DIRS}
|
||||||
${wayland-cursor_INCLUDE_DIRS}
|
${wayland-cursor_INCLUDE_DIRS}
|
||||||
|
${dbus_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND SRC
|
list(APPEND SRC
|
||||||
@@ -321,6 +322,11 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||||||
xdg-shell
|
xdg-shell
|
||||||
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
|
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
|
||||||
)
|
)
|
||||||
|
# xdg-decoration.
|
||||||
|
generate_protocol_bindings(
|
||||||
|
xdg-decoration
|
||||||
|
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||||
|
)
|
||||||
# Pointer-constraints.
|
# Pointer-constraints.
|
||||||
generate_protocol_bindings(
|
generate_protocol_bindings(
|
||||||
pointer-constraints
|
pointer-constraints
|
||||||
@@ -364,6 +370,7 @@ elseif(WIN32)
|
|||||||
intern/GHOST_DropTargetWin32.cpp
|
intern/GHOST_DropTargetWin32.cpp
|
||||||
intern/GHOST_SystemWin32.cpp
|
intern/GHOST_SystemWin32.cpp
|
||||||
intern/GHOST_WindowWin32.cpp
|
intern/GHOST_WindowWin32.cpp
|
||||||
|
intern/GHOST_Wintab.cpp
|
||||||
|
|
||||||
intern/GHOST_ContextD3D.h
|
intern/GHOST_ContextD3D.h
|
||||||
intern/GHOST_DisplayManagerWin32.h
|
intern/GHOST_DisplayManagerWin32.h
|
||||||
@@ -371,6 +378,7 @@ elseif(WIN32)
|
|||||||
intern/GHOST_SystemWin32.h
|
intern/GHOST_SystemWin32.h
|
||||||
intern/GHOST_TaskbarWin32.h
|
intern/GHOST_TaskbarWin32.h
|
||||||
intern/GHOST_WindowWin32.h
|
intern/GHOST_WindowWin32.h
|
||||||
|
intern/GHOST_Wintab.h
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT WITH_GL_EGL)
|
if(NOT WITH_GL_EGL)
|
||||||
@@ -475,10 +483,17 @@ if(WITH_XR_OPENXR)
|
|||||||
shlwapi
|
shlwapi
|
||||||
)
|
)
|
||||||
elseif(UNIX AND NOT APPLE)
|
elseif(UNIX AND NOT APPLE)
|
||||||
list(APPEND XR_PLATFORM_DEFINES
|
list(APPEND XR_PLATFORM_DEFINES -DXR_OS_LINUX)
|
||||||
-DXR_OS_LINUX
|
if (WITH_GHOST_WAYLAND)
|
||||||
-DXR_USE_PLATFORM_XLIB
|
list(APPEND XR_PLATFORM_DEFINES -DXR_USE_PLATFORM_WAYLAND)
|
||||||
)
|
endif()
|
||||||
|
if (WITH_GHOST_X11)
|
||||||
|
if (WITH_GL_EGL)
|
||||||
|
list(APPEND XR_PLATFORM_DEFINES -DXR_USE_PLATFORM_EGL)
|
||||||
|
else()
|
||||||
|
list(APPEND XR_PLATFORM_DEFINES -DXR_USE_PLATFORM_XLIB)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(-DWITH_XR_OPENXR ${XR_PLATFORM_DEFINES})
|
add_definitions(-DWITH_XR_OPENXR ${XR_PLATFORM_DEFINES})
|
||||||
|
@@ -105,7 +105,9 @@ typedef enum {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GHOST_kTabletAutomatic = 0,
|
GHOST_kTabletAutomatic = 0,
|
||||||
GHOST_kTabletNative,
|
/* Show as Windows Ink to users to match "Use Windows Ink" in tablet utilities,
|
||||||
|
* but we use the dependent Windows Pointer API. */
|
||||||
|
GHOST_kTabletWinPointer,
|
||||||
GHOST_kTabletWintab,
|
GHOST_kTabletWintab,
|
||||||
} GHOST_TTabletAPI;
|
} GHOST_TTabletAPI;
|
||||||
|
|
||||||
@@ -168,7 +170,7 @@ typedef enum {
|
|||||||
GHOST_kButtonMaskRight,
|
GHOST_kButtonMaskRight,
|
||||||
GHOST_kButtonMaskButton4,
|
GHOST_kButtonMaskButton4,
|
||||||
GHOST_kButtonMaskButton5,
|
GHOST_kButtonMaskButton5,
|
||||||
/* Trackballs and programmable buttons */
|
/* Trackballs and programmable buttons. */
|
||||||
GHOST_kButtonMaskButton6,
|
GHOST_kButtonMaskButton6,
|
||||||
GHOST_kButtonMaskButton7,
|
GHOST_kButtonMaskButton7,
|
||||||
GHOST_kButtonNumMasks
|
GHOST_kButtonNumMasks
|
||||||
@@ -177,15 +179,15 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
GHOST_kEventUnknown = 0,
|
GHOST_kEventUnknown = 0,
|
||||||
|
|
||||||
GHOST_kEventCursorMove, /// Mouse move event
|
GHOST_kEventCursorMove, /* Mouse move event. */
|
||||||
GHOST_kEventButtonDown, /// Mouse button event
|
GHOST_kEventButtonDown, /* Mouse button event. */
|
||||||
GHOST_kEventButtonUp, /// Mouse button event
|
GHOST_kEventButtonUp, /* Mouse button event. */
|
||||||
GHOST_kEventWheel, /// Mouse wheel event
|
GHOST_kEventWheel, /* Mouse wheel event. */
|
||||||
GHOST_kEventTrackpad, /// Trackpad event
|
GHOST_kEventTrackpad, /* Trackpad event. */
|
||||||
|
|
||||||
#ifdef WITH_INPUT_NDOF
|
#ifdef WITH_INPUT_NDOF
|
||||||
GHOST_kEventNDOFMotion, /// N degree of freedom device motion event
|
GHOST_kEventNDOFMotion, /* N degree of freedom device motion event. */
|
||||||
GHOST_kEventNDOFButton, /// N degree of freedom device button event
|
GHOST_kEventNDOFButton, /* N degree of freedom device button event. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GHOST_kEventKeyDown,
|
GHOST_kEventKeyDown,
|
||||||
@@ -207,8 +209,8 @@ typedef enum {
|
|||||||
GHOST_kEventDraggingExited,
|
GHOST_kEventDraggingExited,
|
||||||
GHOST_kEventDraggingDropDone,
|
GHOST_kEventDraggingDropDone,
|
||||||
|
|
||||||
GHOST_kEventOpenMainFile, // Needed for Cocoa to open double-clicked .blend file at startup
|
GHOST_kEventOpenMainFile, /* Needed for Cocoa to open double-clicked .blend file at startup. */
|
||||||
GHOST_kEventNativeResolutionChange, // Needed for Cocoa when window moves to other display
|
GHOST_kEventNativeResolutionChange, /* Needed for Cocoa when window moves to other display. */
|
||||||
|
|
||||||
GHOST_kEventTimer,
|
GHOST_kEventTimer,
|
||||||
|
|
||||||
@@ -281,7 +283,7 @@ typedef enum {
|
|||||||
GHOST_kKeyPeriod = '.',
|
GHOST_kKeyPeriod = '.',
|
||||||
GHOST_kKeySlash = '/',
|
GHOST_kKeySlash = '/',
|
||||||
|
|
||||||
// Number keys
|
/* Number keys. */
|
||||||
GHOST_kKey0 = '0',
|
GHOST_kKey0 = '0',
|
||||||
GHOST_kKey1,
|
GHOST_kKey1,
|
||||||
GHOST_kKey2,
|
GHOST_kKey2,
|
||||||
@@ -296,7 +298,7 @@ typedef enum {
|
|||||||
GHOST_kKeySemicolon = ';',
|
GHOST_kKeySemicolon = ';',
|
||||||
GHOST_kKeyEqual = '=',
|
GHOST_kKeyEqual = '=',
|
||||||
|
|
||||||
// Character keys
|
/* Character keys. */
|
||||||
GHOST_kKeyA = 'A',
|
GHOST_kKeyA = 'A',
|
||||||
GHOST_kKeyB,
|
GHOST_kKeyB,
|
||||||
GHOST_kKeyC,
|
GHOST_kKeyC,
|
||||||
@@ -335,9 +337,9 @@ typedef enum {
|
|||||||
GHOST_kKeyRightControl,
|
GHOST_kKeyRightControl,
|
||||||
GHOST_kKeyLeftAlt,
|
GHOST_kKeyLeftAlt,
|
||||||
GHOST_kKeyRightAlt,
|
GHOST_kKeyRightAlt,
|
||||||
GHOST_kKeyOS, // Command key on Apple, Windows key(s) on Windows
|
GHOST_kKeyOS, /* Command key on Apple, Windows key(s) on Windows. */
|
||||||
GHOST_kKeyGrLess, // German PC only!
|
GHOST_kKeyGrLess, /* German PC only! */
|
||||||
GHOST_kKeyApp, /* Also known as menu key. */
|
GHOST_kKeyApp, /* Also known as menu key. */
|
||||||
|
|
||||||
GHOST_kKeyCapsLock,
|
GHOST_kKeyCapsLock,
|
||||||
GHOST_kKeyNumLock,
|
GHOST_kKeyNumLock,
|
||||||
@@ -358,7 +360,7 @@ typedef enum {
|
|||||||
GHOST_kKeyUpPage,
|
GHOST_kKeyUpPage,
|
||||||
GHOST_kKeyDownPage,
|
GHOST_kKeyDownPage,
|
||||||
|
|
||||||
// Numpad keys
|
/* Numpad keys. */
|
||||||
GHOST_kKeyNumpad0,
|
GHOST_kKeyNumpad0,
|
||||||
GHOST_kKeyNumpad1,
|
GHOST_kKeyNumpad1,
|
||||||
GHOST_kKeyNumpad2,
|
GHOST_kKeyNumpad2,
|
||||||
@@ -376,7 +378,7 @@ typedef enum {
|
|||||||
GHOST_kKeyNumpadAsterisk,
|
GHOST_kKeyNumpadAsterisk,
|
||||||
GHOST_kKeyNumpadSlash,
|
GHOST_kKeyNumpadSlash,
|
||||||
|
|
||||||
// Function keys
|
/* Function keys. */
|
||||||
GHOST_kKeyF1,
|
GHOST_kKeyF1,
|
||||||
GHOST_kKeyF2,
|
GHOST_kKeyF2,
|
||||||
GHOST_kKeyF3,
|
GHOST_kKeyF3,
|
||||||
@@ -402,7 +404,7 @@ typedef enum {
|
|||||||
GHOST_kKeyF23,
|
GHOST_kKeyF23,
|
||||||
GHOST_kKeyF24,
|
GHOST_kKeyF24,
|
||||||
|
|
||||||
// Multimedia keypad buttons
|
/* Multimedia keypad buttons. */
|
||||||
GHOST_kKeyMediaPlay,
|
GHOST_kKeyMediaPlay,
|
||||||
GHOST_kKeyMediaStop,
|
GHOST_kKeyMediaStop,
|
||||||
GHOST_kKeyMediaFirst,
|
GHOST_kKeyMediaFirst,
|
||||||
@@ -479,9 +481,9 @@ typedef struct {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GHOST_kDragnDropTypeUnknown = 0,
|
GHOST_kDragnDropTypeUnknown = 0,
|
||||||
GHOST_kDragnDropTypeFilenames, /*Array of strings representing file names (full path) */
|
GHOST_kDragnDropTypeFilenames, /* Array of strings representing file names (full path). */
|
||||||
GHOST_kDragnDropTypeString, /* Unformatted text UTF-8 string */
|
GHOST_kDragnDropTypeString, /* Unformatted text UTF-8 string. */
|
||||||
GHOST_kDragnDropTypeBitmap /*Bitmap image data */
|
GHOST_kDragnDropTypeBitmap /* Bitmap image data. */
|
||||||
} GHOST_TDragnDropTypes;
|
} GHOST_TDragnDropTypes;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -527,18 +529,23 @@ typedef enum {
|
|||||||
#ifdef WITH_INPUT_NDOF
|
#ifdef WITH_INPUT_NDOF
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/** N-degree of freedom device data v3 [GSoC 2010] */
|
/** N-degree of freedom device data v3 [GSoC 2010] */
|
||||||
// Each component normally ranges from -1 to +1, but can exceed that.
|
/* Each component normally ranges from -1 to +1, but can exceed that.
|
||||||
// These use blender standard view coordinates, with positive rotations being CCW about the axis.
|
* These use blender standard view coordinates,
|
||||||
float tx, ty, tz; // translation
|
* with positive rotations being CCW about the axis. */
|
||||||
float rx, ry, rz; // rotation:
|
/* translation: */
|
||||||
// axis = (rx,ry,rz).normalized
|
float tx, ty, tz;
|
||||||
// amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg]
|
/* rotation:
|
||||||
float dt; // time since previous NDOF Motion event
|
* - `axis = (rx,ry,rz).normalized`
|
||||||
GHOST_TProgress progress; // Starting, InProgress or Finishing (for modal handlers)
|
* - `amount = (rx,ry,rz).magnitude` [in revolutions, 1.0 = 360 deg]. */
|
||||||
|
float rx, ry, rz;
|
||||||
|
/** Time since previous NDOF Motion event */
|
||||||
|
float dt;
|
||||||
|
/** Starting, #GHOST_kInProgress or #GHOST_kFinishing (for modal handlers) */
|
||||||
|
GHOST_TProgress progress;
|
||||||
} GHOST_TEventNDOFMotionData;
|
} GHOST_TEventNDOFMotionData;
|
||||||
|
|
||||||
typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction;
|
typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction;
|
||||||
// good for mouse or other buttons too, hmmm?
|
/* Good for mouse or other buttons too, hmmm? */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GHOST_TButtonAction action;
|
GHOST_TButtonAction action;
|
||||||
@@ -561,7 +568,7 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
/** The ascii code for the key event ('\0' if none). */
|
/** The ascii code for the key event ('\0' if none). */
|
||||||
char ascii;
|
char ascii;
|
||||||
/** The unicode character. if the length is 6, not NULL terminated if all 6 are set */
|
/** The unicode character. if the length is 6, not NULL terminated if all 6 are set. */
|
||||||
char utf8_buf[6];
|
char utf8_buf[6];
|
||||||
|
|
||||||
/** Generated by auto-repeat. */
|
/** Generated by auto-repeat. */
|
||||||
@@ -594,7 +601,8 @@ typedef void *GHOST_TEmbedderWindowID;
|
|||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// I can't use "Window" from "<X11/Xlib.h>" because it conflits with Window defined in winlay.h
|
/* I can't use "Window" from `X11/Xlib.h`
|
||||||
|
* because it conflicts with Window defined in `winlay.h`. */
|
||||||
typedef int GHOST_TEmbedderWindowID;
|
typedef int GHOST_TEmbedderWindowID;
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
@@ -642,8 +650,10 @@ typedef void *(*GHOST_XrGraphicsContextBindFn)(void);
|
|||||||
typedef void (*GHOST_XrGraphicsContextUnbindFn)(GHOST_ContextHandle graphics_context);
|
typedef void (*GHOST_XrGraphicsContextUnbindFn)(GHOST_ContextHandle graphics_context);
|
||||||
typedef void (*GHOST_XrDrawViewFn)(const struct GHOST_XrDrawViewInfo *draw_view, void *customdata);
|
typedef void (*GHOST_XrDrawViewFn)(const struct GHOST_XrDrawViewInfo *draw_view, void *customdata);
|
||||||
|
|
||||||
/* An array of GHOST_TXrGraphicsBinding items defining the candidate bindings to use. The first
|
/**
|
||||||
* available candidate will be chosen, so order defines priority. */
|
* An array of #GHOST_TXrGraphicsBinding items defining the candidate bindings to use.
|
||||||
|
* The first available candidate will be chosen, so order defines priority.
|
||||||
|
*/
|
||||||
typedef const GHOST_TXrGraphicsBinding *GHOST_XrGraphicsBindingCandidates;
|
typedef const GHOST_TXrGraphicsBinding *GHOST_XrGraphicsBindingCandidates;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -684,7 +694,7 @@ typedef struct GHOST_XrDrawViewInfo {
|
|||||||
float angle_up, angle_down;
|
float angle_up, angle_down;
|
||||||
} fov;
|
} fov;
|
||||||
|
|
||||||
/** Set if the buffer should be submitted with a srgb transfer applied. */
|
/** Set if the buffer should be submitted with a SRGB transfer applied. */
|
||||||
char expects_srgb_buffer;
|
char expects_srgb_buffer;
|
||||||
} GHOST_XrDrawViewInfo;
|
} GHOST_XrDrawViewInfo;
|
||||||
|
|
||||||
@@ -734,7 +744,7 @@ typedef struct GHOST_XrActionSpaceInfo {
|
|||||||
typedef struct GHOST_XrActionBindingInfo {
|
typedef struct GHOST_XrActionBindingInfo {
|
||||||
const char *action_name;
|
const char *action_name;
|
||||||
GHOST_TUns32 count_interaction_paths;
|
GHOST_TUns32 count_interaction_paths;
|
||||||
/** Interaction path: User (subaction) path + component path. */
|
/** Interaction path: User (sub-action) path + component path. */
|
||||||
const char **interaction_paths;
|
const char **interaction_paths;
|
||||||
} GHOST_XrActionBindingInfo;
|
} GHOST_XrActionBindingInfo;
|
||||||
|
|
||||||
|
@@ -149,6 +149,9 @@ static bool egl_chk(bool result, const char *file = NULL, int line = 0, const ch
|
|||||||
static_cast<unsigned int>(error),
|
static_cast<unsigned int>(error),
|
||||||
code ? code : "<Unknown>",
|
code ? code : "<Unknown>",
|
||||||
msg ? msg : "<Unknown>");
|
msg ? msg : "<Unknown>");
|
||||||
|
(void)(file);
|
||||||
|
(void)(line);
|
||||||
|
(void)(text);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +202,8 @@ template<typename T> T &choose_api(EGLenum api, T &a, T &b, T &c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_ContextEGL::GHOST_ContextEGL(bool stereoVisual,
|
GHOST_ContextEGL::GHOST_ContextEGL(const GHOST_System *const system,
|
||||||
|
bool stereoVisual,
|
||||||
EGLNativeWindowType nativeWindow,
|
EGLNativeWindowType nativeWindow,
|
||||||
EGLNativeDisplayType nativeDisplay,
|
EGLNativeDisplayType nativeDisplay,
|
||||||
EGLint contextProfileMask,
|
EGLint contextProfileMask,
|
||||||
@@ -209,6 +213,7 @@ GHOST_ContextEGL::GHOST_ContextEGL(bool stereoVisual,
|
|||||||
EGLint contextResetNotificationStrategy,
|
EGLint contextResetNotificationStrategy,
|
||||||
EGLenum api)
|
EGLenum api)
|
||||||
: GHOST_Context(stereoVisual),
|
: GHOST_Context(stereoVisual),
|
||||||
|
m_system(system),
|
||||||
m_nativeDisplay(nativeDisplay),
|
m_nativeDisplay(nativeDisplay),
|
||||||
m_nativeWindow(nativeWindow),
|
m_nativeWindow(nativeWindow),
|
||||||
m_contextProfileMask(contextProfileMask),
|
m_contextProfileMask(contextProfileMask),
|
||||||
@@ -285,6 +290,21 @@ GHOST_TSuccess GHOST_ContextEGL::getSwapInterval(int &intervalOut)
|
|||||||
return GHOST_kSuccess;
|
return GHOST_kSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EGLDisplay GHOST_ContextEGL::getDisplay() const
|
||||||
|
{
|
||||||
|
return m_display;
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLConfig GHOST_ContextEGL::getConfig() const
|
||||||
|
{
|
||||||
|
return m_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLContext GHOST_ContextEGL::getContext() const
|
||||||
|
{
|
||||||
|
return m_context;
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_ContextEGL::activateDrawingContext()
|
GHOST_TSuccess GHOST_ContextEGL::activateDrawingContext()
|
||||||
{
|
{
|
||||||
if (m_display) {
|
if (m_display) {
|
||||||
@@ -456,9 +476,7 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||||||
|
|
||||||
attrib_list.push_back(EGL_NONE);
|
attrib_list.push_back(EGL_NONE);
|
||||||
|
|
||||||
EGLConfig config;
|
if (!EGL_CHK(::eglChooseConfig(m_display, &(attrib_list[0]), &m_config, 1, &num_config)))
|
||||||
|
|
||||||
if (!EGL_CHK(::eglChooseConfig(m_display, &(attrib_list[0]), &config, 1, &num_config)))
|
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
// A common error is to assume that ChooseConfig worked because it returned EGL_TRUE
|
// A common error is to assume that ChooseConfig worked because it returned EGL_TRUE
|
||||||
@@ -466,7 +484,7 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (m_nativeWindow != 0) {
|
if (m_nativeWindow != 0) {
|
||||||
m_surface = ::eglCreateWindowSurface(m_display, config, m_nativeWindow, NULL);
|
m_surface = ::eglCreateWindowSurface(m_display, m_config, m_nativeWindow, NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
static const EGLint pb_attrib_list[] = {
|
static const EGLint pb_attrib_list[] = {
|
||||||
@@ -476,7 +494,7 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||||||
1,
|
1,
|
||||||
EGL_NONE,
|
EGL_NONE,
|
||||||
};
|
};
|
||||||
m_surface = ::eglCreatePbufferSurface(m_display, config, pb_attrib_list);
|
m_surface = ::eglCreatePbufferSurface(m_display, m_config, pb_attrib_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EGL_CHK(m_surface != EGL_NO_SURFACE))
|
if (!EGL_CHK(m_surface != EGL_NO_SURFACE))
|
||||||
@@ -577,7 +595,7 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||||||
|
|
||||||
attrib_list.push_back(EGL_NONE);
|
attrib_list.push_back(EGL_NONE);
|
||||||
|
|
||||||
m_context = ::eglCreateContext(m_display, config, m_sharedContext, &(attrib_list[0]));
|
m_context = ::eglCreateContext(m_display, m_config, m_sharedContext, &(attrib_list[0]));
|
||||||
|
|
||||||
if (!EGL_CHK(m_context != EGL_NO_CONTEXT))
|
if (!EGL_CHK(m_context != EGL_NO_CONTEXT))
|
||||||
goto error;
|
goto error;
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GHOST_Context.h"
|
#include "GHOST_Context.h"
|
||||||
|
#include "GHOST_System.h"
|
||||||
|
|
||||||
#include <GL/eglew.h>
|
#include <GL/eglew.h>
|
||||||
|
|
||||||
@@ -36,11 +37,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
class GHOST_ContextEGL : public GHOST_Context {
|
class GHOST_ContextEGL : public GHOST_Context {
|
||||||
|
/* XR code needs low level graphics data to send to OpenXR. */
|
||||||
|
friend class GHOST_XrGraphicsBindingOpenGL;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
GHOST_ContextEGL(bool stereoVisual,
|
GHOST_ContextEGL(const GHOST_System *const system,
|
||||||
|
bool stereoVisual,
|
||||||
EGLNativeWindowType nativeWindow,
|
EGLNativeWindowType nativeWindow,
|
||||||
EGLNativeDisplayType nativeDisplay,
|
EGLNativeDisplayType nativeDisplay,
|
||||||
EGLint contextProfileMask,
|
EGLint contextProfileMask,
|
||||||
@@ -100,9 +105,17 @@ class GHOST_ContextEGL : public GHOST_Context {
|
|||||||
*/
|
*/
|
||||||
GHOST_TSuccess getSwapInterval(int &intervalOut);
|
GHOST_TSuccess getSwapInterval(int &intervalOut);
|
||||||
|
|
||||||
|
EGLDisplay getDisplay() const;
|
||||||
|
|
||||||
|
EGLConfig getConfig() const;
|
||||||
|
|
||||||
|
EGLContext getContext() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool initContextEGLEW();
|
bool initContextEGLEW();
|
||||||
|
|
||||||
|
const GHOST_System *const m_system;
|
||||||
|
|
||||||
EGLNativeDisplayType m_nativeDisplay;
|
EGLNativeDisplayType m_nativeDisplay;
|
||||||
EGLNativeWindowType m_nativeWindow;
|
EGLNativeWindowType m_nativeWindow;
|
||||||
|
|
||||||
@@ -117,6 +130,7 @@ class GHOST_ContextEGL : public GHOST_Context {
|
|||||||
EGLContext m_context;
|
EGLContext m_context;
|
||||||
EGLSurface m_surface;
|
EGLSurface m_surface;
|
||||||
EGLDisplay m_display;
|
EGLDisplay m_display;
|
||||||
|
EGLConfig m_config;
|
||||||
|
|
||||||
EGLint m_swap_interval;
|
EGLint m_swap_interval;
|
||||||
|
|
||||||
|
@@ -124,7 +124,7 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
|
|||||||
GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store);
|
GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Begin Inline Glew */
|
/* Begin Inline Glew */
|
||||||
|
|
||||||
#ifdef USE_GLXEW_INIT_WORKAROUND
|
#ifdef USE_GLXEW_INIT_WORKAROUND
|
||||||
const GLubyte *extStart = (GLubyte *)"";
|
const GLubyte *extStart = (GLubyte *)"";
|
||||||
|
@@ -161,5 +161,5 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(
|
|||||||
|
|
||||||
// CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues);
|
// CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues);
|
||||||
|
|
||||||
return /*err == CGDisplayNoErr ?*/ GHOST_kSuccess /*: GHOST_kFailure*/;
|
return /* err == CGDisplayNoErr ? */ GHOST_kSuccess /* : GHOST_kFailure */;
|
||||||
}
|
}
|
||||||
|
@@ -160,7 +160,7 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::setCurrentDisplaySetting(
|
|||||||
else {
|
else {
|
||||||
/* this is a problem for the BGE player :S, perhaps SDL2 will resolve at some point.
|
/* this is a problem for the BGE player :S, perhaps SDL2 will resolve at some point.
|
||||||
* we really need SDL_SetDisplayModeForDisplay() to become an API func! - campbell */
|
* we really need SDL_SetDisplayModeForDisplay() to become an API func! - campbell */
|
||||||
printf("no windows available, cant fullscreen\n");
|
printf("no windows available, can't fullscreen\n");
|
||||||
|
|
||||||
/* do not fail, we will try again later when the window is created - wander */
|
/* do not fail, we will try again later when the window is created - wander */
|
||||||
return GHOST_kSuccess;
|
return GHOST_kSuccess;
|
||||||
|
@@ -31,10 +31,17 @@ class GHOST_IXrGraphicsBinding {
|
|||||||
public:
|
public:
|
||||||
union {
|
union {
|
||||||
#if defined(WITH_GHOST_X11)
|
#if defined(WITH_GHOST_X11)
|
||||||
|
# if defined(WITH_GL_EGL)
|
||||||
|
XrGraphicsBindingEGLMNDX egl;
|
||||||
|
# else
|
||||||
XrGraphicsBindingOpenGLXlibKHR glx;
|
XrGraphicsBindingOpenGLXlibKHR glx;
|
||||||
|
# endif
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
XrGraphicsBindingOpenGLWin32KHR wgl;
|
XrGraphicsBindingOpenGLWin32KHR wgl;
|
||||||
XrGraphicsBindingD3D11KHR d3d11;
|
XrGraphicsBindingD3D11KHR d3d11;
|
||||||
|
#endif
|
||||||
|
#if defined(WITH_GHOST_WAYLAND)
|
||||||
|
XrGraphicsBindingOpenGLWaylandKHR wl;
|
||||||
#endif
|
#endif
|
||||||
} oxr_binding;
|
} oxr_binding;
|
||||||
|
|
||||||
|
@@ -239,7 +239,7 @@ class GHOST_System : public GHOST_ISystem {
|
|||||||
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
|
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
|
||||||
* \param api: Enum indicating which API to use.
|
* \param api: Enum indicating which API to use.
|
||||||
*/
|
*/
|
||||||
void setTabletAPI(GHOST_TTabletAPI api);
|
virtual void setTabletAPI(GHOST_TTabletAPI api);
|
||||||
GHOST_TTabletAPI getTabletAPI(void);
|
GHOST_TTabletAPI getTabletAPI(void);
|
||||||
|
|
||||||
#ifdef WITH_INPUT_NDOF
|
#ifdef WITH_INPUT_NDOF
|
||||||
|
@@ -32,11 +32,7 @@
|
|||||||
#include "GHOST_WindowCocoa.h"
|
#include "GHOST_WindowCocoa.h"
|
||||||
#include "GHOST_WindowManager.h"
|
#include "GHOST_WindowManager.h"
|
||||||
|
|
||||||
#if defined(WITH_GL_EGL)
|
#include "GHOST_ContextCGL.h"
|
||||||
# include "GHOST_ContextEGL.h"
|
|
||||||
#else
|
|
||||||
# include "GHOST_ContextCGL.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WITH_INPUT_NDOF
|
#ifdef WITH_INPUT_NDOF
|
||||||
# include "GHOST_NDOFManagerCocoa.h"
|
# include "GHOST_NDOFManagerCocoa.h"
|
||||||
@@ -553,10 +549,12 @@ GHOST_TSuccess GHOST_SystemCocoa::init()
|
|||||||
// ProcessSerialNumber psn;
|
// ProcessSerialNumber psn;
|
||||||
|
|
||||||
// Carbon stuff to move window & menu to foreground
|
// Carbon stuff to move window & menu to foreground
|
||||||
/*if (!GetCurrentProcess(&psn)) {
|
#if 0
|
||||||
|
if (!GetCurrentProcess(&psn)) {
|
||||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||||
SetFrontProcess(&psn);
|
SetFrontProcess(&psn);
|
||||||
}*/
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[NSApplication sharedApplication]; // initializes NSApp
|
[NSApplication sharedApplication]; // initializes NSApp
|
||||||
|
@@ -376,7 +376,7 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
|
|||||||
bounds.wrapPoint(x_new, y_new, 8, window->getCursorGrabAxis());
|
bounds.wrapPoint(x_new, y_new, 8, window->getCursorGrabAxis());
|
||||||
window->getCursorGrabAccum(x_accum, y_accum);
|
window->getCursorGrabAccum(x_accum, y_accum);
|
||||||
|
|
||||||
// cant use setCursorPosition because the mouse may have no focus!
|
// can't use setCursorPosition because the mouse may have no focus!
|
||||||
if (x_new != x_root || y_new != y_root) {
|
if (x_new != x_root || y_new != y_root) {
|
||||||
if (1) { //xme.time > m_last_warp) {
|
if (1) { //xme.time > m_last_warp) {
|
||||||
/* when wrapping we don't need to add an event because the
|
/* when wrapping we don't need to add an event because the
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "GHOST_WaylandCursorSettings.h"
|
||||||
#include <pointer-constraints-client-protocol.h>
|
#include <pointer-constraints-client-protocol.h>
|
||||||
#include <relative-pointer-client-protocol.h>
|
#include <relative-pointer-client-protocol.h>
|
||||||
#include <wayland-cursor.h>
|
#include <wayland-cursor.h>
|
||||||
@@ -52,15 +53,6 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
struct output_t {
|
|
||||||
struct wl_output *output;
|
|
||||||
int32_t width, height;
|
|
||||||
int transform;
|
|
||||||
int scale;
|
|
||||||
std::string make;
|
|
||||||
std::string model;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct buffer_t {
|
struct buffer_t {
|
||||||
void *data;
|
void *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
@@ -72,6 +64,12 @@ struct cursor_t {
|
|||||||
struct wl_buffer *buffer;
|
struct wl_buffer *buffer;
|
||||||
struct wl_cursor_image image;
|
struct wl_cursor_image image;
|
||||||
struct buffer_t *file_buffer = nullptr;
|
struct buffer_t *file_buffer = nullptr;
|
||||||
|
struct wl_cursor_theme *theme = nullptr;
|
||||||
|
int size;
|
||||||
|
std::string theme_name;
|
||||||
|
// outputs on which the cursor is visible
|
||||||
|
std::unordered_set<const output_t *> outputs;
|
||||||
|
int scale = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct data_offer_t {
|
struct data_offer_t {
|
||||||
@@ -142,10 +140,14 @@ struct display_t {
|
|||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
struct wl_compositor *compositor = nullptr;
|
struct wl_compositor *compositor = nullptr;
|
||||||
struct xdg_wm_base *xdg_shell = nullptr;
|
struct xdg_wm_base *xdg_shell = nullptr;
|
||||||
|
struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr;
|
||||||
struct wl_shm *shm = nullptr;
|
struct wl_shm *shm = nullptr;
|
||||||
std::vector<output_t *> outputs;
|
std::vector<output_t *> outputs;
|
||||||
std::vector<input_t *> inputs;
|
std::vector<input_t *> inputs;
|
||||||
struct wl_cursor_theme *cursor_theme = nullptr;
|
struct {
|
||||||
|
std::string theme;
|
||||||
|
int size;
|
||||||
|
} cursor;
|
||||||
struct wl_data_device_manager *data_device_manager = nullptr;
|
struct wl_data_device_manager *data_device_manager = nullptr;
|
||||||
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr;
|
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr;
|
||||||
struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr;
|
struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr;
|
||||||
@@ -154,6 +156,8 @@ struct display_t {
|
|||||||
std::vector<struct wl_egl_window *> os_egl_windows;
|
std::vector<struct wl_egl_window *> os_egl_windows;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GHOST_WindowManager *window_manager = nullptr;
|
||||||
|
|
||||||
static void display_destroy(display_t *d)
|
static void display_destroy(display_t *d)
|
||||||
{
|
{
|
||||||
if (d->data_device_manager) {
|
if (d->data_device_manager) {
|
||||||
@@ -188,6 +192,9 @@ static void display_destroy(display_t *d)
|
|||||||
if (input->cursor.surface) {
|
if (input->cursor.surface) {
|
||||||
wl_surface_destroy(input->cursor.surface);
|
wl_surface_destroy(input->cursor.surface);
|
||||||
}
|
}
|
||||||
|
if (input->cursor.theme) {
|
||||||
|
wl_cursor_theme_destroy(input->cursor.theme);
|
||||||
|
}
|
||||||
if (input->pointer) {
|
if (input->pointer) {
|
||||||
wl_pointer_destroy(input->pointer);
|
wl_pointer_destroy(input->pointer);
|
||||||
}
|
}
|
||||||
@@ -210,10 +217,6 @@ static void display_destroy(display_t *d)
|
|||||||
delete input;
|
delete input;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->cursor_theme) {
|
|
||||||
wl_cursor_theme_destroy(d->cursor_theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->shm) {
|
if (d->shm) {
|
||||||
wl_shm_destroy(d->shm);
|
wl_shm_destroy(d->shm);
|
||||||
}
|
}
|
||||||
@@ -238,6 +241,10 @@ static void display_destroy(display_t *d)
|
|||||||
wl_compositor_destroy(d->compositor);
|
wl_compositor_destroy(d->compositor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (d->xdg_decoration_manager) {
|
||||||
|
zxdg_decoration_manager_v1_destroy(d->xdg_decoration_manager);
|
||||||
|
}
|
||||||
|
|
||||||
if (d->xdg_shell) {
|
if (d->xdg_shell) {
|
||||||
xdg_wm_base_destroy(d->xdg_shell);
|
xdg_wm_base_destroy(d->xdg_shell);
|
||||||
}
|
}
|
||||||
@@ -478,7 +485,9 @@ static void dnd_events(const input_t *const input, const GHOST_TEventType event)
|
|||||||
static std::string read_pipe(data_offer_t *data_offer, const std::string mime_receive)
|
static std::string read_pipe(data_offer_t *data_offer, const std::string mime_receive)
|
||||||
{
|
{
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
pipe(pipefd);
|
if (pipe(pipefd) != 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]);
|
wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]);
|
||||||
close(pipefd[1]);
|
close(pipefd[1]);
|
||||||
|
|
||||||
@@ -513,7 +522,9 @@ static void data_source_send(void *data,
|
|||||||
int32_t fd)
|
int32_t fd)
|
||||||
{
|
{
|
||||||
const char *const buffer = static_cast<char *>(data);
|
const char *const buffer = static_cast<char *>(data);
|
||||||
write(fd, buffer, strlen(buffer) + 1);
|
if (write(fd, buffer, strlen(buffer) + 1) < 0) {
|
||||||
|
GHOST_PRINT("error writing to clipboard: " << std::strerror(errno) << std::endl);
|
||||||
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -789,13 +800,80 @@ static void cursor_buffer_release(void *data, struct wl_buffer *wl_buffer)
|
|||||||
cursor_t *cursor = static_cast<cursor_t *>(data);
|
cursor_t *cursor = static_cast<cursor_t *>(data);
|
||||||
|
|
||||||
wl_buffer_destroy(wl_buffer);
|
wl_buffer_destroy(wl_buffer);
|
||||||
cursor->buffer = nullptr;
|
|
||||||
|
if (wl_buffer == cursor->buffer) {
|
||||||
|
/* the mapped buffer was from a custom cursor */
|
||||||
|
cursor->buffer = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct wl_buffer_listener cursor_buffer_listener = {
|
const struct wl_buffer_listener cursor_buffer_listener = {
|
||||||
cursor_buffer_release,
|
cursor_buffer_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GHOST_IWindow *get_window(struct wl_surface *surface)
|
||||||
|
{
|
||||||
|
if (!surface) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (GHOST_IWindow *win : window_manager->getWindows()) {
|
||||||
|
if (surface == static_cast<const GHOST_WindowWayland *>(win)->surface()) {
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool update_cursor_scale(cursor_t &cursor, wl_shm *shm)
|
||||||
|
{
|
||||||
|
int scale = 0;
|
||||||
|
for (const output_t *output : cursor.outputs) {
|
||||||
|
if (output->scale > scale)
|
||||||
|
scale = output->scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scale > 0 && cursor.scale != scale) {
|
||||||
|
cursor.scale = scale;
|
||||||
|
wl_surface_set_buffer_scale(cursor.surface, scale);
|
||||||
|
wl_cursor_theme_destroy(cursor.theme);
|
||||||
|
cursor.theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cursor_surface_enter(void *data,
|
||||||
|
struct wl_surface * /*wl_surface*/,
|
||||||
|
struct wl_output *output)
|
||||||
|
{
|
||||||
|
input_t *input = static_cast<input_t *>(data);
|
||||||
|
for (const output_t *reg_output : input->system->outputs()) {
|
||||||
|
if (reg_output->output == output) {
|
||||||
|
input->cursor.outputs.insert(reg_output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_cursor_scale(input->cursor, input->system->shm());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cursor_surface_leave(void *data,
|
||||||
|
struct wl_surface * /*wl_surface*/,
|
||||||
|
struct wl_output *output)
|
||||||
|
{
|
||||||
|
input_t *input = static_cast<input_t *>(data);
|
||||||
|
for (const output_t *reg_output : input->system->outputs()) {
|
||||||
|
if (reg_output->output == output) {
|
||||||
|
input->cursor.outputs.erase(reg_output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_cursor_scale(input->cursor, input->system->shm());
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_surface_listener cursor_surface_listener = {
|
||||||
|
cursor_surface_enter,
|
||||||
|
cursor_surface_leave,
|
||||||
|
};
|
||||||
|
|
||||||
static void pointer_enter(void *data,
|
static void pointer_enter(void *data,
|
||||||
struct wl_pointer * /*wl_pointer*/,
|
struct wl_pointer * /*wl_pointer*/,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
@@ -803,22 +881,28 @@ static void pointer_enter(void *data,
|
|||||||
wl_fixed_t surface_x,
|
wl_fixed_t surface_x,
|
||||||
wl_fixed_t surface_y)
|
wl_fixed_t surface_y)
|
||||||
{
|
{
|
||||||
if (!surface) {
|
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(get_window(surface));
|
||||||
|
|
||||||
|
if (!win) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
win->activate();
|
||||||
|
|
||||||
input_t *input = static_cast<input_t *>(data);
|
input_t *input = static_cast<input_t *>(data);
|
||||||
input->pointer_serial = serial;
|
input->pointer_serial = serial;
|
||||||
input->x = wl_fixed_to_int(surface_x);
|
input->x = win->scale() * wl_fixed_to_int(surface_x);
|
||||||
input->y = wl_fixed_to_int(surface_y);
|
input->y = win->scale() * wl_fixed_to_int(surface_y);
|
||||||
input->focus_pointer = surface;
|
input->focus_pointer = surface;
|
||||||
|
|
||||||
input->system->pushEvent(
|
win->setCursorShape(win->getCursorShape());
|
||||||
new GHOST_EventCursor(input->system->getMilliSeconds(),
|
|
||||||
GHOST_kEventCursorMove,
|
input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
|
||||||
static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface)),
|
GHOST_kEventCursorMove,
|
||||||
input->x,
|
static_cast<GHOST_WindowWayland *>(win),
|
||||||
input->y,
|
input->x,
|
||||||
GHOST_TABLET_DATA_NONE));
|
input->y,
|
||||||
|
GHOST_TABLET_DATA_NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointer_leave(void *data,
|
static void pointer_leave(void *data,
|
||||||
@@ -826,9 +910,14 @@ static void pointer_leave(void *data,
|
|||||||
uint32_t /*serial*/,
|
uint32_t /*serial*/,
|
||||||
struct wl_surface *surface)
|
struct wl_surface *surface)
|
||||||
{
|
{
|
||||||
if (surface != nullptr) {
|
GHOST_IWindow *win = get_window(surface);
|
||||||
static_cast<input_t *>(data)->focus_pointer = nullptr;
|
|
||||||
|
if (!win) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_cast<input_t *>(data)->focus_pointer = nullptr;
|
||||||
|
static_cast<GHOST_WindowWayland *>(win)->deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointer_motion(void *data,
|
static void pointer_motion(void *data,
|
||||||
@@ -839,21 +928,20 @@ static void pointer_motion(void *data,
|
|||||||
{
|
{
|
||||||
input_t *input = static_cast<input_t *>(data);
|
input_t *input = static_cast<input_t *>(data);
|
||||||
|
|
||||||
GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
|
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(get_window(input->focus_pointer));
|
||||||
wl_surface_get_user_data(input->focus_pointer));
|
|
||||||
|
|
||||||
if (!win) {
|
if (!win) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
input->x = wl_fixed_to_int(surface_x);
|
input->x = win->scale() * wl_fixed_to_int(surface_x);
|
||||||
input->y = wl_fixed_to_int(surface_y);
|
input->y = win->scale() * wl_fixed_to_int(surface_y);
|
||||||
|
|
||||||
input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
|
input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
|
||||||
GHOST_kEventCursorMove,
|
GHOST_kEventCursorMove,
|
||||||
win,
|
win,
|
||||||
wl_fixed_to_int(surface_x),
|
input->x,
|
||||||
wl_fixed_to_int(surface_y),
|
input->y,
|
||||||
GHOST_TABLET_DATA_NONE));
|
GHOST_TABLET_DATA_NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -864,6 +952,14 @@ static void pointer_button(void *data,
|
|||||||
uint32_t button,
|
uint32_t button,
|
||||||
uint32_t state)
|
uint32_t state)
|
||||||
{
|
{
|
||||||
|
input_t *input = static_cast<input_t *>(data);
|
||||||
|
|
||||||
|
GHOST_IWindow *win = get_window(input->focus_pointer);
|
||||||
|
|
||||||
|
if (!win) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_TEventType etype = GHOST_kEventUnknown;
|
GHOST_TEventType etype = GHOST_kEventUnknown;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case WL_POINTER_BUTTON_STATE_RELEASED:
|
case WL_POINTER_BUTTON_STATE_RELEASED:
|
||||||
@@ -887,9 +983,6 @@ static void pointer_button(void *data,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
input_t *input = static_cast<input_t *>(data);
|
|
||||||
GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
|
|
||||||
wl_surface_get_user_data(input->focus_pointer));
|
|
||||||
input->data_source->source_serial = serial;
|
input->data_source->source_serial = serial;
|
||||||
input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
|
input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
|
||||||
input->system->pushEvent(new GHOST_EventButton(
|
input->system->pushEvent(new GHOST_EventButton(
|
||||||
@@ -902,12 +995,18 @@ static void pointer_axis(void *data,
|
|||||||
uint32_t axis,
|
uint32_t axis,
|
||||||
wl_fixed_t value)
|
wl_fixed_t value)
|
||||||
{
|
{
|
||||||
|
input_t *input = static_cast<input_t *>(data);
|
||||||
|
|
||||||
|
GHOST_IWindow *win = get_window(input->focus_pointer);
|
||||||
|
|
||||||
|
if (!win) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) {
|
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
input_t *input = static_cast<input_t *>(data);
|
|
||||||
GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
|
|
||||||
wl_surface_get_user_data(input->focus_pointer));
|
|
||||||
input->system->pushEvent(
|
input->system->pushEvent(
|
||||||
new GHOST_EventWheel(input->system->getMilliSeconds(), win, std::signbit(value) ? +1 : -1));
|
new GHOST_EventWheel(input->system->getMilliSeconds(), win, std::signbit(value) ? +1 : -1));
|
||||||
}
|
}
|
||||||
@@ -1137,7 +1236,12 @@ static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capa
|
|||||||
input->cursor.visible = true;
|
input->cursor.visible = true;
|
||||||
input->cursor.buffer = nullptr;
|
input->cursor.buffer = nullptr;
|
||||||
input->cursor.file_buffer = new buffer_t;
|
input->cursor.file_buffer = new buffer_t;
|
||||||
|
if (!get_cursor_settings(input->cursor.theme_name, input->cursor.size)) {
|
||||||
|
input->cursor.theme_name = std::string();
|
||||||
|
input->cursor.size = default_cursor_size;
|
||||||
|
}
|
||||||
wl_pointer_add_listener(input->pointer, &pointer_listener, data);
|
wl_pointer_add_listener(input->pointer, &pointer_listener, data);
|
||||||
|
wl_surface_add_listener(input->cursor.surface, &cursor_surface_listener, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
|
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
|
||||||
@@ -1160,8 +1264,8 @@ static void output_geometry(void *data,
|
|||||||
struct wl_output * /*wl_output*/,
|
struct wl_output * /*wl_output*/,
|
||||||
int32_t /*x*/,
|
int32_t /*x*/,
|
||||||
int32_t /*y*/,
|
int32_t /*y*/,
|
||||||
int32_t /*physical_width*/,
|
int32_t physical_width,
|
||||||
int32_t /*physical_height*/,
|
int32_t physical_height,
|
||||||
int32_t /*subpixel*/,
|
int32_t /*subpixel*/,
|
||||||
const char *make,
|
const char *make,
|
||||||
const char *model,
|
const char *model,
|
||||||
@@ -1171,6 +1275,8 @@ static void output_geometry(void *data,
|
|||||||
output->transform = transform;
|
output->transform = transform;
|
||||||
output->make = std::string(make);
|
output->make = std::string(make);
|
||||||
output->model = std::string(model);
|
output->model = std::string(model);
|
||||||
|
output->width_mm = physical_width;
|
||||||
|
output->height_mm = physical_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void output_mode(void *data,
|
static void output_mode(void *data,
|
||||||
@@ -1181,8 +1287,8 @@ static void output_mode(void *data,
|
|||||||
int32_t /*refresh*/)
|
int32_t /*refresh*/)
|
||||||
{
|
{
|
||||||
output_t *output = static_cast<output_t *>(data);
|
output_t *output = static_cast<output_t *>(data);
|
||||||
output->width = width;
|
output->width_pxl = width;
|
||||||
output->height = height;
|
output->height_pxl = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1227,13 +1333,17 @@ static void global_add(void *data,
|
|||||||
struct display_t *display = static_cast<struct display_t *>(data);
|
struct display_t *display = static_cast<struct display_t *>(data);
|
||||||
if (!strcmp(interface, wl_compositor_interface.name)) {
|
if (!strcmp(interface, wl_compositor_interface.name)) {
|
||||||
display->compositor = static_cast<wl_compositor *>(
|
display->compositor = static_cast<wl_compositor *>(
|
||||||
wl_registry_bind(wl_registry, name, &wl_compositor_interface, 1));
|
wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3));
|
||||||
}
|
}
|
||||||
else if (!strcmp(interface, xdg_wm_base_interface.name)) {
|
else if (!strcmp(interface, xdg_wm_base_interface.name)) {
|
||||||
display->xdg_shell = static_cast<xdg_wm_base *>(
|
display->xdg_shell = static_cast<xdg_wm_base *>(
|
||||||
wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1));
|
wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1));
|
||||||
xdg_wm_base_add_listener(display->xdg_shell, &shell_listener, nullptr);
|
xdg_wm_base_add_listener(display->xdg_shell, &shell_listener, nullptr);
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name)) {
|
||||||
|
display->xdg_decoration_manager = static_cast<zxdg_decoration_manager_v1 *>(
|
||||||
|
wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1));
|
||||||
|
}
|
||||||
else if (!strcmp(interface, wl_output_interface.name)) {
|
else if (!strcmp(interface, wl_output_interface.name)) {
|
||||||
output_t *output = new output_t;
|
output_t *output = new output_t;
|
||||||
output->scale = 1;
|
output->scale = 1;
|
||||||
@@ -1335,16 +1445,6 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t)
|
|||||||
wl_data_device_add_listener(input->data_device, &data_device_listener, input);
|
wl_data_device_add_listener(input->data_device, &data_device_listener, input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *theme = std::getenv("XCURSOR_THEME");
|
|
||||||
const char *size = std::getenv("XCURSOR_SIZE");
|
|
||||||
const int sizei = size ? std::stoi(size) : default_cursor_size;
|
|
||||||
|
|
||||||
d->cursor_theme = wl_cursor_theme_load(theme, sizei, d->shm);
|
|
||||||
if (!d->cursor_theme) {
|
|
||||||
display_destroy(d);
|
|
||||||
throw std::runtime_error("Wayland: unable to access cursor themes!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_SystemWayland::~GHOST_SystemWayland()
|
GHOST_SystemWayland::~GHOST_SystemWayland()
|
||||||
@@ -1471,8 +1571,8 @@ void GHOST_SystemWayland::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TU
|
|||||||
{
|
{
|
||||||
if (getNumDisplays() > 0) {
|
if (getNumDisplays() > 0) {
|
||||||
/* We assume first output as main. */
|
/* We assume first output as main. */
|
||||||
width = uint32_t(d->outputs[0]->width);
|
width = uint32_t(d->outputs[0]->width_pxl) / d->outputs[0]->scale;
|
||||||
height = uint32_t(d->outputs[0]->height);
|
height = uint32_t(d->outputs[0]->height_pxl) / d->outputs[0]->scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1481,7 +1581,7 @@ void GHOST_SystemWayland::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUn
|
|||||||
getMainDisplayDimensions(width, height);
|
getMainDisplayDimensions(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glSettings)
|
GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*glSettings*/)
|
||||||
{
|
{
|
||||||
/* Create new off-screen window. */
|
/* Create new off-screen window. */
|
||||||
wl_surface *os_surface = wl_compositor_create_surface(compositor());
|
wl_surface *os_surface = wl_compositor_create_surface(compositor());
|
||||||
@@ -1490,15 +1590,36 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings glS
|
|||||||
d->os_surfaces.push_back(os_surface);
|
d->os_surfaces.push_back(os_surface);
|
||||||
d->os_egl_windows.push_back(os_egl_window);
|
d->os_egl_windows.push_back(os_egl_window);
|
||||||
|
|
||||||
GHOST_Context *context = new GHOST_ContextEGL(false,
|
GHOST_Context *context;
|
||||||
EGLNativeWindowType(os_egl_window),
|
|
||||||
EGLNativeDisplayType(d->display),
|
for (int minor = 6; minor >= 0; --minor) {
|
||||||
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
context = new GHOST_ContextEGL(this,
|
||||||
3,
|
false,
|
||||||
3,
|
EGLNativeWindowType(os_egl_window),
|
||||||
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
|
EGLNativeDisplayType(d->display),
|
||||||
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
|
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
||||||
EGL_OPENGL_API);
|
4,
|
||||||
|
minor,
|
||||||
|
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
|
||||||
|
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
|
||||||
|
EGL_OPENGL_API);
|
||||||
|
|
||||||
|
if (context->initializeDrawingContext())
|
||||||
|
return context;
|
||||||
|
else
|
||||||
|
delete context;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = new GHOST_ContextEGL(this,
|
||||||
|
false,
|
||||||
|
EGLNativeWindowType(os_egl_window),
|
||||||
|
EGLNativeDisplayType(d->display),
|
||||||
|
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
|
||||||
|
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
|
||||||
|
EGL_OPENGL_API);
|
||||||
|
|
||||||
if (context->initializeDrawingContext()) {
|
if (context->initializeDrawingContext()) {
|
||||||
return context;
|
return context;
|
||||||
@@ -1530,6 +1651,11 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
|
|||||||
const bool is_dialog,
|
const bool is_dialog,
|
||||||
const GHOST_IWindow *parentWindow)
|
const GHOST_IWindow *parentWindow)
|
||||||
{
|
{
|
||||||
|
/* globally store pointer to window manager */
|
||||||
|
if (!window_manager) {
|
||||||
|
window_manager = getWindowManager();
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_WindowWayland *window = new GHOST_WindowWayland(
|
GHOST_WindowWayland *window = new GHOST_WindowWayland(
|
||||||
this,
|
this,
|
||||||
title,
|
title,
|
||||||
@@ -1574,6 +1700,21 @@ xdg_wm_base *GHOST_SystemWayland::shell()
|
|||||||
return d->xdg_shell;
|
return d->xdg_shell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zxdg_decoration_manager_v1 *GHOST_SystemWayland::decoration_manager()
|
||||||
|
{
|
||||||
|
return d->xdg_decoration_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<output_t *> &GHOST_SystemWayland::outputs() const
|
||||||
|
{
|
||||||
|
return d->outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_shm *GHOST_SystemWayland::shm() const
|
||||||
|
{
|
||||||
|
return d->shm;
|
||||||
|
}
|
||||||
|
|
||||||
void GHOST_SystemWayland::setSelection(const std::string &selection)
|
void GHOST_SystemWayland::setSelection(const std::string &selection)
|
||||||
{
|
{
|
||||||
this->selection = selection;
|
this->selection = selection;
|
||||||
@@ -1581,23 +1722,20 @@ void GHOST_SystemWayland::setSelection(const std::string &selection)
|
|||||||
|
|
||||||
static void set_cursor_buffer(input_t *input, wl_buffer *buffer)
|
static void set_cursor_buffer(input_t *input, wl_buffer *buffer)
|
||||||
{
|
{
|
||||||
input->cursor.visible = (buffer != nullptr);
|
cursor_t *c = &input->cursor;
|
||||||
|
|
||||||
wl_surface_attach(input->cursor.surface, buffer, 0, 0);
|
c->visible = (buffer != nullptr);
|
||||||
wl_surface_commit(input->cursor.surface);
|
|
||||||
|
|
||||||
if (input->cursor.visible) {
|
wl_surface_attach(c->surface, buffer, 0, 0);
|
||||||
wl_surface_damage(input->cursor.surface,
|
|
||||||
0,
|
wl_surface_damage(c->surface, 0, 0, int32_t(c->image.width), int32_t(c->image.height));
|
||||||
0,
|
wl_pointer_set_cursor(input->pointer,
|
||||||
int32_t(input->cursor.image.width),
|
input->pointer_serial,
|
||||||
int32_t(input->cursor.image.height));
|
c->visible ? c->surface : nullptr,
|
||||||
wl_pointer_set_cursor(input->pointer,
|
int32_t(c->image.hotspot_x) / c->scale,
|
||||||
input->pointer_serial,
|
int32_t(c->image.hotspot_y) / c->scale);
|
||||||
input->cursor.surface,
|
|
||||||
int32_t(input->cursor.image.hotspot_x),
|
wl_surface_commit(c->surface);
|
||||||
int32_t(input->cursor.image.hotspot_y));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape)
|
GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape)
|
||||||
@@ -1608,7 +1746,15 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape)
|
|||||||
const std::string cursor_name = cursors.count(shape) ? cursors.at(shape) :
|
const std::string cursor_name = cursors.count(shape) ? cursors.at(shape) :
|
||||||
cursors.at(GHOST_kStandardCursorDefault);
|
cursors.at(GHOST_kStandardCursorDefault);
|
||||||
|
|
||||||
wl_cursor *cursor = wl_cursor_theme_get_cursor(d->cursor_theme, cursor_name.c_str());
|
input_t *input = d->inputs[0];
|
||||||
|
cursor_t *c = &input->cursor;
|
||||||
|
|
||||||
|
if (!c->theme) {
|
||||||
|
/* The cursor surface hasn't entered an output yet. Initialize theme with scale 1. */
|
||||||
|
c->theme = wl_cursor_theme_load(c->theme_name.c_str(), c->size, d->inputs[0]->system->shm());
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_cursor *cursor = wl_cursor_theme_get_cursor(c->theme, cursor_name.c_str());
|
||||||
|
|
||||||
if (!cursor) {
|
if (!cursor) {
|
||||||
GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl);
|
GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl);
|
||||||
@@ -1620,11 +1766,11 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape)
|
|||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
return GHOST_kFailure;
|
return GHOST_kFailure;
|
||||||
}
|
}
|
||||||
cursor_t *c = &d->inputs[0]->cursor;
|
|
||||||
c->buffer = buffer;
|
c->buffer = buffer;
|
||||||
c->image = *image;
|
c->image = *image;
|
||||||
|
|
||||||
set_cursor_buffer(d->inputs[0], buffer);
|
set_cursor_buffer(input, buffer);
|
||||||
|
|
||||||
return GHOST_kSuccess;
|
return GHOST_kSuccess;
|
||||||
}
|
}
|
||||||
@@ -1735,6 +1881,11 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible)
|
|||||||
GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode,
|
GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode,
|
||||||
wl_surface *surface)
|
wl_surface *surface)
|
||||||
{
|
{
|
||||||
|
/* ignore, if the required protocols are not supported */
|
||||||
|
if (!d->relative_pointer_manager || !d->pointer_constraints) {
|
||||||
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
|
|
||||||
if (d->inputs.empty()) {
|
if (d->inputs.empty()) {
|
||||||
return GHOST_kFailure;
|
return GHOST_kFailure;
|
||||||
}
|
}
|
||||||
@@ -1754,6 +1905,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GHOST_kGrabNormal:
|
case GHOST_kGrabNormal:
|
||||||
|
break;
|
||||||
case GHOST_kGrabWrap:
|
case GHOST_kGrabWrap:
|
||||||
input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
|
input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
|
||||||
d->relative_pointer_manager, input->pointer);
|
d->relative_pointer_manager, input->pointer);
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include "GHOST_WindowWayland.h"
|
#include "GHOST_WindowWayland.h"
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
#include <xdg-decoration-client-protocol.h>
|
||||||
#include <xdg-shell-client-protocol.h>
|
#include <xdg-shell-client-protocol.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -34,6 +35,16 @@ class GHOST_WindowWayland;
|
|||||||
|
|
||||||
struct display_t;
|
struct display_t;
|
||||||
|
|
||||||
|
struct output_t {
|
||||||
|
struct wl_output *output;
|
||||||
|
int32_t width_pxl, height_pxl; // dimensions in pixel
|
||||||
|
int32_t width_mm, height_mm; // dimensions in millimeter
|
||||||
|
int transform;
|
||||||
|
int scale;
|
||||||
|
std::string make;
|
||||||
|
std::string model;
|
||||||
|
};
|
||||||
|
|
||||||
class GHOST_SystemWayland : public GHOST_System {
|
class GHOST_SystemWayland : public GHOST_System {
|
||||||
public:
|
public:
|
||||||
GHOST_SystemWayland();
|
GHOST_SystemWayland();
|
||||||
@@ -84,6 +95,12 @@ class GHOST_SystemWayland : public GHOST_System {
|
|||||||
|
|
||||||
xdg_wm_base *shell();
|
xdg_wm_base *shell();
|
||||||
|
|
||||||
|
zxdg_decoration_manager_v1 *decoration_manager();
|
||||||
|
|
||||||
|
const std::vector<output_t *> &outputs() const;
|
||||||
|
|
||||||
|
wl_shm *shm() const;
|
||||||
|
|
||||||
void setSelection(const std::string &selection);
|
void setSelection(const std::string &selection);
|
||||||
|
|
||||||
GHOST_TSuccess setCursorShape(GHOST_TStandardCursor shape);
|
GHOST_TSuccess setCursorShape(GHOST_TStandardCursor shape);
|
||||||
|
@@ -50,11 +50,7 @@
|
|||||||
#include "GHOST_WindowManager.h"
|
#include "GHOST_WindowManager.h"
|
||||||
#include "GHOST_WindowWin32.h"
|
#include "GHOST_WindowWin32.h"
|
||||||
|
|
||||||
#if defined(WITH_GL_EGL)
|
#include "GHOST_ContextWGL.h"
|
||||||
# include "GHOST_ContextEGL.h"
|
|
||||||
#else
|
|
||||||
# include "GHOST_ContextWGL.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WITH_INPUT_NDOF
|
#ifdef WITH_INPUT_NDOF
|
||||||
# include "GHOST_NDOFManagerWin32.h"
|
# include "GHOST_NDOFManagerWin32.h"
|
||||||
@@ -139,7 +135,6 @@ static void initRawInput()
|
|||||||
#undef DEVICE_COUNT
|
#undef DEVICE_COUNT
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef HRESULT(API *GHOST_WIN32_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
|
||||||
typedef BOOL(API *GHOST_WIN32_EnableNonClientDpiScaling)(HWND);
|
typedef BOOL(API *GHOST_WIN32_EnableNonClientDpiScaling)(HWND);
|
||||||
|
|
||||||
GHOST_SystemWin32::GHOST_SystemWin32()
|
GHOST_SystemWin32::GHOST_SystemWin32()
|
||||||
@@ -867,15 +862,151 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
|
|||||||
{
|
{
|
||||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||||
|
|
||||||
if (type == GHOST_kEventButtonDown) {
|
GHOST_TabletData td = window->getTabletData();
|
||||||
window->updateMouseCapture(MousePressed);
|
|
||||||
}
|
/* Move mouse to button event position. */
|
||||||
else if (type == GHOST_kEventButtonUp) {
|
if (window->getTabletData().Active != GHOST_kTabletModeNone) {
|
||||||
window->updateMouseCapture(MouseReleased);
|
/* Tablet should be handling in between mouse moves, only move to event position. */
|
||||||
|
DWORD msgPos = ::GetMessagePos();
|
||||||
|
int msgPosX = GET_X_LPARAM(msgPos);
|
||||||
|
int msgPosY = GET_Y_LPARAM(msgPos);
|
||||||
|
system->pushEvent(new GHOST_EventCursor(
|
||||||
|
::GetMessageTime(), GHOST_kEventCursorMove, window, msgPosX, msgPosY, td));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GHOST_EventButton(
|
window->updateMouseCapture(type == GHOST_kEventButtonDown ? MousePressed : MouseReleased);
|
||||||
system->getMilliSeconds(), type, window, mask, window->getTabletData());
|
return new GHOST_EventButton(system->getMilliSeconds(), type, window, mask, td);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
||||||
|
{
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (!wt) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||||
|
|
||||||
|
std::vector<GHOST_WintabInfoWin32> wintabInfo;
|
||||||
|
wt->getInput(wintabInfo);
|
||||||
|
|
||||||
|
/* Wintab provided coordinates are untrusted until a Wintab and Win32 button down event match.
|
||||||
|
* This is checked on every button down event, and revoked if there is a mismatch. This can
|
||||||
|
* happen when Wintab incorrectly scales cursor position or is in mouse mode.
|
||||||
|
*
|
||||||
|
* If Wintab was never trusted while processing this Win32 event, a fallback Ghost cursor move
|
||||||
|
* event is created at the position of the Win32 WT_PACKET event. */
|
||||||
|
bool mouseMoveHandled;
|
||||||
|
bool useWintabPos;
|
||||||
|
mouseMoveHandled = useWintabPos = wt->trustCoordinates();
|
||||||
|
|
||||||
|
for (GHOST_WintabInfoWin32 &info : wintabInfo) {
|
||||||
|
switch (info.type) {
|
||||||
|
case GHOST_kEventCursorMove: {
|
||||||
|
if (!useWintabPos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wt->mapWintabToSysCoordinates(info.x, info.y, info.x, info.y);
|
||||||
|
system->pushEvent(new GHOST_EventCursor(
|
||||||
|
info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GHOST_kEventButtonDown: {
|
||||||
|
UINT message;
|
||||||
|
switch (info.button) {
|
||||||
|
case GHOST_kButtonMaskLeft:
|
||||||
|
message = WM_LBUTTONDOWN;
|
||||||
|
break;
|
||||||
|
case GHOST_kButtonMaskRight:
|
||||||
|
message = WM_RBUTTONDOWN;
|
||||||
|
break;
|
||||||
|
case GHOST_kButtonMaskMiddle:
|
||||||
|
message = WM_MBUTTONDOWN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wintab buttons are modal, but the API does not inform us what mode a pressed button is
|
||||||
|
* in. Only issue button events if we can steal an equivalent Win32 button event from the
|
||||||
|
* event queue. */
|
||||||
|
MSG msg;
|
||||||
|
if (PeekMessage(&msg, window->getHWND(), message, message, PM_NOYIELD) &&
|
||||||
|
msg.message != WM_QUIT) {
|
||||||
|
|
||||||
|
/* Test for Win32/Wintab button down match. */
|
||||||
|
useWintabPos = wt->testCoordinates(msg.pt.x, msg.pt.y, info.x, info.y);
|
||||||
|
if (!useWintabPos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Steal the Win32 event which was previously peeked. */
|
||||||
|
PeekMessage(&msg, window->getHWND(), message, message, PM_REMOVE | PM_NOYIELD);
|
||||||
|
|
||||||
|
/* Move cursor to button location, to prevent incorrect cursor position when
|
||||||
|
* transitioning from unsynchronized Win32 to Wintab cursor control. */
|
||||||
|
wt->mapWintabToSysCoordinates(info.x, info.y, info.x, info.y);
|
||||||
|
system->pushEvent(new GHOST_EventCursor(
|
||||||
|
info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
|
||||||
|
|
||||||
|
window->updateMouseCapture(MousePressed);
|
||||||
|
system->pushEvent(
|
||||||
|
new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
|
||||||
|
|
||||||
|
mouseMoveHandled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case GHOST_kEventButtonUp: {
|
||||||
|
if (!useWintabPos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT message;
|
||||||
|
switch (info.button) {
|
||||||
|
case GHOST_kButtonMaskLeft:
|
||||||
|
message = WM_LBUTTONUP;
|
||||||
|
break;
|
||||||
|
case GHOST_kButtonMaskRight:
|
||||||
|
message = WM_RBUTTONUP;
|
||||||
|
break;
|
||||||
|
case GHOST_kButtonMaskMiddle:
|
||||||
|
message = WM_MBUTTONUP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wintab buttons are modal, but the API does not inform us what mode a pressed button is
|
||||||
|
* in. Only issue button events if we can steal an equivalent Win32 button event from the
|
||||||
|
* event queue. */
|
||||||
|
MSG msg;
|
||||||
|
if (PeekMessage(&msg, window->getHWND(), message, message, PM_REMOVE | PM_NOYIELD) &&
|
||||||
|
msg.message != WM_QUIT) {
|
||||||
|
|
||||||
|
window->updateMouseCapture(MouseReleased);
|
||||||
|
system->pushEvent(
|
||||||
|
new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fallback cursor movement if Wintab position were never trusted while processing this event. */
|
||||||
|
if (!mouseMoveHandled) {
|
||||||
|
DWORD pos = GetMessagePos();
|
||||||
|
int x = GET_X_LPARAM(pos);
|
||||||
|
int y = GET_Y_LPARAM(pos);
|
||||||
|
|
||||||
|
/* TODO supply tablet data */
|
||||||
|
system->pushEvent(new GHOST_EventCursor(
|
||||||
|
system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y, GHOST_TABLET_DATA_NONE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GHOST_SystemWin32::processPointerEvent(
|
void GHOST_SystemWin32::processPointerEvent(
|
||||||
@@ -883,7 +1014,7 @@ void GHOST_SystemWin32::processPointerEvent(
|
|||||||
{
|
{
|
||||||
/* Pointer events might fire when changing windows for a device which is set to use Wintab, even
|
/* Pointer events might fire when changing windows for a device which is set to use Wintab, even
|
||||||
* when when Wintab is left enabled but set to the bottom of Wintab overlap order. */
|
* when when Wintab is left enabled but set to the bottom of Wintab overlap order. */
|
||||||
if (!window->useTabletAPI(GHOST_kTabletNative)) {
|
if (!window->usingTabletAPI(GHOST_kTabletWinPointer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,20 +1025,21 @@ void GHOST_SystemWin32::processPointerEvent(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pointerInfo[0].isPrimary) {
|
|
||||||
eventHandled = true;
|
|
||||||
return; // For multi-touch displays we ignore these events
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case WM_POINTERENTER:
|
case WM_POINTERUPDATE:
|
||||||
window->m_tabletInRange = true;
|
/* Coalesced pointer events are reverse chronological order, reorder chronologically.
|
||||||
system->pushEvent(new GHOST_EventCursor(pointerInfo[0].time,
|
* Only contiguous move events are coalesced. */
|
||||||
GHOST_kEventCursorMove,
|
for (GHOST_TUns32 i = pointerInfo.size(); i-- > 0;) {
|
||||||
window,
|
system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time,
|
||||||
pointerInfo[0].pixelLocation.x,
|
GHOST_kEventCursorMove,
|
||||||
pointerInfo[0].pixelLocation.y,
|
window,
|
||||||
pointerInfo[0].tabletData));
|
pointerInfo[i].pixelLocation.x,
|
||||||
|
pointerInfo[i].pixelLocation.y,
|
||||||
|
pointerInfo[i].tabletData));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Leave event unhandled so that system cursor is moved. */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case WM_POINTERDOWN:
|
case WM_POINTERDOWN:
|
||||||
/* Move cursor to point of contact because GHOST_EventButton does not include position. */
|
/* Move cursor to point of contact because GHOST_EventButton does not include position. */
|
||||||
@@ -923,18 +1055,10 @@ void GHOST_SystemWin32::processPointerEvent(
|
|||||||
pointerInfo[0].buttonMask,
|
pointerInfo[0].buttonMask,
|
||||||
pointerInfo[0].tabletData));
|
pointerInfo[0].tabletData));
|
||||||
window->updateMouseCapture(MousePressed);
|
window->updateMouseCapture(MousePressed);
|
||||||
break;
|
|
||||||
case WM_POINTERUPDATE:
|
/* Mark event handled so that mouse button events are not generated. */
|
||||||
/* Coalesced pointer events are reverse chronological order, reorder chronologically.
|
eventHandled = true;
|
||||||
* Only contiguous move events are coalesced. */
|
|
||||||
for (GHOST_TUns32 i = pointerInfo.size(); i-- > 0;) {
|
|
||||||
system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time,
|
|
||||||
GHOST_kEventCursorMove,
|
|
||||||
window,
|
|
||||||
pointerInfo[i].pixelLocation.x,
|
|
||||||
pointerInfo[i].pixelLocation.y,
|
|
||||||
pointerInfo[i].tabletData));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case WM_POINTERUP:
|
case WM_POINTERUP:
|
||||||
system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
|
system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
|
||||||
@@ -943,16 +1067,14 @@ void GHOST_SystemWin32::processPointerEvent(
|
|||||||
pointerInfo[0].buttonMask,
|
pointerInfo[0].buttonMask,
|
||||||
pointerInfo[0].tabletData));
|
pointerInfo[0].tabletData));
|
||||||
window->updateMouseCapture(MouseReleased);
|
window->updateMouseCapture(MouseReleased);
|
||||||
break;
|
|
||||||
case WM_POINTERLEAVE:
|
/* Mark event handled so that mouse button events are not generated. */
|
||||||
window->m_tabletInRange = false;
|
eventHandled = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventHandled = true;
|
|
||||||
system->setCursorPosition(pointerInfo[0].pixelLocation.x, pointerInfo[0].pixelLocation.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
|
GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
|
||||||
@@ -960,18 +1082,14 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
|||||||
GHOST_TInt32 x_screen, y_screen;
|
GHOST_TInt32 x_screen, y_screen;
|
||||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||||
|
|
||||||
if (window->m_tabletInRange) {
|
if (window->getTabletData().Active != GHOST_kTabletModeNone) {
|
||||||
if (window->useTabletAPI(GHOST_kTabletNative)) {
|
/* While pen devices are in range, cursor movement is handled by tablet input processing. */
|
||||||
/* Tablet input handled in WM_POINTER* events. WM_MOUSEMOVE events in response to tablet
|
return NULL;
|
||||||
* input aren't normally generated when using WM_POINTER events, but manually moving the
|
|
||||||
* system cursor as we do in WM_POINTER handling does. */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
system->getCursorPosition(x_screen, y_screen);
|
system->getCursorPosition(x_screen, y_screen);
|
||||||
|
|
||||||
if (window->getCursorGrabModeIsWarp() && !window->m_tabletInRange) {
|
if (window->getCursorGrabModeIsWarp()) {
|
||||||
GHOST_TInt32 x_new = x_screen;
|
GHOST_TInt32 x_new = x_screen;
|
||||||
GHOST_TInt32 y_new = y_screen;
|
GHOST_TInt32 y_new = y_screen;
|
||||||
GHOST_TInt32 x_accum, y_accum;
|
GHOST_TInt32 x_accum, y_accum;
|
||||||
@@ -983,7 +1101,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Could also clamp to screen bounds wrap with a window outside the view will fail atm.
|
/* Could also clamp to screen bounds wrap with a window outside the view will fail atm.
|
||||||
* Use offset of 8 in case the window is at screen bounds. */
|
* Use inset in case the window is at screen bounds. */
|
||||||
bounds.wrapPoint(x_new, y_new, 2, window->getCursorGrabAxis());
|
bounds.wrapPoint(x_new, y_new, 2, window->getCursorGrabAxis());
|
||||||
|
|
||||||
window->getCursorGrabAccum(x_accum, y_accum);
|
window->getCursorGrabAccum(x_accum, y_accum);
|
||||||
@@ -999,7 +1117,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
|||||||
window,
|
window,
|
||||||
x_screen + x_accum,
|
x_screen + x_accum,
|
||||||
y_screen + y_accum,
|
y_screen + y_accum,
|
||||||
window->getTabletData());
|
GHOST_TABLET_DATA_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1008,7 +1126,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
|||||||
window,
|
window,
|
||||||
x_screen,
|
x_screen,
|
||||||
y_screen,
|
y_screen,
|
||||||
window->getTabletData());
|
GHOST_TABLET_DATA_NONE);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1118,6 +1236,23 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GHOST_Event *GHOST_SystemWin32::processWindowSizeEvent(GHOST_WindowWin32 *window)
|
||||||
|
{
|
||||||
|
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||||
|
GHOST_Event *sizeEvent = new GHOST_Event(
|
||||||
|
system->getMilliSeconds(), GHOST_kEventWindowSize, window);
|
||||||
|
|
||||||
|
/* We get WM_SIZE before we fully init. Do not dispatch before we are continuously resizing. */
|
||||||
|
if (window->m_inLiveResize) {
|
||||||
|
system->pushEvent(sizeEvent);
|
||||||
|
system->dispatchEvents();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return sizeEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type,
|
GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type,
|
||||||
GHOST_WindowWin32 *window)
|
GHOST_WindowWin32 *window)
|
||||||
{
|
{
|
||||||
@@ -1125,7 +1260,6 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type,
|
|||||||
|
|
||||||
if (type == GHOST_kEventWindowActivate) {
|
if (type == GHOST_kEventWindowActivate) {
|
||||||
system->getWindowManager()->setActiveWindow(window);
|
system->getWindowManager()->setActiveWindow(window);
|
||||||
window->bringTabletContextToFront();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GHOST_Event(system->getMilliSeconds(), type, window);
|
return new GHOST_Event(system->getMilliSeconds(), type, window);
|
||||||
@@ -1153,6 +1287,31 @@ GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
|
|||||||
system->getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, data));
|
system->getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GHOST_SystemWin32::setTabletAPI(GHOST_TTabletAPI api)
|
||||||
|
{
|
||||||
|
GHOST_System::setTabletAPI(api);
|
||||||
|
|
||||||
|
/* If API is set to WinPointer (Windows Ink), unload Wintab so that trouble drivers don't disable
|
||||||
|
* Windows Ink. Load Wintab when API is Automatic because decision logic relies on knowing
|
||||||
|
* whether a Wintab device is present. */
|
||||||
|
const bool loadWintab = GHOST_kTabletWinPointer != api;
|
||||||
|
GHOST_WindowManager *wm = getWindowManager();
|
||||||
|
|
||||||
|
for (GHOST_IWindow *win : wm->getWindows()) {
|
||||||
|
GHOST_WindowWin32 *windowWin32 = (GHOST_WindowWin32 *)win;
|
||||||
|
if (loadWintab) {
|
||||||
|
windowWin32->loadWintab(GHOST_kWindowStateMinimized != windowWin32->getState());
|
||||||
|
|
||||||
|
if (windowWin32->usingTabletAPI(GHOST_kTabletWintab)) {
|
||||||
|
windowWin32->resetPointerPenInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
windowWin32->closeWintab();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax)
|
void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax)
|
||||||
{
|
{
|
||||||
minmax->ptMinTrackSize.x = 320;
|
minmax->ptMinTrackSize.x = 320;
|
||||||
@@ -1387,33 +1546,100 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
case SC_KEYMENU:
|
case SC_KEYMENU:
|
||||||
eventHandled = true;
|
eventHandled = true;
|
||||||
break;
|
break;
|
||||||
case SC_RESTORE:
|
case SC_RESTORE: {
|
||||||
::ShowWindow(hwnd, SW_RESTORE);
|
::ShowWindow(hwnd, SW_RESTORE);
|
||||||
window->setState(window->getState());
|
window->setState(window->getState());
|
||||||
|
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->enable();
|
||||||
|
}
|
||||||
|
|
||||||
eventHandled = true;
|
eventHandled = true;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case SC_MAXIMIZE: {
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->enable();
|
||||||
|
}
|
||||||
|
/* Don't report event as handled so that default handling occurs. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SC_MINIMIZE: {
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->disable();
|
||||||
|
}
|
||||||
|
/* Don't report event as handled so that default handling occurs. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Wintab events, processed
|
// Wintab events, processed
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
case WT_PACKET:
|
case WT_CSRCHANGE: {
|
||||||
window->processWin32TabletEvent(wParam, lParam);
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->updateCursorInfo();
|
||||||
|
}
|
||||||
|
eventHandled = true;
|
||||||
break;
|
break;
|
||||||
case WT_CSRCHANGE:
|
}
|
||||||
case WT_PROXIMITY:
|
case WT_PROXIMITY: {
|
||||||
window->processWin32TabletInitEvent();
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
bool inRange = LOWORD(lParam);
|
||||||
|
if (inRange) {
|
||||||
|
/* Some devices don't emit WT_CSRCHANGE events, so update cursor info here. */
|
||||||
|
wt->updateCursorInfo();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wt->leaveRange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eventHandled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WT_INFOCHANGE: {
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->processInfoChange(lParam);
|
||||||
|
|
||||||
|
if (window->usingTabletAPI(GHOST_kTabletWintab)) {
|
||||||
|
window->resetPointerPenInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eventHandled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WT_PACKET:
|
||||||
|
processWintabEvent(window);
|
||||||
|
eventHandled = true;
|
||||||
break;
|
break;
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Pointer events, processed
|
// Pointer events, processed
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
case WM_POINTERENTER:
|
|
||||||
case WM_POINTERDOWN:
|
|
||||||
case WM_POINTERUPDATE:
|
case WM_POINTERUPDATE:
|
||||||
|
case WM_POINTERDOWN:
|
||||||
case WM_POINTERUP:
|
case WM_POINTERUP:
|
||||||
case WM_POINTERLEAVE:
|
|
||||||
processPointerEvent(msg, window, wParam, lParam, eventHandled);
|
processPointerEvent(msg, window, wParam, lParam, eventHandled);
|
||||||
break;
|
break;
|
||||||
|
case WM_POINTERLEAVE: {
|
||||||
|
GHOST_TUns32 pointerId = GET_POINTERID_WPARAM(wParam);
|
||||||
|
POINTER_INFO pointerInfo;
|
||||||
|
if (!GetPointerInfo(pointerId, &pointerInfo)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset pointer pen info if pen device has left tracking range. */
|
||||||
|
if (pointerInfo.pointerType == PT_PEN && !IS_POINTER_INRANGE_WPARAM(wParam)) {
|
||||||
|
window->resetPointerPenInfo();
|
||||||
|
eventHandled = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Mouse events, processed
|
// Mouse events, processed
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1452,7 +1678,20 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WM_MOUSEMOVE:
|
case WM_MOUSEMOVE:
|
||||||
|
if (!window->m_mousePresent) {
|
||||||
|
TRACKMOUSEEVENT tme = {sizeof(tme)};
|
||||||
|
tme.dwFlags = TME_LEAVE;
|
||||||
|
tme.hwndTrack = hwnd;
|
||||||
|
TrackMouseEvent(&tme);
|
||||||
|
window->m_mousePresent = true;
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->gainFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
event = processCursorEvent(window);
|
event = processCursorEvent(window);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case WM_MOUSEWHEEL: {
|
case WM_MOUSEWHEEL: {
|
||||||
/* The WM_MOUSEWHEEL message is sent to the focus window
|
/* The WM_MOUSEWHEEL message is sent to the focus window
|
||||||
@@ -1462,14 +1701,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
* since DefWindowProc propagates it up the parent chain
|
* since DefWindowProc propagates it up the parent chain
|
||||||
* until it finds a window that processes it.
|
* until it finds a window that processes it.
|
||||||
*/
|
*/
|
||||||
|
processWheelEvent(window, wParam, lParam);
|
||||||
/* Get the window under the mouse and send event to its queue. */
|
|
||||||
POINT mouse_pos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
|
|
||||||
HWND mouse_hwnd = ChildWindowFromPoint(HWND_DESKTOP, mouse_pos);
|
|
||||||
GHOST_WindowWin32 *mouse_window = (GHOST_WindowWin32 *)::GetWindowLongPtr(mouse_hwnd,
|
|
||||||
GWLP_USERDATA);
|
|
||||||
|
|
||||||
processWheelEvent(mouse_window ? mouse_window : window, wParam, lParam);
|
|
||||||
eventHandled = true;
|
eventHandled = true;
|
||||||
#ifdef BROKEN_PEEK_TOUCHPAD
|
#ifdef BROKEN_PEEK_TOUCHPAD
|
||||||
PostMessage(hwnd, WM_USER, 0, 0);
|
PostMessage(hwnd, WM_USER, 0, 0);
|
||||||
@@ -1494,7 +1726,17 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
window->loadCursor(true, GHOST_kStandardCursorDefault);
|
window->loadCursor(true, GHOST_kStandardCursorDefault);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case WM_MOUSELEAVE: {
|
||||||
|
window->m_mousePresent = false;
|
||||||
|
if (window->getTabletData().Active == GHOST_kTabletModeNone) {
|
||||||
|
processCursorEvent(window);
|
||||||
|
}
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->loseFocus();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Mouse events, ignored
|
// Mouse events, ignored
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1542,7 +1784,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
* will not be dispatched to OUR active window if we minimize one of OUR windows. */
|
* will not be dispatched to OUR active window if we minimize one of OUR windows. */
|
||||||
if (LOWORD(wParam) == WA_INACTIVE)
|
if (LOWORD(wParam) == WA_INACTIVE)
|
||||||
window->lostMouseCapture();
|
window->lostMouseCapture();
|
||||||
window->processWin32TabletActivateEvent(GET_WM_ACTIVATE_STATE(wParam, lParam));
|
|
||||||
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
|
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1584,6 +1826,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
/* Let DefWindowProc handle it. */
|
/* Let DefWindowProc handle it. */
|
||||||
break;
|
break;
|
||||||
case WM_SIZING:
|
case WM_SIZING:
|
||||||
|
event = processWindowSizeEvent(window);
|
||||||
|
break;
|
||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
/* The WM_SIZE message is sent to a window after its size has changed.
|
/* The WM_SIZE message is sent to a window after its size has changed.
|
||||||
* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
|
* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
|
||||||
@@ -1591,15 +1835,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
* to perform any move or size change processing during the WM_WINDOWPOSCHANGED
|
* to perform any move or size change processing during the WM_WINDOWPOSCHANGED
|
||||||
* message without calling DefWindowProc.
|
* message without calling DefWindowProc.
|
||||||
*/
|
*/
|
||||||
/* we get first WM_SIZE before we fully init.
|
event = processWindowSizeEvent(window);
|
||||||
* So, do not dispatch before we continuously resizing. */
|
|
||||||
if (window->m_inLiveResize) {
|
|
||||||
system->pushEvent(processWindowEvent(GHOST_kEventWindowSize, window));
|
|
||||||
system->dispatchEvents();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
event = processWindowEvent(GHOST_kEventWindowSize, window);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case WM_CAPTURECHANGED:
|
case WM_CAPTURECHANGED:
|
||||||
window->lostMouseCapture();
|
window->lostMouseCapture();
|
||||||
@@ -1650,6 +1886,21 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
SWP_NOZORDER | SWP_NOACTIVATE);
|
SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case WM_DISPLAYCHANGE: {
|
||||||
|
GHOST_Wintab *wt = window->getWintab();
|
||||||
|
if (wt) {
|
||||||
|
wt->remapCoordinates();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_KILLFOCUS:
|
||||||
|
/* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard
|
||||||
|
* focus. We want to prevent this if a window is still active and it loses focus to
|
||||||
|
* nowhere. */
|
||||||
|
if (!wParam && hwnd == ::GetActiveWindow()) {
|
||||||
|
::SetFocus(hwnd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Window events, ignored
|
// Window events, ignored
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1686,12 +1937,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||||||
* object associated with the window.
|
* object associated with the window.
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
case WM_KILLFOCUS:
|
|
||||||
/* The WM_KILLFOCUS message is sent to a window immediately before it loses the
|
|
||||||
* keyboard focus. We want to prevent this if a window is still active and it loses
|
|
||||||
* focus to nowhere. */
|
|
||||||
if (!wParam && hwnd == ::GetActiveWindow())
|
|
||||||
::SetFocus(hwnd);
|
|
||||||
case WM_SHOWWINDOW:
|
case WM_SHOWWINDOW:
|
||||||
/* The WM_SHOWWINDOW message is sent to a window when the window is
|
/* The WM_SHOWWINDOW message is sent to a window when the window is
|
||||||
* about to be hidden or shown. */
|
* about to be hidden or shown. */
|
||||||
|
@@ -265,6 +265,16 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||||||
int mouseY,
|
int mouseY,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Modify tablet API
|
||||||
|
***************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set which tablet API to use.
|
||||||
|
* \param api: Enum indicating which API to use.
|
||||||
|
*/
|
||||||
|
void setTabletAPI(GHOST_TTabletAPI api) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Initializes the system.
|
* Initializes the system.
|
||||||
@@ -308,6 +318,12 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||||||
GHOST_WindowWin32 *window,
|
GHOST_WindowWin32 *window,
|
||||||
GHOST_TButtonMask mask);
|
GHOST_TButtonMask mask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates tablet events from Wintab events.
|
||||||
|
* \param window: The window receiving the event (the active window).
|
||||||
|
*/
|
||||||
|
static void processWintabEvent(GHOST_WindowWin32 *window);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates tablet events from pointer events.
|
* Creates tablet events from pointer events.
|
||||||
* \param type: The type of pointer event.
|
* \param type: The type of pointer event.
|
||||||
@@ -351,6 +367,13 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||||||
*/
|
*/
|
||||||
GHOST_TKey processSpecialKey(short vKey, short scanCode) const;
|
GHOST_TKey processSpecialKey(short vKey, short scanCode) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a window size event.
|
||||||
|
* \param window: The window receiving the event (the active window).
|
||||||
|
* \return The event created.
|
||||||
|
*/
|
||||||
|
static GHOST_Event *processWindowSizeEvent(GHOST_WindowWin32 *window);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a window event.
|
* Creates a window event.
|
||||||
* \param type: The type of event to create.
|
* \param type: The type of event to create.
|
||||||
|
@@ -441,7 +441,8 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
|
|||||||
|
|
||||||
for (int minor = 5; minor >= 0; --minor) {
|
for (int minor = 5; minor >= 0; --minor) {
|
||||||
#if defined(WITH_GL_EGL)
|
#if defined(WITH_GL_EGL)
|
||||||
context = new GHOST_ContextEGL(false,
|
context = new GHOST_ContextEGL(this,
|
||||||
|
false,
|
||||||
EGLNativeWindowType(nullptr),
|
EGLNativeWindowType(nullptr),
|
||||||
EGLNativeDisplayType(m_display),
|
EGLNativeDisplayType(m_display),
|
||||||
profile_mask,
|
profile_mask,
|
||||||
@@ -471,7 +472,8 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WITH_GL_EGL)
|
#if defined(WITH_GL_EGL)
|
||||||
context = new GHOST_ContextEGL(false,
|
context = new GHOST_ContextEGL(this,
|
||||||
|
false,
|
||||||
EGLNativeWindowType(nullptr),
|
EGLNativeWindowType(nullptr),
|
||||||
EGLNativeDisplayType(m_display),
|
EGLNativeDisplayType(m_display),
|
||||||
profile_mask,
|
profile_mask,
|
||||||
@@ -589,9 +591,7 @@ static void SleepTillEvent(Display *display, GHOST_TInt64 maxSleep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function borrowed from Qt's X11 support
|
/* This function borrowed from Qt's X11 support qclipboard_x11.cpp */
|
||||||
* qclipboard_x11.cpp
|
|
||||||
* */
|
|
||||||
struct init_timestamp_data {
|
struct init_timestamp_data {
|
||||||
Time timestamp;
|
Time timestamp;
|
||||||
};
|
};
|
||||||
@@ -2563,7 +2563,7 @@ static bool is_filler_char(char c)
|
|||||||
return isspace(c) || c == '_' || c == '-' || c == ';' || c == ':';
|
return isspace(c) || c == '_' || c == '-' || c == ';' || c == ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These C functions are copied from Wine 3.12's wintab.c */
|
/* These C functions are copied from Wine 3.12's `wintab.c` */
|
||||||
static bool match_token(const char *haystack, const char *needle)
|
static bool match_token(const char *haystack, const char *needle)
|
||||||
{
|
{
|
||||||
const char *h, *n;
|
const char *h, *n;
|
||||||
@@ -2675,8 +2675,8 @@ void GHOST_SystemX11::refreshXInputDevices()
|
|||||||
xtablet.PressureLevels = xvi->axes[2].max_value;
|
xtablet.PressureLevels = xvi->axes[2].max_value;
|
||||||
|
|
||||||
if (xvi->num_axes > 3) {
|
if (xvi->num_axes > 3) {
|
||||||
/* this is assuming that the tablet has the same tilt resolution in both
|
/* This is assuming that the tablet has the same tilt resolution in both
|
||||||
* positive and negative directions. It would be rather weird if it didn't.. */
|
* positive and negative directions. It would be rather weird if it didn't. */
|
||||||
xtablet.XtiltLevels = xvi->axes[3].max_value;
|
xtablet.XtiltLevels = xvi->axes[3].max_value;
|
||||||
xtablet.YtiltLevels = xvi->axes[4].max_value;
|
xtablet.YtiltLevels = xvi->axes[4].max_value;
|
||||||
}
|
}
|
||||||
|
130
intern/ghost/intern/GHOST_WaylandCursorSettings.h
Normal file
130
intern/ghost/intern/GHOST_WaylandCursorSettings.h
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup GHOST
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <dbus/dbus.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
static DBusMessage *get_setting_sync(DBusConnection *const connection,
|
||||||
|
const char *key,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
DBusError error;
|
||||||
|
dbus_bool_t success;
|
||||||
|
DBusMessage *message;
|
||||||
|
DBusMessage *reply;
|
||||||
|
|
||||||
|
dbus_error_init(&error);
|
||||||
|
|
||||||
|
message = dbus_message_new_method_call("org.freedesktop.portal.Desktop",
|
||||||
|
"/org/freedesktop/portal/desktop",
|
||||||
|
"org.freedesktop.portal.Settings",
|
||||||
|
"Read");
|
||||||
|
|
||||||
|
success = dbus_message_append_args(
|
||||||
|
message, DBUS_TYPE_STRING, &key, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = dbus_connection_send_with_reply_and_block(
|
||||||
|
connection, message, DBUS_TIMEOUT_USE_DEFAULT, &error);
|
||||||
|
|
||||||
|
dbus_message_unref(message);
|
||||||
|
|
||||||
|
if (dbus_error_is_set(&error)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool parse_type(DBusMessage *const reply, const int type, void *value)
|
||||||
|
{
|
||||||
|
DBusMessageIter iter[3];
|
||||||
|
|
||||||
|
dbus_message_iter_init(reply, &iter[0]);
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter[0]) != DBUS_TYPE_VARIANT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_iter_recurse(&iter[0], &iter[1]);
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter[1]) != DBUS_TYPE_VARIANT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_iter_recurse(&iter[1], &iter[2]);
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter[2]) != type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&iter[2], value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool get_cursor_settings(std::string &theme, int &size)
|
||||||
|
{
|
||||||
|
static const char name[] = "org.gnome.desktop.interface";
|
||||||
|
static const char key_theme[] = "cursor-theme";
|
||||||
|
static const char key_size[] = "cursor-size";
|
||||||
|
|
||||||
|
DBusError error;
|
||||||
|
DBusConnection *connection;
|
||||||
|
DBusMessage *reply;
|
||||||
|
const char *value_theme = NULL;
|
||||||
|
|
||||||
|
dbus_error_init(&error);
|
||||||
|
|
||||||
|
connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
|
||||||
|
|
||||||
|
if (dbus_error_is_set(&error)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = get_setting_sync(connection, name, key_theme);
|
||||||
|
if (!reply) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_type(reply, DBUS_TYPE_STRING, &value_theme)) {
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
theme = std::string(value_theme);
|
||||||
|
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
|
||||||
|
reply = get_setting_sync(connection, name, key_size);
|
||||||
|
if (!reply) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parse_type(reply, DBUS_TYPE_INT32, &size)) {
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@@ -22,11 +22,7 @@
|
|||||||
#include "GHOST_Debug.h"
|
#include "GHOST_Debug.h"
|
||||||
#include "GHOST_SystemCocoa.h"
|
#include "GHOST_SystemCocoa.h"
|
||||||
|
|
||||||
#if defined(WITH_GL_EGL)
|
#include "GHOST_ContextCGL.h"
|
||||||
# include "GHOST_ContextEGL.h"
|
|
||||||
#else
|
|
||||||
# include "GHOST_ContextCGL.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <Cocoa/Cocoa.h>
|
#include <Cocoa/Cocoa.h>
|
||||||
#include <Metal/Metal.h>
|
#include <Metal/Metal.h>
|
||||||
|
@@ -556,7 +556,7 @@ static SDL_Cursor *sdl_ghost_CreateCursor(
|
|||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO, this is currently never freed but it wont leak either. */
|
/* TODO, this is currently never freed but it won't leak either. */
|
||||||
static SDL_Cursor *getStandardCursorShape(GHOST_TStandardCursor shape)
|
static SDL_Cursor *getStandardCursorShape(GHOST_TStandardCursor shape)
|
||||||
{
|
{
|
||||||
if (sdl_std_cursor_array[0] == NULL) {
|
if (sdl_std_cursor_array[0] == NULL) {
|
||||||
|
@@ -29,11 +29,19 @@
|
|||||||
|
|
||||||
#include <wayland-egl.h>
|
#include <wayland-egl.h>
|
||||||
|
|
||||||
|
static constexpr size_t base_dpi = 96;
|
||||||
|
|
||||||
struct window_t {
|
struct window_t {
|
||||||
GHOST_WindowWayland *w;
|
GHOST_WindowWayland *w;
|
||||||
wl_surface *surface;
|
wl_surface *surface;
|
||||||
|
// outputs on which the window is currently shown on
|
||||||
|
std::unordered_set<const output_t *> outputs;
|
||||||
|
GHOST_TUns16 dpi = 0;
|
||||||
|
int scale = 1;
|
||||||
struct xdg_surface *xdg_surface;
|
struct xdg_surface *xdg_surface;
|
||||||
struct xdg_toplevel *xdg_toplevel;
|
struct xdg_toplevel *xdg_toplevel;
|
||||||
|
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration = nullptr;
|
||||||
|
enum zxdg_toplevel_decoration_v1_mode decoration_mode;
|
||||||
wl_egl_window *egl_window;
|
wl_egl_window *egl_window;
|
||||||
int32_t pending_width, pending_height;
|
int32_t pending_width, pending_height;
|
||||||
bool is_maximised;
|
bool is_maximised;
|
||||||
@@ -93,17 +101,30 @@ static const xdg_toplevel_listener toplevel_listener = {
|
|||||||
toplevel_close,
|
toplevel_close,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void toplevel_decoration_configure(
|
||||||
|
void *data,
|
||||||
|
struct zxdg_toplevel_decoration_v1 * /*zxdg_toplevel_decoration_v1*/,
|
||||||
|
uint32_t mode)
|
||||||
|
{
|
||||||
|
static_cast<window_t *>(data)->decoration_mode = zxdg_toplevel_decoration_v1_mode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listener = {
|
||||||
|
toplevel_decoration_configure,
|
||||||
|
};
|
||||||
|
|
||||||
static void surface_configure(void *data, xdg_surface *xdg_surface, uint32_t serial)
|
static void surface_configure(void *data, xdg_surface *xdg_surface, uint32_t serial)
|
||||||
{
|
{
|
||||||
window_t *win = static_cast<window_t *>(data);
|
window_t *win = static_cast<window_t *>(data);
|
||||||
|
|
||||||
int w, h;
|
if (win->xdg_surface != xdg_surface) {
|
||||||
wl_egl_window_get_attached_size(win->egl_window, &w, &h);
|
return;
|
||||||
if (win->pending_width != 0 && win->pending_height != 0 && win->pending_width != w &&
|
}
|
||||||
win->pending_height != h) {
|
|
||||||
win->width = win->pending_width;
|
if (win->pending_width != 0 && win->pending_height != 0) {
|
||||||
win->height = win->pending_height;
|
win->width = win->scale * win->pending_width;
|
||||||
wl_egl_window_resize(win->egl_window, win->pending_width, win->pending_height, 0, 0);
|
win->height = win->scale * win->pending_height;
|
||||||
|
wl_egl_window_resize(win->egl_window, win->width, win->height, 0, 0);
|
||||||
win->pending_width = 0;
|
win->pending_width = 0;
|
||||||
win->pending_height = 0;
|
win->pending_height = 0;
|
||||||
win->w->notify_size();
|
win->w->notify_size();
|
||||||
@@ -123,6 +144,52 @@ static const xdg_surface_listener surface_listener = {
|
|||||||
surface_configure,
|
surface_configure,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool update_scale(GHOST_WindowWayland *window)
|
||||||
|
{
|
||||||
|
int scale = 0;
|
||||||
|
for (const output_t *output : window->outputs_active()) {
|
||||||
|
if (output->scale > scale)
|
||||||
|
scale = output->scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scale > 0 && window->scale() != scale) {
|
||||||
|
window->scale() = scale;
|
||||||
|
// using the real DPI will cause wrong scaling of the UI
|
||||||
|
// use a multiplier for the default DPI as workaround
|
||||||
|
window->dpi() = scale * base_dpi;
|
||||||
|
wl_surface_set_buffer_scale(window->surface(), scale);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_enter(void *data, struct wl_surface * /*wl_surface*/, struct wl_output *output)
|
||||||
|
{
|
||||||
|
GHOST_WindowWayland *w = static_cast<GHOST_WindowWayland *>(data);
|
||||||
|
for (const output_t *reg_output : w->outputs()) {
|
||||||
|
if (reg_output->output == output) {
|
||||||
|
w->outputs_active().insert(reg_output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_scale(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surface_leave(void *data, struct wl_surface * /*wl_surface*/, struct wl_output *output)
|
||||||
|
{
|
||||||
|
GHOST_WindowWayland *w = static_cast<GHOST_WindowWayland *>(data);
|
||||||
|
for (const output_t *reg_output : w->outputs()) {
|
||||||
|
if (reg_output->output == output) {
|
||||||
|
w->outputs_active().erase(reg_output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_scale(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_surface_listener wl_surface_listener = {
|
||||||
|
surface_enter,
|
||||||
|
surface_leave,
|
||||||
|
};
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
@@ -161,17 +228,28 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||||||
|
|
||||||
/* Window surfaces. */
|
/* Window surfaces. */
|
||||||
w->surface = wl_compositor_create_surface(m_system->compositor());
|
w->surface = wl_compositor_create_surface(m_system->compositor());
|
||||||
|
wl_surface_add_listener(w->surface, &wl_surface_listener, this);
|
||||||
|
|
||||||
w->egl_window = wl_egl_window_create(w->surface, int(width), int(height));
|
w->egl_window = wl_egl_window_create(w->surface, int(width), int(height));
|
||||||
|
|
||||||
w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->shell(), w->surface);
|
w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->shell(), w->surface);
|
||||||
w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface);
|
w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface);
|
||||||
|
|
||||||
|
if (m_system->decoration_manager()) {
|
||||||
|
w->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
||||||
|
m_system->decoration_manager(), w->xdg_toplevel);
|
||||||
|
zxdg_toplevel_decoration_v1_add_listener(
|
||||||
|
w->xdg_toplevel_decoration, &toplevel_decoration_v1_listener, w);
|
||||||
|
zxdg_toplevel_decoration_v1_set_mode(w->xdg_toplevel_decoration,
|
||||||
|
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||||
|
}
|
||||||
|
|
||||||
wl_surface_set_user_data(w->surface, this);
|
wl_surface_set_user_data(w->surface, this);
|
||||||
|
|
||||||
xdg_surface_add_listener(w->xdg_surface, &surface_listener, w);
|
xdg_surface_add_listener(w->xdg_surface, &surface_listener, w);
|
||||||
xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w);
|
xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w);
|
||||||
|
|
||||||
if (parentWindow) {
|
if (parentWindow && is_dialog) {
|
||||||
xdg_toplevel_set_parent(
|
xdg_toplevel_set_parent(
|
||||||
w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel);
|
w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel);
|
||||||
}
|
}
|
||||||
@@ -192,6 +270,9 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||||||
if (setDrawingContextType(type) == GHOST_kFailure) {
|
if (setDrawingContextType(type) == GHOST_kFailure) {
|
||||||
GHOST_PRINT("Failed to create EGL context" << std::endl);
|
GHOST_PRINT("Failed to create EGL context" << std::endl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set swap interval to 0 to prevent blocking */
|
||||||
|
setSwapInterval(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_WindowWayland::close()
|
GHOST_TSuccess GHOST_WindowWayland::close()
|
||||||
@@ -226,6 +307,31 @@ GHOST_TSuccess GHOST_WindowWayland::notify_size()
|
|||||||
new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowSize, this));
|
new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowSize, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_surface *GHOST_WindowWayland::surface() const
|
||||||
|
{
|
||||||
|
return w->surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<output_t *> &GHOST_WindowWayland::outputs() const
|
||||||
|
{
|
||||||
|
return m_system->outputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<const output_t *> &GHOST_WindowWayland::outputs_active()
|
||||||
|
{
|
||||||
|
return w->outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t &GHOST_WindowWayland::dpi()
|
||||||
|
{
|
||||||
|
return w->dpi;
|
||||||
|
}
|
||||||
|
|
||||||
|
int &GHOST_WindowWayland::scale()
|
||||||
|
{
|
||||||
|
return w->scale;
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
|
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
|
||||||
{
|
{
|
||||||
return m_system->setCursorGrab(mode, w->surface);
|
return m_system->setCursorGrab(mode, w->surface);
|
||||||
@@ -310,6 +416,9 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
|
|||||||
releaseNativeHandles();
|
releaseNativeHandles();
|
||||||
|
|
||||||
wl_egl_window_destroy(w->egl_window);
|
wl_egl_window_destroy(w->egl_window);
|
||||||
|
if (w->xdg_toplevel_decoration) {
|
||||||
|
zxdg_toplevel_decoration_v1_destroy(w->xdg_toplevel_decoration);
|
||||||
|
}
|
||||||
xdg_toplevel_destroy(w->xdg_toplevel);
|
xdg_toplevel_destroy(w->xdg_toplevel);
|
||||||
xdg_surface_destroy(w->xdg_surface);
|
xdg_surface_destroy(w->xdg_surface);
|
||||||
wl_surface_destroy(w->surface);
|
wl_surface_destroy(w->surface);
|
||||||
@@ -317,6 +426,11 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
|
|||||||
delete w;
|
delete w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GHOST_TUns16 GHOST_WindowWayland::getDPIHint()
|
||||||
|
{
|
||||||
|
return w->dpi;
|
||||||
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible)
|
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible)
|
||||||
{
|
{
|
||||||
return m_system->setCursorVisibility(visible);
|
return m_system->setCursorVisibility(visible);
|
||||||
@@ -418,7 +532,25 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType
|
|||||||
context = new GHOST_ContextNone(m_wantStereoVisual);
|
context = new GHOST_ContextNone(m_wantStereoVisual);
|
||||||
break;
|
break;
|
||||||
case GHOST_kDrawingContextTypeOpenGL:
|
case GHOST_kDrawingContextTypeOpenGL:
|
||||||
context = new GHOST_ContextEGL(m_wantStereoVisual,
|
for (int minor = 6; minor >= 0; --minor) {
|
||||||
|
context = new GHOST_ContextEGL(this->m_system,
|
||||||
|
m_wantStereoVisual,
|
||||||
|
EGLNativeWindowType(w->egl_window),
|
||||||
|
EGLNativeDisplayType(m_system->display()),
|
||||||
|
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
||||||
|
4,
|
||||||
|
minor,
|
||||||
|
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
|
||||||
|
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
|
||||||
|
EGL_OPENGL_API);
|
||||||
|
|
||||||
|
if (context->initializeDrawingContext())
|
||||||
|
return context;
|
||||||
|
else
|
||||||
|
delete context;
|
||||||
|
}
|
||||||
|
context = new GHOST_ContextEGL(this->m_system,
|
||||||
|
m_wantStereoVisual,
|
||||||
EGLNativeWindowType(w->egl_window),
|
EGLNativeWindowType(w->egl_window),
|
||||||
EGLNativeDisplayType(m_system->display()),
|
EGLNativeDisplayType(m_system->display()),
|
||||||
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
||||||
@@ -427,7 +559,6 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType
|
|||||||
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
|
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
|
||||||
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
|
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
|
||||||
EGL_OPENGL_API);
|
EGL_OPENGL_API);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr;
|
return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr;
|
||||||
|
@@ -24,9 +24,14 @@
|
|||||||
|
|
||||||
#include "GHOST_Window.h"
|
#include "GHOST_Window.h"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class GHOST_SystemWayland;
|
class GHOST_SystemWayland;
|
||||||
|
|
||||||
struct window_t;
|
struct window_t;
|
||||||
|
struct wl_surface;
|
||||||
|
struct output_t;
|
||||||
|
|
||||||
class GHOST_WindowWayland : public GHOST_Window {
|
class GHOST_WindowWayland : public GHOST_Window {
|
||||||
public:
|
public:
|
||||||
@@ -47,6 +52,8 @@ class GHOST_WindowWayland : public GHOST_Window {
|
|||||||
|
|
||||||
~GHOST_WindowWayland() override;
|
~GHOST_WindowWayland() override;
|
||||||
|
|
||||||
|
GHOST_TUns16 getDPIHint() override;
|
||||||
|
|
||||||
GHOST_TSuccess close();
|
GHOST_TSuccess close();
|
||||||
|
|
||||||
GHOST_TSuccess activate();
|
GHOST_TSuccess activate();
|
||||||
@@ -55,6 +62,16 @@ class GHOST_WindowWayland : public GHOST_Window {
|
|||||||
|
|
||||||
GHOST_TSuccess notify_size();
|
GHOST_TSuccess notify_size();
|
||||||
|
|
||||||
|
wl_surface *surface() const;
|
||||||
|
|
||||||
|
const std::vector<output_t *> &outputs() const;
|
||||||
|
|
||||||
|
std::unordered_set<const output_t *> &outputs_active();
|
||||||
|
|
||||||
|
uint16_t &dpi();
|
||||||
|
|
||||||
|
int &scale();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) override;
|
GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) override;
|
||||||
|
|
||||||
|
@@ -21,8 +21,6 @@
|
|||||||
* \ingroup GHOST
|
* \ingroup GHOST
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _USE_MATH_DEFINES
|
|
||||||
|
|
||||||
#include "GHOST_WindowWin32.h"
|
#include "GHOST_WindowWin32.h"
|
||||||
#include "GHOST_ContextD3D.h"
|
#include "GHOST_ContextD3D.h"
|
||||||
#include "GHOST_ContextNone.h"
|
#include "GHOST_ContextNone.h"
|
||||||
@@ -32,11 +30,8 @@
|
|||||||
#include "utf_winfunc.h"
|
#include "utf_winfunc.h"
|
||||||
#include "utfconv.h"
|
#include "utfconv.h"
|
||||||
|
|
||||||
#if defined(WITH_GL_EGL)
|
#include "GHOST_ContextWGL.h"
|
||||||
# include "GHOST_ContextEGL.h"
|
|
||||||
#else
|
|
||||||
# include "GHOST_ContextWGL.h"
|
|
||||||
#endif
|
|
||||||
#ifdef WIN32_COMPOSITING
|
#ifdef WIN32_COMPOSITING
|
||||||
# include <Dwmapi.h>
|
# include <Dwmapi.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -72,7 +67,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
|||||||
bool is_debug,
|
bool is_debug,
|
||||||
bool dialog)
|
bool dialog)
|
||||||
: GHOST_Window(width, height, state, wantStereoVisual, false),
|
: GHOST_Window(width, height, state, wantStereoVisual, false),
|
||||||
m_tabletInRange(false),
|
m_mousePresent(false),
|
||||||
m_inLiveResize(false),
|
m_inLiveResize(false),
|
||||||
m_system(system),
|
m_system(system),
|
||||||
m_hDC(0),
|
m_hDC(0),
|
||||||
@@ -82,6 +77,8 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
|||||||
m_nPressedButtons(0),
|
m_nPressedButtons(0),
|
||||||
m_customCursor(0),
|
m_customCursor(0),
|
||||||
m_wantAlphaBackground(alphaBackground),
|
m_wantAlphaBackground(alphaBackground),
|
||||||
|
m_wintab(NULL),
|
||||||
|
m_lastPointerTabletData(GHOST_TABLET_DATA_NONE),
|
||||||
m_normal_state(GHOST_kWindowStateNormal),
|
m_normal_state(GHOST_kWindowStateNormal),
|
||||||
m_user32(NULL),
|
m_user32(NULL),
|
||||||
m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : HWND_DESKTOP),
|
m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : HWND_DESKTOP),
|
||||||
@@ -90,10 +87,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
|||||||
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
|
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
|
||||||
RECT win_rect = {left, top, (long)(left + width), (long)(top + height)};
|
RECT win_rect = {left, top, (long)(left + width), (long)(top + height)};
|
||||||
|
|
||||||
// Initialize tablet variables
|
|
||||||
memset(&m_wintab, 0, sizeof(m_wintab));
|
|
||||||
m_tabletData = GHOST_TABLET_DATA_NONE;
|
|
||||||
|
|
||||||
DWORD style = parentwindow ?
|
DWORD style = parentwindow ?
|
||||||
WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX :
|
WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX :
|
||||||
WS_OVERLAPPEDWINDOW;
|
WS_OVERLAPPEDWINDOW;
|
||||||
@@ -218,65 +211,10 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize Wintab
|
// Initialize Wintab
|
||||||
m_wintab.handle = ::LoadLibrary("Wintab32.dll");
|
if (system->getTabletAPI() != GHOST_kTabletWinPointer) {
|
||||||
if (m_wintab.handle && m_system->getTabletAPI() != GHOST_kTabletNative) {
|
loadWintab(GHOST_kWindowStateMinimized != state);
|
||||||
// Get API functions
|
|
||||||
m_wintab.info = (GHOST_WIN32_WTInfo)::GetProcAddress(m_wintab.handle, "WTInfoA");
|
|
||||||
m_wintab.open = (GHOST_WIN32_WTOpen)::GetProcAddress(m_wintab.handle, "WTOpenA");
|
|
||||||
m_wintab.close = (GHOST_WIN32_WTClose)::GetProcAddress(m_wintab.handle, "WTClose");
|
|
||||||
m_wintab.packet = (GHOST_WIN32_WTPacket)::GetProcAddress(m_wintab.handle, "WTPacket");
|
|
||||||
m_wintab.enable = (GHOST_WIN32_WTEnable)::GetProcAddress(m_wintab.handle, "WTEnable");
|
|
||||||
m_wintab.overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(m_wintab.handle, "WTOverlap");
|
|
||||||
|
|
||||||
// Let's see if we can initialize tablet here.
|
|
||||||
// Check if WinTab available by getting system context info.
|
|
||||||
LOGCONTEXT lc = {0};
|
|
||||||
lc.lcOptions |= CXO_SYSTEM;
|
|
||||||
if (m_wintab.open && m_wintab.info && m_wintab.info(WTI_DEFSYSCTX, 0, &lc)) {
|
|
||||||
// Now init the tablet
|
|
||||||
/* The maximum tablet size, pressure and orientation (tilt) */
|
|
||||||
AXIS TabletX, TabletY, Pressure, Orientation[3];
|
|
||||||
|
|
||||||
// Open a Wintab context
|
|
||||||
|
|
||||||
// Open the context
|
|
||||||
lc.lcPktData = PACKETDATA;
|
|
||||||
lc.lcPktMode = PACKETMODE;
|
|
||||||
lc.lcOptions |= CXO_MESSAGES;
|
|
||||||
lc.lcMoveMask = PACKETDATA;
|
|
||||||
|
|
||||||
/* Set the entire tablet as active */
|
|
||||||
m_wintab.info(WTI_DEVICES, DVC_X, &TabletX);
|
|
||||||
m_wintab.info(WTI_DEVICES, DVC_Y, &TabletY);
|
|
||||||
|
|
||||||
/* get the max pressure, to divide into a float */
|
|
||||||
BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
|
||||||
if (pressureSupport)
|
|
||||||
m_wintab.maxPressure = Pressure.axMax;
|
|
||||||
else
|
|
||||||
m_wintab.maxPressure = 0;
|
|
||||||
|
|
||||||
/* get the max tilt axes, to divide into floats */
|
|
||||||
BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
|
|
||||||
if (tiltSupport) {
|
|
||||||
/* does the tablet support azimuth ([0]) and altitude ([1]) */
|
|
||||||
if (Orientation[0].axResolution && Orientation[1].axResolution) {
|
|
||||||
/* all this assumes the minimum is 0 */
|
|
||||||
m_wintab.maxAzimuth = Orientation[0].axMax;
|
|
||||||
m_wintab.maxAltitude = Orientation[1].axMax;
|
|
||||||
}
|
|
||||||
else { /* No so don't do tilt stuff. */
|
|
||||||
m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The Wintab spec says we must open the context disabled if we are using cursor masks.
|
|
||||||
m_wintab.tablet = m_wintab.open(m_hWnd, &lc, FALSE);
|
|
||||||
if (m_wintab.enable && m_wintab.tablet) {
|
|
||||||
m_wintab.enable(m_wintab.tablet, TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoCreateInstance(
|
CoCreateInstance(
|
||||||
CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
|
CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
|
||||||
}
|
}
|
||||||
@@ -289,14 +227,7 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
|
|||||||
m_Bar = NULL;
|
m_Bar = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_wintab.handle) {
|
closeWintab();
|
||||||
if (m_wintab.close && m_wintab.tablet) {
|
|
||||||
m_wintab.close(m_wintab.tablet);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeLibrary(m_wintab.handle);
|
|
||||||
memset(&m_wintab, 0, sizeof(m_wintab));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_user32) {
|
if (m_user32) {
|
||||||
FreeLibrary(m_user32);
|
FreeLibrary(m_user32);
|
||||||
@@ -913,20 +844,16 @@ GHOST_TSuccess GHOST_WindowWin32::hasCursorShape(GHOST_TStandardCursor cursorSha
|
|||||||
GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
|
GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
|
||||||
std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam)
|
std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (!useTabletAPI(GHOST_kTabletNative)) {
|
|
||||||
return GHOST_kFailure;
|
|
||||||
}
|
|
||||||
|
|
||||||
GHOST_TInt32 pointerId = GET_POINTERID_WPARAM(wParam);
|
GHOST_TInt32 pointerId = GET_POINTERID_WPARAM(wParam);
|
||||||
GHOST_TInt32 isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam);
|
GHOST_TInt32 isPrimary = IS_POINTER_PRIMARY_WPARAM(wParam);
|
||||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
|
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
|
||||||
GHOST_TUns32 outCount;
|
GHOST_TUns32 outCount = 0;
|
||||||
|
|
||||||
if (!(GetPointerInfoHistory(pointerId, &outCount, NULL))) {
|
if (!(GetPointerPenInfoHistory(pointerId, &outCount, NULL))) {
|
||||||
return GHOST_kFailure;
|
return GHOST_kFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pointerPenInfo = std::vector<POINTER_PEN_INFO>(outCount);
|
std::vector<POINTER_PEN_INFO> pointerPenInfo(outCount);
|
||||||
outPointerInfo.resize(outCount);
|
outPointerInfo.resize(outCount);
|
||||||
|
|
||||||
if (!(GetPointerPenInfoHistory(pointerId, &outCount, pointerPenInfo.data()))) {
|
if (!(GetPointerPenInfoHistory(pointerId, &outCount, pointerPenInfo.data()))) {
|
||||||
@@ -988,148 +915,77 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!outPointerInfo.empty()) {
|
||||||
|
m_lastPointerTabletData = outPointerInfo.back().tabletData;
|
||||||
|
}
|
||||||
|
|
||||||
return GHOST_kSuccess;
|
return GHOST_kSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GHOST_WindowWin32::processWin32TabletActivateEvent(WORD state)
|
void GHOST_WindowWin32::resetPointerPenInfo()
|
||||||
{
|
{
|
||||||
if (!useTabletAPI(GHOST_kTabletWintab)) {
|
m_lastPointerTabletData = GHOST_TABLET_DATA_NONE;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (m_wintab.enable && m_wintab.tablet) {
|
GHOST_Wintab *GHOST_WindowWin32::getWintab() const
|
||||||
m_wintab.enable(m_wintab.tablet, state);
|
{
|
||||||
|
return m_wintab;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_wintab.overlap && state) {
|
void GHOST_WindowWin32::loadWintab(bool enable)
|
||||||
m_wintab.overlap(m_wintab.tablet, TRUE);
|
{
|
||||||
|
if (!m_wintab) {
|
||||||
|
if (m_wintab = GHOST_Wintab::loadWintab(m_hWnd)) {
|
||||||
|
if (enable) {
|
||||||
|
m_wintab->enable();
|
||||||
|
|
||||||
|
/* Focus Wintab if cursor is inside this window. This ensures Wintab is enabled when the
|
||||||
|
* tablet is used to change the Tablet API. */
|
||||||
|
GHOST_TInt32 x, y;
|
||||||
|
if (m_system->getCursorPosition(x, y)) {
|
||||||
|
GHOST_Rect rect;
|
||||||
|
getClientBounds(rect);
|
||||||
|
|
||||||
|
if (rect.isInside(x, y)) {
|
||||||
|
m_wintab->gainFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const
|
void GHOST_WindowWin32::closeWintab()
|
||||||
|
{
|
||||||
|
delete m_wintab;
|
||||||
|
m_wintab = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GHOST_WindowWin32::usingTabletAPI(GHOST_TTabletAPI api) const
|
||||||
{
|
{
|
||||||
if (m_system->getTabletAPI() == api) {
|
if (m_system->getTabletAPI() == api) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (m_system->getTabletAPI() == GHOST_kTabletAutomatic) {
|
else if (m_system->getTabletAPI() == GHOST_kTabletAutomatic) {
|
||||||
if (m_wintab.tablet)
|
if (m_wintab && m_wintab->devicesPresent()) {
|
||||||
return api == GHOST_kTabletWintab;
|
return api == GHOST_kTabletWintab;
|
||||||
else
|
}
|
||||||
return api == GHOST_kTabletNative;
|
else {
|
||||||
|
return api == GHOST_kTabletWinPointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GHOST_WindowWin32::processWin32TabletInitEvent()
|
GHOST_TabletData GHOST_WindowWin32::getTabletData()
|
||||||
{
|
{
|
||||||
if (!useTabletAPI(GHOST_kTabletWintab)) {
|
if (usingTabletAPI(GHOST_kTabletWintab)) {
|
||||||
return;
|
return m_wintab ? m_wintab->getLastTabletData() : GHOST_TABLET_DATA_NONE;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
// Let's see if we can initialize tablet here
|
return m_lastPointerTabletData;
|
||||||
if (m_wintab.info && m_wintab.tablet) {
|
|
||||||
AXIS Pressure, Orientation[3]; /* The maximum tablet size */
|
|
||||||
|
|
||||||
BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
|
||||||
if (pressureSupport)
|
|
||||||
m_wintab.maxPressure = Pressure.axMax;
|
|
||||||
else
|
|
||||||
m_wintab.maxPressure = 0;
|
|
||||||
|
|
||||||
BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
|
|
||||||
if (tiltSupport) {
|
|
||||||
/* does the tablet support azimuth ([0]) and altitude ([1]) */
|
|
||||||
if (Orientation[0].axResolution && Orientation[1].axResolution) {
|
|
||||||
m_wintab.maxAzimuth = Orientation[0].axMax;
|
|
||||||
m_wintab.maxAltitude = Orientation[1].axMax;
|
|
||||||
}
|
|
||||||
else { /* No so don't do tilt stuff. */
|
|
||||||
m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_tabletData.Active = GHOST_kTabletModeNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
if (!useTabletAPI(GHOST_kTabletWintab)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_wintab.packet && m_wintab.tablet) {
|
|
||||||
PACKET pkt;
|
|
||||||
if (m_wintab.packet((HCTX)lParam, wParam, &pkt)) {
|
|
||||||
switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */
|
|
||||||
case 0:
|
|
||||||
m_tabletData.Active = GHOST_kTabletModeNone; /* puck - not yet supported */
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
m_tabletData.Active = GHOST_kTabletModeStylus; /* stylus */
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
m_tabletData.Active = GHOST_kTabletModeEraser; /* eraser */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_wintab.maxPressure > 0) {
|
|
||||||
m_tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_wintab.maxPressure;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_tabletData.Pressure = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_wintab.maxAzimuth > 0) && (m_wintab.maxAltitude > 0)) {
|
|
||||||
ORIENTATION ort = pkt.pkOrientation;
|
|
||||||
float vecLen;
|
|
||||||
float altRad, azmRad; /* in radians */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* from the wintab spec:
|
|
||||||
* orAzimuth Specifies the clockwise rotation of the
|
|
||||||
* cursor about the z axis through a full circular range.
|
|
||||||
*
|
|
||||||
* orAltitude Specifies the angle with the x-y plane
|
|
||||||
* through a signed, semicircular range. Positive values
|
|
||||||
* specify an angle upward toward the positive z axis;
|
|
||||||
* negative values specify an angle downward toward the negative z axis.
|
|
||||||
*
|
|
||||||
* wintab.h defines .orAltitude as a UINT but documents .orAltitude
|
|
||||||
* as positive for upward angles and negative for downward angles.
|
|
||||||
* WACOM uses negative altitude values to show that the pen is inverted;
|
|
||||||
* therefore we cast .orAltitude as an (int) and then use the absolute value.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* convert raw fixed point data to radians */
|
|
||||||
altRad = (float)((fabs((float)ort.orAltitude) / (float)m_wintab.maxAltitude) * M_PI / 2.0);
|
|
||||||
azmRad = (float)(((float)ort.orAzimuth / (float)m_wintab.maxAzimuth) * M_PI * 2.0);
|
|
||||||
|
|
||||||
/* find length of the stylus' projected vector on the XY plane */
|
|
||||||
vecLen = cos(altRad);
|
|
||||||
|
|
||||||
/* from there calculate X and Y components based on azimuth */
|
|
||||||
m_tabletData.Xtilt = sin(azmRad) * vecLen;
|
|
||||||
m_tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_tabletData.Xtilt = 0.0f;
|
|
||||||
m_tabletData.Ytilt = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GHOST_WindowWin32::bringTabletContextToFront()
|
|
||||||
{
|
|
||||||
if (!useTabletAPI(GHOST_kTabletWintab)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_wintab.overlap && m_wintab.tablet) {
|
|
||||||
m_wintab.overlap(m_wintab.tablet, TRUE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,34 +30,18 @@
|
|||||||
|
|
||||||
#include "GHOST_TaskbarWin32.h"
|
#include "GHOST_TaskbarWin32.h"
|
||||||
#include "GHOST_Window.h"
|
#include "GHOST_Window.h"
|
||||||
|
#include "GHOST_Wintab.h"
|
||||||
#ifdef WITH_INPUT_IME
|
#ifdef WITH_INPUT_IME
|
||||||
# include "GHOST_ImeWin32.h"
|
# include "GHOST_ImeWin32.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <wintab.h>
|
|
||||||
// PACKETDATA and PACKETMODE modify structs in pktdef.h, so make sure they come first
|
|
||||||
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
|
|
||||||
#define PACKETMODE PK_BUTTONS
|
|
||||||
#include <pktdef.h>
|
|
||||||
|
|
||||||
class GHOST_SystemWin32;
|
class GHOST_SystemWin32;
|
||||||
class GHOST_DropTargetWin32;
|
class GHOST_DropTargetWin32;
|
||||||
|
|
||||||
// typedefs for WinTab functions to allow dynamic loading
|
|
||||||
typedef UINT(API *GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID);
|
|
||||||
typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
|
|
||||||
typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX);
|
|
||||||
typedef BOOL(API *GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID);
|
|
||||||
typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL);
|
|
||||||
typedef BOOL(API *GHOST_WIN32_WTOverlap)(HCTX, BOOL);
|
|
||||||
|
|
||||||
// typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions
|
// typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions
|
||||||
typedef UINT(API *GHOST_WIN32_GetDpiForWindow)(HWND);
|
typedef UINT(API *GHOST_WIN32_GetDpiForWindow)(HWND);
|
||||||
#ifndef USER_DEFAULT_SCREEN_DPI
|
|
||||||
# define USER_DEFAULT_SCREEN_DPI 96
|
|
||||||
#endif // USER_DEFAULT_SCREEN_DPI
|
|
||||||
|
|
||||||
struct GHOST_PointerInfoWin32 {
|
struct GHOST_PointerInfoWin32 {
|
||||||
GHOST_TInt32 pointerId;
|
GHOST_TInt32 pointerId;
|
||||||
@@ -65,7 +49,6 @@ struct GHOST_PointerInfoWin32 {
|
|||||||
GHOST_TButtonMask buttonMask;
|
GHOST_TButtonMask buttonMask;
|
||||||
POINT pixelLocation;
|
POINT pixelLocation;
|
||||||
GHOST_TUns64 time;
|
GHOST_TUns64 time;
|
||||||
|
|
||||||
GHOST_TabletData tabletData;
|
GHOST_TabletData tabletData;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -259,16 +242,11 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
|||||||
HCURSOR getStandardCursor(GHOST_TStandardCursor shape) const;
|
HCURSOR getStandardCursor(GHOST_TStandardCursor shape) const;
|
||||||
void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const;
|
void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const;
|
||||||
|
|
||||||
const GHOST_TabletData &getTabletData()
|
|
||||||
{
|
|
||||||
return m_tabletData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query whether given tablet API should be used.
|
* Query whether given tablet API should be used.
|
||||||
* \param api: Tablet API to test.
|
* \param api: Tablet API to test.
|
||||||
*/
|
*/
|
||||||
bool useTabletAPI(GHOST_TTabletAPI api) const;
|
bool usingTabletAPI(GHOST_TTabletAPI api) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translate WM_POINTER events into GHOST_PointerInfoWin32 structs.
|
* Translate WM_POINTER events into GHOST_PointerInfoWin32 structs.
|
||||||
@@ -281,10 +259,34 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
|||||||
WPARAM wParam,
|
WPARAM wParam,
|
||||||
LPARAM lParam);
|
LPARAM lParam);
|
||||||
|
|
||||||
void processWin32TabletActivateEvent(WORD state);
|
/**
|
||||||
void processWin32TabletInitEvent();
|
* Resets pointer pen tablet state.
|
||||||
void processWin32TabletEvent(WPARAM wParam, LPARAM lParam);
|
*/
|
||||||
void bringTabletContextToFront();
|
void resetPointerPenInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves pointer to Wintab if Wintab is the set Tablet API.
|
||||||
|
* \return Pointer to Wintab member.
|
||||||
|
*/
|
||||||
|
GHOST_Wintab *getWintab() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads Wintab context for the window.
|
||||||
|
* \param enable: True if Wintab should be enabled after loading. Wintab should not be enabled if
|
||||||
|
* the window is minimized.
|
||||||
|
*/
|
||||||
|
void loadWintab(bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes Wintab for the window.
|
||||||
|
*/
|
||||||
|
void closeWintab();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the most recent Windows Pointer tablet data.
|
||||||
|
* \return Most recent pointer tablet data.
|
||||||
|
*/
|
||||||
|
GHOST_TabletData getTabletData();
|
||||||
|
|
||||||
GHOST_TSuccess beginFullScreen() const
|
GHOST_TSuccess beginFullScreen() const
|
||||||
{
|
{
|
||||||
@@ -298,10 +300,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
|||||||
|
|
||||||
GHOST_TUns16 getDPIHint() override;
|
GHOST_TUns16 getDPIHint() override;
|
||||||
|
|
||||||
/** Whether a tablet stylus is being tracked. */
|
/** True if the mouse is either over or captured by the window. */
|
||||||
bool m_tabletInRange;
|
bool m_mousePresent;
|
||||||
|
|
||||||
/** if the window currently resizing */
|
/** True if the window currently resizing. */
|
||||||
bool m_inLiveResize;
|
bool m_inLiveResize;
|
||||||
|
|
||||||
#ifdef WITH_INPUT_IME
|
#ifdef WITH_INPUT_IME
|
||||||
@@ -385,27 +387,11 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
|||||||
static const wchar_t *s_windowClassName;
|
static const wchar_t *s_windowClassName;
|
||||||
static const int s_maxTitleLength;
|
static const int s_maxTitleLength;
|
||||||
|
|
||||||
/** Tablet data for GHOST */
|
/** Pointer to Wintab manager if Wintab is loaded. */
|
||||||
GHOST_TabletData m_tabletData;
|
GHOST_Wintab *m_wintab;
|
||||||
|
|
||||||
/* Wintab API */
|
/** Most recent tablet data. */
|
||||||
struct {
|
GHOST_TabletData m_lastPointerTabletData;
|
||||||
/** `WinTab.dll` handle. */
|
|
||||||
HMODULE handle = NULL;
|
|
||||||
|
|
||||||
/** API functions */
|
|
||||||
GHOST_WIN32_WTInfo info;
|
|
||||||
GHOST_WIN32_WTOpen open;
|
|
||||||
GHOST_WIN32_WTClose close;
|
|
||||||
GHOST_WIN32_WTPacket packet;
|
|
||||||
GHOST_WIN32_WTEnable enable;
|
|
||||||
GHOST_WIN32_WTOverlap overlap;
|
|
||||||
|
|
||||||
/** Stores the Tablet context if detected Tablet features using `WinTab.dll` */
|
|
||||||
HCTX tablet;
|
|
||||||
LONG maxPressure;
|
|
||||||
LONG maxAzimuth, maxAltitude;
|
|
||||||
} m_wintab;
|
|
||||||
|
|
||||||
GHOST_TWindowState m_normal_state;
|
GHOST_TWindowState m_normal_state;
|
||||||
|
|
||||||
|
@@ -1325,6 +1325,7 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
|
|||||||
for (int minor = 5; minor >= 0; --minor) {
|
for (int minor = 5; minor >= 0; --minor) {
|
||||||
#ifdef WITH_GL_EGL
|
#ifdef WITH_GL_EGL
|
||||||
context = new GHOST_ContextEGL(
|
context = new GHOST_ContextEGL(
|
||||||
|
this->m_system,
|
||||||
m_wantStereoVisual,
|
m_wantStereoVisual,
|
||||||
EGLNativeWindowType(m_window),
|
EGLNativeWindowType(m_window),
|
||||||
EGLNativeDisplayType(m_display),
|
EGLNativeDisplayType(m_display),
|
||||||
@@ -1355,7 +1356,8 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_GL_EGL
|
#ifdef WITH_GL_EGL
|
||||||
context = new GHOST_ContextEGL(m_wantStereoVisual,
|
context = new GHOST_ContextEGL(this->m_system,
|
||||||
|
m_wantStereoVisual,
|
||||||
EGLNativeWindowType(m_window),
|
EGLNativeWindowType(m_window),
|
||||||
EGLNativeDisplayType(m_display),
|
EGLNativeDisplayType(m_display),
|
||||||
profile_mask,
|
profile_mask,
|
||||||
|
491
intern/ghost/intern/GHOST_Wintab.cpp
Normal file
491
intern/ghost/intern/GHOST_Wintab.cpp
Normal file
@@ -0,0 +1,491 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup GHOST
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
|
||||||
|
#include "GHOST_Wintab.h"
|
||||||
|
|
||||||
|
GHOST_Wintab *GHOST_Wintab::loadWintab(HWND hwnd)
|
||||||
|
{
|
||||||
|
/* Load Wintab library if available. */
|
||||||
|
|
||||||
|
auto handle = unique_hmodule(::LoadLibrary("Wintab32.dll"), &::FreeLibrary);
|
||||||
|
if (!handle) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get Wintab functions. */
|
||||||
|
|
||||||
|
auto info = (GHOST_WIN32_WTInfo)::GetProcAddress(handle.get(), "WTInfoA");
|
||||||
|
if (!info) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto open = (GHOST_WIN32_WTOpen)::GetProcAddress(handle.get(), "WTOpenA");
|
||||||
|
if (!open) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto get = (GHOST_WIN32_WTGet)::GetProcAddress(handle.get(), "WTGetA");
|
||||||
|
if (!get) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto set = (GHOST_WIN32_WTSet)::GetProcAddress(handle.get(), "WTSetA");
|
||||||
|
if (!set) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto close = (GHOST_WIN32_WTClose)::GetProcAddress(handle.get(), "WTClose");
|
||||||
|
if (!close) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto packetsGet = (GHOST_WIN32_WTPacketsGet)::GetProcAddress(handle.get(), "WTPacketsGet");
|
||||||
|
if (!packetsGet) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto queueSizeGet = (GHOST_WIN32_WTQueueSizeGet)::GetProcAddress(handle.get(), "WTQueueSizeGet");
|
||||||
|
if (!queueSizeGet) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto queueSizeSet = (GHOST_WIN32_WTQueueSizeSet)::GetProcAddress(handle.get(), "WTQueueSizeSet");
|
||||||
|
if (!queueSizeSet) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto enable = (GHOST_WIN32_WTEnable)::GetProcAddress(handle.get(), "WTEnable");
|
||||||
|
if (!enable) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(handle.get(), "WTOverlap");
|
||||||
|
if (!overlap) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build Wintab context. */
|
||||||
|
|
||||||
|
LOGCONTEXT lc = {0};
|
||||||
|
if (!info(WTI_DEFSYSCTX, 0, &lc)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Coord tablet, system;
|
||||||
|
extractCoordinates(lc, tablet, system);
|
||||||
|
modifyContext(lc);
|
||||||
|
|
||||||
|
/* The Wintab spec says we must open the context disabled if we are using cursor masks. */
|
||||||
|
auto hctx = unique_hctx(open(hwnd, &lc, FALSE), close);
|
||||||
|
if (!hctx) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wintab provides no way to determine the maximum queue size aside from checking if attempts
|
||||||
|
* to change the queue size are successful. */
|
||||||
|
const int maxQueue = 500;
|
||||||
|
int queueSize = queueSizeGet(hctx.get());
|
||||||
|
|
||||||
|
while (queueSize < maxQueue) {
|
||||||
|
int testSize = min(queueSize + 16, maxQueue);
|
||||||
|
if (queueSizeSet(hctx.get(), testSize)) {
|
||||||
|
queueSize = testSize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* From Windows Wintab Documentation for WTQueueSizeSet:
|
||||||
|
* "If the return value is zero, the context has no queue because the function deletes the
|
||||||
|
* original queue before attempting to create a new one. The application must continue
|
||||||
|
* calling the function with a smaller queue size until the function returns a non - zero
|
||||||
|
* value."
|
||||||
|
*
|
||||||
|
* In our case we start with a known valid queue size and in the event of failure roll
|
||||||
|
* back to the last valid queue size. The Wintab spec dates back to 16 bit Windows, thus
|
||||||
|
* assumes memory recently deallocated may not be available, which is no longer a practical
|
||||||
|
* concern. */
|
||||||
|
if (!queueSizeSet(hctx.get(), queueSize)) {
|
||||||
|
/* If a previously valid queue size is no longer valid, there is likely something wrong in
|
||||||
|
* the Wintab implementation and we should not use it. */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GHOST_Wintab(hwnd,
|
||||||
|
std::move(handle),
|
||||||
|
info,
|
||||||
|
get,
|
||||||
|
set,
|
||||||
|
packetsGet,
|
||||||
|
enable,
|
||||||
|
overlap,
|
||||||
|
std::move(hctx),
|
||||||
|
tablet,
|
||||||
|
system,
|
||||||
|
queueSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::modifyContext(LOGCONTEXT &lc)
|
||||||
|
{
|
||||||
|
lc.lcPktData = PACKETDATA;
|
||||||
|
lc.lcPktMode = PACKETMODE;
|
||||||
|
lc.lcMoveMask = PACKETDATA;
|
||||||
|
lc.lcOptions |= CXO_CSRMESSAGES | CXO_MESSAGES;
|
||||||
|
|
||||||
|
/* Tablet scaling is handled manually because some drivers don't handle HIDPI or multi-display
|
||||||
|
* correctly; reset tablet scale factors to un-scaled tablet coordinates. */
|
||||||
|
lc.lcOutOrgX = lc.lcInOrgX;
|
||||||
|
lc.lcOutOrgY = lc.lcInOrgY;
|
||||||
|
lc.lcOutExtX = lc.lcInExtX;
|
||||||
|
lc.lcOutExtY = lc.lcInExtY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::extractCoordinates(LOGCONTEXT &lc, Coord &tablet, Coord &system)
|
||||||
|
{
|
||||||
|
tablet.x.org = lc.lcInOrgX;
|
||||||
|
tablet.x.ext = lc.lcInExtX;
|
||||||
|
tablet.y.org = lc.lcInOrgY;
|
||||||
|
tablet.y.ext = lc.lcInExtY;
|
||||||
|
|
||||||
|
system.x.org = lc.lcSysOrgX;
|
||||||
|
system.x.ext = lc.lcSysExtX;
|
||||||
|
system.y.org = lc.lcSysOrgY;
|
||||||
|
/* Wintab maps y origin to the tablet's bottom; invert y to match Windows y origin mapping to the
|
||||||
|
* screen top. */
|
||||||
|
system.y.ext = -lc.lcSysExtY;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_Wintab::GHOST_Wintab(HWND hwnd,
|
||||||
|
unique_hmodule handle,
|
||||||
|
GHOST_WIN32_WTInfo info,
|
||||||
|
GHOST_WIN32_WTGet get,
|
||||||
|
GHOST_WIN32_WTSet set,
|
||||||
|
GHOST_WIN32_WTPacketsGet packetsGet,
|
||||||
|
GHOST_WIN32_WTEnable enable,
|
||||||
|
GHOST_WIN32_WTOverlap overlap,
|
||||||
|
unique_hctx hctx,
|
||||||
|
Coord tablet,
|
||||||
|
Coord system,
|
||||||
|
int queueSize)
|
||||||
|
: m_handle{std::move(handle)},
|
||||||
|
m_fpInfo{info},
|
||||||
|
m_fpGet{get},
|
||||||
|
m_fpSet{set},
|
||||||
|
m_fpPacketsGet{packetsGet},
|
||||||
|
m_fpEnable{enable},
|
||||||
|
m_fpOverlap{overlap},
|
||||||
|
m_context{std::move(hctx)},
|
||||||
|
m_tabletCoord{tablet},
|
||||||
|
m_systemCoord{system},
|
||||||
|
m_pkts{queueSize}
|
||||||
|
{
|
||||||
|
m_fpInfo(WTI_INTERFACE, IFC_NDEVICES, &m_numDevices);
|
||||||
|
updateCursorInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::enable()
|
||||||
|
{
|
||||||
|
m_fpEnable(m_context.get(), true);
|
||||||
|
m_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::disable()
|
||||||
|
{
|
||||||
|
if (m_focused) {
|
||||||
|
loseFocus();
|
||||||
|
}
|
||||||
|
m_fpEnable(m_context.get(), false);
|
||||||
|
m_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::gainFocus()
|
||||||
|
{
|
||||||
|
m_fpOverlap(m_context.get(), true);
|
||||||
|
m_focused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::loseFocus()
|
||||||
|
{
|
||||||
|
if (m_lastTabletData.Active != GHOST_kTabletModeNone) {
|
||||||
|
leaveRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mouse mode of tablet or display layout may change when Wintab or Window is inactive. Don't
|
||||||
|
* trust for mouse movement until re-verified. */
|
||||||
|
m_coordTrusted = false;
|
||||||
|
|
||||||
|
m_fpOverlap(m_context.get(), false);
|
||||||
|
m_focused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::leaveRange()
|
||||||
|
{
|
||||||
|
/* Button state can't be tracked while out of range, reset it. */
|
||||||
|
m_buttons = 0;
|
||||||
|
/* Set to none to indicate tablet is inactive. */
|
||||||
|
m_lastTabletData = GHOST_TABLET_DATA_NONE;
|
||||||
|
/* Clear the packet queue. */
|
||||||
|
m_fpPacketsGet(m_context.get(), m_pkts.size(), m_pkts.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::remapCoordinates()
|
||||||
|
{
|
||||||
|
LOGCONTEXT lc = {0};
|
||||||
|
|
||||||
|
if (m_fpInfo(WTI_DEFSYSCTX, 0, &lc)) {
|
||||||
|
extractCoordinates(lc, m_tabletCoord, m_systemCoord);
|
||||||
|
modifyContext(lc);
|
||||||
|
|
||||||
|
m_fpSet(m_context.get(), &lc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::updateCursorInfo()
|
||||||
|
{
|
||||||
|
AXIS Pressure, Orientation[3];
|
||||||
|
|
||||||
|
BOOL pressureSupport = m_fpInfo(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
||||||
|
m_maxPressure = pressureSupport ? Pressure.axMax : 0;
|
||||||
|
|
||||||
|
BOOL tiltSupport = m_fpInfo(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
|
||||||
|
/* Check if tablet supports azimuth [0] and altitude [1], encoded in axResolution. */
|
||||||
|
if (tiltSupport && Orientation[0].axResolution && Orientation[1].axResolution) {
|
||||||
|
m_maxAzimuth = Orientation[0].axMax;
|
||||||
|
m_maxAltitude = Orientation[1].axMax;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_maxAzimuth = m_maxAltitude = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::processInfoChange(LPARAM lParam)
|
||||||
|
{
|
||||||
|
/* Update number of connected Wintab digitizers. */
|
||||||
|
if (LOWORD(lParam) == WTI_INTERFACE && HIWORD(lParam) == IFC_NDEVICES) {
|
||||||
|
m_fpInfo(WTI_INTERFACE, IFC_NDEVICES, &m_numDevices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GHOST_Wintab::devicesPresent()
|
||||||
|
{
|
||||||
|
return m_numDevices > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TabletData GHOST_Wintab::getLastTabletData()
|
||||||
|
{
|
||||||
|
return m_lastTabletData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
|
||||||
|
{
|
||||||
|
const int numPackets = m_fpPacketsGet(m_context.get(), m_pkts.size(), m_pkts.data());
|
||||||
|
outWintabInfo.resize(numPackets);
|
||||||
|
size_t outExtent = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < numPackets; i++) {
|
||||||
|
PACKET pkt = m_pkts[i];
|
||||||
|
GHOST_WintabInfoWin32 &out = outWintabInfo[i + outExtent];
|
||||||
|
|
||||||
|
out.tabletData = GHOST_TABLET_DATA_NONE;
|
||||||
|
/* % 3 for multiple devices ("DualTrack"). */
|
||||||
|
switch (pkt.pkCursor % 3) {
|
||||||
|
case 0:
|
||||||
|
/* Puck - processed as mouse. */
|
||||||
|
out.tabletData.Active = GHOST_kTabletModeNone;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
out.tabletData.Active = GHOST_kTabletModeStylus;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
out.tabletData.Active = GHOST_kTabletModeEraser;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.x = pkt.pkX;
|
||||||
|
out.y = pkt.pkY;
|
||||||
|
|
||||||
|
if (m_maxPressure > 0) {
|
||||||
|
out.tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_maxPressure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_maxAzimuth > 0) && (m_maxAltitude > 0)) {
|
||||||
|
ORIENTATION ort = pkt.pkOrientation;
|
||||||
|
float vecLen;
|
||||||
|
float altRad, azmRad; /* In radians. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From the wintab spec:
|
||||||
|
* orAzimuth: Specifies the clockwise rotation of the cursor about the z axis through a
|
||||||
|
* full circular range.
|
||||||
|
* orAltitude: Specifies the angle with the x-y plane through a signed, semicircular range.
|
||||||
|
* Positive values specify an angle upward toward the positive z axis; negative values
|
||||||
|
* specify an angle downward toward the negative z axis.
|
||||||
|
*
|
||||||
|
* wintab.h defines orAltitude as a UINT but documents orAltitude as positive for upward
|
||||||
|
* angles and negative for downward angles. WACOM uses negative altitude values to show that
|
||||||
|
* the pen is inverted; therefore we cast orAltitude as an (int) and then use the absolute
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Convert raw fixed point data to radians. */
|
||||||
|
altRad = (float)((fabs((float)ort.orAltitude) / (float)m_maxAltitude) * M_PI / 2.0);
|
||||||
|
azmRad = (float)(((float)ort.orAzimuth / (float)m_maxAzimuth) * M_PI * 2.0);
|
||||||
|
|
||||||
|
/* Find length of the stylus' projected vector on the XY plane. */
|
||||||
|
vecLen = cos(altRad);
|
||||||
|
|
||||||
|
/* From there calculate X and Y components based on azimuth. */
|
||||||
|
out.tabletData.Xtilt = sin(azmRad) * vecLen;
|
||||||
|
out.tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
out.time = pkt.pkTime;
|
||||||
|
|
||||||
|
/* Some Wintab libraries don't handle relative button input, so we track button presses
|
||||||
|
* manually. */
|
||||||
|
out.button = GHOST_kButtonMaskNone;
|
||||||
|
out.type = GHOST_kEventCursorMove;
|
||||||
|
|
||||||
|
DWORD buttonsChanged = m_buttons ^ pkt.pkButtons;
|
||||||
|
WORD buttonIndex = 0;
|
||||||
|
GHOST_WintabInfoWin32 buttonRef = out;
|
||||||
|
int buttons = 0;
|
||||||
|
|
||||||
|
while (buttonsChanged) {
|
||||||
|
if (buttonsChanged & 1) {
|
||||||
|
/* Find the index for the changed button from the button map. */
|
||||||
|
GHOST_TButtonMask button = mapWintabToGhostButton(pkt.pkCursor, buttonIndex);
|
||||||
|
|
||||||
|
if (button != GHOST_kButtonMaskNone) {
|
||||||
|
/* Extend output if multiple buttons are pressed. We don't extend input until we confirm
|
||||||
|
* a Wintab buttons maps to a system button. */
|
||||||
|
if (buttons > 0) {
|
||||||
|
outWintabInfo.resize(outWintabInfo.size() + 1);
|
||||||
|
outExtent++;
|
||||||
|
GHOST_WintabInfoWin32 &out = outWintabInfo[i + outExtent];
|
||||||
|
out = buttonRef;
|
||||||
|
}
|
||||||
|
buttons++;
|
||||||
|
|
||||||
|
out.button = button;
|
||||||
|
if (buttonsChanged & pkt.pkButtons) {
|
||||||
|
out.type = GHOST_kEventButtonDown;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out.type = GHOST_kEventButtonUp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buttons ^= 1 << buttonIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonsChanged >>= 1;
|
||||||
|
buttonIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outWintabInfo.empty()) {
|
||||||
|
m_lastTabletData = outWintabInfo.back().tabletData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GHOST_TButtonMask GHOST_Wintab::mapWintabToGhostButton(UINT cursor, WORD physicalButton)
|
||||||
|
{
|
||||||
|
const WORD numButtons = 32;
|
||||||
|
BYTE logicalButtons[numButtons] = {0};
|
||||||
|
BYTE systemButtons[numButtons] = {0};
|
||||||
|
|
||||||
|
if (!m_fpInfo(WTI_CURSORS + cursor, CSR_BUTTONMAP, &logicalButtons) ||
|
||||||
|
!m_fpInfo(WTI_CURSORS + cursor, CSR_SYSBTNMAP, &systemButtons)) {
|
||||||
|
return GHOST_kButtonMaskNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (physicalButton >= numButtons) {
|
||||||
|
return GHOST_kButtonMaskNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE lb = logicalButtons[physicalButton];
|
||||||
|
|
||||||
|
if (lb >= numButtons) {
|
||||||
|
return GHOST_kButtonMaskNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (systemButtons[lb]) {
|
||||||
|
case SBN_LCLICK:
|
||||||
|
return GHOST_kButtonMaskLeft;
|
||||||
|
case SBN_RCLICK:
|
||||||
|
return GHOST_kButtonMaskRight;
|
||||||
|
case SBN_MCLICK:
|
||||||
|
return GHOST_kButtonMaskMiddle;
|
||||||
|
default:
|
||||||
|
return GHOST_kButtonMaskNone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GHOST_Wintab::mapWintabToSysCoordinates(int x_in, int y_in, int &x_out, int &y_out)
|
||||||
|
{
|
||||||
|
/* Maps from range [in.org, in.org + abs(in.ext)] to [out.org, out.org + abs(out.ext)], in
|
||||||
|
* reverse if in.ext and out.ext have differing sign. */
|
||||||
|
auto remap = [](int inPoint, Range in, Range out) -> int {
|
||||||
|
int absInExt = abs(in.ext);
|
||||||
|
int absOutExt = abs(out.ext);
|
||||||
|
|
||||||
|
/* Translate input from range [in.org, in.org + absInExt] to [0, absInExt] */
|
||||||
|
int inMagnitude = inPoint - in.org;
|
||||||
|
|
||||||
|
/* If signs of extents differ, reverse input over range. */
|
||||||
|
if ((in.ext < 0) != (out.ext < 0)) {
|
||||||
|
inMagnitude = absInExt - inMagnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scale from [0, absInExt] to [0, absOutExt]. */
|
||||||
|
int outMagnitude = inMagnitude * absOutExt / absInExt;
|
||||||
|
|
||||||
|
/* Translate from range [0, absOutExt] to [out.org, out.org + absOutExt]. */
|
||||||
|
int outPoint = outMagnitude + out.org;
|
||||||
|
|
||||||
|
return outPoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
x_out = remap(x_in, m_tabletCoord.x, m_systemCoord.x);
|
||||||
|
y_out = remap(y_in, m_tabletCoord.y, m_systemCoord.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GHOST_Wintab::trustCoordinates()
|
||||||
|
{
|
||||||
|
return m_coordTrusted;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GHOST_Wintab::testCoordinates(int sysX, int sysY, int wtX, int wtY)
|
||||||
|
{
|
||||||
|
mapWintabToSysCoordinates(wtX, wtY, wtX, wtY);
|
||||||
|
|
||||||
|
/* Allow off by one pixel tolerance in case of rounding error. */
|
||||||
|
if (abs(sysX - wtX) <= 1 && abs(sysY - wtY) <= 1) {
|
||||||
|
m_coordTrusted = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_coordTrusted = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
250
intern/ghost/intern/GHOST_Wintab.h
Normal file
250
intern/ghost/intern/GHOST_Wintab.h
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup GHOST
|
||||||
|
* Declaration of GHOST_WintabWin32 class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Wacom's Wintab documentation is periodically offline, moved, and increasingly hidden away. You
|
||||||
|
* can find a (painstakingly) archived copy of the documentation at
|
||||||
|
* https://web.archive.org/web/20201122230125/https://developer-docs-legacy.wacom.com/display/DevDocs/Windows+Wintab+Documentation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <wtypes.h>
|
||||||
|
|
||||||
|
#include "GHOST_Types.h"
|
||||||
|
|
||||||
|
#include <wintab.h>
|
||||||
|
/* PACKETDATA and PACKETMODE modify structs in pktdef.h, so make sure they come first. */
|
||||||
|
#define PACKETDATA \
|
||||||
|
(PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_X | PK_Y | PK_TIME)
|
||||||
|
#define PACKETMODE 0
|
||||||
|
#include <pktdef.h>
|
||||||
|
|
||||||
|
/* Typedefs for Wintab functions to allow dynamic loading. */
|
||||||
|
typedef UINT(API *GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID);
|
||||||
|
typedef BOOL(API *GHOST_WIN32_WTGet)(HCTX, LPLOGCONTEXTA);
|
||||||
|
typedef BOOL(API *GHOST_WIN32_WTSet)(HCTX, LPLOGCONTEXTA);
|
||||||
|
typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
|
||||||
|
typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX);
|
||||||
|
typedef int(API *GHOST_WIN32_WTPacketsGet)(HCTX, int, LPVOID);
|
||||||
|
typedef int(API *GHOST_WIN32_WTQueueSizeGet)(HCTX);
|
||||||
|
typedef BOOL(API *GHOST_WIN32_WTQueueSizeSet)(HCTX, int);
|
||||||
|
typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL);
|
||||||
|
typedef BOOL(API *GHOST_WIN32_WTOverlap)(HCTX, BOOL);
|
||||||
|
|
||||||
|
/* Typedefs for Wintab and Windows resource management. */
|
||||||
|
typedef std::unique_ptr<std::remove_pointer_t<HMODULE>, decltype(&::FreeLibrary)> unique_hmodule;
|
||||||
|
typedef std::unique_ptr<std::remove_pointer_t<HCTX>, GHOST_WIN32_WTClose> unique_hctx;
|
||||||
|
|
||||||
|
struct GHOST_WintabInfoWin32 {
|
||||||
|
GHOST_TInt32 x, y;
|
||||||
|
GHOST_TEventType type;
|
||||||
|
GHOST_TButtonMask button;
|
||||||
|
GHOST_TUns64 time;
|
||||||
|
GHOST_TabletData tabletData;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GHOST_Wintab {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Loads Wintab if available.
|
||||||
|
* \param hwnd: Window to attach Wintab context to.
|
||||||
|
*/
|
||||||
|
static GHOST_Wintab *loadWintab(HWND hwnd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables Wintab context.
|
||||||
|
*/
|
||||||
|
void enable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables the Wintab context and unwinds Wintab state.
|
||||||
|
*/
|
||||||
|
void disable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Brings Wintab context to the top of the overlap order.
|
||||||
|
*/
|
||||||
|
void gainFocus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts Wintab context at bottom of overlap order and unwinds Wintab state.
|
||||||
|
*/
|
||||||
|
void loseFocus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up when Wintab leaves tracking range.
|
||||||
|
*/
|
||||||
|
void leaveRange();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle Wintab coordinate changes when DisplayChange events occur.
|
||||||
|
*/
|
||||||
|
void remapCoordinates();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps Wintab to Win32 display coordinates.
|
||||||
|
* \param x_in: The tablet x coordinate.
|
||||||
|
* \param y_in: The tablet y coordinate.
|
||||||
|
* \param x_out: Output for the Win32 mapped x coordinate.
|
||||||
|
* \param y_out: Output for the Win32 mapped y coordinate.
|
||||||
|
*/
|
||||||
|
void mapWintabToSysCoordinates(int x_in, int y_in, int &x_out, int &y_out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates cached Wintab properties for current cursor.
|
||||||
|
*/
|
||||||
|
void updateCursorInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle Wintab info changes such as change in number of connected tablets.
|
||||||
|
* \param lParam: LPARAM of the event.
|
||||||
|
*/
|
||||||
|
void processInfoChange(LPARAM lParam);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether Wintab devices are present.
|
||||||
|
* \return True if Wintab devices are present.
|
||||||
|
*/
|
||||||
|
bool devicesPresent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate Wintab packets into GHOST_WintabInfoWin32 structs.
|
||||||
|
* \param outWintabInfo: Storage to return resulting GHOST_WintabInfoWin32 data.
|
||||||
|
*/
|
||||||
|
void getInput(std::vector<GHOST_WintabInfoWin32> &outWintabInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether Wintab coordinates should be trusted.
|
||||||
|
* \return True if Wintab coordinates should be trusted.
|
||||||
|
*/
|
||||||
|
bool trustCoordinates();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether Wintab coordinates can be trusted by comparing Win32 and Wintab reported cursor
|
||||||
|
* position.
|
||||||
|
* \param sysX: System cursor x position.
|
||||||
|
* \param sysY: System cursor y position.
|
||||||
|
* \param wtX: Wintab cursor x position.
|
||||||
|
* \param wtY: Wintab cursor y position.
|
||||||
|
* \return True if Win32 and Wintab cursor positions match within tolerance.
|
||||||
|
*
|
||||||
|
* Note: Only test coordinates on button press, not release. This prevents issues when async
|
||||||
|
* mismatch causes mouse movement to replay and snap back, which is only an issue while drawing.
|
||||||
|
*/
|
||||||
|
bool testCoordinates(int sysX, int sysY, int wtX, int wtY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the most recent tablet data, or none if pen is not in range.
|
||||||
|
* \return Most recent tablet data, or none if pen is not in range.
|
||||||
|
*/
|
||||||
|
GHOST_TabletData getLastTabletData();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Wintab DLL handle. */
|
||||||
|
unique_hmodule m_handle;
|
||||||
|
/** Wintab API functions. */
|
||||||
|
GHOST_WIN32_WTInfo m_fpInfo = nullptr;
|
||||||
|
GHOST_WIN32_WTGet m_fpGet = nullptr;
|
||||||
|
GHOST_WIN32_WTSet m_fpSet = nullptr;
|
||||||
|
GHOST_WIN32_WTPacketsGet m_fpPacketsGet = nullptr;
|
||||||
|
GHOST_WIN32_WTEnable m_fpEnable = nullptr;
|
||||||
|
GHOST_WIN32_WTOverlap m_fpOverlap = nullptr;
|
||||||
|
|
||||||
|
/** Stores the Wintab tablet context. */
|
||||||
|
unique_hctx m_context;
|
||||||
|
/** Whether the context is enabled. */
|
||||||
|
bool m_enabled = false;
|
||||||
|
/** Whether the context has focus and is at the top of overlap order. */
|
||||||
|
bool m_focused = false;
|
||||||
|
|
||||||
|
/** Pressed button map. */
|
||||||
|
GHOST_TUns8 m_buttons = 0;
|
||||||
|
|
||||||
|
/** Range of a coordinate space. */
|
||||||
|
struct Range {
|
||||||
|
/** Origin of range. */
|
||||||
|
int org = 0;
|
||||||
|
/** Extent of range. */
|
||||||
|
int ext = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 2D Coordinate space. */
|
||||||
|
struct Coord {
|
||||||
|
/** Range of x. */
|
||||||
|
Range x = {};
|
||||||
|
/** Range of y. */
|
||||||
|
Range y = {};
|
||||||
|
};
|
||||||
|
/** Whether Wintab coordinates are trusted. */
|
||||||
|
bool m_coordTrusted = false;
|
||||||
|
/** Tablet input range. */
|
||||||
|
Coord m_tabletCoord = {};
|
||||||
|
/** System output range. */
|
||||||
|
Coord m_systemCoord = {};
|
||||||
|
|
||||||
|
int m_maxPressure = 0;
|
||||||
|
int m_maxAzimuth = 0;
|
||||||
|
int m_maxAltitude = 0;
|
||||||
|
|
||||||
|
/** Number of connected Wintab devices. */
|
||||||
|
UINT m_numDevices = 0;
|
||||||
|
/** Reusable buffer to read in Wintab packets. */
|
||||||
|
std::vector<PACKET> m_pkts;
|
||||||
|
/** Most recently received tablet data, or none if pen is not in range. */
|
||||||
|
GHOST_TabletData m_lastTabletData = GHOST_TABLET_DATA_NONE;
|
||||||
|
|
||||||
|
GHOST_Wintab(HWND hwnd,
|
||||||
|
unique_hmodule handle,
|
||||||
|
GHOST_WIN32_WTInfo info,
|
||||||
|
GHOST_WIN32_WTGet get,
|
||||||
|
GHOST_WIN32_WTSet set,
|
||||||
|
GHOST_WIN32_WTPacketsGet packetsGet,
|
||||||
|
GHOST_WIN32_WTEnable enable,
|
||||||
|
GHOST_WIN32_WTOverlap overlap,
|
||||||
|
unique_hctx hctx,
|
||||||
|
Coord tablet,
|
||||||
|
Coord system,
|
||||||
|
int queueSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert Wintab system mapped (mouse) buttons into Ghost button mask.
|
||||||
|
* \param cursor: The Wintab cursor associated to the button.
|
||||||
|
* \param physicalButton: The physical button ID to inspect.
|
||||||
|
* \return The system mapped button.
|
||||||
|
*/
|
||||||
|
GHOST_TButtonMask mapWintabToGhostButton(UINT cursor, WORD physicalButton);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies common modifications to Wintab context.
|
||||||
|
* \param lc: Wintab context to modify.
|
||||||
|
*/
|
||||||
|
static void modifyContext(LOGCONTEXT &lc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts tablet and system coordinates from Wintab context.
|
||||||
|
* \param lc: Wintab context to extract coordinates from.
|
||||||
|
* \param tablet: Tablet coordinates.
|
||||||
|
* \param system: System coordinates.
|
||||||
|
*/
|
||||||
|
static void extractCoordinates(LOGCONTEXT &lc, Coord &tablet, Coord &system);
|
||||||
|
};
|
@@ -392,9 +392,10 @@ GHOST_XrActionSet::GHOST_XrActionSet(XrInstance instance, const GHOST_XrActionSe
|
|||||||
{
|
{
|
||||||
XrActionSetCreateInfo action_set_info{XR_TYPE_ACTION_SET_CREATE_INFO};
|
XrActionSetCreateInfo action_set_info{XR_TYPE_ACTION_SET_CREATE_INFO};
|
||||||
strcpy(action_set_info.actionSetName, info.name);
|
strcpy(action_set_info.actionSetName, info.name);
|
||||||
strcpy(action_set_info.localizedActionSetName,
|
|
||||||
info.name); /* Just use same name for localized. This can be changed in the future if
|
/* Just use same name for localized. This can be changed in the future if necessary. */
|
||||||
necessary. */
|
strcpy(action_set_info.localizedActionSetName, info.name);
|
||||||
|
|
||||||
action_set_info.priority = 0; /* Use same (default) priority for all action sets. */
|
action_set_info.priority = 0; /* Use same (default) priority for all action sets. */
|
||||||
|
|
||||||
CHECK_XR(xrCreateActionSet(instance, &action_set_info, &m_action_set),
|
CHECK_XR(xrCreateActionSet(instance, &action_set_info, &m_action_set),
|
||||||
|
@@ -420,6 +420,11 @@ void GHOST_XrContext::getExtensionsToEnable(
|
|||||||
r_ext_names.push_back(gpu_binding);
|
r_ext_names.push_back(gpu_binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(WITH_GHOST_X11) && defined(WITH_GL_EGL)
|
||||||
|
assert(openxr_extension_is_available(m_oxr->extensions, XR_MNDX_EGL_ENABLE_EXTENSION_NAME));
|
||||||
|
r_ext_names.push_back(XR_MNDX_EGL_ENABLE_EXTENSION_NAME);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (const std::string_view &ext : try_ext) {
|
for (const std::string_view &ext : try_ext) {
|
||||||
if (openxr_extension_is_available(m_oxr->extensions, ext)) {
|
if (openxr_extension_is_available(m_oxr->extensions, ext)) {
|
||||||
r_ext_names.push_back(ext.data());
|
r_ext_names.push_back(ext.data());
|
||||||
|
@@ -22,7 +22,15 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#if defined(WITH_GHOST_X11)
|
#if defined(WITH_GL_EGL)
|
||||||
|
# include "GHOST_ContextEGL.h"
|
||||||
|
# if defined(WITH_GHOST_X11)
|
||||||
|
# include "GHOST_SystemX11.h"
|
||||||
|
# endif
|
||||||
|
# if defined(WITH_GHOST_WAYLAND)
|
||||||
|
# include "GHOST_SystemWayland.h"
|
||||||
|
# endif
|
||||||
|
#elif defined(WITH_GHOST_X11)
|
||||||
# include "GHOST_ContextGLX.h"
|
# include "GHOST_ContextGLX.h"
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
# include "GHOST_ContextD3D.h"
|
# include "GHOST_ContextD3D.h"
|
||||||
@@ -66,7 +74,9 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
|
|||||||
XrSystemId system_id,
|
XrSystemId system_id,
|
||||||
std::string *r_requirement_info) const override
|
std::string *r_requirement_info) const override
|
||||||
{
|
{
|
||||||
#if defined(WITH_GHOST_X11)
|
#if defined(WITH_GL_EGL)
|
||||||
|
GHOST_ContextEGL &ctx_gl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
|
||||||
|
#elif defined(WITH_GHOST_X11)
|
||||||
GHOST_ContextGLX &ctx_gl = static_cast<GHOST_ContextGLX &>(ghost_ctx);
|
GHOST_ContextGLX &ctx_gl = static_cast<GHOST_ContextGLX &>(ghost_ctx);
|
||||||
#else
|
#else
|
||||||
GHOST_ContextWGL &ctx_gl = static_cast<GHOST_ContextWGL &>(ghost_ctx);
|
GHOST_ContextWGL &ctx_gl = static_cast<GHOST_ContextWGL &>(ghost_ctx);
|
||||||
@@ -106,6 +116,17 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
|
|||||||
void initFromGhostContext(GHOST_Context &ghost_ctx) override
|
void initFromGhostContext(GHOST_Context &ghost_ctx) override
|
||||||
{
|
{
|
||||||
#if defined(WITH_GHOST_X11)
|
#if defined(WITH_GHOST_X11)
|
||||||
|
# if defined(WITH_GL_EGL)
|
||||||
|
GHOST_ContextEGL &ctx_egl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
|
||||||
|
|
||||||
|
if (dynamic_cast<const GHOST_SystemX11 *const>(ctx_egl.m_system)) {
|
||||||
|
oxr_binding.egl.type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX;
|
||||||
|
oxr_binding.egl.getProcAddress = eglGetProcAddress;
|
||||||
|
oxr_binding.egl.display = ctx_egl.getDisplay();
|
||||||
|
oxr_binding.egl.config = ctx_egl.getConfig();
|
||||||
|
oxr_binding.egl.context = ctx_egl.getContext();
|
||||||
|
}
|
||||||
|
# else
|
||||||
GHOST_ContextGLX &ctx_glx = static_cast<GHOST_ContextGLX &>(ghost_ctx);
|
GHOST_ContextGLX &ctx_glx = static_cast<GHOST_ContextGLX &>(ghost_ctx);
|
||||||
XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx.m_display, ctx_glx.m_fbconfig);
|
XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx.m_display, ctx_glx.m_fbconfig);
|
||||||
|
|
||||||
@@ -117,6 +138,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
|
|||||||
oxr_binding.glx.visualid = visual_info->visualid;
|
oxr_binding.glx.visualid = visual_info->visualid;
|
||||||
|
|
||||||
XFree(visual_info);
|
XFree(visual_info);
|
||||||
|
# endif
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
GHOST_ContextWGL &ctx_wgl = static_cast<GHOST_ContextWGL &>(ghost_ctx);
|
GHOST_ContextWGL &ctx_wgl = static_cast<GHOST_ContextWGL &>(ghost_ctx);
|
||||||
|
|
||||||
@@ -125,6 +147,14 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
|
|||||||
oxr_binding.wgl.hGLRC = ctx_wgl.m_hGLRC;
|
oxr_binding.wgl.hGLRC = ctx_wgl.m_hGLRC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WITH_GHOST_WAYLAND)
|
||||||
|
GHOST_ContextEGL &ctx_wl_egl = static_cast<GHOST_ContextEGL &>(ghost_ctx);
|
||||||
|
if (dynamic_cast<const GHOST_SystemWayland *const>(ctx_wl_egl.m_system)) {
|
||||||
|
oxr_binding.wl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR;
|
||||||
|
oxr_binding.wl.display = (struct wl_display *)ctx_wl_egl.m_nativeDisplay;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Generate a frame-buffer to use for blitting into the texture. */
|
/* Generate a frame-buffer to use for blitting into the texture. */
|
||||||
glGenFramebuffers(1, &m_fbo);
|
glGenFramebuffers(1, &m_fbo);
|
||||||
}
|
}
|
||||||
|
@@ -74,10 +74,11 @@ class GHOST_XrSession {
|
|||||||
const GHOST_XrActionProfileInfo *infos);
|
const GHOST_XrActionProfileInfo *infos);
|
||||||
bool attachActionSets();
|
bool attachActionSets();
|
||||||
|
|
||||||
/** Action functions to be called post-session start. */
|
/**
|
||||||
bool syncActions(
|
* Action functions to be called post-session start.
|
||||||
const char *action_set_name = nullptr); /* If action_set_name is nullptr, all attached
|
* \param action_set_name: When `nullptr`, all attached action sets will be synced.
|
||||||
* action sets will be synced. */
|
*/
|
||||||
|
bool syncActions(const char *action_set_name = nullptr);
|
||||||
bool applyHapticAction(const char *action_set_name,
|
bool applyHapticAction(const char *action_set_name,
|
||||||
const char *action_name,
|
const char *action_name,
|
||||||
const GHOST_TInt64 &duration,
|
const GHOST_TInt64 &duration,
|
||||||
|
@@ -42,7 +42,13 @@
|
|||||||
# include <d3d12.h>
|
# include <d3d12.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_GHOST_X11
|
#ifdef WITH_GHOST_X11
|
||||||
# include <GL/glxew.h>
|
# ifdef WITH_GL_EGL
|
||||||
|
/* TODO: Why do we have to create this typedef manually? */
|
||||||
|
typedef void (*(*PFNEGLGETPROCADDRESSPROC)(const char *procname))(void);
|
||||||
|
# include <GL/eglew.h>
|
||||||
|
# else
|
||||||
|
# include <GL/glxew.h>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <openxr/openxr.h>
|
#include <openxr/openxr.h>
|
||||||
|
@@ -78,7 +78,7 @@ extern short (*MEM_testN)(void *vmemh);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Duplicates a block of memory, and returns a pointer to the
|
* Duplicates a block of memory, and returns a pointer to the
|
||||||
* newly allocated block. */
|
* newly allocated block. */
|
||||||
extern void *(*MEM_dupallocN)(const void *vmemh) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT;
|
extern void *(*MEM_dupallocN)(const void *vmemh) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -103,7 +103,7 @@ int main(int argc, char *argv[])
|
|||||||
/* ----------------------------------------------------------------- */
|
/* ----------------------------------------------------------------- */
|
||||||
/* Round two, do a normal allocation, and corrupt some blocks. */
|
/* Round two, do a normal allocation, and corrupt some blocks. */
|
||||||
/* ----------------------------------------------------------------- */
|
/* ----------------------------------------------------------------- */
|
||||||
/* switch off, because it will complain about some things. */
|
/* Switch off, because it will complain about some things. */
|
||||||
MEM_set_error_callback(NULL);
|
MEM_set_error_callback(NULL);
|
||||||
|
|
||||||
for (i = 0; i < NUM_BLOCKS; i++) {
|
for (i = 0; i < NUM_BLOCKS; i++) {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user