Merge branch 'master' into refactor-mesh-position-generic
This commit is contained in:
commit
6192f0c712
|
@ -242,17 +242,17 @@ if(UNIX AND NOT (APPLE OR HAIKU))
|
|||
option(WITH_GHOST_X11 "Enable building Blender against X11 for windowing" ON)
|
||||
mark_as_advanced(WITH_GHOST_X11)
|
||||
|
||||
option(WITH_GHOST_WAYLAND "Enable building Blender against Wayland for windowing (under development)" OFF)
|
||||
option(WITH_GHOST_WAYLAND "Enable building Blender against Wayland for windowing" ON)
|
||||
mark_as_advanced(WITH_GHOST_WAYLAND)
|
||||
|
||||
if(WITH_GHOST_WAYLAND)
|
||||
option(WITH_GHOST_WAYLAND_LIBDECOR "Optionally build with LibDecor window decorations" OFF)
|
||||
option(WITH_GHOST_WAYLAND_LIBDECOR "Optionally build with LibDecor window decorations" ON)
|
||||
mark_as_advanced(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
|
||||
option(WITH_GHOST_WAYLAND_DBUS "Optionally build with DBUS support (used for Cursor themes). May hang on startup systems where DBUS is not used." OFF)
|
||||
mark_as_advanced(WITH_GHOST_WAYLAND_DBUS)
|
||||
|
||||
option(WITH_GHOST_WAYLAND_DYNLOAD "Enable runtime dynamic WAYLAND libraries loading" OFF)
|
||||
option(WITH_GHOST_WAYLAND_DYNLOAD "Enable runtime dynamic WAYLAND libraries loading" ON)
|
||||
mark_as_advanced(WITH_GHOST_WAYLAND_DYNLOAD)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -1913,9 +1913,25 @@ if(FIRST_RUN)
|
|||
info_cfg_option(WITH_INSTALL_PORTABLE)
|
||||
info_cfg_option(WITH_MEM_JEMALLOC)
|
||||
info_cfg_option(WITH_MEM_VALGRIND)
|
||||
info_cfg_option(WITH_X11_XF86VMODE)
|
||||
info_cfg_option(WITH_X11_XFIXES)
|
||||
info_cfg_option(WITH_X11_XINPUT)
|
||||
|
||||
info_cfg_text("GHOST Options:")
|
||||
info_cfg_option(WITH_GHOST_DEBUG)
|
||||
info_cfg_option(WITH_GHOST_SDL)
|
||||
if(UNIX AND NOT APPLE)
|
||||
info_cfg_option(WITH_GHOST_X11)
|
||||
info_cfg_option(WITH_GHOST_WAYLAND)
|
||||
if(WITH_GHOST_X11)
|
||||
info_cfg_option(WITH_GHOST_XDND)
|
||||
info_cfg_option(WITH_X11_XF86VMODE)
|
||||
info_cfg_option(WITH_X11_XFIXES)
|
||||
info_cfg_option(WITH_X11_XINPUT)
|
||||
endif()
|
||||
if(WITH_GHOST_WAYLAND)
|
||||
info_cfg_option(WITH_GHOST_WAYLAND_DYNLOAD)
|
||||
info_cfg_option(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
info_cfg_option(WITH_GHOST_WAYLAND_DBUS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
info_cfg_text("Image Formats:")
|
||||
info_cfg_option(WITH_IMAGE_CINEON)
|
||||
|
|
|
@ -176,3 +176,4 @@ if(UNIX AND NOT APPLE)
|
|||
endif()
|
||||
|
||||
include(cmake/harvest.cmake)
|
||||
include(cmake/cve_check.cmake)
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# CVE Check requirements
|
||||
#
|
||||
# - A working installation of intels cve-bin-tool [1] has to be available in
|
||||
# your path
|
||||
#
|
||||
# - Not strictly required, but highly recommended is obtaining a NVD key from
|
||||
# nist since it significantly speeds up downloading/updating the required
|
||||
# databases one can request a key on the following website:
|
||||
# https://nvd.nist.gov/developers/request-an-api-key
|
||||
|
||||
# Bill of Materials construction
|
||||
#
|
||||
# This constructs a CSV cve-bin-tool [1] can read and process. Sadly
|
||||
# cve-bin-tool at this point does not take a list of CPE's and output a check
|
||||
# based on that list. so we need to pick apart the CPE retrieve the vendor,
|
||||
# product and version tokens and generate a CSV.
|
||||
#
|
||||
# [1] https://github.com/intel/cve-bin-tool
|
||||
|
||||
# Because not all deps are downloaded (ie python packages) but can still have a
|
||||
# xxx_CPE declared loop over all variables and look for variables ending in CPE.
|
||||
|
||||
set(SBOMCONTENTS)
|
||||
get_cmake_property(_variableNames VARIABLES)
|
||||
foreach (_variableName ${_variableNames})
|
||||
if(_variableName MATCHES "CPE$")
|
||||
string(REPLACE ":" ";" CPE_LIST ${${_variableName}})
|
||||
list(GET CPE_LIST 3 CPE_VENDOR)
|
||||
list(GET CPE_LIST 4 CPE_NAME)
|
||||
list(GET CPE_LIST 5 CPE_VERSION)
|
||||
set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}\n")
|
||||
endif()
|
||||
endforeach()
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/cve_check.csv.in ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv @ONLY)
|
||||
|
||||
# Custom Targets
|
||||
#
|
||||
# This defines two new custom targets one could run in the build folder
|
||||
# `cve_check` which will output the report to the console, and `cve_check_html`
|
||||
# which will write out blender_dependencies.html in the build folder that one
|
||||
# could share with other people or be used to get more information on the
|
||||
# reported CVE's.
|
||||
#
|
||||
# cve-bin-tool takes data from the nist nvd database which rate limits
|
||||
# unauthenticated requests to 1 requests per 6 seconds making the database
|
||||
# download take "quite a bit" of time.
|
||||
#
|
||||
# When adding -DCVE_CHECK_NVD_KEY=your_api_key_here to your cmake invocation
|
||||
# this key will be passed on to cve-bin-tool speeding up the process.
|
||||
#
|
||||
if(DEFINED CVE_CHECK_NVD_KEY)
|
||||
set(NVD_ARGS --nvd-api-key ${CVE_CHECK_NVD_KEY})
|
||||
endif()
|
||||
|
||||
# This will just report to the console
|
||||
add_custom_target(cve_check
|
||||
COMMAND cve-bin-tool
|
||||
${NVD_ARGS}
|
||||
-i ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
|
||||
--affected-versions
|
||||
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
|
||||
)
|
||||
|
||||
# This will write out blender_dependencies.html
|
||||
add_custom_target(cve_check_html
|
||||
COMMAND cve-bin-tool
|
||||
${NVD_ARGS}
|
||||
-i ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
|
||||
-f html
|
||||
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
|
||||
)
|
|
@ -0,0 +1,2 @@
|
|||
vendor,product,version
|
||||
@SBOMCONTENTS@
|
|
@ -4,11 +4,9 @@
|
|||
# library itself does not depend on them, so should give no problems.
|
||||
|
||||
set(OPENPGL_EXTRA_ARGS
|
||||
-DOPENPGL_BUILD_PYTHON=OFF
|
||||
-DOPENPGL_BUILD_STATIC=ON
|
||||
-DOPENPGL_TBB_ROOT=${LIBDIR}/tbb
|
||||
-DTBB_ROOT=${LIBDIR}/tbb
|
||||
-Dembree_DIR=${LIBDIR}/embree/lib/cmake/embree-${EMBREE_VERSION}
|
||||
-DCMAKE_DEBUG_POSTFIX=_d
|
||||
)
|
||||
|
||||
|
@ -31,7 +29,6 @@ ExternalProject_Add(external_openpgl
|
|||
add_dependencies(
|
||||
external_openpgl
|
||||
external_tbb
|
||||
external_embree
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
@ -43,6 +40,7 @@ if(WIN32)
|
|||
else()
|
||||
ExternalProject_Add_Step(external_openpgl after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openpgl/lib/openpgl_d.lib ${HARVEST_TARGET}/openpgl/lib/openpgl_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openpgl/lib/cmake/openpgl-${OPENPGL_SHORT_VERSION}/openpgl_Exports-debug.cmake ${HARVEST_TARGET}/openpgl/lib/cmake/openpgl-${OPENPGL_SHORT_VERSION}/openpgl_Exports-debug.cmake
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# CPE's are used to identify dependencies, for more information on what they
|
||||
# are please see https://nvd.nist.gov/products/cpe
|
||||
#
|
||||
# We use them in combination with cve-bin-tool to scan for known security issues.
|
||||
#
|
||||
# Not all of our dependencies are currently in the nvd database so not all
|
||||
# dependencies have one assigned.
|
||||
|
||||
set(ZLIB_VERSION 1.2.12)
|
||||
set(ZLIB_URI https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz)
|
||||
set(ZLIB_HASH 5fc414a9726be31427b440b434d05f78)
|
||||
set(ZLIB_HASH_TYPE MD5)
|
||||
set(ZLIB_FILE zlib-${ZLIB_VERSION}.tar.gz)
|
||||
set(ZLIB_CPE "cpe:2.3:a:zlib:zlib:${ZLIB_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(OPENAL_VERSION 1.21.1)
|
||||
set(OPENAL_URI http://openal-soft.org/openal-releases/openal-soft-${OPENAL_VERSION}.tar.bz2)
|
||||
|
@ -17,12 +26,14 @@ set(PNG_URI http://prdownloads.sourceforge.net/libpng/libpng-${PNG_VERSION}.tar.
|
|||
set(PNG_HASH 505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca)
|
||||
set(PNG_HASH_TYPE SHA256)
|
||||
set(PNG_FILE libpng-${PNG_VERSION}.tar.xz)
|
||||
set(PNG_CPE "cpe:2.3:a:libpng:libpng:${PNG_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(JPEG_VERSION 2.1.3)
|
||||
set(JPEG_URI https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${JPEG_VERSION}.tar.gz)
|
||||
set(JPEG_HASH 627b980fad0573e08e4c3b80b290fc91)
|
||||
set(JPEG_HASH_TYPE MD5)
|
||||
set(JPEG_FILE libjpeg-turbo-${JPEG_VERSION}.tar.gz)
|
||||
set(JPEG_CPE "cpe:2.3:a:d.r.commander:libjpeg-turbo:${JPEG_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(BOOST_VERSION 1.78.0)
|
||||
set(BOOST_VERSION_SHORT 1.78)
|
||||
|
@ -32,12 +43,14 @@ set(BOOST_URI https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION
|
|||
set(BOOST_HASH c2f6428ac52b0e5a3c9b2e1d8cc832b5)
|
||||
set(BOOST_HASH_TYPE MD5)
|
||||
set(BOOST_FILE boost_${BOOST_VERSION_NODOTS}.tar.gz)
|
||||
set(BOOST_CPE "cpe:2.3:a:boost:boost:${BOOST_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(BLOSC_VERSION 1.21.1)
|
||||
set(BLOSC_URI https://github.com/Blosc/c-blosc/archive/v${BLOSC_VERSION}.tar.gz)
|
||||
set(BLOSC_HASH 134b55813b1dca57019d2a2dc1f7a923)
|
||||
set(BLOSC_HASH_TYPE MD5)
|
||||
set(BLOSC_FILE blosc-${BLOSC_VERSION}.tar.gz)
|
||||
set(BLOSC_CPE "cpe:2.3:a:c-blosc2_project:c-blosc2:${BLOSC_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(PTHREADS_VERSION 3.0.0)
|
||||
set(PTHREADS_URI http://prdownloads.sourceforge.net/pthreads4w/pthreads4w-code-v${PTHREADS_VERSION}.zip)
|
||||
|
@ -50,6 +63,7 @@ set(OPENEXR_URI https://github.com/AcademySoftwareFoundation/openexr/archive/v${
|
|||
set(OPENEXR_HASH a92f38eedd43e56c0af56d4852506886)
|
||||
set(OPENEXR_HASH_TYPE MD5)
|
||||
set(OPENEXR_FILE openexr-${OPENEXR_VERSION}.tar.gz)
|
||||
set(OPENEXR_CPE "cpe:2.3:a:openexr:openexr:${OPENEXR_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(IMATH_VERSION 3.1.5)
|
||||
set(IMATH_URI https://github.com/AcademySoftwareFoundation/Imath/archive/v${OPENEXR_VERSION}.tar.gz)
|
||||
|
@ -79,6 +93,7 @@ set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE
|
|||
set(FREETYPE_HASH bd4e3b007474319909a6b79d50908e85)
|
||||
set(FREETYPE_HASH_TYPE MD5)
|
||||
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)
|
||||
SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(EPOXY_VERSION 1.5.10)
|
||||
set(EPOXY_URI https://github.com/anholt/libepoxy/archive/refs/tags/${EPOXY_VERSION}.tar.gz)
|
||||
|
@ -97,6 +112,7 @@ set(ALEMBIC_URI https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.ta
|
|||
set(ALEMBIC_HASH 2cd8d6e5a3ac4a014e24a4b04f4fadf9)
|
||||
set(ALEMBIC_HASH_TYPE MD5)
|
||||
set(ALEMBIC_FILE alembic-${ALEMBIC_VERSION}.tar.gz)
|
||||
SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(OPENSUBDIV_VERSION v3_4_4)
|
||||
set(OPENSUBDIV_URI https://github.com/PixarAnimationStudios/OpenSubdiv/archive/${OPENSUBDIV_VERSION}.tar.gz)
|
||||
|
@ -109,6 +125,7 @@ set(SDL_URI https://www.libsdl.org/release/SDL2-${SDL_VERSION}.tar.gz)
|
|||
set(SDL_HASH a53acc02e1cca98c4123229069b67c9e)
|
||||
set(SDL_HASH_TYPE MD5)
|
||||
set(SDL_FILE SDL2-${SDL_VERSION}.tar.gz)
|
||||
set(SDL_CPE "cpe:2.3:a:libsdl:sdl:${SDL_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(OPENCOLLADA_VERSION v1.6.68)
|
||||
set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz)
|
||||
|
@ -127,6 +144,7 @@ set(LLVM_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LL
|
|||
set(LLVM_HASH 5a4fab4d7fc84aefffb118ac2c8a4fc0)
|
||||
set(LLVM_HASH_TYPE MD5)
|
||||
set(LLVM_FILE llvm-project-${LLVM_VERSION}.src.tar.xz)
|
||||
set(LLVM_CPE "cpe:2.3:a:llvm:compiler:${LLVM_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
if(APPLE)
|
||||
# Cloth physics test is crashing due to this bug:
|
||||
|
@ -154,6 +172,7 @@ set(FMT_URI https://github.com/fmtlib/fmt/archive/refs/tags/${FMT_VERSION}.tar.g
|
|||
set(FMT_HASH 7bce0e9e022e586b178b150002e7c2339994e3c2bbe44027e9abb0d60f9cce83)
|
||||
set(FMT_HASH_TYPE SHA256)
|
||||
set(FMT_FILE fmt-${FMT_VERSION}.tar.gz)
|
||||
set(FMT_CPE "cpe:2.3:a:fmt:fmt:${FMT_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
# 0.6.2 is currently oiio's preferred version although never versions may be available.
|
||||
# the preferred version can be found in oiio's externalpackages.cmake
|
||||
|
@ -168,6 +187,7 @@ set(TIFF_URI http://download.osgeo.org/libtiff/tiff-${TIFF_VERSION}.tar.gz)
|
|||
set(TIFF_HASH 376f17f189e9d02280dfe709b2b2bbea)
|
||||
set(TIFF_HASH_TYPE MD5)
|
||||
set(TIFF_FILE tiff-${TIFF_VERSION}.tar.gz)
|
||||
set(TIFF_CPE "cpe:2.3:a:libtiff:libtiff:${TIFF_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(OSL_VERSION 1.11.17.0)
|
||||
set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz)
|
||||
|
@ -182,12 +202,15 @@ set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTH
|
|||
set(PYTHON_HASH 14e8c22458ed7779a1957b26cde01db9)
|
||||
set(PYTHON_HASH_TYPE MD5)
|
||||
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
|
||||
set(PYTHON_CPE "cpe:2.3:a:python:python:${PYTHON_VERSION}:-:*:*:*:*:*:*")
|
||||
|
||||
set(TBB_VERSION 2020_U3)
|
||||
set(TBB_YEAR 2020)
|
||||
set(TBB_VERSION ${TBB_YEAR}_U3)
|
||||
set(TBB_URI https://github.com/oneapi-src/oneTBB/archive/${TBB_VERSION}.tar.gz)
|
||||
set(TBB_HASH 55ec8df6eae5ed6364a47f0e671e460c)
|
||||
set(TBB_HASH_TYPE MD5)
|
||||
set(TBB_FILE oneTBB-${TBB_VERSION}.tar.gz)
|
||||
set(TBB_CPE "cpe:2.3:a:intel:threading_building_blocks:${TBB_YEAR}:*:*:*:*:*:*:*")
|
||||
|
||||
set(OPENVDB_VERSION 9.0.0)
|
||||
set(OPENVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/v${OPENVDB_VERSION}.tar.gz)
|
||||
|
@ -198,6 +221,7 @@ set(OPENVDB_FILE openvdb-${OPENVDB_VERSION}.tar.gz)
|
|||
set(IDNA_VERSION 3.3)
|
||||
set(CHARSET_NORMALIZER_VERSION 2.0.10)
|
||||
set(URLLIB3_VERSION 1.26.8)
|
||||
set(URLLIB3_CPE "cpe:2.3:a:urllib3:urllib3:${URLLIB3_VERSION}:*:*:*:*:*:*:*")
|
||||
set(CERTIFI_VERSION 2021.10.8)
|
||||
set(REQUESTS_VERSION 2.27.1)
|
||||
set(CYTHON_VERSION 0.29.26)
|
||||
|
@ -214,12 +238,14 @@ set(NUMPY_URI https://github.com/numpy/numpy/releases/download/v${NUMPY_VERSION}
|
|||
set(NUMPY_HASH 252de134862a27bd66705d29622edbfe)
|
||||
set(NUMPY_HASH_TYPE MD5)
|
||||
set(NUMPY_FILE numpy-${NUMPY_VERSION}.zip)
|
||||
set(NUMPY_CPE "cpe:2.3:a:numpy:numpy:${NUMPY_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(LAME_VERSION 3.100)
|
||||
set(LAME_URI http://downloads.sourceforge.net/project/lame/lame/3.100/lame-${LAME_VERSION}.tar.gz)
|
||||
set(LAME_HASH 83e260acbe4389b54fe08e0bdbf7cddb)
|
||||
set(LAME_HASH_TYPE MD5)
|
||||
set(LAME_FILE lame-${LAME_VERSION}.tar.gz)
|
||||
set(LAME_CPE "cpe:2.3:a:lame_project:lame:${LAME_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(OGG_VERSION 1.3.5)
|
||||
set(OGG_URI http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz)
|
||||
|
@ -232,6 +258,7 @@ set(VORBIS_URI http://downloads.xiph.org/releases/vorbis/libvorbis-${VORBIS_VERS
|
|||
set(VORBIS_HASH 0e982409a9c3fc82ee06e08205b1355e5c6aa4c36bca58146ef399621b0ce5ab)
|
||||
set(VORBIS_HASH_TYPE SHA256)
|
||||
set(VORBIS_FILE libvorbis-${VORBIS_VERSION}.tar.gz)
|
||||
set(VORBIS_CPE "cpe:2.3:a:xiph.org:libvorbis:${VORBIS_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(THEORA_VERSION 1.1.1)
|
||||
set(THEORA_URI http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.bz2)
|
||||
|
@ -244,12 +271,14 @@ set(FLAC_URI http://downloads.xiph.org/releases/flac/flac-${FLAC_VERSION}.tar.xz
|
|||
set(FLAC_HASH 8ff0607e75a322dd7cd6ec48f4f225471404ae2730d0ea945127b1355155e737 )
|
||||
set(FLAC_HASH_TYPE SHA256)
|
||||
set(FLAC_FILE flac-${FLAC_VERSION}.tar.xz)
|
||||
set(FLAC_CPE "cpe:2.3:a:flac_project:flac:${FLAC_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(VPX_VERSION 1.11.0)
|
||||
set(VPX_URI https://github.com/webmproject/libvpx/archive/v${VPX_VERSION}/libvpx-v${VPX_VERSION}.tar.gz)
|
||||
set(VPX_HASH 965e51c91ad9851e2337aebcc0f517440c637c506f3a03948062e3d5ea129a83)
|
||||
set(VPX_HASH_TYPE SHA256)
|
||||
set(VPX_FILE libvpx-v${VPX_VERSION}.tar.gz)
|
||||
set(VPX_CPE "cpe:2.3:a:webmproject:libvpx:${VPX_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(OPUS_VERSION 1.3.1)
|
||||
set(OPUS_URI https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz)
|
||||
|
@ -275,12 +304,14 @@ set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSI
|
|||
set(OPENJPEG_HASH 8702ba68b442657f11aaeb2b338443ca8d5fb95b0d845757968a7be31ef7f16d)
|
||||
set(OPENJPEG_HASH_TYPE SHA256)
|
||||
set(OPENJPEG_FILE openjpeg-v${OPENJPEG_VERSION}.tar.gz)
|
||||
set(OPENJPEG_CPE "cpe:2.3:a:uclouvain:openjpeg:${OPENJPEG_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(FFMPEG_VERSION 5.0)
|
||||
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
|
||||
set(FFMPEG_HASH c0130b8db2c763430fd1c6905288d61bc44ee0548ad5fcd2dfd650b88432bed9)
|
||||
set(FFMPEG_HASH_TYPE SHA256)
|
||||
set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2)
|
||||
set(FFMPEG_CPE "cpe:2.3:a:ffmpeg:ffmpeg:${FFMPEG_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(FFTW_VERSION 3.3.10)
|
||||
set(FFTW_URI http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz)
|
||||
|
@ -299,12 +330,14 @@ set(SNDFILE_URI http://www.mega-nerd.com/libsndfile/files/libsndfile-${SNDFILE_V
|
|||
set(SNDFILE_HASH 646b5f98ce89ac60cdb060fcd398247c)
|
||||
set(SNDFILE_HASH_TYPE MD5)
|
||||
set(SNDFILE_FILE libsndfile-${SNDFILE_VERSION}.tar.gz)
|
||||
set(SNDFILE_CPE "cpe:2.3:a:libsndfile_project:libsndfile:${SNDFILE_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(WEBP_VERSION 1.2.2)
|
||||
set(WEBP_URI https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz)
|
||||
set(WEBP_HASH b5e2e414a8adee4c25fe56b18dd9c549)
|
||||
set(WEBP_HASH_TYPE MD5)
|
||||
set(WEBP_FILE libwebp-${WEBP_VERSION}.tar.gz)
|
||||
set(WEBP_CPE "cpe:2.3:a:webmproject:libwebp:${WEBP_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(SPNAV_VERSION 0.2.3)
|
||||
set(SPNAV_URI http://downloads.sourceforge.net/project/spacenav/spacenav%20library%20%28SDK%29/libspnav%20${SPNAV_VERSION}/libspnav-${SPNAV_VERSION}.tar.gz)
|
||||
|
@ -323,6 +356,7 @@ set(XML2_URI http://xmlsoft.org/sources/libxml2-${XML2_VERSION}.tar.gz)
|
|||
set(XML2_HASH 10942a1dc23137a8aa07f0639cbfece5)
|
||||
set(XML2_HASH_TYPE MD5)
|
||||
set(XML2_FILE libxml2-${XML2_VERSION}.tar.gz)
|
||||
set(XML2_CPE "cpe:2.3:a:xmlsoft:libxml2:${XML2_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(TINYXML_VERSION 2_6_2)
|
||||
set(TINYXML_VERSION_DOTS 2.6.2)
|
||||
|
@ -330,12 +364,14 @@ set(TINYXML_URI https://nchc.dl.sourceforge.net/project/tinyxml/tinyxml/${TINYXM
|
|||
set(TINYXML_HASH c1b864c96804a10526540c664ade67f0)
|
||||
set(TINYXML_HASH_TYPE MD5)
|
||||
set(TINYXML_FILE tinyxml_${TINYXML_VERSION}.tar.gz)
|
||||
set(TINYXML_CPE "cpe:2.3:a:tinyxml_project:tinyxml:${TINYXML_VERSION_DOTS}:*:*:*:*:*:*:*")
|
||||
|
||||
set(YAMLCPP_VERSION 0.6.3)
|
||||
set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION})
|
||||
set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2)
|
||||
set(YAMLCPP_HASH_TYPE MD5)
|
||||
set(YAMLCPP_FILE yaml-cpp-${YAMLCPP_VERSION}.tar.gz)
|
||||
set(YAMLCPP "cpe:2.3:a:yaml-cpp_project:yaml-cpp:${YAMLCPP_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(PYSTRING_VERSION v1.1.3)
|
||||
set(PYSTRING_URI https://codeload.github.com/imageworks/pystring/tar.gz/refs/tags/${PYSTRING_VERSION})
|
||||
|
@ -344,16 +380,19 @@ set(PYSTRING_HASH_TYPE MD5)
|
|||
set(PYSTRING_FILE pystring-${PYSTRING_VERSION}.tar.gz)
|
||||
|
||||
set(EXPAT_VERSION 2_4_4)
|
||||
set(EXPAT_VERSION_DOTS 2.4.4)
|
||||
set(EXPAT_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz)
|
||||
set(EXPAT_HASH 2d3e81dee94b452369dc6394ff0f8f98)
|
||||
set(EXPAT_HASH_TYPE MD5)
|
||||
set(EXPAT_FILE libexpat-${EXPAT_VERSION}.tar.gz)
|
||||
set(EXPAT_CPE "cpe:2.3:a:libexpat_project:libexpat:${EXPAT_VERSION_DOTS}:*:*:*:*:*:*:*")
|
||||
|
||||
set(PUGIXML_VERSION 1.10)
|
||||
set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar.gz)
|
||||
set(PUGIXML_HASH 0c208b0664c7fb822bf1b49ad035e8fd)
|
||||
set(PUGIXML_HASH_TYPE MD5)
|
||||
set(PUGIXML_FILE pugixml-${PUGIXML_VERSION}.tar.gz)
|
||||
set(PUGIXML_CPE "cpe:2.3:a:pugixml_project:pugixml:${PUGIXML_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(FLEXBISON_VERSION 2.5.24)
|
||||
set(FLEXBISON_URI http://prdownloads.sourceforge.net/winflexbison/win_flex_bison-${FLEXBISON_VERSION}.zip)
|
||||
|
@ -376,12 +415,14 @@ set(BZIP2_URI http://http.debian.net/debian/pool/main/b/bzip2/bzip2_${BZIP2_VERS
|
|||
set(BZIP2_HASH ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269)
|
||||
set(BZIP2_HASH_TYPE SHA256)
|
||||
set(BZIP2_FILE bzip2_${BZIP2_VERSION}.orig.tar.gz)
|
||||
set(BZIP2_CPE "cpe:2.3:a:bzip:bzip2:${BZIP2_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(FFI_VERSION 3.3)
|
||||
set(FFI_URI https://sourceware.org/pub/libffi/libffi-${FFI_VERSION}.tar.gz)
|
||||
set(FFI_HASH 72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056)
|
||||
set(FFI_HASH_TYPE SHA256)
|
||||
set(FFI_FILE libffi-${FFI_VERSION}.tar.gz)
|
||||
set(FFI_CPE "cpe:2.3:a:libffi_project:libffi:${FFI_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(LZMA_VERSION 5.2.5)
|
||||
set(LZMA_URI https://tukaani.org/xz/xz-${LZMA_VERSION}.tar.bz2)
|
||||
|
@ -403,12 +444,14 @@ else()
|
|||
set(SSL_HASH_TYPE SHA256)
|
||||
set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
|
||||
endif()
|
||||
set(SSL_CPE "cpe:2.3:a:openssl:openssl:${SSL_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(SQLITE_VERSION 3.31.1)
|
||||
set(SQLITE_URI https://www.sqlite.org/2018/sqlite-src-3240000.zip)
|
||||
set(SQLITE_HASH fb558c49ee21a837713c4f1e7e413309aabdd9c7)
|
||||
set(SQLITE_HASH_TYPE SHA1)
|
||||
set(SQLITE_FILE sqlite-src-3240000.zip)
|
||||
set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(EMBREE_VERSION 3.13.4)
|
||||
set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip)
|
||||
|
@ -439,12 +482,14 @@ set(MESA_URI ftp://ftp.freedesktop.org/pub/mesa/mesa-${MESA_VERSION}.tar.xz)
|
|||
set(MESA_HASH 022c7293074aeeced2278c872db4fa693147c70f8595b076cf3f1ef81520766d)
|
||||
set(MESA_HASH_TYPE SHA256)
|
||||
set(MESA_FILE mesa-${MESA_VERSION}.tar.xz)
|
||||
set(MESA_CPE "cpe:2.3:a:mesa3d:mesa:${MESA_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(NASM_VERSION 2.15.02)
|
||||
set(NASM_URI https://github.com/netwide-assembler/nasm/archive/nasm-${NASM_VERSION}.tar.gz)
|
||||
set(NASM_HASH aded8b796c996a486a56e0515c83e414116decc3b184d88043480b32eb0a8589)
|
||||
set(NASM_HASH_TYPE SHA256)
|
||||
set(NASM_FILE nasm-${NASM_VERSION}.tar.gz)
|
||||
set(NASM_PCE "cpe:2.3:a:nasm:nasm:${NASM_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(XR_OPENXR_SDK_VERSION 1.0.22)
|
||||
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)
|
||||
|
@ -481,12 +526,14 @@ set(GMP_URI https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.xz)
|
|||
set(GMP_HASH 0b82665c4a92fd2ade7440c13fcaa42b)
|
||||
set(GMP_HASH_TYPE MD5)
|
||||
set(GMP_FILE gmp-${GMP_VERSION}.tar.xz)
|
||||
set(GMP_CPE "cpe:2.3:a:gmplib:gmp:${GMP_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(POTRACE_VERSION 1.16)
|
||||
set(POTRACE_URI http://potrace.sourceforge.net/download/${POTRACE_VERSION}/potrace-${POTRACE_VERSION}.tar.gz)
|
||||
set(POTRACE_HASH 5f0bd87ddd9a620b0c4e65652ef93d69)
|
||||
set(POTRACE_HASH_TYPE MD5)
|
||||
set(POTRACE_FILE potrace-${POTRACE_VERSION}.tar.gz)
|
||||
set(POTRACE_CPE "cpe:2.3:a:icoasoft:potrace:${POTRACE_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(HARU_VERSION 2_3_0)
|
||||
set(HARU_URI https://github.com/libharu/libharu/archive/RELEASE_${HARU_VERSION}.tar.gz)
|
||||
|
@ -499,6 +546,7 @@ set(ZSTD_URI https://github.com/facebook/zstd/releases/download/v${ZSTD_VERSION}
|
|||
set(ZSTD_HASH 5194fbfa781fcf45b98c5e849651aa7b3b0a008c6b72d4a0db760f3002291e94)
|
||||
set(ZSTD_HASH_TYPE SHA256)
|
||||
set(ZSTD_FILE zstd-${ZSTD_VERSION}.tar.gz)
|
||||
set(ZSTD_CPE "cpe:2.3:a:facebook:zstandard:${ZSTD_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(SSE2NEON_VERSION fe5ff00bb8d19b327714a3c290f3e2ce81ba3525)
|
||||
set(SSE2NEON_URI https://github.com/DLTcollab/sse2neon/archive/${SSE2NEON_VERSION}.tar.gz)
|
||||
|
@ -506,16 +554,17 @@ set(SSE2NEON_HASH 0780253525d299c31775ef95853698d03db9c7739942af8570000f4a25a5d6
|
|||
set(SSE2NEON_HASH_TYPE SHA256)
|
||||
set(SSE2NEON_FILE sse2neon-${SSE2NEON_VERSION}.tar.gz)
|
||||
|
||||
set(BROTLI_VERSION v1.0.9)
|
||||
set(BROTLI_URI https://github.com/google/brotli/archive/refs/tags/${BROTLI_VERSION}.tar.gz)
|
||||
set(BROTLI_VERSION 1.0.9)
|
||||
set(BROTLI_URI https://github.com/google/brotli/archive/refs/tags/v${BROTLI_VERSION}.tar.gz)
|
||||
set(BROTLI_HASH f9e8d81d0405ba66d181529af42a3354f838c939095ff99930da6aa9cdf6fe46)
|
||||
set(BROTLI_HASH_TYPE SHA256)
|
||||
set(BROTLI_FILE brotli-${BROTLI_VERSION}.tar.gz)
|
||||
set(BROTLI_FILE brotli-v${BROTLI_VERSION}.tar.gz)
|
||||
set(BROTLI_CPE "cpe:2.3:a:google:brotli:${BROTLI_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(OPENPGL_VERSION v0.3.1-beta)
|
||||
set(OPENPGL_SHORT_VERSION 0.3.1)
|
||||
set(OPENPGL_VERSION v0.4.0-beta)
|
||||
set(OPENPGL_SHORT_VERSION 0.4.0)
|
||||
set(OPENPGL_URI https://github.com/OpenPathGuidingLibrary/openpgl/archive/refs/tags/${OPENPGL_VERSION}.tar.gz)
|
||||
set(OPENPGL_HASH 3830098c485c962018932766199527aab453a8029528dbbc04d4454d82431e2c)
|
||||
set(OPENPGL_HASH 58d5b65c533ce6cac3f7e1d51cf169a5411adf356abcd85f04049bbcaecc2e77)
|
||||
set(OPENPGL_HASH_TYPE SHA256)
|
||||
set(OPENPGL_FILE openpgl-${OPENPGL_VERSION}.tar.gz)
|
||||
|
||||
|
|
|
@ -5,7 +5,14 @@ ExternalProject_Add(external_wayland_protocols
|
|||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${WL_PROTOCOLS_HASH_TYPE}=${WL_PROTOCOLS_HASH}
|
||||
PREFIX ${BUILD_DIR}/wayland-protocols
|
||||
CONFIGURE_COMMAND meson --prefix ${LIBDIR}/wayland-protocols . ../external_wayland_protocols -Dtests=false
|
||||
# Use `-E` so the `PKG_CONFIG_PATH` can be defined to link against our own WAYLAND.
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/wayland/lib64/pkgconfig:$PKG_CONFIG_PATH
|
||||
meson --prefix ${LIBDIR}/wayland-protocols . ../external_wayland_protocols -Dtests=false
|
||||
BUILD_COMMAND ninja
|
||||
INSTALL_COMMAND ninja install
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
external_wayland_protocols
|
||||
external_wayland
|
||||
)
|
||||
|
|
|
@ -1222,7 +1222,7 @@ Those libraries should be available as packages in all recent distributions (opt
|
|||
* Basics of dev environment (cmake, gcc, svn , git, ...).
|
||||
* libjpeg, libpng, libtiff, [openjpeg2], [libopenal].
|
||||
* libx11, libxcursor, libxi, libxrandr, libxinerama (and other libx... as needed).
|
||||
* libwayland-client0, libwayland-cursor0, libwayland-egl1, libxkbcommon0, libdbus-1-3, libegl1 (Wayland)
|
||||
* libwayland-client0, libdecor, libwayland-cursor0, libwayland-egl1, libxkbcommon0, libdbus-1-3, libegl1 (Wayland)
|
||||
* libsqlite3, libzstd, libbz2, libssl, libfftw3, libxml2, libtinyxml, yasm, libyaml-cpp, flex.
|
||||
* libsdl2, libepoxy, libpugixml, libpotrace, [libgmp], fontconfig, [libharu/libhpdf].\""
|
||||
|
||||
|
@ -4205,7 +4205,7 @@ install_DEB() {
|
|||
_packages="gawk cmake cmake-curses-gui build-essential libjpeg-dev libpng-dev libtiff-dev \
|
||||
git libfreetype6-dev libfontconfig-dev libx11-dev flex bison libxxf86vm-dev \
|
||||
libxcursor-dev libxi-dev wget libsqlite3-dev libxrandr-dev libxinerama-dev \
|
||||
libwayland-dev wayland-protocols libegl-dev libxkbcommon-dev libdbus-1-dev linux-libc-dev \
|
||||
libwayland-dev libdecor-0-dev wayland-protocols libegl-dev libxkbcommon-dev libdbus-1-dev linux-libc-dev \
|
||||
libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev \
|
||||
libopenal-dev libepoxy-dev yasm \
|
||||
libsdl2-dev libfftw3-dev patch bzip2 libxml2-dev libtinyxml-dev libjemalloc-dev \
|
||||
|
@ -4928,7 +4928,7 @@ install_RPM() {
|
|||
_packages="gcc gcc-c++ git make cmake tar bzip2 xz findutils flex bison fontconfig-devel \
|
||||
libtiff-devel libjpeg-devel libpng-devel sqlite-devel fftw-devel SDL2-devel \
|
||||
libX11-devel libXi-devel libXcursor-devel libXrandr-devel libXinerama-devel \
|
||||
wayland-devel wayland-protocols-devel mesa-libEGL-devel libxkbcommon-devel dbus-devel kernel-headers \
|
||||
wayland-devel libdecor-devel wayland-protocols-devel mesa-libEGL-devel libxkbcommon-devel dbus-devel kernel-headers \
|
||||
wget ncurses-devel readline-devel $OPENJPEG_DEV openal-soft-devel \
|
||||
libepoxy-devel yasm patch \
|
||||
libxml2-devel yaml-cpp-devel tinyxml-devel jemalloc-devel \
|
||||
|
@ -5582,7 +5582,7 @@ install_ARCH() {
|
|||
fi
|
||||
|
||||
_packages="$BASE_DEVEL git cmake fontconfig flex \
|
||||
libxi libxcursor libxrandr libxinerama libepoxy libpng libtiff wget openal \
|
||||
libxi libxcursor libxrandr libxinerama libepoxy libdecor libpng libtiff wget openal \
|
||||
$OPENJPEG_DEV yasm sdl2 fftw \
|
||||
libxml2 yaml-cpp tinyxml python-requests jemalloc gmp potrace pugixml libharu \
|
||||
zstd pystring"
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
#!/bin/sh
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# This script is part of the official build environment, see WIKI page for details.
|
||||
# https://wiki.blender.org/wiki/Building_Blender/Other/CentOS7ReleaseEnvironment
|
||||
|
||||
set -e
|
||||
|
||||
|
@ -22,18 +26,79 @@ yum -y install centos-release-scl
|
|||
yum -y install devtoolset-9
|
||||
|
||||
# Install packages needed for Blender's dependencies.
|
||||
yum -y install -y \
|
||||
git subversion bzip2 tar cmake3 patch make autoconf automake libtool \
|
||||
meson ninja-build \
|
||||
libXrandr-devel libXinerama-devel libXcursor-devel libXi-devel \
|
||||
libX11-devel libXt-devel \
|
||||
mesa-libEGL-devel mesa-libGL-devel mesa-libGLU-devel \
|
||||
zlib-devel \
|
||||
rubygem-asciidoctor \
|
||||
wget tcl yasm python36 python-setuptools bison flex \
|
||||
ncurses-devel \
|
||||
wayland-devel libwayland-client libwayland-server \
|
||||
PACKAGES_FOR_LIBS=(
|
||||
# Used to checkout Blender's code.
|
||||
git
|
||||
# Used to checkout Blender's `../lib/` directory.
|
||||
subversion
|
||||
# Used to extract packages.
|
||||
bzip2
|
||||
# Used to extract packages.
|
||||
tar
|
||||
# Blender and some dependencies use `cmake`.
|
||||
cmake3
|
||||
# Apply patches from Blender's: `./build_files/build_environment/patches`
|
||||
patch
|
||||
# Use by `cmake` and `autoconf`.
|
||||
make
|
||||
|
||||
# Required by: `external_nasm` which uses an `autoconf` build-system.
|
||||
autoconf
|
||||
automake
|
||||
libtool
|
||||
|
||||
# Meta-build system used by various packages.
|
||||
meson
|
||||
# Builds generated by meson use Ninja for the actual build.
|
||||
ninja-build
|
||||
|
||||
# Required by Blender build option: `WITH_GHOST_X11`.
|
||||
libXrandr-devel
|
||||
libXinerama-devel
|
||||
libXcursor-devel
|
||||
libXi-devel
|
||||
libX11-devel
|
||||
libXt-devel
|
||||
|
||||
# Required by Blender build option: `WITH_GHOST_WAYLAND`.
|
||||
mesa-libEGL-devel
|
||||
# Required by: Blender & `external_opensubdiv` (probably others).
|
||||
mesa-libGL-devel
|
||||
mesa-libGLU-devel
|
||||
|
||||
# Required by: `external_ispc`.
|
||||
zlib-devel
|
||||
# TODO: dependencies build without this, consider removal.
|
||||
rubygem-asciidoctor
|
||||
# TODO: dependencies build without this, consider removal.
|
||||
wget
|
||||
# Required by: `external_sqlite` as a build-time dependency (needed for the `tclsh` command).
|
||||
tcl
|
||||
# Required by: `external_aom`.
|
||||
# TODO: Blender is already building `external_nasm` which is listed as an alternative to `yasm`.
|
||||
# Why are both needed?
|
||||
yasm
|
||||
|
||||
# Required by: `meson` (Python based build system).
|
||||
python36
|
||||
# Required by: `mako` (Python module used for building `external_mesa`)
|
||||
python-setuptools
|
||||
|
||||
# Required by: `external_igc` & `external_osl` as a build-time dependency.
|
||||
bison
|
||||
# Required by: `external_osl` as a build-time dependency.
|
||||
flex
|
||||
# TODO: dependencies build without this, consider removal.
|
||||
ncurses-devel
|
||||
)
|
||||
|
||||
# Additional packages needed for building Blender.
|
||||
PACKAGES_FOR_BLENDER=(
|
||||
# Required by Blender build option: `WITH_GHOST_WAYLAND`.
|
||||
libxkbcommon-devel
|
||||
)
|
||||
|
||||
yum -y install -y ${PACKAGES_FOR_LIBS[@]} ${PACKAGES_FOR_BLENDER[@]}
|
||||
|
||||
# Dependencies for Mesa
|
||||
yum -y install expat-devel
|
||||
|
|
|
@ -778,31 +778,11 @@ if(WITH_GHOST_WAYLAND)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
${xkbcommon_LINK_LIBRARIES}
|
||||
)
|
||||
|
||||
if(NOT WITH_GHOST_WAYLAND_DYNLOAD)
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
${wayland-client_LINK_LIBRARIES}
|
||||
${wayland-egl_LINK_LIBRARIES}
|
||||
${wayland-cursor_LINK_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_WAYLAND_DBUS)
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
${dbus_LINK_LIBRARIES}
|
||||
)
|
||||
add_definitions(-DWITH_GHOST_WAYLAND_DBUS)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
if(NOT WITH_GHOST_WAYLAND_DYNLOAD)
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
${libdecor_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR)
|
||||
endif()
|
||||
|
||||
|
@ -855,12 +835,8 @@ if(WITH_GHOST_X11)
|
|||
find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH})
|
||||
mark_as_advanced(X11_XF86keysym_INCLUDE_PATH)
|
||||
|
||||
list(APPEND PLATFORM_LINKLIBS ${X11_X11_LIB})
|
||||
|
||||
if(WITH_X11_XINPUT)
|
||||
if(X11_Xinput_LIB)
|
||||
list(APPEND PLATFORM_LINKLIBS ${X11_Xinput_LIB})
|
||||
else()
|
||||
if(NOT X11_Xinput_LIB)
|
||||
message(FATAL_ERROR "LibXi not found. Disable WITH_X11_XINPUT if you
|
||||
want to build without tablet support")
|
||||
endif()
|
||||
|
@ -870,18 +846,14 @@ if(WITH_GHOST_X11)
|
|||
# XXX, why doesn't cmake make this available?
|
||||
find_library(X11_Xxf86vmode_LIB Xxf86vm ${X11_LIB_SEARCH_PATH})
|
||||
mark_as_advanced(X11_Xxf86vmode_LIB)
|
||||
if(X11_Xxf86vmode_LIB)
|
||||
list(APPEND PLATFORM_LINKLIBS ${X11_Xxf86vmode_LIB})
|
||||
else()
|
||||
if(NOT X11_Xxf86vmode_LIB)
|
||||
message(FATAL_ERROR "libXxf86vm not found. Disable WITH_X11_XF86VMODE if you
|
||||
want to build without")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_X11_XFIXES)
|
||||
if(X11_Xfixes_LIB)
|
||||
list(APPEND PLATFORM_LINKLIBS ${X11_Xfixes_LIB})
|
||||
else()
|
||||
if(NOT X11_Xfixes_LIB)
|
||||
message(FATAL_ERROR "libXfixes not found. Disable WITH_X11_XFIXES if you
|
||||
want to build without")
|
||||
endif()
|
||||
|
@ -890,9 +862,7 @@ if(WITH_GHOST_X11)
|
|||
if(WITH_X11_ALPHA)
|
||||
find_library(X11_Xrender_LIB Xrender ${X11_LIB_SEARCH_PATH})
|
||||
mark_as_advanced(X11_Xrender_LIB)
|
||||
if(X11_Xrender_LIB)
|
||||
list(APPEND PLATFORM_LINKLIBS ${X11_Xrender_LIB})
|
||||
else()
|
||||
if(NOT X11_Xrender_LIB)
|
||||
message(FATAL_ERROR "libXrender not found. Disable WITH_X11_ALPHA if you
|
||||
want to build without")
|
||||
endif()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
sphinx==5.1.1
|
||||
sphinx==5.2.3
|
||||
|
||||
# Sphinx dependencies that are important
|
||||
Jinja2==3.1.2
|
||||
|
@ -6,7 +6,7 @@ Pygments==2.13.0
|
|||
docutils==0.17.1
|
||||
snowballstemmer==2.2.0
|
||||
babel==2.10.3
|
||||
requests==2.27.1
|
||||
requests==2.28.1
|
||||
|
||||
# Only needed to match the theme used for the official documentation.
|
||||
# Without this theme, the default theme will be used.
|
||||
|
|
|
@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN
|
|||
* Utility class to map between Blender datablocks and Cycles data structures,
|
||||
* and keep track of recalc tags from the dependency graph. */
|
||||
|
||||
template<typename K, typename T> class id_map {
|
||||
template<typename K, typename T, typename Flags = uint> class id_map {
|
||||
public:
|
||||
id_map(Scene *scene_) : scene(scene_)
|
||||
{
|
||||
|
@ -63,6 +63,11 @@ template<typename K, typename T> class id_map {
|
|||
b_recalc.insert(id_ptr);
|
||||
}
|
||||
|
||||
bool check_recalc(const BL::ID &id)
|
||||
{
|
||||
return id.ptr.data && b_recalc.find(id.ptr.data) != b_recalc.end();
|
||||
}
|
||||
|
||||
bool has_recalc()
|
||||
{
|
||||
return !(b_recalc.empty());
|
||||
|
@ -154,6 +159,7 @@ template<typename K, typename T> class id_map {
|
|||
TMapPair &pair = *jt;
|
||||
|
||||
if (do_delete && used_set.find(pair.second) == used_set.end()) {
|
||||
flags.erase(pair.second);
|
||||
scene->delete_node(pair.second);
|
||||
}
|
||||
else {
|
||||
|
@ -171,9 +177,33 @@ template<typename K, typename T> class id_map {
|
|||
return b_map;
|
||||
}
|
||||
|
||||
bool test_flag(T *data, Flags val)
|
||||
{
|
||||
typename map<T *, uint>::iterator it = flags.find(data);
|
||||
return it != flags.end() && (it->second & (1 << val)) != 0;
|
||||
}
|
||||
|
||||
void set_flag(T *data, Flags val)
|
||||
{
|
||||
flags[data] |= (1 << val);
|
||||
}
|
||||
|
||||
void clear_flag(T *data, Flags val)
|
||||
{
|
||||
typename map<T *, uint>::iterator it = flags.find(data);
|
||||
if (it != flags.end()) {
|
||||
it->second &= ~(1 << val);
|
||||
|
||||
if (it->second == 0) {
|
||||
flags.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
map<K, T *> b_map;
|
||||
set<T *> used_set;
|
||||
map<T *, uint> flags;
|
||||
set<void *> b_recalc;
|
||||
Scene *scene;
|
||||
};
|
||||
|
|
|
@ -96,6 +96,13 @@ bool BlenderSync::object_is_light(BL::Object &b_ob)
|
|||
return (b_ob_data && b_ob_data.is_a(&RNA_Light));
|
||||
}
|
||||
|
||||
bool BlenderSync::object_is_camera(BL::Object &b_ob)
|
||||
{
|
||||
BL::ID b_ob_data = b_ob.data();
|
||||
|
||||
return (b_ob_data && b_ob_data.is_a(&RNA_Camera));
|
||||
}
|
||||
|
||||
void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object)
|
||||
{
|
||||
/* Initialize motion blur for object, detecting if it's enabled and creating motion
|
||||
|
@ -400,7 +407,8 @@ bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance
|
|||
std::string real_name;
|
||||
BlenderAttributeType type = blender_attribute_name_split_type(name, &real_name);
|
||||
|
||||
if (type != BL::ShaderNodeAttribute::attribute_type_GEOMETRY) {
|
||||
if (type == BL::ShaderNodeAttribute::attribute_type_OBJECT ||
|
||||
type == BL::ShaderNodeAttribute::attribute_type_INSTANCER) {
|
||||
bool use_instancer = (type == BL::ShaderNodeAttribute::attribute_type_INSTANCER);
|
||||
float4 value = lookup_instance_property(b_instance, real_name, use_instancer);
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ static void export_pointcloud(Scene *scene,
|
|||
/* Export points. */
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
const float3 co = get_float3(b_attr_position.data[i].vector());
|
||||
const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.0f;
|
||||
const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.01f;
|
||||
pointcloud->add_point(co, radius);
|
||||
|
||||
/* Random number per point. */
|
||||
|
@ -232,7 +232,7 @@ static void export_pointcloud_motion(PointCloud *pointcloud,
|
|||
|
||||
for (int i = 0; i < std::min(num_points, b_points_num); i++) {
|
||||
const float3 co = get_float3(b_attr_position.data[i].vector());
|
||||
const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.0f;
|
||||
const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.01f;
|
||||
float3 P = co;
|
||||
P.w = radius;
|
||||
mP[i] = P;
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "util/string.h"
|
||||
#include "util/task.h"
|
||||
|
||||
#include "BKE_duplilist.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
typedef map<void *, ShaderInput *> PtrInputMap;
|
||||
|
@ -103,6 +105,7 @@ static ImageAlphaType get_image_alpha_type(BL::Image &b_image)
|
|||
|
||||
static const string_view object_attr_prefix("\x01object:");
|
||||
static const string_view instancer_attr_prefix("\x01instancer:");
|
||||
static const string_view view_layer_attr_prefix("\x01layer:");
|
||||
|
||||
static ustring blender_attribute_name_add_type(const string &name, BlenderAttributeType type)
|
||||
{
|
||||
|
@ -111,6 +114,8 @@ static ustring blender_attribute_name_add_type(const string &name, BlenderAttrib
|
|||
return ustring::concat(object_attr_prefix, name);
|
||||
case BL::ShaderNodeAttribute::attribute_type_INSTANCER:
|
||||
return ustring::concat(instancer_attr_prefix, name);
|
||||
case BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER:
|
||||
return ustring::concat(view_layer_attr_prefix, name);
|
||||
default:
|
||||
return ustring(name);
|
||||
}
|
||||
|
@ -130,6 +135,11 @@ BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_r
|
|||
return BL::ShaderNodeAttribute::attribute_type_INSTANCER;
|
||||
}
|
||||
|
||||
if (sname.substr(0, view_layer_attr_prefix.size()) == view_layer_attr_prefix) {
|
||||
*r_real_name = sname.substr(view_layer_attr_prefix.size());
|
||||
return BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER;
|
||||
}
|
||||
|
||||
return BL::ShaderNodeAttribute::attribute_type_GEOMETRY;
|
||||
}
|
||||
|
||||
|
@ -205,7 +215,9 @@ static void set_default_value(ShaderInput *input,
|
|||
}
|
||||
case SocketType::INT: {
|
||||
if (b_sock.type() == BL::NodeSocket::type_BOOLEAN) {
|
||||
node->set(socket, get_boolean(b_sock.ptr, "default_value"));
|
||||
/* Make sure to call the int overload of set() since this is an integer socket as far as
|
||||
* Cycles is concerned. */
|
||||
node->set(socket, get_boolean(b_sock.ptr, "default_value") ? 1 : 0);
|
||||
}
|
||||
else {
|
||||
node->set(socket, get_int(b_sock.ptr, "default_value"));
|
||||
|
@ -1420,6 +1432,89 @@ static void add_nodes(Scene *scene,
|
|||
empty_proxy_map);
|
||||
}
|
||||
|
||||
/* Look up and constant fold all references to View Layer attributes. */
|
||||
void BlenderSync::resolve_view_layer_attributes(Shader *shader,
|
||||
ShaderGraph *graph,
|
||||
BL::Depsgraph &b_depsgraph)
|
||||
{
|
||||
bool updated = false;
|
||||
|
||||
foreach (ShaderNode *node, graph->nodes) {
|
||||
if (node->is_a(AttributeNode::node_type)) {
|
||||
AttributeNode *attr_node = static_cast<AttributeNode *>(node);
|
||||
|
||||
std::string real_name;
|
||||
BlenderAttributeType type = blender_attribute_name_split_type(attr_node->get_attribute(),
|
||||
&real_name);
|
||||
|
||||
if (type == BL::ShaderNodeAttribute::attribute_type_VIEW_LAYER) {
|
||||
/* Look up the value. */
|
||||
BL::ViewLayer b_layer = b_depsgraph.view_layer_eval();
|
||||
BL::Scene b_scene = b_depsgraph.scene_eval();
|
||||
float4 value;
|
||||
|
||||
BKE_view_layer_find_rgba_attribute((::Scene *)b_scene.ptr.data,
|
||||
(::ViewLayer *)b_layer.ptr.data,
|
||||
real_name.c_str(),
|
||||
&value.x);
|
||||
|
||||
/* Replace all outgoing links, using appropriate output types. */
|
||||
float val_avg = (value.x + value.y + value.z) / 3.0f;
|
||||
|
||||
foreach (ShaderOutput *output, node->outputs) {
|
||||
float val_float;
|
||||
float3 val_float3;
|
||||
|
||||
if (output->type() == SocketType::FLOAT) {
|
||||
val_float = (output->name() == "Alpha") ? value.w : val_avg;
|
||||
val_float3 = make_float3(val_float);
|
||||
}
|
||||
else {
|
||||
val_float = val_avg;
|
||||
val_float3 = float4_to_float3(value);
|
||||
}
|
||||
|
||||
foreach (ShaderInput *sock, output->links) {
|
||||
if (sock->type() == SocketType::FLOAT) {
|
||||
sock->set(val_float);
|
||||
}
|
||||
else if (SocketType::is_float3(sock->type())) {
|
||||
sock->set(val_float3);
|
||||
}
|
||||
|
||||
sock->constant_folded_in = true;
|
||||
}
|
||||
|
||||
graph->disconnect(output);
|
||||
}
|
||||
|
||||
/* Clear the attribute name to avoid further attempts to look up. */
|
||||
attr_node->set_attribute(ustring());
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
shader_map.set_flag(shader, SHADER_WITH_LAYER_ATTRS);
|
||||
}
|
||||
else {
|
||||
shader_map.clear_flag(shader, SHADER_WITH_LAYER_ATTRS);
|
||||
}
|
||||
}
|
||||
|
||||
bool BlenderSync::scene_attr_needs_recalc(Shader *shader, BL::Depsgraph &b_depsgraph)
|
||||
{
|
||||
if (shader && shader_map.test_flag(shader, SHADER_WITH_LAYER_ATTRS)) {
|
||||
BL::Scene scene = b_depsgraph.scene_eval();
|
||||
|
||||
return shader_map.check_recalc(scene) || shader_map.check_recalc(scene.world()) ||
|
||||
shader_map.check_recalc(scene.camera());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Sync Materials */
|
||||
|
||||
void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
|
||||
|
@ -1438,7 +1533,8 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
|
|||
Shader *shader;
|
||||
|
||||
/* test if we need to sync */
|
||||
if (shader_map.add_or_update(&shader, b_mat) || update_all) {
|
||||
if (shader_map.add_or_update(&shader, b_mat) || update_all ||
|
||||
scene_attr_needs_recalc(shader, b_depsgraph)) {
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
|
||||
shader->name = b_mat.name().c_str();
|
||||
|
@ -1459,6 +1555,8 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
|
|||
graph->connect(diffuse->output("BSDF"), out->input("Surface"));
|
||||
}
|
||||
|
||||
resolve_view_layer_attributes(shader, graph, b_depsgraph);
|
||||
|
||||
/* settings */
|
||||
PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles");
|
||||
shader->set_use_mis(get_boolean(cmat, "sample_as_light"));
|
||||
|
@ -1515,9 +1613,11 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
|||
|
||||
BlenderViewportParameters new_viewport_parameters(b_v3d, use_developer_ui);
|
||||
|
||||
Shader *shader = scene->default_background;
|
||||
|
||||
if (world_recalc || update_all || b_world.ptr.data != world_map ||
|
||||
viewport_parameters.shader_modified(new_viewport_parameters)) {
|
||||
Shader *shader = scene->default_background;
|
||||
viewport_parameters.shader_modified(new_viewport_parameters) ||
|
||||
scene_attr_needs_recalc(shader, b_depsgraph)) {
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
|
||||
/* create nodes */
|
||||
|
@ -1615,6 +1715,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
|||
background->set_visibility(visibility);
|
||||
}
|
||||
|
||||
resolve_view_layer_attributes(shader, graph, b_depsgraph);
|
||||
|
||||
shader->set_graph(graph);
|
||||
shader->tag_update(scene);
|
||||
}
|
||||
|
@ -1681,7 +1783,8 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
|
|||
Shader *shader;
|
||||
|
||||
/* test if we need to sync */
|
||||
if (shader_map.add_or_update(&shader, b_light) || update_all) {
|
||||
if (shader_map.add_or_update(&shader, b_light) || update_all ||
|
||||
scene_attr_needs_recalc(shader, b_depsgraph)) {
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
|
||||
/* create nodes */
|
||||
|
@ -1702,6 +1805,8 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
|
|||
graph->connect(emission->output("Emission"), out->input("Surface"));
|
||||
}
|
||||
|
||||
resolve_view_layer_attributes(shader, graph, b_depsgraph);
|
||||
|
||||
shader->set_graph(graph);
|
||||
shader->tag_update(scene);
|
||||
}
|
||||
|
|
|
@ -206,6 +206,9 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (object_is_camera(b_ob)) {
|
||||
shader_map.set_recalc(b_ob);
|
||||
}
|
||||
}
|
||||
/* Mesh */
|
||||
else if (b_id.is_a(&RNA_Mesh)) {
|
||||
|
@ -218,6 +221,11 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
|||
if (world_map == b_world.ptr.data) {
|
||||
world_recalc = true;
|
||||
}
|
||||
shader_map.set_recalc(b_world);
|
||||
}
|
||||
/* World */
|
||||
else if (b_id.is_a(&RNA_Scene)) {
|
||||
shader_map.set_recalc(b_id);
|
||||
}
|
||||
/* Volume */
|
||||
else if (b_id.is_a(&RNA_Volume)) {
|
||||
|
|
|
@ -120,6 +120,11 @@ class BlenderSync {
|
|||
void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all);
|
||||
void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree);
|
||||
|
||||
bool scene_attr_needs_recalc(Shader *shader, BL::Depsgraph &b_depsgraph);
|
||||
void resolve_view_layer_attributes(Shader *shader,
|
||||
ShaderGraph *graph,
|
||||
BL::Depsgraph &b_depsgraph);
|
||||
|
||||
/* Object */
|
||||
Object *sync_object(BL::Depsgraph &b_depsgraph,
|
||||
BL::ViewLayer &b_view_layer,
|
||||
|
@ -207,13 +212,16 @@ class BlenderSync {
|
|||
bool object_is_geometry(BObjectInfo &b_ob_info);
|
||||
bool object_can_have_geometry(BL::Object &b_ob);
|
||||
bool object_is_light(BL::Object &b_ob);
|
||||
bool object_is_camera(BL::Object &b_ob);
|
||||
|
||||
/* variables */
|
||||
BL::RenderEngine b_engine;
|
||||
BL::BlendData b_data;
|
||||
BL::Scene b_scene;
|
||||
|
||||
id_map<void *, Shader> shader_map;
|
||||
enum ShaderFlags { SHADER_WITH_LAYER_ATTRS };
|
||||
|
||||
id_map<void *, Shader, ShaderFlags> shader_map;
|
||||
id_map<ObjectKey, Object> object_map;
|
||||
id_map<void *, Procedural> procedural_map;
|
||||
id_map<GeometryKey, Geometry> geometry_map;
|
||||
|
|
|
@ -254,6 +254,10 @@ void MetalDevice::make_source(MetalPipelineType pso_type, const uint kernel_feat
|
|||
break;
|
||||
}
|
||||
|
||||
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
|
||||
NSOperatingSystemVersion macos_ver = [processInfo operatingSystemVersion];
|
||||
global_defines += "#define __KERNEL_METAL_MACOS__ " + to_string(macos_ver.majorVersion) + "\n";
|
||||
|
||||
string &source = this->source[pso_type];
|
||||
source = "\n#include \"kernel/device/metal/kernel.metal\"\n";
|
||||
source = path_source_replace_includes(source, path_get("source"));
|
||||
|
|
|
@ -43,7 +43,7 @@ OneapiDevice::OneapiDevice(const DeviceInfo &info, Stats &stats, Profiler &profi
|
|||
}
|
||||
|
||||
size_t globals_segment_size;
|
||||
is_finished_ok = kernel_globals_size(device_queue_, globals_segment_size);
|
||||
is_finished_ok = kernel_globals_size(globals_segment_size);
|
||||
if (is_finished_ok == false) {
|
||||
set_error("oneAPI constant memory initialization got runtime exception \"" +
|
||||
oneapi_error_string_ + "\"");
|
||||
|
@ -88,18 +88,26 @@ BVHLayoutMask OneapiDevice::get_bvh_layout_mask() const
|
|||
bool OneapiDevice::load_kernels(const uint requested_features)
|
||||
{
|
||||
assert(device_queue_);
|
||||
/* NOTE(@nsirgien): oneAPI can support compilation of kernel code with certain feature set
|
||||
* with specialization constants, but it hasn't been implemented yet. */
|
||||
(void)requested_features;
|
||||
|
||||
bool is_finished_ok = oneapi_run_test_kernel(device_queue_);
|
||||
if (is_finished_ok == false) {
|
||||
set_error("oneAPI kernel load: got runtime exception \"" + oneapi_error_string_ + "\"");
|
||||
set_error("oneAPI test kernel execution: got a runtime exception \"" + oneapi_error_string_ +
|
||||
"\"");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
VLOG_INFO << "Runtime compilation done for \"" << info.description << "\"";
|
||||
VLOG_INFO << "Test kernel has been executed successfully for \"" << info.description << "\"";
|
||||
assert(device_queue_);
|
||||
}
|
||||
|
||||
is_finished_ok = oneapi_load_kernels(device_queue_, (const unsigned int)requested_features);
|
||||
if (is_finished_ok == false) {
|
||||
set_error("oneAPI kernels loading: got a runtime exception \"" + oneapi_error_string_ + "\"");
|
||||
}
|
||||
else {
|
||||
VLOG_INFO << "Kernels loading (compilation) has been done for \"" << info.description << "\"";
|
||||
}
|
||||
|
||||
return is_finished_ok;
|
||||
}
|
||||
|
||||
|
@ -425,6 +433,11 @@ void OneapiDevice::check_usm(SyclQueue *queue_, const void *usm_ptr, bool allow_
|
|||
((device_type == sycl::info::device_type::host ||
|
||||
device_type == sycl::info::device_type::cpu || allow_host) &&
|
||||
usm_type == sycl::usm::alloc::host));
|
||||
# else
|
||||
/* Silence warning about unused arguments. */
|
||||
(void)queue_;
|
||||
(void)usm_ptr;
|
||||
(void)allow_host;
|
||||
# endif
|
||||
}
|
||||
|
||||
|
@ -552,7 +565,7 @@ bool OneapiDevice::queue_synchronize(SyclQueue *queue_)
|
|||
}
|
||||
}
|
||||
|
||||
bool OneapiDevice::kernel_globals_size(SyclQueue *queue_, size_t &kernel_global_size)
|
||||
bool OneapiDevice::kernel_globals_size(size_t &kernel_global_size)
|
||||
{
|
||||
kernel_global_size = sizeof(KernelGlobalsGPU);
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ class OneapiDevice : public Device {
|
|||
int get_num_multiprocessors();
|
||||
int get_max_num_threads_per_multiprocessor();
|
||||
bool queue_synchronize(SyclQueue *queue);
|
||||
bool kernel_globals_size(SyclQueue *queue, size_t &kernel_global_size);
|
||||
bool kernel_globals_size(size_t &kernel_global_size);
|
||||
void set_global_memory(SyclQueue *queue,
|
||||
void *kernel_globals,
|
||||
const char *memory_name,
|
||||
|
|
|
@ -43,8 +43,11 @@ PathTrace::PathTrace(Device *device,
|
|||
/* Create path tracing work in advance, so that it can be reused by incremental sampling as much
|
||||
* as possible. */
|
||||
device_->foreach_device([&](Device *path_trace_device) {
|
||||
path_trace_works_.emplace_back(PathTraceWork::create(
|
||||
path_trace_device, film, device_scene, &render_cancel_.is_requested));
|
||||
unique_ptr<PathTraceWork> work = PathTraceWork::create(
|
||||
path_trace_device, film, device_scene, &render_cancel_.is_requested);
|
||||
if (work) {
|
||||
path_trace_works_.emplace_back(std::move(work));
|
||||
}
|
||||
});
|
||||
|
||||
work_balance_infos_.resize(path_trace_works_.size());
|
||||
|
|
|
@ -23,6 +23,10 @@ unique_ptr<PathTraceWork> PathTraceWork::create(Device *device,
|
|||
if (device->info.type == DEVICE_CPU) {
|
||||
return make_unique<PathTraceWorkCPU>(device, film, device_scene, cancel_requested_flag);
|
||||
}
|
||||
if (device->info.type == DEVICE_DUMMY) {
|
||||
/* Dummy devices can't perform any work. */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return make_unique<PathTraceWorkGPU>(device, film, device_scene, cancel_requested_flag);
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ void PathTraceWorkCPU::cryptomatte_postproces()
|
|||
}
|
||||
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
/* Note: It seems that this is called before every rendering iteration/progression and not once per
|
||||
/* NOTE: It seems that this is called before every rendering iteration/progression and not once per
|
||||
* rendering. May be we find a way to call it only once per rendering. */
|
||||
void PathTraceWorkCPU::guiding_init_kernel_globals(void *guiding_field,
|
||||
void *sample_data_storage,
|
||||
|
|
|
@ -17,6 +17,9 @@ void work_balance_do_initial(vector<WorkBalanceInfo> &work_balance_infos)
|
|||
work_balance_infos[0].weight = 1.0;
|
||||
return;
|
||||
}
|
||||
else if (num_infos == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* There is no statistics available, so start with an equal distribution. */
|
||||
const double weight = 1.0 / num_infos;
|
||||
|
|
|
@ -727,16 +727,9 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
|
|||
${SRC_UTIL_HEADERS}
|
||||
)
|
||||
|
||||
set (ONEAPI_OFFLINE_COMPILER_PARALLEL_JOBS 1)
|
||||
set (SYCL_OFFLINE_COMPILER_PARALLEL_JOBS 1 CACHE STRING "Number of parallel compiler instances to use for device binaries compilation (expect ~8GB peak memory usage per instance).")
|
||||
if (WITH_CYCLES_ONEAPI_BINARIES)
|
||||
cmake_host_system_information(RESULT AVAILABLE_MEMORY_AMOUNT QUERY AVAILABLE_PHYSICAL_MEMORY)
|
||||
# Conservative value of peak consumption here, just to be fully sure that other backend compilers will have enough memory as well
|
||||
set(ONEAPI_GPU_COMPILER_MEMORY_AT_PEAK_MB 8150)
|
||||
math(EXPR ONEAPI_OFFLINE_COMPILER_PARALLEL_JOBS "${AVAILABLE_MEMORY_AMOUNT} / ${ONEAPI_GPU_COMPILER_MEMORY_AT_PEAK_MB}")
|
||||
if (ONEAPI_OFFLINE_COMPILER_PARALLEL_JOBS LESS 1)
|
||||
set(ONEAPI_OFFLINE_COMPILER_PARALLEL_JOBS 1)
|
||||
endif()
|
||||
message(STATUS "${ONEAPI_OFFLINE_COMPILER_PARALLEL_JOBS} instance(s) of oneAPI offline compiler will be used.")
|
||||
message(STATUS "${SYCL_OFFLINE_COMPILER_PARALLEL_JOBS} instance(s) of oneAPI offline compiler will be used.")
|
||||
endif()
|
||||
# SYCL_CPP_FLAGS is a variable that the user can set to pass extra compiler options
|
||||
set(sycl_compiler_flags
|
||||
|
@ -747,7 +740,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
|
|||
-mllvm -inlinedefault-threshold=250
|
||||
-mllvm -inlinehint-threshold=350
|
||||
-fsycl-device-code-split=per_kernel
|
||||
-fsycl-max-parallel-link-jobs=${ONEAPI_OFFLINE_COMPILER_PARALLEL_JOBS}
|
||||
-fsycl-max-parallel-link-jobs=${SYCL_OFFLINE_COMPILER_PARALLEL_JOBS}
|
||||
-shared
|
||||
-DWITH_ONEAPI
|
||||
-ffast-math
|
||||
|
|
|
@ -25,38 +25,57 @@ void oneapi_set_error_cb(OneAPIErrorCallback cb, void *user_ptr)
|
|||
s_error_user_ptr = user_ptr;
|
||||
}
|
||||
|
||||
/* NOTE(@nsirgien): Execution of this simple kernel will check basic functionality and
|
||||
* also trigger runtime compilation of all existing oneAPI kernels */
|
||||
/* NOTE(@nsirgien): Execution of this simple kernel will check basic functionality like
|
||||
* memory allocations, memory transfers and execution of kernel with USM memory. */
|
||||
bool oneapi_run_test_kernel(SyclQueue *queue_)
|
||||
{
|
||||
assert(queue_);
|
||||
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
|
||||
size_t N = 8;
|
||||
sycl::buffer<float, 1> A(N);
|
||||
sycl::buffer<float, 1> B(N);
|
||||
|
||||
{
|
||||
sycl::host_accessor A_host_acc(A, sycl::write_only);
|
||||
for (size_t i = (size_t)0; i < N; i++)
|
||||
A_host_acc[i] = rand() % 32;
|
||||
}
|
||||
const size_t N = 8;
|
||||
const size_t memory_byte_size = sizeof(int) * N;
|
||||
|
||||
bool is_computation_correct = true;
|
||||
try {
|
||||
queue->submit([&](sycl::handler &cgh) {
|
||||
sycl::accessor A_acc(A, cgh, sycl::read_only);
|
||||
sycl::accessor B_acc(B, cgh, sycl::write_only, sycl::no_init);
|
||||
int *A_host = (int *)sycl::aligned_alloc_host(16, memory_byte_size, *queue);
|
||||
|
||||
cgh.parallel_for(N, [=](sycl::id<1> idx) { B_acc[idx] = A_acc[idx] + idx.get(0); });
|
||||
for (size_t i = (size_t)0; i < N; i++) {
|
||||
A_host[i] = rand() % 32;
|
||||
}
|
||||
|
||||
int *A_device = (int *)sycl::malloc_device(memory_byte_size, *queue);
|
||||
int *B_device = (int *)sycl::malloc_device(memory_byte_size, *queue);
|
||||
|
||||
queue->memcpy(A_device, A_host, memory_byte_size);
|
||||
queue->wait_and_throw();
|
||||
|
||||
queue->submit([&](sycl::handler &cgh) {
|
||||
cgh.parallel_for(N, [=](sycl::id<1> idx) { B_device[idx] = A_device[idx] + idx.get(0); });
|
||||
});
|
||||
queue->wait_and_throw();
|
||||
|
||||
sycl::host_accessor A_host_acc(A, sycl::read_only);
|
||||
sycl::host_accessor B_host_acc(B, sycl::read_only);
|
||||
int *B_host = (int *)sycl::aligned_alloc_host(16, memory_byte_size, *queue);
|
||||
|
||||
queue->memcpy(B_host, B_device, memory_byte_size);
|
||||
queue->wait_and_throw();
|
||||
|
||||
for (size_t i = (size_t)0; i < N; i++) {
|
||||
float result = A_host_acc[i] + B_host_acc[i];
|
||||
(void)result;
|
||||
const int expected_result = i + A_host[i];
|
||||
if (B_host[i] != expected_result) {
|
||||
is_computation_correct = false;
|
||||
if (s_error_cb) {
|
||||
s_error_cb(("Incorrect result in test kernel execution - expected " +
|
||||
std::to_string(expected_result) + ", got " + std::to_string(B_host[i]))
|
||||
.c_str(),
|
||||
s_error_user_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sycl::free(A_host, *queue);
|
||||
sycl::free(B_host, *queue);
|
||||
sycl::free(A_device, *queue);
|
||||
sycl::free(B_device, *queue);
|
||||
queue->wait_and_throw();
|
||||
}
|
||||
catch (sycl::exception const &e) {
|
||||
if (s_error_cb) {
|
||||
|
@ -65,7 +84,7 @@ bool oneapi_run_test_kernel(SyclQueue *queue_)
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return is_computation_correct;
|
||||
}
|
||||
|
||||
/* TODO: Move device information to OneapiDevice initialized on creation and use it. */
|
||||
|
@ -123,6 +142,52 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue,
|
|||
return std::min(limit_work_group_size, preferred_work_group_size);
|
||||
}
|
||||
|
||||
bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features)
|
||||
{
|
||||
assert(queue_);
|
||||
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
|
||||
|
||||
try {
|
||||
sycl::kernel_bundle<sycl::bundle_state::input> all_kernels_bundle =
|
||||
sycl::get_kernel_bundle<sycl::bundle_state::input>(queue->get_context(),
|
||||
{queue->get_device()});
|
||||
|
||||
for (const sycl::kernel_id &kernel_id : all_kernels_bundle.get_kernel_ids()) {
|
||||
const std::string &kernel_name = kernel_id.get_name();
|
||||
|
||||
/* NOTE(@nsirgien): Names in this conditions below should match names from
|
||||
* oneapi_call macro in oneapi_enqueue_kernel below */
|
||||
if (((requested_features & KERNEL_FEATURE_VOLUME) == 0) &&
|
||||
kernel_name.find("oneapi_kernel_integrator_shade_volume") != std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (((requested_features & KERNEL_FEATURE_MNEE) == 0) &&
|
||||
kernel_name.find("oneapi_kernel_integrator_shade_surface_mnee") != std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (((requested_features & KERNEL_FEATURE_NODE_RAYTRACE) == 0) &&
|
||||
kernel_name.find("oneapi_kernel_integrator_shade_surface_raytrace") !=
|
||||
std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sycl::kernel_bundle<sycl::bundle_state::input> one_kernel_bundle =
|
||||
sycl::get_kernel_bundle<sycl::bundle_state::input>(queue->get_context(), {kernel_id});
|
||||
sycl::build(one_kernel_bundle, {queue->get_device()}, sycl::property::queue::in_order());
|
||||
}
|
||||
}
|
||||
catch (sycl::exception const &e) {
|
||||
if (s_error_cb) {
|
||||
s_error_cb(e.what(), s_error_user_ptr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool oneapi_enqueue_kernel(KernelContext *kernel_context,
|
||||
int kernel,
|
||||
size_t global_size,
|
||||
|
|
|
@ -48,6 +48,8 @@ CYCLES_KERNEL_ONEAPI_EXPORT bool oneapi_enqueue_kernel(KernelContext *context,
|
|||
int kernel,
|
||||
size_t global_size,
|
||||
void **args);
|
||||
CYCLES_KERNEL_ONEAPI_EXPORT bool oneapi_load_kernels(SyclQueue *queue,
|
||||
const unsigned int requested_features);
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
|
|
@ -279,7 +279,15 @@ ccl_device_forceinline void mnee_setup_manifold_vertex(KernelGlobals kg,
|
|||
}
|
||||
|
||||
/* Compute constraint derivatives. */
|
||||
ccl_device_forceinline bool mnee_compute_constraint_derivatives(
|
||||
|
||||
# if defined(__KERNEL_METAL__)
|
||||
/* Temporary workaround for front-end compilation bug (incorrect MNEE rendering when this is
|
||||
* inlined). */
|
||||
__attribute__((noinline))
|
||||
# else
|
||||
ccl_device_forceinline
|
||||
# endif
|
||||
bool mnee_compute_constraint_derivatives(
|
||||
int vertex_count,
|
||||
ccl_private ManifoldVertex *vertices,
|
||||
ccl_private const float3 &surface_sample_pos,
|
||||
|
|
|
@ -100,7 +100,7 @@ ccl_device_inline bool sample_is_class_A(int pattern, int sample)
|
|||
if (!(pattern == SAMPLING_PATTERN_PMJ || pattern == SAMPLING_PATTERN_SOBOL_BURLEY)) {
|
||||
/* Fallback: assign samples randomly.
|
||||
* This is guaranteed to work "okay" for any sampler, but isn't good.
|
||||
* (Note: the seed constant is just a random number to guard against
|
||||
* (NOTE: the seed constant is just a random number to guard against
|
||||
* possible interactions with other uses of the hash. There's nothing
|
||||
* special about it.)
|
||||
*/
|
||||
|
|
|
@ -85,9 +85,9 @@ CCL_NAMESPACE_BEGIN
|
|||
# define __VOLUME_RECORD_ALL__
|
||||
#endif /* !__KERNEL_GPU__ */
|
||||
|
||||
/* MNEE currently causes "Compute function exceeds available temporary registers"
|
||||
* on Metal, disabled for now. */
|
||||
#ifndef __KERNEL_METAL__
|
||||
/* MNEE caused "Compute function exceeds available temporary registers" in macOS < 13 due to a bug
|
||||
* in spill buffer allocation sizing. */
|
||||
#if !defined(__KERNEL_METAL__) || (__KERNEL_METAL_MACOS__ >= 13)
|
||||
# define __MNEE__
|
||||
#endif
|
||||
|
||||
|
|
|
@ -43,6 +43,10 @@ Session::Session(const SessionParams ¶ms_, const SceneParams &scene_params)
|
|||
|
||||
device = Device::create(params.device, stats, profiler);
|
||||
|
||||
if (device->have_error()) {
|
||||
progress.set_error(device->error_message());
|
||||
}
|
||||
|
||||
scene = new Scene(scene_params, device);
|
||||
|
||||
/* Configure path tracer. */
|
||||
|
|
|
@ -262,6 +262,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||
${xkbcommon_INCLUDE_DIRS}
|
||||
${wayland-cursor_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND LIB
|
||||
${xkbcommon_LINK_LIBRARIES}
|
||||
)
|
||||
|
||||
if(WITH_GHOST_WAYLAND_DYNLOAD)
|
||||
list(APPEND INC_SYS
|
||||
|
@ -271,18 +274,32 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||
bf_intern_wayland_dynload
|
||||
)
|
||||
add_definitions(-DWITH_GHOST_WAYLAND_DYNLOAD)
|
||||
else()
|
||||
list(APPEND LIB
|
||||
${wayland-client_LINK_LIBRARIES}
|
||||
${wayland-egl_LINK_LIBRARIES}
|
||||
${wayland-cursor_LINK_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_WAYLAND_DBUS)
|
||||
list(APPEND INC_SYS
|
||||
${dbus_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND LIB
|
||||
${dbus_LINK_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
list(APPEND INC_SYS
|
||||
${libdecor_INCLUDE_DIRS}
|
||||
)
|
||||
if(NOT WITH_GHOST_WAYLAND_DYNLOAD)
|
||||
list(APPEND LIB
|
||||
${libdecor_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CheckSymbolExists)
|
||||
|
@ -332,16 +349,16 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||
${INC_DST}
|
||||
)
|
||||
|
||||
if(NOT WITH_GHOST_WAYLAND_LIBDECOR)
|
||||
# `xdg-shell`.
|
||||
generate_protocol_bindings(
|
||||
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
|
||||
)
|
||||
# `xdg-decoration`.
|
||||
generate_protocol_bindings(
|
||||
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||
)
|
||||
endif()
|
||||
# Used when: LIBDECOR is not needed.
|
||||
# `xdg-shell`.
|
||||
generate_protocol_bindings(
|
||||
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
|
||||
)
|
||||
# `xdg-decoration`.
|
||||
generate_protocol_bindings(
|
||||
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||
)
|
||||
# End LIBDECOR alternative.
|
||||
|
||||
# `xdg-output`.
|
||||
generate_protocol_bindings(
|
||||
|
|
|
@ -36,6 +36,10 @@ extern GHOST_SystemHandle GHOST_CreateSystemBackground(void);
|
|||
*/
|
||||
extern void GHOST_SystemInitDebug(GHOST_SystemHandle systemhandle, GHOST_Debug debug);
|
||||
|
||||
#if !(defined(WIN32) || defined(__APPLE__))
|
||||
extern const char *GHOST_SystemBackend(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Disposes the one and only system.
|
||||
* \param systemhandle: The handle to the system.
|
||||
|
|
|
@ -134,6 +134,15 @@ class GHOST_ISystem {
|
|||
* \return A pointer to the system.
|
||||
*/
|
||||
static GHOST_ISystem *getSystem();
|
||||
/**
|
||||
* Return an identifier for the one and only system.
|
||||
* \warning while it may be tempting this should never be used to check for supported features,
|
||||
* in that case, the GHOST API should be extended to query capabilities.
|
||||
* This is needed for X11/WAYLAND on Unix, without this - there is no convenient way for users to
|
||||
* check if WAYLAND or XWAYLAND are in use since they are dynamically selected at startup.
|
||||
* When dynamically switching between X11/WAYLAND is removed, this function can go too.
|
||||
*/
|
||||
static const char *getSystemBackend();
|
||||
|
||||
static GHOST_TBacktraceFn getBacktraceFn();
|
||||
static void setBacktraceFn(GHOST_TBacktraceFn backtrace_fn);
|
||||
|
@ -515,6 +524,7 @@ class GHOST_ISystem {
|
|||
|
||||
/** The one and only system */
|
||||
static GHOST_ISystem *m_system;
|
||||
static const char *m_system_backend_id;
|
||||
|
||||
/** Function to call that sets the back-trace. */
|
||||
static GHOST_TBacktraceFn m_backtrace_fn;
|
||||
|
|
|
@ -52,6 +52,13 @@ GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle)
|
|||
return system->disposeSystem();
|
||||
}
|
||||
|
||||
#if !(defined(WIN32) || defined(__APPLE__))
|
||||
const char *GHOST_SystemBackend()
|
||||
{
|
||||
return GHOST_ISystem::getSystemBackend();
|
||||
}
|
||||
#endif
|
||||
|
||||
void GHOST_ShowMessageBox(GHOST_SystemHandle systemhandle,
|
||||
const char *title,
|
||||
const char *message,
|
||||
|
|
|
@ -306,7 +306,7 @@ GHOST_TSuccess GHOST_ContextGLX::releaseNativeHandles()
|
|||
|
||||
GHOST_TSuccess GHOST_ContextGLX::setSwapInterval(int interval)
|
||||
{
|
||||
if (!epoxy_has_glx_extension(m_display, DefaultScreen(m_display), "GLX_EXT_swap_control")) {
|
||||
if (epoxy_has_glx_extension(m_display, DefaultScreen(m_display), "GLX_EXT_swap_control")) {
|
||||
::glXSwapIntervalEXT(m_display, m_window, interval);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#endif
|
||||
|
||||
GHOST_ISystem *GHOST_ISystem::m_system = nullptr;
|
||||
const char *GHOST_ISystem::m_system_backend_id = nullptr;
|
||||
|
||||
GHOST_TBacktraceFn GHOST_ISystem::m_backtrace_fn = nullptr;
|
||||
|
||||
|
@ -47,7 +48,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
|
|||
/* Pass. */
|
||||
#elif defined(WITH_GHOST_WAYLAND)
|
||||
# if defined(WITH_GHOST_WAYLAND_DYNLOAD)
|
||||
const bool has_wayland_libraries = ghost_wl_dynload_libraries();
|
||||
const bool has_wayland_libraries = ghost_wl_dynload_libraries_init();
|
||||
# else
|
||||
const bool has_wayland_libraries = true;
|
||||
# endif
|
||||
|
@ -65,6 +66,9 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
|
|||
catch (const std::runtime_error &) {
|
||||
delete m_system;
|
||||
m_system = nullptr;
|
||||
# ifdef WITH_GHOST_WAYLAND_DYNLOAD
|
||||
ghost_wl_dynload_libraries_exit();
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -100,6 +104,9 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
|
|||
catch (const std::runtime_error &) {
|
||||
delete m_system;
|
||||
m_system = nullptr;
|
||||
# ifdef WITH_GHOST_WAYLAND_DYNLOAD
|
||||
ghost_wl_dynload_libraries_exit();
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -122,7 +129,10 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
|
|||
m_system = new GHOST_SystemCocoa();
|
||||
#endif
|
||||
|
||||
if ((m_system == nullptr) && verbose) {
|
||||
if (m_system) {
|
||||
m_system_backend_id = backends_attempted[backends_attempted_num - 1];
|
||||
}
|
||||
else if (verbose) {
|
||||
fprintf(stderr, "GHOST: failed to initialize display for back-end(s): [");
|
||||
for (int i = 0; i < backends_attempted_num; i++) {
|
||||
if (i != 0) {
|
||||
|
@ -186,6 +196,11 @@ GHOST_ISystem *GHOST_ISystem::getSystem()
|
|||
return m_system;
|
||||
}
|
||||
|
||||
const char *GHOST_ISystem::getSystemBackend()
|
||||
{
|
||||
return m_system_backend_id;
|
||||
}
|
||||
|
||||
GHOST_TBacktraceFn GHOST_ISystem::getBacktraceFn()
|
||||
{
|
||||
return GHOST_ISystem::m_backtrace_fn;
|
||||
|
|
|
@ -54,6 +54,11 @@
|
|||
#include <tablet-unstable-v2-client-protocol.h>
|
||||
#include <xdg-output-unstable-v1-client-protocol.h>
|
||||
|
||||
/* Decorations `xdg_decor`. */
|
||||
#include <xdg-decoration-unstable-v1-client-protocol.h>
|
||||
#include <xdg-shell-client-protocol.h>
|
||||
/* End `xdg_decor`. */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
@ -64,6 +69,15 @@
|
|||
/* Logging, use `ghost.wl.*` prefix. */
|
||||
#include "CLG_log.h"
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
static bool use_libdecor = true;
|
||||
# ifdef WITH_GHOST_WAYLAND_DYNLOAD
|
||||
static bool has_libdecor = false;
|
||||
# else
|
||||
static bool has_libdecor = true;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static void keyboard_handle_key_repeat_cancel(struct GWL_Seat *seat);
|
||||
|
||||
static void output_handle_done(void *data, struct wl_output *wl_output);
|
||||
|
@ -106,6 +120,15 @@ static bool use_gnome_confine_hack = false;
|
|||
*/
|
||||
#define USE_GNOME_KEYBOARD_SUPPRESS_WARNING
|
||||
|
||||
/**
|
||||
* When GNOME is found, require `libdecor`.
|
||||
* This is a hack because it seems there is no way to check if the compositor supports
|
||||
* server side decorations when initializing WAYLAND.
|
||||
*/
|
||||
#if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(WITH_GHOST_X11)
|
||||
# define USE_GNOME_NEEDS_LIBDECOR_HACK
|
||||
#endif
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -357,6 +380,36 @@ struct WGL_KeyboardDepressedState {
|
|||
int16_t mods[GHOST_KEY_MODIFIER_NUM] = {0};
|
||||
};
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
struct WGL_LibDecor_System {
|
||||
struct libdecor *context = nullptr;
|
||||
};
|
||||
|
||||
static void wgl_libdecor_system_destroy(WGL_LibDecor_System *decor)
|
||||
{
|
||||
if (decor->context) {
|
||||
libdecor_unref(decor->context);
|
||||
}
|
||||
delete decor;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct WGL_XDG_Decor_System {
|
||||
struct xdg_wm_base *shell = nullptr;
|
||||
struct zxdg_decoration_manager_v1 *manager = nullptr;
|
||||
};
|
||||
|
||||
static void wgl_xdg_decor_system_destroy(WGL_XDG_Decor_System *decor)
|
||||
{
|
||||
if (decor->manager) {
|
||||
zxdg_decoration_manager_v1_destroy(decor->manager);
|
||||
}
|
||||
if (decor->shell) {
|
||||
xdg_wm_base_destroy(decor->shell);
|
||||
}
|
||||
delete decor;
|
||||
}
|
||||
|
||||
struct GWL_Seat {
|
||||
GHOST_SystemWayland *system = nullptr;
|
||||
|
||||
|
@ -455,11 +508,10 @@ struct GWL_Display {
|
|||
struct wl_compositor *compositor = nullptr;
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
struct libdecor *decor_context = nullptr;
|
||||
#else
|
||||
struct xdg_wm_base *xdg_shell = nullptr;
|
||||
struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr;
|
||||
WGL_LibDecor_System *libdecor = nullptr;
|
||||
bool libdecor_required = false;
|
||||
#endif
|
||||
WGL_XDG_Decor_System *xdg_decor = nullptr;
|
||||
|
||||
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
|
||||
struct wl_shm *shm = nullptr;
|
||||
|
@ -626,19 +678,19 @@ static void display_destroy(GWL_Display *d)
|
|||
}
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
if (d->decor_context) {
|
||||
libdecor_unref(d->decor_context);
|
||||
if (use_libdecor) {
|
||||
if (d->libdecor) {
|
||||
wgl_libdecor_system_destroy(d->libdecor);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (d->xdg_decoration_manager) {
|
||||
zxdg_decoration_manager_v1_destroy(d->xdg_decoration_manager);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (d->xdg_decor) {
|
||||
wgl_xdg_decor_system_destroy(d->xdg_decor);
|
||||
}
|
||||
}
|
||||
|
||||
if (d->xdg_shell) {
|
||||
xdg_wm_base_destroy(d->xdg_shell);
|
||||
}
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
if (eglGetDisplay) {
|
||||
::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display)));
|
||||
}
|
||||
|
@ -2903,10 +2955,8 @@ static const struct wl_output_listener output_listener = {
|
|||
/** \name Listener (XDG WM Base), #xdg_wm_base_listener
|
||||
* \{ */
|
||||
|
||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
static CLG_LogRef LOG_WL_XDG_WM_BASE = {"ghost.wl.handle.xdg_wm_base"};
|
||||
# define LOG (&LOG_WL_XDG_WM_BASE)
|
||||
#define LOG (&LOG_WL_XDG_WM_BASE)
|
||||
|
||||
static void shell_handle_ping(void * /*data*/,
|
||||
struct xdg_wm_base *xdg_wm_base,
|
||||
|
@ -2920,9 +2970,7 @@ static const struct xdg_wm_base_listener shell_listener = {
|
|||
shell_handle_ping,
|
||||
};
|
||||
|
||||
# undef LOG
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
#undef LOG
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -2978,19 +3026,17 @@ static void global_handle_add(void *data,
|
|||
display->compositor = static_cast<wl_compositor *>(
|
||||
wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3));
|
||||
}
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
/* Pass. */
|
||||
#else
|
||||
else if (STREQ(interface, xdg_wm_base_interface.name)) {
|
||||
display->xdg_shell = static_cast<xdg_wm_base *>(
|
||||
WGL_XDG_Decor_System &decor = *display->xdg_decor;
|
||||
decor.shell = static_cast<xdg_wm_base *>(
|
||||
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(decor.shell, &shell_listener, nullptr);
|
||||
}
|
||||
else if (STREQ(interface, zxdg_decoration_manager_v1_interface.name)) {
|
||||
display->xdg_decoration_manager = static_cast<zxdg_decoration_manager_v1 *>(
|
||||
WGL_XDG_Decor_System &decor = *display->xdg_decor;
|
||||
decor.manager = static_cast<zxdg_decoration_manager_v1 *>(
|
||||
wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1));
|
||||
}
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
else if (STREQ(interface, zxdg_output_manager_v1_interface.name)) {
|
||||
display->xdg_output_manager = static_cast<zxdg_output_manager_v1 *>(
|
||||
wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 2));
|
||||
|
@ -3048,6 +3094,14 @@ static void global_handle_add(void *data,
|
|||
}
|
||||
else {
|
||||
found = false;
|
||||
|
||||
#ifdef USE_GNOME_NEEDS_LIBDECOR_HACK
|
||||
if (STRPREFIX(interface, "gtk_shell")) { /* `gtk_shell1` at time of writing. */
|
||||
/* Only require `libdecor` when built with X11 support,
|
||||
* otherwise there is nothing to fall back on. */
|
||||
display->libdecor_required = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CLOG_INFO(LOG,
|
||||
|
@ -3102,6 +3156,9 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display)
|
|||
throw std::runtime_error("Wayland: unable to connect to display!");
|
||||
}
|
||||
|
||||
/* This may be removed later if decorations are required, needed as part of registration. */
|
||||
d->xdg_decor = new WGL_XDG_Decor_System;
|
||||
|
||||
/* Register interfaces. */
|
||||
struct wl_registry *registry = wl_display_get_registry(d->display);
|
||||
wl_registry_add_listener(registry, ®istry_listener, d);
|
||||
|
@ -3112,17 +3169,45 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display)
|
|||
wl_registry_destroy(registry);
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
d->decor_context = libdecor_new(d->display, &libdecor_interface);
|
||||
if (!d->decor_context) {
|
||||
display_destroy(d);
|
||||
throw std::runtime_error("Wayland: unable to create window decorations!");
|
||||
if (d->libdecor_required) {
|
||||
wgl_xdg_decor_system_destroy(d->xdg_decor);
|
||||
d->xdg_decor = nullptr;
|
||||
|
||||
if (!has_libdecor) {
|
||||
# ifdef WITH_GHOST_X11
|
||||
/* LIBDECOR was the only reason X11 was used, let the user know they need it installed. */
|
||||
fprintf(stderr,
|
||||
"WAYLAND found but libdecor was not, install libdecor for Wayland support, "
|
||||
"falling back to X11\n");
|
||||
# endif
|
||||
display_destroy(d);
|
||||
throw std::runtime_error("Wayland: unable to find libdecor!");
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!d->xdg_shell) {
|
||||
display_destroy(d);
|
||||
throw std::runtime_error("Wayland: unable to access xdg_shell!");
|
||||
else {
|
||||
use_libdecor = false;
|
||||
}
|
||||
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
if (use_libdecor) {
|
||||
d->libdecor = new WGL_LibDecor_System;
|
||||
WGL_LibDecor_System &decor = *d->libdecor;
|
||||
decor.context = libdecor_new(d->display, &libdecor_interface);
|
||||
if (!decor.context) {
|
||||
display_destroy(d);
|
||||
throw std::runtime_error("Wayland: unable to create window decorations!");
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
WGL_XDG_Decor_System &decor = *d->xdg_decor;
|
||||
if (!decor.shell) {
|
||||
display_destroy(d);
|
||||
throw std::runtime_error("Wayland: unable to access xdg_shell!");
|
||||
}
|
||||
}
|
||||
|
||||
/* Register data device per seat for IPC between Wayland clients. */
|
||||
if (d->data_device_manager) {
|
||||
|
@ -4052,25 +4137,25 @@ wl_compositor *GHOST_SystemWayland::compositor()
|
|||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
libdecor *GHOST_SystemWayland::decor_context()
|
||||
libdecor *GHOST_SystemWayland::libdecor_context()
|
||||
{
|
||||
return d->decor_context;
|
||||
}
|
||||
|
||||
#else /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
xdg_wm_base *GHOST_SystemWayland::xdg_shell()
|
||||
{
|
||||
return d->xdg_shell;
|
||||
}
|
||||
|
||||
zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decoration_manager()
|
||||
{
|
||||
return d->xdg_decoration_manager;
|
||||
return d->libdecor->context;
|
||||
}
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
xdg_wm_base *GHOST_SystemWayland::xdg_decor_shell()
|
||||
{
|
||||
return d->xdg_decor->shell;
|
||||
}
|
||||
|
||||
zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decor_manager()
|
||||
{
|
||||
return d->xdg_decor->manager;
|
||||
}
|
||||
|
||||
/* End `xdg_decor`. */
|
||||
|
||||
const std::vector<GWL_Output *> &GHOST_SystemWayland::outputs() const
|
||||
{
|
||||
return d->outputs;
|
||||
|
@ -4317,35 +4402,52 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
|
|||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_DYNLOAD
|
||||
bool ghost_wl_dynload_libraries()
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
bool GHOST_SystemWayland::use_libdecor_runtime()
|
||||
{
|
||||
return use_libdecor;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_DYNLOAD
|
||||
bool ghost_wl_dynload_libraries_init()
|
||||
{
|
||||
/* Only report when `libwayland-client` is not found when building without X11,
|
||||
* which will be used as a fallback. */
|
||||
# ifdef WITH_GHOST_X11
|
||||
bool verbose = false;
|
||||
/* When running in WAYLAND, let the user know when a missing library is the only reason
|
||||
* WAYLAND could not be used. Otherwise it's not obvious why X11 is used as a fallback.
|
||||
* Otherwise when X11 is used, reporting WAYLAND library warnings is unwelcome noise. */
|
||||
bool verbose = getenv("WAYLAND_DISPLAY") != nullptr;
|
||||
# else
|
||||
bool verbose = true;
|
||||
# endif
|
||||
# endif /* !WITH_GHOST_X11 */
|
||||
|
||||
if (wayland_dynload_client_init(verbose) && /* `libwayland-client`. */
|
||||
wayland_dynload_cursor_init(verbose) && /* `libwayland-cursor`. */
|
||||
wayland_dynload_egl_init(verbose) && /* `libwayland-egl`. */
|
||||
wayland_dynload_egl_init(verbose) /* `libwayland-egl`. */
|
||||
) {
|
||||
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
wayland_dynload_libdecor_init(verbose) && /* `libdecor-0`. */
|
||||
has_libdecor = wayland_dynload_libdecor_init(verbose); /* `libdecor-0`. */
|
||||
# endif
|
||||
true) {
|
||||
return true;
|
||||
}
|
||||
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
wayland_dynload_libdecor_exit();
|
||||
# endif
|
||||
|
||||
wayland_dynload_client_exit();
|
||||
wayland_dynload_cursor_exit();
|
||||
wayland_dynload_egl_exit();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ghost_wl_dynload_libraries_exit()
|
||||
{
|
||||
wayland_dynload_client_exit();
|
||||
wayland_dynload_cursor_exit();
|
||||
wayland_dynload_egl_exit();
|
||||
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
wayland_dynload_libdecor_exit();
|
||||
# endif
|
||||
}
|
||||
|
||||
#endif /* WITH_GHOST_WAYLAND_DYNLOAD */
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -21,18 +21,12 @@
|
|||
# include <wayland_dynload_libdecor.h>
|
||||
# endif
|
||||
# include <libdecor.h>
|
||||
#else
|
||||
/* Generated by `wayland-scanner`. */
|
||||
# include <xdg-decoration-unstable-v1-client-protocol.h>
|
||||
# include <xdg-shell-client-protocol.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
class GHOST_WindowWayland;
|
||||
|
||||
struct GWL_Display;
|
||||
|
||||
bool ghost_wl_output_own(const struct wl_output *wl_output);
|
||||
void ghost_wl_output_tag(struct wl_output *wl_output);
|
||||
struct GWL_Output *ghost_wl_output_user_data(struct wl_output *wl_output);
|
||||
|
@ -52,7 +46,8 @@ void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *surface);
|
|||
* Return true when all required WAYLAND libraries are present,
|
||||
* Performs dynamic loading when `WITH_GHOST_WAYLAND_DYNLOAD` is in use.
|
||||
*/
|
||||
bool ghost_wl_dynload_libraries();
|
||||
bool ghost_wl_dynload_libraries_init();
|
||||
void ghost_wl_dynload_libraries_exit();
|
||||
#endif
|
||||
|
||||
struct GWL_Output {
|
||||
|
@ -167,11 +162,11 @@ class GHOST_SystemWayland : public GHOST_System {
|
|||
wl_compositor *compositor();
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor *decor_context();
|
||||
#else
|
||||
xdg_wm_base *xdg_shell();
|
||||
zxdg_decoration_manager_v1 *xdg_decoration_manager();
|
||||
libdecor *libdecor_context();
|
||||
#endif
|
||||
struct xdg_wm_base *xdg_decor_shell();
|
||||
struct zxdg_decoration_manager_v1 *xdg_decor_manager();
|
||||
/* End `xdg_decor`. */
|
||||
|
||||
const std::vector<GWL_Output *> &outputs() const;
|
||||
|
||||
|
@ -192,6 +187,10 @@ class GHOST_SystemWayland : public GHOST_System {
|
|||
wl_surface *wl_surface,
|
||||
int scale);
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
static bool use_libdecor_runtime();
|
||||
#endif
|
||||
|
||||
private:
|
||||
struct GWL_Display *d;
|
||||
std::string selection;
|
||||
|
|
|
@ -2435,11 +2435,11 @@ GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title,
|
|||
utf8Str,
|
||||
8,
|
||||
PropModeReplace,
|
||||
(const unsigned char *)title,
|
||||
(const uchar *)title,
|
||||
int(strlen(title)));
|
||||
|
||||
XChangeProperty(
|
||||
m_display, window, winType, XA_ATOM, 32, PropModeReplace, (unsigned char *)&typeDialog, 1);
|
||||
m_display, window, winType, XA_ATOM, 32, PropModeReplace, (uchar *)&typeDialog, 1);
|
||||
}
|
||||
|
||||
/* Create buttons GC */
|
||||
|
|
|
@ -31,13 +31,52 @@
|
|||
# include <libdecor.h>
|
||||
#endif
|
||||
|
||||
/* Generated by `wayland-scanner`. */
|
||||
#include <xdg-decoration-unstable-v1-client-protocol.h>
|
||||
#include <xdg-shell-client-protocol.h>
|
||||
|
||||
/* Logging, use `ghost.wl.*` prefix. */
|
||||
#include "CLG_log.h"
|
||||
|
||||
static constexpr size_t base_dpi = 96;
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
/* Access `use_libdecor` in #GHOST_SystemWayland. */
|
||||
# define use_libdecor GHOST_SystemWayland::use_libdecor_runtime()
|
||||
#endif
|
||||
|
||||
static GHOST_WindowManager *window_manager = nullptr;
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
struct WGL_LibDecor_Window {
|
||||
struct libdecor_frame *frame = nullptr;
|
||||
bool configured = false;
|
||||
};
|
||||
|
||||
static void wgl_libdecor_window_destroy(WGL_LibDecor_Window *decor)
|
||||
{
|
||||
libdecor_frame_unref(decor->frame);
|
||||
delete decor;
|
||||
}
|
||||
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
struct WGL_XDG_Decor_Window {
|
||||
struct xdg_surface *surface = nullptr;
|
||||
struct zxdg_toplevel_decoration_v1 *toplevel_decor = nullptr;
|
||||
struct xdg_toplevel *toplevel = nullptr;
|
||||
enum zxdg_toplevel_decoration_v1_mode mode = (enum zxdg_toplevel_decoration_v1_mode)0;
|
||||
};
|
||||
|
||||
static void wgl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
|
||||
{
|
||||
if (decor->toplevel_decor) {
|
||||
zxdg_toplevel_decoration_v1_destroy(decor->toplevel_decor);
|
||||
}
|
||||
xdg_toplevel_destroy(decor->toplevel);
|
||||
xdg_surface_destroy(decor->surface);
|
||||
delete decor;
|
||||
}
|
||||
|
||||
struct GWL_Window {
|
||||
GHOST_WindowWayland *w = nullptr;
|
||||
struct wl_surface *wl_surface = nullptr;
|
||||
|
@ -60,15 +99,9 @@ struct GWL_Window {
|
|||
uint32_t dpi = 0;
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
struct libdecor_frame *decor_frame = nullptr;
|
||||
bool decor_configured = false;
|
||||
#else
|
||||
struct xdg_surface *xdg_surface = nullptr;
|
||||
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration = nullptr;
|
||||
struct xdg_toplevel *xdg_toplevel = nullptr;
|
||||
|
||||
enum zxdg_toplevel_decoration_v1_mode decoration_mode = (enum zxdg_toplevel_decoration_v1_mode)0;
|
||||
WGL_LibDecor_Window *libdecor = nullptr;
|
||||
#endif
|
||||
WGL_XDG_Decor_Window *xdg_decor = nullptr;
|
||||
|
||||
wl_egl_window *egl_window = nullptr;
|
||||
bool is_maximised = false;
|
||||
|
@ -146,10 +179,8 @@ static int outputs_max_scale_or_default(const std::vector<GWL_Output *> &outputs
|
|||
/** \name Listener (XDG Top Level), #xdg_toplevel_listener
|
||||
* \{ */
|
||||
|
||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
static CLG_LogRef LOG_WL_XDG_TOPLEVEL = {"ghost.wl.handle.xdg_toplevel"};
|
||||
# define LOG (&LOG_WL_XDG_TOPLEVEL)
|
||||
#define LOG (&LOG_WL_XDG_TOPLEVEL)
|
||||
|
||||
static void xdg_toplevel_handle_configure(void *data,
|
||||
xdg_toplevel * /*xdg_toplevel*/,
|
||||
|
@ -197,9 +228,7 @@ static const xdg_toplevel_listener toplevel_listener = {
|
|||
xdg_toplevel_handle_close,
|
||||
};
|
||||
|
||||
# undef LOG
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
#undef LOG
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -250,7 +279,7 @@ static void frame_handle_configure(struct libdecor_frame *frame,
|
|||
libdecor_frame_commit(frame, state, configuration);
|
||||
libdecor_state_free(state);
|
||||
|
||||
win->decor_configured = true;
|
||||
win->libdecor->configured = true;
|
||||
}
|
||||
|
||||
static void frame_handle_close(struct libdecor_frame * /*frame*/, void *data)
|
||||
|
@ -285,10 +314,8 @@ static struct libdecor_frame_interface libdecor_frame_iface = {
|
|||
/** \name Listener (XDG Decoration Listener), #zxdg_toplevel_decoration_v1_listener
|
||||
* \{ */
|
||||
|
||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
static CLG_LogRef LOG_WL_XDG_TOPLEVEL_DECORATION = {"ghost.wl.handle.xdg_toplevel_decoration"};
|
||||
# define LOG (&LOG_WL_XDG_TOPLEVEL_DECORATION)
|
||||
#define LOG (&LOG_WL_XDG_TOPLEVEL_DECORATION)
|
||||
|
||||
static void xdg_toplevel_decoration_handle_configure(
|
||||
void *data,
|
||||
|
@ -296,16 +323,14 @@ static void xdg_toplevel_decoration_handle_configure(
|
|||
const uint32_t mode)
|
||||
{
|
||||
CLOG_INFO(LOG, 2, "configure (mode=%u)", mode);
|
||||
static_cast<GWL_Window *>(data)->decoration_mode = (zxdg_toplevel_decoration_v1_mode)mode;
|
||||
static_cast<GWL_Window *>(data)->xdg_decor->mode = (zxdg_toplevel_decoration_v1_mode)mode;
|
||||
}
|
||||
|
||||
static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listener = {
|
||||
xdg_toplevel_decoration_handle_configure,
|
||||
};
|
||||
|
||||
# undef LOG
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
#undef LOG
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -313,10 +338,8 @@ static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listene
|
|||
/** \name Listener (XDG Surface Handle Configure), #xdg_surface_listener
|
||||
* \{ */
|
||||
|
||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
|
||||
static CLG_LogRef LOG_WL_XDG_SURFACE = {"ghost.wl.handle.xdg_surface"};
|
||||
# define LOG (&LOG_WL_XDG_SURFACE)
|
||||
#define LOG (&LOG_WL_XDG_SURFACE)
|
||||
|
||||
static void xdg_surface_handle_configure(void *data,
|
||||
xdg_surface *xdg_surface,
|
||||
|
@ -324,7 +347,7 @@ static void xdg_surface_handle_configure(void *data,
|
|||
{
|
||||
GWL_Window *win = static_cast<GWL_Window *>(data);
|
||||
|
||||
if (win->xdg_surface != xdg_surface) {
|
||||
if (win->xdg_decor->surface != xdg_surface) {
|
||||
CLOG_INFO(LOG, 2, "configure (skipped)");
|
||||
return;
|
||||
}
|
||||
|
@ -354,9 +377,7 @@ static const xdg_surface_listener xdg_surface_listener = {
|
|||
xdg_surface_handle_configure,
|
||||
};
|
||||
|
||||
# undef LOG
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
||||
#undef LOG
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -476,43 +497,64 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
* when the `w->scale` changed. */
|
||||
const int32_t size_min[2] = {320, 240};
|
||||
|
||||
/* This value is expected to match the base name of the `.desktop` file. see T101805.
|
||||
*
|
||||
* NOTE: the XDG desktop-entry-spec defines that this should follow the "reverse DNS" convention.
|
||||
* For e.g. `org.blender.Blender` - however the `.desktop` file distributed with Blender is
|
||||
* simply called `blender.desktop`, so the it's important to follow that name.
|
||||
* Other distributions such as SNAP & FLATPAK may need to change this value T101779.
|
||||
* Currently there isn't a way to configure this, we may want to support that. */
|
||||
const char *xdg_app_id = "blender";
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
/* create window decorations */
|
||||
w->decor_frame = libdecor_decorate(
|
||||
m_system->decor_context(), w->wl_surface, &libdecor_frame_iface, w);
|
||||
libdecor_frame_map(w->decor_frame);
|
||||
if (use_libdecor) {
|
||||
w->libdecor = new WGL_LibDecor_Window;
|
||||
WGL_LibDecor_Window &decor = *w->libdecor;
|
||||
|
||||
libdecor_frame_set_min_content_size(w->decor_frame, UNPACK2(size_min));
|
||||
/* create window decorations */
|
||||
decor.frame = libdecor_decorate(
|
||||
m_system->libdecor_context(), w->wl_surface, &libdecor_frame_iface, w);
|
||||
libdecor_frame_map(w->libdecor->frame);
|
||||
|
||||
if (parentWindow) {
|
||||
libdecor_frame_set_parent(
|
||||
w->decor_frame, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->decor_frame);
|
||||
libdecor_frame_set_min_content_size(decor.frame, UNPACK2(size_min));
|
||||
libdecor_frame_set_app_id(decor.frame, xdg_app_id);
|
||||
|
||||
if (parentWindow) {
|
||||
WGL_LibDecor_Window &decor_parent =
|
||||
*dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->libdecor;
|
||||
libdecor_frame_set_parent(decor.frame, decor_parent.frame);
|
||||
}
|
||||
}
|
||||
#else
|
||||
w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->xdg_shell(), w->wl_surface);
|
||||
w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
w->xdg_decor = new WGL_XDG_Decor_Window;
|
||||
WGL_XDG_Decor_Window &decor = *w->xdg_decor;
|
||||
decor.surface = xdg_wm_base_get_xdg_surface(m_system->xdg_decor_shell(), w->wl_surface);
|
||||
decor.toplevel = xdg_surface_get_toplevel(decor.surface);
|
||||
|
||||
xdg_toplevel_set_min_size(w->xdg_toplevel, UNPACK2(size_min));
|
||||
xdg_toplevel_set_min_size(decor.toplevel, UNPACK2(size_min));
|
||||
xdg_toplevel_set_app_id(decor.toplevel, xdg_app_id);
|
||||
|
||||
if (m_system->xdg_decoration_manager()) {
|
||||
w->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
||||
m_system->xdg_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);
|
||||
if (m_system->xdg_decor_manager()) {
|
||||
decor.toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
||||
m_system->xdg_decor_manager(), decor.toplevel);
|
||||
zxdg_toplevel_decoration_v1_add_listener(
|
||||
decor.toplevel_decor, &toplevel_decoration_v1_listener, w);
|
||||
zxdg_toplevel_decoration_v1_set_mode(decor.toplevel_decor,
|
||||
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||
}
|
||||
|
||||
xdg_surface_add_listener(decor.surface, &xdg_surface_listener, w);
|
||||
xdg_toplevel_add_listener(decor.toplevel, &toplevel_listener, w);
|
||||
|
||||
if (parentWindow && is_dialog) {
|
||||
WGL_XDG_Decor_Window &decor_parent =
|
||||
*dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_decor;
|
||||
xdg_toplevel_set_parent(decor.toplevel, decor_parent.toplevel);
|
||||
}
|
||||
}
|
||||
|
||||
xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w);
|
||||
xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w);
|
||||
|
||||
if (parentWindow && is_dialog) {
|
||||
xdg_toplevel_set_parent(
|
||||
w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel);
|
||||
}
|
||||
|
||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
setTitle(title);
|
||||
|
||||
wl_surface_set_user_data(w->wl_surface, this);
|
||||
|
@ -522,11 +564,14 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
wl_display_roundtrip(m_system->display());
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
/* It's important not to return until the window is configured or
|
||||
* calls to `setState` from Blender will crash `libdecor`. */
|
||||
while (!w->decor_configured) {
|
||||
if (libdecor_dispatch(m_system->decor_context(), 0) < 0) {
|
||||
break;
|
||||
if (use_libdecor) {
|
||||
WGL_LibDecor_Window &decor = *w->libdecor;
|
||||
/* It's important not to return until the window is configured or
|
||||
* calls to `setState` from Blender will crash `libdecor`. */
|
||||
while (!decor.configured) {
|
||||
if (libdecor_dispatch(m_system->libdecor_context(), 0) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -535,9 +580,13 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
setOpaque();
|
||||
#endif
|
||||
|
||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR /* Causes a glitch with `libdecor` for some reason. */
|
||||
setState(state);
|
||||
/* Causes a glitch with `libdecor` for some reason. */
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
if (use_libdecor == false)
|
||||
#endif
|
||||
{
|
||||
setState(state);
|
||||
}
|
||||
|
||||
/* EGL context. */
|
||||
if (setDrawingContextType(type) == GHOST_kFailure) {
|
||||
|
@ -596,12 +645,16 @@ GHOST_TSuccess GHOST_WindowWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitma
|
|||
void GHOST_WindowWayland::setTitle(const char *title)
|
||||
{
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_set_app_id(w->decor_frame, title);
|
||||
libdecor_frame_set_title(w->decor_frame, title);
|
||||
#else
|
||||
xdg_toplevel_set_title(w->xdg_toplevel, title);
|
||||
xdg_toplevel_set_app_id(w->xdg_toplevel, title);
|
||||
if (use_libdecor) {
|
||||
WGL_LibDecor_Window &decor = *w->libdecor;
|
||||
libdecor_frame_set_title(decor.frame, title);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
WGL_XDG_Decor_Window &decor = *w->xdg_decor;
|
||||
xdg_toplevel_set_title(decor.toplevel, title);
|
||||
}
|
||||
|
||||
this->title = title;
|
||||
}
|
||||
|
@ -672,14 +725,14 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
|
|||
wl_egl_window_destroy(w->egl_window);
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_unref(w->decor_frame);
|
||||
#else
|
||||
if (w->xdg_toplevel_decoration) {
|
||||
zxdg_toplevel_decoration_v1_destroy(w->xdg_toplevel_decoration);
|
||||
if (use_libdecor) {
|
||||
wgl_libdecor_window_destroy(w->libdecor);
|
||||
}
|
||||
xdg_toplevel_destroy(w->xdg_toplevel);
|
||||
xdg_surface_destroy(w->xdg_surface);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
wgl_xdg_decor_window_destroy(w->xdg_decor);
|
||||
}
|
||||
|
||||
/* Clear any pointers to this window. This is needed because there are no guarantees
|
||||
* that flushing the display will the "leave" handlers before handling events. */
|
||||
|
@ -711,47 +764,74 @@ GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state)
|
|||
case GHOST_kWindowStateNormal:
|
||||
/* Unset states. */
|
||||
switch (getState()) {
|
||||
case GHOST_kWindowStateMaximized:
|
||||
case GHOST_kWindowStateMaximized: {
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_unset_maximized(w->decor_frame);
|
||||
#else
|
||||
xdg_toplevel_unset_maximized(w->xdg_toplevel);
|
||||
if (use_libdecor) {
|
||||
libdecor_frame_unset_maximized(w->libdecor->frame);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
xdg_toplevel_unset_maximized(w->xdg_decor->toplevel);
|
||||
}
|
||||
break;
|
||||
case GHOST_kWindowStateFullScreen:
|
||||
}
|
||||
case GHOST_kWindowStateFullScreen: {
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_unset_fullscreen(w->decor_frame);
|
||||
#else
|
||||
xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
|
||||
if (use_libdecor) {
|
||||
libdecor_frame_unset_fullscreen(w->libdecor->frame);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
xdg_toplevel_unset_fullscreen(w->xdg_decor->toplevel);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GHOST_kWindowStateMaximized:
|
||||
case GHOST_kWindowStateMaximized: {
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_set_maximized(w->decor_frame);
|
||||
#else
|
||||
xdg_toplevel_set_maximized(w->xdg_toplevel);
|
||||
if (use_libdecor) {
|
||||
libdecor_frame_set_maximized(w->libdecor->frame);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
xdg_toplevel_set_maximized(w->xdg_decor->toplevel);
|
||||
}
|
||||
break;
|
||||
case GHOST_kWindowStateMinimized:
|
||||
}
|
||||
case GHOST_kWindowStateMinimized: {
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_set_minimized(w->decor_frame);
|
||||
#else
|
||||
xdg_toplevel_set_minimized(w->xdg_toplevel);
|
||||
if (use_libdecor) {
|
||||
libdecor_frame_set_minimized(w->libdecor->frame);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
xdg_toplevel_set_minimized(w->xdg_decor->toplevel);
|
||||
}
|
||||
break;
|
||||
case GHOST_kWindowStateFullScreen:
|
||||
}
|
||||
case GHOST_kWindowStateFullScreen: {
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_set_fullscreen(w->decor_frame, nullptr);
|
||||
#else
|
||||
xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
|
||||
if (use_libdecor) {
|
||||
libdecor_frame_set_fullscreen(w->libdecor->frame, nullptr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
xdg_toplevel_set_fullscreen(w->xdg_decor->toplevel, nullptr);
|
||||
}
|
||||
break;
|
||||
case GHOST_kWindowStateEmbedded:
|
||||
}
|
||||
case GHOST_kWindowStateEmbedded: {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
@ -780,20 +860,29 @@ GHOST_TSuccess GHOST_WindowWayland::setOrder(GHOST_TWindowOrder /*order*/)
|
|||
GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const
|
||||
{
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_set_fullscreen(w->decor_frame, nullptr);
|
||||
#else
|
||||
xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
|
||||
if (use_libdecor) {
|
||||
libdecor_frame_set_fullscreen(w->libdecor->frame, nullptr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
xdg_toplevel_set_fullscreen(w->xdg_decor->toplevel, nullptr);
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const
|
||||
{
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
libdecor_frame_unset_fullscreen(w->decor_frame);
|
||||
#else
|
||||
xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
|
||||
if (use_libdecor) {
|
||||
libdecor_frame_unset_fullscreen(w->libdecor->frame);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
xdg_toplevel_unset_fullscreen(w->xdg_decor->toplevel);
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ void (*MEM_set_error_callback)(void (*func)(const char *)) = MEM_lockfree_set_er
|
|||
bool (*MEM_consistency_check)(void) = MEM_lockfree_consistency_check;
|
||||
void (*MEM_set_memory_debug)(void) = MEM_lockfree_set_memory_debug;
|
||||
size_t (*MEM_get_memory_in_use)(void) = MEM_lockfree_get_memory_in_use;
|
||||
unsigned int (*MEM_get_memory_blocks_in_use)(void) = MEM_lockfree_get_memory_blocks_in_use;
|
||||
uint (*MEM_get_memory_blocks_in_use)(void) = MEM_lockfree_get_memory_blocks_in_use;
|
||||
void (*MEM_reset_peak_memory)(void) = MEM_lockfree_reset_peak_memory;
|
||||
size_t (*MEM_get_peak_memory)(void) = MEM_lockfree_get_peak_memory;
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ void *MEM_lockfree_callocN(size_t len, const char *str)
|
|||
print_error("Calloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
|
||||
SIZET_ARG(len),
|
||||
str,
|
||||
(unsigned int)mem_in_use);
|
||||
(uint)mem_in_use);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,7 @@ void *MEM_lockfree_mallocN(size_t len, const char *str)
|
|||
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
|
||||
SIZET_ARG(len),
|
||||
str,
|
||||
(unsigned int)mem_in_use);
|
||||
(uint)mem_in_use);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -292,7 +292,7 @@ void *MEM_lockfree_malloc_arrayN(size_t len, size_t size, const char *str)
|
|||
SIZET_ARG(len),
|
||||
SIZET_ARG(size),
|
||||
str,
|
||||
(unsigned int)mem_in_use);
|
||||
(uint)mem_in_use);
|
||||
abort();
|
||||
return NULL;
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ void *MEM_lockfree_mallocN_aligned(size_t len, size_t alignment, const char *str
|
|||
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
|
||||
SIZET_ARG(len),
|
||||
str,
|
||||
(unsigned int)mem_in_use);
|
||||
(uint)mem_in_use);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -401,7 +401,7 @@ size_t MEM_lockfree_get_memory_in_use(void)
|
|||
return mem_in_use;
|
||||
}
|
||||
|
||||
unsigned int MEM_lockfree_get_memory_blocks_in_use(void)
|
||||
uint MEM_lockfree_get_memory_blocks_in_use(void)
|
||||
{
|
||||
return totblock;
|
||||
}
|
||||
|
|
|
@ -723,12 +723,11 @@ template<typename Mesh> class Mikktspace {
|
|||
|
||||
void build4RuleGroups()
|
||||
{
|
||||
/* Note: This could be parallelized by grouping all [t, i] pairs into
|
||||
/* NOTE: This could be parallelized by grouping all [t, i] pairs into
|
||||
* shards by hash(triangles[t].vertices[i]). This way, each shard can be processed
|
||||
* independently and in parallel.
|
||||
* However, the groupWithAny logic needs special handling (e.g. lock a mutex when
|
||||
* encountering a groupWithAny triangle, then sort it out, then unlock and proceed).
|
||||
*/
|
||||
* However, the `groupWithAny` logic needs special handling (e.g. lock a mutex when
|
||||
* encountering a `groupWithAny` triangle, then sort it out, then unlock and proceed). */
|
||||
for (uint t = 0; t < nrTriangles; t++) {
|
||||
Triangle &triangle = triangles[t];
|
||||
for (uint i = 0; i < 3; i++) {
|
||||
|
|
|
@ -22,7 +22,7 @@ bool wayland_dynload_egl_init(const bool verbose)
|
|||
{
|
||||
/* Library paths. */
|
||||
const char *paths[] = {
|
||||
"libwayland-egl.so.0",
|
||||
"libwayland-egl.so.1",
|
||||
"libwayland-egl.so",
|
||||
};
|
||||
const int paths_num = sizeof(paths) / sizeof(*paths);
|
||||
|
|
|
@ -367,9 +367,9 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
|
|||
"all and invert unselected",
|
||||
"and AMD driver version 22.10 or newer",
|
||||
"and AMD Radeon Pro 21.Q4 driver or newer",
|
||||
"and Linux driver version xx.xx.23570 or newer",
|
||||
"and Linux driver version xx.xx.23904 or newer",
|
||||
"and NVIDIA driver version 470 or newer",
|
||||
"and Windows driver version 101.3268 or newer",
|
||||
"and Windows driver version 101.3430 or newer",
|
||||
"available with",
|
||||
"brown fox",
|
||||
"can't save image while rendering",
|
||||
|
|
|
@ -389,6 +389,8 @@ class SpellChecker:
|
|||
"albedo",
|
||||
"anamorphic",
|
||||
"anisotropic", "anisotropy",
|
||||
"arcminute", "arcminutes",
|
||||
"arcsecond", "arcseconds",
|
||||
"bimanual", # OpenXR?
|
||||
"bitangent",
|
||||
"boid", "boids",
|
||||
|
@ -449,7 +451,7 @@ class SpellChecker:
|
|||
"superellipse",
|
||||
"thumbstick",
|
||||
"tooltip", "tooltips",
|
||||
"trackpad",
|
||||
"touchpad", "trackpad",
|
||||
"tuple",
|
||||
"unicode",
|
||||
"viewport", "viewports",
|
||||
|
@ -650,6 +652,7 @@ class SpellChecker:
|
|||
"mikktspace",
|
||||
"minkowski",
|
||||
"minnaert",
|
||||
"mises", # von Mises-Fisher
|
||||
"moskowitz", # Pierson-Moskowitz
|
||||
"musgrave",
|
||||
"nayar",
|
||||
|
@ -665,6 +668,7 @@ class SpellChecker:
|
|||
"runge",
|
||||
"sobol",
|
||||
"verlet",
|
||||
"von", # von Mises-Fisher
|
||||
"wilkie",
|
||||
"worley",
|
||||
|
||||
|
@ -724,6 +728,7 @@ class SpellChecker:
|
|||
"lmb", "mmb", "rmb",
|
||||
"lscm",
|
||||
"kb",
|
||||
"mis",
|
||||
"mocap",
|
||||
"msgid", "msgids",
|
||||
"mux",
|
||||
|
@ -751,6 +756,7 @@ class SpellChecker:
|
|||
"uuid",
|
||||
"vbo", "vbos",
|
||||
"vfx",
|
||||
"vmm",
|
||||
"vr",
|
||||
"wxyz",
|
||||
"xr",
|
||||
|
|
|
@ -53,6 +53,13 @@ def write_sysinfo(filepath):
|
|||
output.write("build linkflags: %s\n" % prepr(bpy.app.build_linkflags))
|
||||
output.write("build system: %s\n" % prepr(bpy.app.build_system))
|
||||
|
||||
# Windowing Environment (include when dynamically selectable).
|
||||
from _bpy import _ghost_backend
|
||||
ghost_backend = _ghost_backend()
|
||||
if ghost_backend not in {'NONE', 'DEFAULT'}:
|
||||
output.write("windowing environment: %s\n" % prepr(ghost_backend))
|
||||
del _ghost_backend, ghost_backend
|
||||
|
||||
# Python info.
|
||||
output.write(title("Python"))
|
||||
output.write("version: %s\n" % (sys.version.replace("\n", " ")))
|
||||
|
|
|
@ -2073,6 +2073,8 @@ def km_node_editor(params):
|
|||
op_menu("NODE_MT_add", {"type": 'A', "value": 'PRESS', "shift": True}),
|
||||
("node.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),
|
||||
("node.duplicate_move_linked", {"type": 'D', "value": 'PRESS', "alt": True},
|
||||
{"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),
|
||||
("node.duplicate_move_keep_inputs", {"type": 'D', "value": 'PRESS', "shift": True, "ctrl": True},
|
||||
{"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),
|
||||
("node.parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),
|
||||
|
|
|
@ -89,6 +89,17 @@ class PREFERENCES_OT_copy_prev(Operator):
|
|||
if os.path.isdir(cls._old_version_path(version_split)):
|
||||
return version_split
|
||||
version_old = version_old - 1
|
||||
|
||||
# Support loading 2.8x..2.9x startup (any older isn't so useful to load).
|
||||
# NOTE: remove this block for Blender 4.0 and later.
|
||||
if version_old == 299:
|
||||
version_old = 294
|
||||
while version_old >= 280:
|
||||
version_split = version_old // 100, version_old % 100
|
||||
if os.path.isdir(cls._old_version_path(version_split)):
|
||||
return version_split
|
||||
version_old = version_old - 1
|
||||
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -3158,6 +3158,15 @@ class WM_MT_splash_about(Menu):
|
|||
bpy.app.build_commit_time.decode('utf-8', 'replace')), translate=False)
|
||||
col.label(text=iface_("Hash: %s") % bpy.app.build_hash.decode('ascii'), translate=False)
|
||||
col.label(text=iface_("Branch: %s") % bpy.app.build_branch.decode('utf-8', 'replace'), translate=False)
|
||||
|
||||
# This isn't useful information on MS-Windows or Apple systems as dynamically switching
|
||||
# between windowing systems is only supported between X11/WAYLAND.
|
||||
from _bpy import _ghost_backend
|
||||
ghost_backend = _ghost_backend()
|
||||
if ghost_backend not in {'NONE', 'DEFAULT'}:
|
||||
col.label(text=iface_("Windowing Environment: %s") % _ghost_backend(), translate=False)
|
||||
del _ghost_backend, ghost_backend
|
||||
|
||||
col.separator(factor=2.0)
|
||||
col.label(text="Blender is free software")
|
||||
col.label(text="Licensed under the GNU General Public License")
|
||||
|
|
|
@ -239,6 +239,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
|
|||
|
||||
class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
|
||||
bl_label = "Emission"
|
||||
bl_translation_context = i18n_contexts.id_particlesettings
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
import bpy
|
||||
from bpy.types import Panel, Header, Menu, UIList
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
from bpy.app.translations import (
|
||||
pgettext_iface as iface_,
|
||||
contexts as i18n_contexts,
|
||||
)
|
||||
from bl_ui.utils import PresetPanel
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
AnnotationDrawingToolsPanel,
|
||||
|
@ -1751,6 +1754,7 @@ class CLIP_MT_marker_pie(Menu):
|
|||
class CLIP_MT_tracking_pie(Menu):
|
||||
# Tracking Operators
|
||||
bl_label = "Tracking"
|
||||
bl_translation_context = i18n_contexts.id_movieclip
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
|
|
@ -1528,36 +1528,23 @@ class IMAGE_PT_overlay_guides(Panel):
|
|||
layout.active = overlay.show_overlays
|
||||
|
||||
row = layout.row()
|
||||
row_el = row.column()
|
||||
row_el.prop(overlay, "show_grid_background", text="Grid")
|
||||
row.prop(overlay, "show_grid_background", text="Grid")
|
||||
|
||||
if overlay.show_grid_background:
|
||||
layout.use_property_split = True
|
||||
|
||||
col = layout.column(align=False, heading="Grid Over Image")
|
||||
col.use_property_decorate = False
|
||||
row = col.row(align=True)
|
||||
sub = row.row(align=True)
|
||||
sub.prop(uvedit, "show_grid_over_image", text="")
|
||||
sub = row.row()
|
||||
sub.prop(uvedit, "show_grid_over_image", text="Over Image")
|
||||
sub.active = sima.image is not None
|
||||
|
||||
col = layout.column(align=False, heading="Fixed Subdivisions")
|
||||
col.use_property_decorate = False
|
||||
layout.row().prop(uvedit, "grid_shape_source", expand=True)
|
||||
|
||||
row = col.row(align=True)
|
||||
sub = row.row(align=True)
|
||||
sub.prop(uvedit, "use_custom_grid", text="")
|
||||
if uvedit.use_custom_grid:
|
||||
row = layout.row()
|
||||
row.use_property_split = True
|
||||
row.use_property_decorate = False
|
||||
sub = sub.row(align=True)
|
||||
sub.prop(uvedit, "custom_grid_subdivisions", text="")
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
row = layout.row()
|
||||
row.use_property_split = True
|
||||
row.use_property_decorate = False
|
||||
row.prop(uvedit, "tile_grid_shape", text="Tiles")
|
||||
row.prop(uvedit, "custom_grid_subdivisions", text="Fixed Subdivisions")
|
||||
row.active = uvedit.grid_shape_source == 'FIXED'
|
||||
|
||||
layout.prop(uvedit, "tile_grid_shape", text="Tiles")
|
||||
|
||||
|
||||
class IMAGE_PT_overlay_uv_edit(Panel):
|
||||
|
|
|
@ -318,6 +318,7 @@ class NODE_MT_node(Menu):
|
|||
layout.operator("node.clipboard_copy", text="Copy")
|
||||
layout.operator("node.clipboard_paste", text="Paste")
|
||||
layout.operator("node.duplicate_move")
|
||||
layout.operator("node.duplicate_move_linked")
|
||||
layout.operator("node.delete")
|
||||
layout.operator("node.delete_reconnect")
|
||||
|
||||
|
|
|
@ -683,7 +683,7 @@ class SEQUENCER_MT_add(Menu):
|
|||
elif bpy_data_movieclips_len > 0:
|
||||
layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip", icon='TRACKER')
|
||||
else:
|
||||
layout.menu("SEQUENCER_MT_add_empty", text="Clip", icon='TRACKER')
|
||||
layout.menu("SEQUENCER_MT_add_empty", text="Clip", text_ctxt=i18n_contexts.id_movieclip, icon='TRACKER')
|
||||
del bpy_data_movieclips_len
|
||||
|
||||
bpy_data_masks_len = len(bpy.data.masks)
|
||||
|
|
|
@ -397,17 +397,18 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa
|
|||
# col.prop(edit, "use_duplicate_fcurve", text="F-Curve") # Not implemented.
|
||||
col.prop(edit, "use_duplicate_curves", text="Curves")
|
||||
col.prop(edit, "use_duplicate_grease_pencil", text="Grease Pencil")
|
||||
col.prop(edit, "use_duplicate_lattice", text="Lattice")
|
||||
|
||||
col = flow.column()
|
||||
col.prop(edit, "use_duplicate_lattice", text="Lattice")
|
||||
col.prop(edit, "use_duplicate_light", text="Light")
|
||||
col.prop(edit, "use_duplicate_lightprobe", text="Light Probe")
|
||||
col.prop(edit, "use_duplicate_material", text="Material")
|
||||
col.prop(edit, "use_duplicate_mesh", text="Mesh")
|
||||
col.prop(edit, "use_duplicate_metaball", text="Metaball")
|
||||
col.prop(edit, "use_duplicate_node_tree", text="Node Tree")
|
||||
col.prop(edit, "use_duplicate_particle", text="Particle")
|
||||
|
||||
col = flow.column()
|
||||
col.prop(edit, "use_duplicate_particle", text="Particle")
|
||||
if hasattr(edit, "use_duplicate_pointcloud"):
|
||||
col.prop(edit, "use_duplicate_pointcloud", text="Point Cloud")
|
||||
col.prop(edit, "use_duplicate_speaker", text="Speaker")
|
||||
|
|
|
@ -3356,8 +3356,7 @@ class VIEW3D_MT_face_sets(Menu):
|
|||
op = layout.operator("sculpt.face_set_change_visibility", text='Invert Visible Face Sets')
|
||||
op.mode = 'INVERT'
|
||||
|
||||
op = layout.operator("sculpt.face_set_change_visibility", text='Show All Face Sets')
|
||||
op.mode = 'SHOW_ALL'
|
||||
op = layout.operator("sculpt.reveal_all", text='Show All Face Sets')
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -5518,8 +5517,7 @@ class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
|
|||
op = pie.operator("sculpt.face_set_change_visibility", text='Invert Visible')
|
||||
op.mode = 'INVERT'
|
||||
|
||||
op = pie.operator("sculpt.face_set_change_visibility", text='Show All')
|
||||
op.mode = 'SHOW_ALL'
|
||||
op = pie.operator("sculpt.reveal_all", text='Show All')
|
||||
|
||||
|
||||
class VIEW3D_MT_wpaint_vgroup_lock_pie(Menu):
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#include "BLI_kdopbvh.h"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include <mutex>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -195,6 +199,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
|
|||
BVHCacheType bvh_cache_type,
|
||||
int tree_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/**
|
||||
* Builds or queries a BVH-cache for the cache BVH-tree of the request type.
|
||||
*/
|
||||
|
@ -203,7 +209,9 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
|
|||
int tree_type,
|
||||
BVHCacheType bvh_cache_type,
|
||||
struct BVHCache **bvh_cache_p,
|
||||
ThreadMutex *mesh_eval_mutex);
|
||||
std::mutex *mesh_eval_mutex);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Frees data allocated by a call to `bvhtree_from_editmesh_*`.
|
||||
|
|
|
@ -146,15 +146,6 @@ void CustomData_copy(const struct CustomData *source,
|
|||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
|
||||
/**
|
||||
* Like #CustomData_copy but skips copying layers that are stored as flags on #BMesh.
|
||||
*/
|
||||
void CustomData_copy_mesh_to_bmesh(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
|
||||
/* BMESH_TODO, not really a public function but readfile.c needs it */
|
||||
void CustomData_update_typemap(struct CustomData *data);
|
||||
|
||||
|
@ -168,15 +159,6 @@ bool CustomData_merge(const struct CustomData *source,
|
|||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
|
||||
/**
|
||||
* Like #CustomData_copy but skips copying layers that are stored as flags on #BMesh.
|
||||
*/
|
||||
bool CustomData_merge_mesh_to_bmesh(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
eCustomDataMask mask,
|
||||
eCDAllocType alloctype,
|
||||
int totelem);
|
||||
|
||||
/**
|
||||
* Reallocate custom data to a new element count. If the new size is larger, the new values use
|
||||
* the #CD_CONSTRUCT behavior, so trivial types must be initialized by the caller. After being
|
||||
|
@ -196,6 +178,14 @@ bool CustomData_bmesh_merge(const struct CustomData *source,
|
|||
struct BMesh *bm,
|
||||
char htype);
|
||||
|
||||
/**
|
||||
* Remove layers that aren't stored in BMesh or are stored as flags on BMesh.
|
||||
* The `layers` array of the returned #CustomData must be freed, but may be null.
|
||||
* Used during conversion of #Mesh data to #BMesh storage format.
|
||||
*/
|
||||
CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src,
|
||||
eCustomDataMask mask);
|
||||
|
||||
/**
|
||||
* NULL's all members and resets the #CustomData.typemap.
|
||||
*/
|
||||
|
|
|
@ -16,6 +16,7 @@ struct ListBase;
|
|||
struct Object;
|
||||
struct ParticleSystem;
|
||||
struct Scene;
|
||||
struct ViewLayer;
|
||||
struct ViewerPath;
|
||||
struct GeometrySet;
|
||||
|
||||
|
@ -83,6 +84,13 @@ bool BKE_object_dupli_find_rgba_attribute(struct Object *ob,
|
|||
const char *name,
|
||||
float r_value[4]);
|
||||
|
||||
/** Look up the RGBA value of a view layer/scene/world shader attribute.
|
||||
* \return true if the attribute was found; if not, r_value is also set to zero. */
|
||||
bool BKE_view_layer_find_rgba_attribute(struct Scene *scene,
|
||||
struct ViewLayer *layer,
|
||||
const char *name,
|
||||
float r_value[4]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -11,15 +11,25 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
struct BMEditMesh;
|
||||
struct EditMeshData;
|
||||
|
||||
void BKE_editmesh_cache_ensure_poly_normals(struct BMEditMesh *em, struct EditMeshData *emd);
|
||||
void BKE_editmesh_cache_ensure_vert_normals(struct BMEditMesh *em, struct EditMeshData *emd);
|
||||
typedef struct EditMeshData {
|
||||
/** when set, \a vertexNos, polyNos are lazy initialized */
|
||||
const float (*vertexCos)[3];
|
||||
|
||||
void BKE_editmesh_cache_ensure_poly_centers(struct BMEditMesh *em, struct EditMeshData *emd);
|
||||
/** lazy initialize (when \a vertexCos is set) */
|
||||
float const (*vertexNos)[3];
|
||||
float const (*polyNos)[3];
|
||||
/** also lazy init but don't depend on \a vertexCos */
|
||||
const float (*polyCos)[3];
|
||||
} EditMeshData;
|
||||
|
||||
void BKE_editmesh_cache_ensure_poly_normals(struct BMEditMesh *em, EditMeshData *emd);
|
||||
void BKE_editmesh_cache_ensure_vert_normals(struct BMEditMesh *em, EditMeshData *emd);
|
||||
|
||||
void BKE_editmesh_cache_ensure_poly_centers(struct BMEditMesh *em, EditMeshData *emd);
|
||||
|
||||
bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em,
|
||||
struct EditMeshData *emd,
|
||||
EditMeshData *emd,
|
||||
float min[3],
|
||||
float max[3]);
|
||||
|
||||
|
|
|
@ -334,7 +334,7 @@ int *BKE_mesh_calc_smoothgroups(const struct MEdge *medge,
|
|||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace blender::mesh_topology {
|
||||
namespace blender::bke::mesh_topology {
|
||||
|
||||
Array<int> build_loop_to_poly_map(Span<MPoly> polys, int loops_num);
|
||||
|
||||
|
@ -346,5 +346,5 @@ inline int previous_poly_loop(const MPoly &poly, int loop_i)
|
|||
return loop_i - 1 + (loop_i == poly.loopstart) * poly.totloop;
|
||||
}
|
||||
|
||||
} // namespace blender::mesh_topology
|
||||
} // namespace blender::bke::mesh_topology
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
|
||||
//#include "BKE_customdata.h" /* for eCustomDataMask */
|
||||
#include "BKE_mesh_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -25,22 +26,11 @@ struct Mesh;
|
|||
struct Object;
|
||||
struct Scene;
|
||||
|
||||
/**
|
||||
* \brief Initialize the runtime of the given mesh.
|
||||
*
|
||||
* Function expects that the runtime is already cleared.
|
||||
*/
|
||||
void BKE_mesh_runtime_init_data(struct Mesh *mesh);
|
||||
/**
|
||||
* \brief Free all data (and mutexes) inside the runtime of the given mesh.
|
||||
*/
|
||||
void BKE_mesh_runtime_free_data(struct Mesh *mesh);
|
||||
/**
|
||||
* Clear all pointers which we don't want to be shared on copying the datablock.
|
||||
* However, keep all the flags which defines what the mesh is (for example, that
|
||||
* it's deformed only, or that its custom data layers are out of date.)
|
||||
*/
|
||||
void BKE_mesh_runtime_reset_on_copy(struct Mesh *mesh, int flag);
|
||||
|
||||
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh);
|
||||
void BKE_mesh_runtime_looptri_recalc(struct Mesh *mesh);
|
||||
/**
|
||||
|
@ -66,6 +56,11 @@ void BKE_mesh_runtime_verttri_from_looptri(struct MVertTri *r_verttri,
|
|||
const struct MLoopTri *looptri,
|
||||
int looptri_num);
|
||||
|
||||
/** \note Only used for access in C. */
|
||||
bool BKE_mesh_is_deformed_only(const struct Mesh *mesh);
|
||||
/** \note Only used for access in C. */
|
||||
eMeshWrapperType BKE_mesh_wrapper_type(const struct Mesh *mesh);
|
||||
|
||||
/* NOTE: the functions below are defined in DerivedMesh.cc, and are intended to be moved
|
||||
* to a more suitable location when that file is removed.
|
||||
* They should also be renamed to use conventions from BKE, not old DerivedMesh.cc.
|
||||
|
|
|
@ -1,11 +1,35 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2020 Blender Foundation. All rights reserved. */
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
# include <mutex>
|
||||
|
||||
# include "BLI_span.hh"
|
||||
|
||||
# include "DNA_customdata_types.h"
|
||||
|
||||
# include "MEM_guardedalloc.h"
|
||||
|
||||
struct BVHCache;
|
||||
struct EditMeshData;
|
||||
struct MLoopTri;
|
||||
struct ShrinkwrapBoundaryData;
|
||||
struct SubdivCCG;
|
||||
struct SubsurfRuntimeData;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum eMeshBatchDirtyMode {
|
||||
BKE_MESH_BATCH_DIRTY_ALL = 0,
|
||||
BKE_MESH_BATCH_DIRTY_SELECT,
|
||||
|
@ -14,3 +38,125 @@ typedef enum eMeshBatchDirtyMode {
|
|||
BKE_MESH_BATCH_DIRTY_UVEDIT_ALL,
|
||||
BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT,
|
||||
} eMeshBatchDirtyMode;
|
||||
|
||||
/** #MeshRuntime.wrapper_type */
|
||||
typedef enum eMeshWrapperType {
|
||||
/** Use mesh data (#Mesh.mvert, #Mesh.medge, #Mesh.mloop, #Mesh.mpoly). */
|
||||
ME_WRAPPER_TYPE_MDATA = 0,
|
||||
/** Use edit-mesh data (#Mesh.edit_mesh, #MeshRuntime.edit_data). */
|
||||
ME_WRAPPER_TYPE_BMESH = 1,
|
||||
/** Use subdivision mesh data (#MeshRuntime.mesh_eval). */
|
||||
ME_WRAPPER_TYPE_SUBD = 2,
|
||||
} eMeshWrapperType;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
/**
|
||||
* \warning Typical access is done via #Mesh::looptris().
|
||||
*/
|
||||
struct MLoopTri_Store {
|
||||
/* WARNING! swapping between array (ready-to-be-used data) and array_wip
|
||||
* (where data is actually computed)
|
||||
* shall always be protected by same lock as one used for looptris computing. */
|
||||
MLoopTri *array = nullptr;
|
||||
MLoopTri *array_wip = nullptr;
|
||||
int len = 0;
|
||||
int len_alloc = 0;
|
||||
};
|
||||
|
||||
struct MeshRuntime {
|
||||
/* Evaluated mesh for objects which do not have effective modifiers.
|
||||
* This mesh is used as a result of modifier stack evaluation.
|
||||
* Since modifier stack evaluation is threaded on object level we need some synchronization. */
|
||||
Mesh *mesh_eval = nullptr;
|
||||
std::mutex eval_mutex;
|
||||
|
||||
/* A separate mutex is needed for normal calculation, because sometimes
|
||||
* the normals are needed while #eval_mutex is already locked. */
|
||||
std::mutex normals_mutex;
|
||||
|
||||
/** Needed to ensure some thread-safety during render data pre-processing. */
|
||||
std::mutex render_mutex;
|
||||
|
||||
/** Lazily initialized SoA data from the #edit_mesh field in #Mesh. */
|
||||
EditMeshData *edit_data = nullptr;
|
||||
|
||||
/**
|
||||
* Data used to efficiently draw the mesh in the viewport, especially useful when
|
||||
* the same mesh is used in many objects or instances. See `draw_cache_impl_mesh.cc`.
|
||||
*/
|
||||
void *batch_cache = nullptr;
|
||||
|
||||
/** Cache for derived triangulation of the mesh. */
|
||||
MLoopTri_Store looptris;
|
||||
|
||||
/** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */
|
||||
BVHCache *bvh_cache = nullptr;
|
||||
|
||||
/** Cache of non-manifold boundary data for Shrinkwrap Target Project. */
|
||||
ShrinkwrapBoundaryData *shrinkwrap_data = nullptr;
|
||||
|
||||
/** Needed in case we need to lazily initialize the mesh. */
|
||||
CustomData_MeshMasks cd_mask_extra = {};
|
||||
|
||||
SubdivCCG *subdiv_ccg = nullptr;
|
||||
int subdiv_ccg_tot_level = 0;
|
||||
|
||||
/** Set by modifier stack if only deformed from original. */
|
||||
bool deformed_only = false;
|
||||
/**
|
||||
* Copied from edit-mesh (hint, draw with edit-mesh data when true).
|
||||
*
|
||||
* Modifiers that edit the mesh data in-place must set this to false
|
||||
* (most #eModifierTypeType_NonGeometrical modifiers). Otherwise the edit-mesh
|
||||
* data will be used for drawing, missing changes from modifiers. See T79517.
|
||||
*/
|
||||
bool is_original_bmesh = false;
|
||||
|
||||
/** #eMeshWrapperType and others. */
|
||||
eMeshWrapperType wrapper_type = ME_WRAPPER_TYPE_MDATA;
|
||||
/**
|
||||
* A type mask from wrapper_type,
|
||||
* in case there are differences in finalizing logic between types.
|
||||
*/
|
||||
eMeshWrapperType wrapper_type_finalize = ME_WRAPPER_TYPE_MDATA;
|
||||
|
||||
/**
|
||||
* Settings for lazily evaluating the subdivision on the CPU if needed. These are
|
||||
* set in the modifier when GPU subdivision can be performed, and owned by the by
|
||||
* the modifier in the object.
|
||||
*/
|
||||
SubsurfRuntimeData *subsurf_runtime_data = nullptr;
|
||||
|
||||
/**
|
||||
* Caches for lazily computed vertex and polygon normals. These are stored here rather than in
|
||||
* #CustomData because they can be calculated on a const mesh, and adding custom data layers on a
|
||||
* const mesh is not thread-safe.
|
||||
*/
|
||||
bool vert_normals_dirty = false;
|
||||
bool poly_normals_dirty = false;
|
||||
float (*vert_normals)[3] = nullptr;
|
||||
float (*poly_normals)[3] = nullptr;
|
||||
|
||||
/**
|
||||
* A #BLI_bitmap containing tags for the center vertices of subdivided polygons, set by the
|
||||
* subdivision surface modifier and used by drawing code instead of polygon center face dots.
|
||||
*/
|
||||
uint32_t *subsurf_face_dot_tags = nullptr;
|
||||
|
||||
MeshRuntime() = default;
|
||||
/** \warning This does not free all data currently. See #BKE_mesh_runtime_free_data. */
|
||||
~MeshRuntime() = default;
|
||||
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("MeshRuntime")
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
#endif
|
||||
|
|
|
@ -246,6 +246,24 @@ float BKE_nlastrip_compute_frame_from_previous_strip(struct NlaStrip *strip);
|
|||
*/
|
||||
float BKE_nlastrip_compute_frame_to_next_strip(struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* Returns the next strip in this strip's NLA track, or a null pointer.
|
||||
*
|
||||
* \param strip The strip to find the next trip from.
|
||||
* \param check_transitions Whether or not to skip transitions.
|
||||
* \return The next strip in the track, or NULL if none are present.
|
||||
*/
|
||||
struct NlaStrip *BKE_nlastrip_next_in_track(struct NlaStrip *strip, bool skip_transitions);
|
||||
|
||||
/**
|
||||
* Returns the previous strip in this strip's NLA track, or a null pointer.
|
||||
*
|
||||
* \param strip The strip to find the previous trip from.
|
||||
* \param check_transitions Whether or not to skip transitions.
|
||||
* \return The previous strip in the track, or NULL if none are present.
|
||||
*/
|
||||
struct NlaStrip *BKE_nlastrip_prev_in_track(struct NlaStrip *strip, bool skip_transitions);
|
||||
|
||||
/* ............ */
|
||||
|
||||
/**
|
||||
|
|
|
@ -124,6 +124,7 @@ typedef enum {
|
|||
PBVH_UpdateTopology = 1 << 13,
|
||||
PBVH_UpdateColor = 1 << 14,
|
||||
PBVH_RebuildPixels = 1 << 15,
|
||||
PBVH_TopologyUpdated = 1 << 16, /* Used internally by pbvh_bmesh.c */
|
||||
|
||||
} PBVHNodeFlags;
|
||||
|
||||
|
@ -481,7 +482,10 @@ struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
|
|||
*
|
||||
* Skips triangles that are hidden.
|
||||
*/
|
||||
void BKE_pbvh_bmesh_node_save_orig(struct BMesh *bm, PBVHNode *node);
|
||||
void BKE_pbvh_bmesh_node_save_orig(struct BMesh *bm,
|
||||
struct BMLog *log,
|
||||
PBVHNode *node,
|
||||
bool use_original);
|
||||
void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh);
|
||||
|
||||
/* Update Bounding Box/Redraw and clear flags. */
|
||||
|
@ -659,7 +663,8 @@ void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot);
|
|||
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
|
||||
int (**r_orco_tris)[3],
|
||||
int *r_orco_tris_num,
|
||||
float (**r_orco_coords)[3]);
|
||||
float (**r_orco_coords)[3],
|
||||
struct BMVert ***r_orco_verts);
|
||||
|
||||
/**
|
||||
* \note doing a full search on all vertices here seems expensive,
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "BKE_colorband.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_editmesh_cache.h"
|
||||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_geometry_set_instances.hh"
|
||||
#include "BKE_key.h"
|
||||
|
@ -534,7 +535,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
|
|||
(final_datamask->lmask & CD_MASK_NORMAL) != 0);
|
||||
|
||||
/* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */
|
||||
SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime.subsurf_runtime_data;
|
||||
SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data;
|
||||
if (subsurf_runtime_data) {
|
||||
subsurf_runtime_data->calc_loop_normals = calc_loop_normals;
|
||||
}
|
||||
|
@ -582,11 +583,12 @@ static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval)
|
|||
void BKE_mesh_wrapper_deferred_finalize_mdata(Mesh *me_eval,
|
||||
const CustomData_MeshMasks *cd_mask_finalize)
|
||||
{
|
||||
if (me_eval->runtime.wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) {
|
||||
if (me_eval->runtime->wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) {
|
||||
editbmesh_calc_modifier_final_normals(me_eval, cd_mask_finalize);
|
||||
me_eval->runtime.wrapper_type_finalize &= ~(1 << ME_WRAPPER_TYPE_BMESH);
|
||||
me_eval->runtime->wrapper_type_finalize = eMeshWrapperType(
|
||||
me_eval->runtime->wrapper_type_finalize & ~(1 << ME_WRAPPER_TYPE_BMESH));
|
||||
}
|
||||
BLI_assert(me_eval->runtime.wrapper_type_finalize == 0);
|
||||
BLI_assert(me_eval->runtime->wrapper_type_finalize == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1047,7 +1049,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
append_mask.lmask |= CD_MASK_PREVIEW_MLOOPCOL;
|
||||
}
|
||||
|
||||
mesh_final->runtime.deformed_only = false;
|
||||
mesh_final->runtime->deformed_only = false;
|
||||
}
|
||||
|
||||
isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
|
||||
|
@ -1114,10 +1116,9 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
mesh_calc_finalize(mesh_input, mesh_final);
|
||||
}
|
||||
else {
|
||||
Mesh_Runtime *runtime = &mesh_input->runtime;
|
||||
blender::bke::MeshRuntime *runtime = mesh_input->runtime;
|
||||
if (runtime->mesh_eval == nullptr) {
|
||||
BLI_assert(runtime->eval_mutex != nullptr);
|
||||
BLI_mutex_lock((ThreadMutex *)runtime->eval_mutex);
|
||||
std::lock_guard lock{mesh_input->runtime->eval_mutex};
|
||||
if (runtime->mesh_eval == nullptr) {
|
||||
/* Not yet finalized by any instance, do it now
|
||||
* Isolate since computing normals is multithreaded and we are holding a lock. */
|
||||
|
@ -1133,7 +1134,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
/* Already finalized by another instance, reuse. */
|
||||
mesh_final = runtime->mesh_eval;
|
||||
}
|
||||
BLI_mutex_unlock((ThreadMutex *)runtime->eval_mutex);
|
||||
}
|
||||
else if (!mesh_has_modifier_final_normals(mesh_input, &final_datamask, runtime->mesh_eval)) {
|
||||
/* Modifier stack was (re-)evaluated with a request for additional normals
|
||||
|
@ -1202,7 +1202,7 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
|
|||
const bool calc_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 ||
|
||||
(final_datamask->lmask & CD_MASK_NORMAL) != 0);
|
||||
|
||||
SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime.subsurf_runtime_data;
|
||||
SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data;
|
||||
if (subsurf_runtime_data) {
|
||||
subsurf_runtime_data->calc_loop_normals = calc_loop_normals;
|
||||
}
|
||||
|
@ -1229,9 +1229,10 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
|
|||
static void editbmesh_calc_modifier_final_normals_or_defer(
|
||||
Mesh *mesh_final, const CustomData_MeshMasks *final_datamask)
|
||||
{
|
||||
if (mesh_final->runtime.wrapper_type != ME_WRAPPER_TYPE_MDATA) {
|
||||
if (mesh_final->runtime->wrapper_type != ME_WRAPPER_TYPE_MDATA) {
|
||||
/* Generated at draw time. */
|
||||
mesh_final->runtime.wrapper_type_finalize = (1 << mesh_final->runtime.wrapper_type);
|
||||
mesh_final->runtime->wrapper_type_finalize = eMeshWrapperType(
|
||||
1 << mesh_final->runtime->wrapper_type);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1445,7 +1446,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
deformed_verts = nullptr;
|
||||
}
|
||||
}
|
||||
mesh_final->runtime.deformed_only = false;
|
||||
mesh_final->runtime->deformed_only = false;
|
||||
}
|
||||
|
||||
if (r_cage && i == cageIndex) {
|
||||
|
@ -1464,7 +1465,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
if (!BKE_mesh_runtime_ensure_edit_data(me_orig)) {
|
||||
BKE_mesh_runtime_reset_edit_data(me_orig);
|
||||
}
|
||||
me_orig->runtime.edit_data->vertexCos = (const float(*)[3])MEM_dupallocN(deformed_verts);
|
||||
me_orig->runtime->edit_data->vertexCos = (const float(*)[3])MEM_dupallocN(
|
||||
deformed_verts);
|
||||
}
|
||||
mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords(
|
||||
em_input,
|
||||
|
@ -1578,7 +1580,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph,
|
|||
* object's runtime: this could cause access freed data on depsgraph destruction (mesh who owns
|
||||
* the final result might be freed prior to object). */
|
||||
Mesh *mesh = (Mesh *)ob->data;
|
||||
const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime.mesh_eval);
|
||||
const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime->mesh_eval);
|
||||
BKE_object_eval_assign_data(ob, &mesh_eval->id, is_mesh_eval_owned);
|
||||
|
||||
/* Add the final mesh as a non-owning component to the geometry set. */
|
||||
|
@ -1638,7 +1640,7 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph,
|
|||
}
|
||||
}
|
||||
|
||||
const bool is_mesh_eval_owned = (me_final != mesh->runtime.mesh_eval);
|
||||
const bool is_mesh_eval_owned = (me_final != mesh->runtime->mesh_eval);
|
||||
BKE_object_eval_assign_data(obedit, &me_final->id, is_mesh_eval_owned);
|
||||
|
||||
obedit->runtime.editmesh_eval_cage = me_cage;
|
||||
|
@ -1894,7 +1896,7 @@ struct MappedUserData {
|
|||
static void make_vertexcos__mapFunc(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no[3]))
|
||||
const float /*no*/[3])
|
||||
{
|
||||
MappedUserData *mappedData = (MappedUserData *)userData;
|
||||
|
||||
|
@ -1909,7 +1911,7 @@ static void make_vertexcos__mapFunc(void *userData,
|
|||
|
||||
void mesh_get_mapped_verts_coords(Mesh *me_eval, float (*r_cos)[3], const int totcos)
|
||||
{
|
||||
if (me_eval->runtime.deformed_only == false) {
|
||||
if (me_eval->runtime->deformed_only == false) {
|
||||
MappedUserData userData;
|
||||
memset(r_cos, 0, sizeof(*r_cos) * totcos);
|
||||
userData.vertexcos = r_cos;
|
||||
|
|
|
@ -52,13 +52,13 @@ struct BVHCache {
|
|||
* When the `r_locked` is filled and the tree could not be found the caches mutex will be
|
||||
* locked. This mutex can be unlocked by calling `bvhcache_unlock`.
|
||||
*
|
||||
* When `r_locked` is used the `mesh_eval_mutex` must contain the `Mesh_Runtime.eval_mutex`.
|
||||
* When `r_locked` is used the `mesh_eval_mutex` must contain the `MeshRuntime.eval_mutex`.
|
||||
*/
|
||||
static bool bvhcache_find(BVHCache **bvh_cache_p,
|
||||
BVHCacheType type,
|
||||
BVHTree **r_tree,
|
||||
bool *r_locked,
|
||||
ThreadMutex *mesh_eval_mutex)
|
||||
std::mutex *mesh_eval_mutex)
|
||||
{
|
||||
bool do_lock = r_locked;
|
||||
if (r_locked) {
|
||||
|
@ -70,11 +70,10 @@ static bool bvhcache_find(BVHCache **bvh_cache_p,
|
|||
return false;
|
||||
}
|
||||
/* Lazy initialization of the bvh_cache using the `mesh_eval_mutex`. */
|
||||
BLI_mutex_lock(mesh_eval_mutex);
|
||||
std::lock_guard lock{*mesh_eval_mutex};
|
||||
if (*bvh_cache_p == nullptr) {
|
||||
*bvh_cache_p = bvhcache_init();
|
||||
}
|
||||
BLI_mutex_unlock(mesh_eval_mutex);
|
||||
}
|
||||
BVHCache *bvh_cache = *bvh_cache_p;
|
||||
|
||||
|
@ -1222,8 +1221,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
|
|||
const BVHCacheType bvh_cache_type,
|
||||
const int tree_type)
|
||||
{
|
||||
BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime.bvh_cache;
|
||||
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
|
||||
BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime->bvh_cache;
|
||||
|
||||
const MLoopTri *looptri = nullptr;
|
||||
int looptri_len = 0;
|
||||
|
@ -1249,7 +1247,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
|
|||
|
||||
bool lock_started = false;
|
||||
data->cached = bvhcache_find(
|
||||
bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, mesh_eval_mutex);
|
||||
bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, &mesh->runtime->eval_mutex);
|
||||
|
||||
if (data->cached) {
|
||||
BLI_assert(lock_started == false);
|
||||
|
@ -1352,7 +1350,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
|
|||
const int tree_type,
|
||||
const BVHCacheType bvh_cache_type,
|
||||
BVHCache **bvh_cache_p,
|
||||
ThreadMutex *mesh_eval_mutex)
|
||||
std::mutex *mesh_eval_mutex)
|
||||
{
|
||||
bool lock_started = false;
|
||||
|
||||
|
|
|
@ -825,7 +825,7 @@ static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mes
|
|||
const MLoop *mloop = BKE_mesh_loops(mesh);
|
||||
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh);
|
||||
const uint mvert_num = mesh->totvert;
|
||||
const uint looptri_num = mesh->runtime.looptris.len;
|
||||
const uint looptri_num = BKE_mesh_runtime_looptri_len(mesh);
|
||||
|
||||
/* Allocate our vertices. */
|
||||
clmd->clothObject->mvert_num = mvert_num;
|
||||
|
|
|
@ -2386,16 +2386,21 @@ static bool attribute_stored_in_bmesh_flag(const StringRef name)
|
|||
"material_index");
|
||||
}
|
||||
|
||||
static CustomData shallow_copy_remove_non_bmesh_attributes(const CustomData &src)
|
||||
CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src,
|
||||
const eCustomDataMask mask)
|
||||
{
|
||||
Vector<CustomDataLayer> dst_layers;
|
||||
for (const CustomDataLayer &layer : Span<CustomDataLayer>{src.layers, src.totlayer}) {
|
||||
if (!attribute_stored_in_bmesh_flag(layer.name)) {
|
||||
dst_layers.append(layer);
|
||||
for (const CustomDataLayer &layer : Span<CustomDataLayer>{src->layers, src->totlayer}) {
|
||||
if (attribute_stored_in_bmesh_flag(layer.name)) {
|
||||
continue;
|
||||
}
|
||||
if (!(mask & CD_TYPE_AS_MASK(layer.type))) {
|
||||
continue;
|
||||
}
|
||||
dst_layers.append(layer);
|
||||
}
|
||||
|
||||
CustomData dst = src;
|
||||
CustomData dst = *src;
|
||||
dst.layers = static_cast<CustomDataLayer *>(
|
||||
MEM_calloc_arrayN(dst_layers.size(), sizeof(CustomDataLayer), __func__));
|
||||
dst.totlayer = dst_layers.size();
|
||||
|
@ -2406,18 +2411,6 @@ static CustomData shallow_copy_remove_non_bmesh_attributes(const CustomData &src
|
|||
return dst;
|
||||
}
|
||||
|
||||
bool CustomData_merge_mesh_to_bmesh(const CustomData *source,
|
||||
CustomData *dest,
|
||||
const eCustomDataMask mask,
|
||||
const eCDAllocType alloctype,
|
||||
const int totelem)
|
||||
{
|
||||
CustomData source_copy = shallow_copy_remove_non_bmesh_attributes(*source);
|
||||
const bool result = CustomData_merge(&source_copy, dest, mask, alloctype, totelem);
|
||||
MEM_SAFE_FREE(source_copy.layers);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CustomData_realloc(CustomData *data, const int old_size, const int new_size)
|
||||
{
|
||||
BLI_assert(new_size >= 0);
|
||||
|
@ -2467,17 +2460,6 @@ void CustomData_copy(const CustomData *source,
|
|||
CustomData_merge(source, dest, mask, alloctype, totelem);
|
||||
}
|
||||
|
||||
void CustomData_copy_mesh_to_bmesh(const CustomData *source,
|
||||
CustomData *dest,
|
||||
const eCustomDataMask mask,
|
||||
const eCDAllocType alloctype,
|
||||
const int totelem)
|
||||
{
|
||||
CustomData source_copy = shallow_copy_remove_non_bmesh_attributes(*source);
|
||||
CustomData_copy(&source_copy, dest, mask, alloctype, totelem);
|
||||
MEM_SAFE_FREE(source_copy.layers);
|
||||
}
|
||||
|
||||
static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem)
|
||||
{
|
||||
const LayerTypeInfo *typeInfo;
|
||||
|
@ -3701,7 +3683,7 @@ bool CustomData_bmesh_merge(const CustomData *source,
|
|||
destold.layers = static_cast<CustomDataLayer *>(MEM_dupallocN(destold.layers));
|
||||
}
|
||||
|
||||
if (CustomData_merge_mesh_to_bmesh(source, dest, mask, alloctype, 0) == false) {
|
||||
if (CustomData_merge(source, dest, mask, alloctype, 0) == false) {
|
||||
if (destold.layers) {
|
||||
MEM_freeN(destold.layers);
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ struct CageUserData {
|
|||
static void cage_mapped_verts_callback(void *userData,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no[3]))
|
||||
const float /*no*/[3])
|
||||
{
|
||||
CageUserData *data = static_cast<CageUserData *>(userData);
|
||||
|
||||
|
@ -240,12 +240,12 @@ const float (*BKE_editmesh_vert_coords_when_deformed(Depsgraph *depsgraph,
|
|||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object_eval);
|
||||
|
||||
if ((me->runtime.edit_data != nullptr) && (me->runtime.edit_data->vertexCos != nullptr)) {
|
||||
if ((me->runtime->edit_data != nullptr) && (me->runtime->edit_data->vertexCos != nullptr)) {
|
||||
/* Deformed, and we have deformed coords already. */
|
||||
coords = me->runtime.edit_data->vertexCos;
|
||||
coords = me->runtime->edit_data->vertexCos;
|
||||
}
|
||||
else if ((editmesh_eval_final != nullptr) &&
|
||||
(editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
|
||||
(editmesh_eval_final->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
|
||||
/* If this is an edit-mesh type, leave nullptr as we can use the vertex coords. */
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_mapping.h"
|
||||
|
||||
#include "FN_multi_function_builder.hh"
|
||||
|
||||
|
@ -213,11 +214,15 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
|
|||
}
|
||||
|
||||
/* Deselect loose vertices without corners that are still selected from the 'true' default. */
|
||||
for (const int vert_index : IndexRange(mesh.totvert)) {
|
||||
if (loose_verts[vert_index]) {
|
||||
r_values[vert_index] = false;
|
||||
/* The record fact says that the value is true.
|
||||
*Writing to the array from different threads is okay because each thread sets the same value. */
|
||||
threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int vert_index : range) {
|
||||
if (loose_verts[vert_index]) {
|
||||
r_values[vert_index] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray)
|
||||
|
@ -413,16 +418,16 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
|
|||
const Span<MLoop> loops = mesh.loops();
|
||||
|
||||
r_values.fill(false);
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const MPoly &poly = polys[poly_index];
|
||||
if (old_values[poly_index]) {
|
||||
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
|
||||
const MLoop &loop = loops[loop_index];
|
||||
const int vert_index = loop.v;
|
||||
r_values[vert_index] = true;
|
||||
threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int poly_index : range) {
|
||||
if (old_values[poly_index]) {
|
||||
const MPoly &poly = polys[poly_index];
|
||||
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
|
||||
r_values[loop.v] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static GVArray adapt_mesh_domain_face_to_point(const Mesh &mesh, const GVArray &varray)
|
||||
|
@ -502,16 +507,16 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
|
|||
const Span<MLoop> loops = mesh.loops();
|
||||
|
||||
r_values.fill(false);
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const MPoly &poly = polys[poly_index];
|
||||
if (old_values[poly_index]) {
|
||||
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
|
||||
const MLoop &loop = loops[loop_index];
|
||||
const int edge_index = loop.e;
|
||||
r_values[edge_index] = true;
|
||||
threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int poly_index : range) {
|
||||
if (old_values[poly_index]) {
|
||||
const MPoly &poly = polys[poly_index];
|
||||
for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
|
||||
r_values[loop.e] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray)
|
||||
|
@ -619,7 +624,7 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
|
|||
|
||||
/* For every corner, mix the values from the adjacent edges on the face. */
|
||||
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
|
||||
const int loop_index_prev = loop_index - 1 + (loop_index == poly.loopstart) * poly.totloop;
|
||||
const int loop_index_prev = mesh_topology::previous_poly_loop(poly, loop_index);
|
||||
const MLoop &loop = loops[loop_index];
|
||||
const MLoop &loop_prev = loops[loop_index_prev];
|
||||
mixer.mix_in(loop_index, old_values[loop.e]);
|
||||
|
@ -642,17 +647,19 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
|
|||
|
||||
r_values.fill(false);
|
||||
|
||||
for (const int poly_index : polys.index_range()) {
|
||||
const MPoly &poly = polys[poly_index];
|
||||
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
|
||||
const int loop_index_prev = loop_index - 1 + (loop_index == poly.loopstart) * poly.totloop;
|
||||
const MLoop &loop = loops[loop_index];
|
||||
const MLoop &loop_prev = loops[loop_index_prev];
|
||||
if (old_values[loop.e] && old_values[loop_prev.e]) {
|
||||
r_values[loop_index] = true;
|
||||
threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
|
||||
for (const int poly_index : range) {
|
||||
const MPoly &poly = polys[poly_index];
|
||||
for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
|
||||
const int loop_index_prev = mesh_topology::previous_poly_loop(poly, loop_index);
|
||||
const MLoop &loop = loops[loop_index];
|
||||
const MLoop &loop_prev = loops[loop_index_prev];
|
||||
if (old_values[loop.e] && old_values[loop_prev.e]) {
|
||||
r_values[loop_index] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static GVArray adapt_mesh_domain_edge_to_corner(const Mesh &mesh, const GVArray &varray)
|
||||
|
@ -697,14 +704,18 @@ void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh,
|
|||
BLI_assert(r_values.size() == mesh.totvert);
|
||||
const Span<MEdge> edges = mesh.edges();
|
||||
|
||||
/* Multiple threads can write to the same index here, but they are only
|
||||
* writing true, and writing to single bytes is expected to be threadsafe. */
|
||||
r_values.fill(false);
|
||||
for (const int edge_index : edges.index_range()) {
|
||||
const MEdge &edge = edges[edge_index];
|
||||
if (old_values[edge_index]) {
|
||||
r_values[edge.v1] = true;
|
||||
r_values[edge.v2] = true;
|
||||
threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
|
||||
for (const int edge_index : range) {
|
||||
if (old_values[edge_index]) {
|
||||
const MEdge &edge = edges[edge_index];
|
||||
r_values[edge.v1] = true;
|
||||
r_values[edge.v2] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray)
|
||||
|
|
|
@ -1856,6 +1856,10 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps)
|
|||
pt->strength = interpf(pt2->strength, pt1->strength, step);
|
||||
pt->flag = 0;
|
||||
interp_v4_v4v4(pt->vert_color, pt1->vert_color, pt2->vert_color, step);
|
||||
/* Set point as selected. */
|
||||
if (gps->flag & GP_STROKE_SELECT) {
|
||||
pt->flag |= GP_SPOINT_SELECT;
|
||||
}
|
||||
|
||||
/* Set weights. */
|
||||
if (gps->dvert != nullptr) {
|
||||
|
|
|
@ -1495,7 +1495,7 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
|
|||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
normalize_v3(process.no[i]);
|
||||
}
|
||||
mesh->runtime.vert_normals = process.no;
|
||||
mesh->runtime->vert_normals = process.no;
|
||||
BKE_mesh_vertex_normals_clear_dirty(mesh);
|
||||
|
||||
mesh->totloop = loop_offset;
|
||||
|
|
|
@ -91,7 +91,7 @@ static void mesh_init_data(ID *id)
|
|||
CustomData_reset(&mesh->pdata);
|
||||
CustomData_reset(&mesh->ldata);
|
||||
|
||||
BKE_mesh_runtime_init_data(mesh);
|
||||
mesh->runtime = new blender::bke::MeshRuntime();
|
||||
|
||||
/* A newly created mesh does not have normals, so tag them dirty. This will be cleared
|
||||
* by #BKE_mesh_vertex_normals_clear_dirty or #BKE_mesh_poly_normals_ensure. */
|
||||
|
@ -105,14 +105,19 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
|
|||
Mesh *mesh_dst = (Mesh *)id_dst;
|
||||
const Mesh *mesh_src = (const Mesh *)id_src;
|
||||
|
||||
BKE_mesh_runtime_reset_on_copy(mesh_dst, flag);
|
||||
mesh_dst->runtime = new blender::bke::MeshRuntime();
|
||||
mesh_dst->runtime->deformed_only = mesh_src->runtime->deformed_only;
|
||||
mesh_dst->runtime->wrapper_type = mesh_src->runtime->wrapper_type;
|
||||
mesh_dst->runtime->wrapper_type_finalize = mesh_src->runtime->wrapper_type_finalize;
|
||||
mesh_dst->runtime->subsurf_runtime_data = mesh_src->runtime->subsurf_runtime_data;
|
||||
mesh_dst->runtime->cd_mask_extra = mesh_src->runtime->cd_mask_extra;
|
||||
/* Copy face dot tags, since meshes may be duplicated after a subsurf modifier
|
||||
* or node, but we still need to be able to draw face center vertices. */
|
||||
mesh_dst->runtime.subsurf_face_dot_tags = static_cast<uint32_t *>(
|
||||
MEM_dupallocN(mesh_src->runtime.subsurf_face_dot_tags));
|
||||
mesh_dst->runtime->subsurf_face_dot_tags = static_cast<uint32_t *>(
|
||||
MEM_dupallocN(mesh_src->runtime->subsurf_face_dot_tags));
|
||||
if ((mesh_src->id.tag & LIB_TAG_NO_MAIN) == 0) {
|
||||
/* This is a direct copy of a main mesh, so for now it has the same topology. */
|
||||
mesh_dst->runtime.deformed_only = true;
|
||||
mesh_dst->runtime->deformed_only = true;
|
||||
}
|
||||
/* This option is set for run-time meshes that have been copied from the current objects mode.
|
||||
* Currently this is used for edit-mesh although it could be used for sculpt or other
|
||||
|
@ -123,7 +128,7 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
|
|||
*
|
||||
* While this could be the callers responsibility, keep here since it's
|
||||
* highly unlikely we want to create a duplicate and not use it for drawing. */
|
||||
mesh_dst->runtime.is_original_bmesh = false;
|
||||
mesh_dst->runtime->is_original_bmesh = false;
|
||||
|
||||
/* Only do tessface if we have no polys. */
|
||||
const bool do_tessface = ((mesh_src->totface != 0) && (mesh_src->totpoly == 0));
|
||||
|
@ -196,6 +201,8 @@ static void mesh_free_data(ID *id)
|
|||
BKE_mesh_runtime_free_data(mesh);
|
||||
mesh_clear_geometry(mesh);
|
||||
MEM_SAFE_FREE(mesh->mat);
|
||||
|
||||
delete mesh->runtime;
|
||||
}
|
||||
|
||||
static void mesh_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
|
@ -232,7 +239,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
|
|||
mesh->mface = nullptr;
|
||||
mesh->totface = 0;
|
||||
memset(&mesh->fdata, 0, sizeof(mesh->fdata));
|
||||
mesh->runtime = blender::dna::shallow_zero_initialize();
|
||||
mesh->runtime = nullptr;
|
||||
|
||||
/* Do not store actual geometry data in case this is a library override ID. */
|
||||
if (ID_IS_OVERRIDE_LIBRARY(mesh) && !is_undo) {
|
||||
|
@ -345,8 +352,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
mesh->texflag &= ~ME_AUTOSPACE_EVALUATED;
|
||||
mesh->edit_mesh = nullptr;
|
||||
|
||||
mesh->runtime = blender::dna::shallow_zero_initialize();
|
||||
BKE_mesh_runtime_init_data(mesh);
|
||||
mesh->runtime = new blender::bke::MeshRuntime();
|
||||
|
||||
/* happens with old files */
|
||||
if (mesh->mselect == nullptr) {
|
||||
|
@ -1132,7 +1138,7 @@ static void ensure_orig_index_layer(CustomData &data, const int size)
|
|||
|
||||
void BKE_mesh_ensure_default_orig_index_customdata(Mesh *mesh)
|
||||
{
|
||||
BLI_assert(mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA);
|
||||
BLI_assert(mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_MDATA);
|
||||
BKE_mesh_ensure_default_orig_index_customdata_no_check(mesh);
|
||||
}
|
||||
|
||||
|
@ -2082,8 +2088,8 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
|
|||
}
|
||||
|
||||
/* Update normals manually to avoid recalculation after this operation. */
|
||||
mesh->runtime.vert_normals = (float(*)[3])MEM_reallocN(mesh->runtime.vert_normals,
|
||||
sizeof(float[3]) * mesh->totvert);
|
||||
mesh->runtime->vert_normals = (float(*)[3])MEM_reallocN(mesh->runtime->vert_normals,
|
||||
sizeof(float[3]) * mesh->totvert);
|
||||
|
||||
/* Perform actual split of vertices and edges. */
|
||||
split_faces_split_new_verts(mesh, new_verts, num_new_verts);
|
||||
|
@ -2117,10 +2123,10 @@ void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)
|
|||
/* We are here because something did change in the mesh. This means we can not trust the existing
|
||||
* evaluated mesh, and we don't know what parts of the mesh did change. So we simply delete the
|
||||
* evaluated mesh and let objects to re-create it with updated settings. */
|
||||
if (mesh->runtime.mesh_eval != nullptr) {
|
||||
mesh->runtime.mesh_eval->edit_mesh = nullptr;
|
||||
BKE_id_free(nullptr, mesh->runtime.mesh_eval);
|
||||
mesh->runtime.mesh_eval = nullptr;
|
||||
if (mesh->runtime->mesh_eval != nullptr) {
|
||||
mesh->runtime->mesh_eval->edit_mesh = nullptr;
|
||||
BKE_id_free(nullptr, mesh->runtime->mesh_eval);
|
||||
mesh->runtime->mesh_eval = nullptr;
|
||||
}
|
||||
if (DEG_is_active(depsgraph)) {
|
||||
Mesh *mesh_orig = (Mesh *)DEG_get_original_id(&mesh->id);
|
||||
|
|
|
@ -881,7 +881,7 @@ static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh)
|
|||
{
|
||||
/* While we could copy this into the new mesh,
|
||||
* add the data to 'mesh' so future calls to this function don't need to re-convert the data. */
|
||||
if (mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
||||
if (mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
||||
BKE_mesh_wrapper_ensure_mdata(mesh);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -41,9 +41,9 @@ char *BKE_mesh_debug_info(const Mesh *me)
|
|||
BLI_dynstr_appendf(dynstr, " 'totface': %d,\n", me->totface);
|
||||
BLI_dynstr_appendf(dynstr, " 'totpoly': %d,\n", me->totpoly);
|
||||
|
||||
BLI_dynstr_appendf(dynstr, " 'runtime.deformed_only': %d,\n", me->runtime.deformed_only);
|
||||
BLI_dynstr_appendf(dynstr, " 'runtime.deformed_only': %d,\n", me->runtime->deformed_only);
|
||||
BLI_dynstr_appendf(
|
||||
dynstr, " 'runtime.is_original_bmesh': %d,\n", me->runtime.is_original_bmesh);
|
||||
dynstr, " 'runtime->is_original_bmesh': %d,\n", me->runtime->is_original_bmesh);
|
||||
|
||||
BLI_dynstr_append(dynstr, " 'vert_layers': (\n");
|
||||
CustomData_debug_info_from_layers(&me->vdata, indent8, dynstr);
|
||||
|
|
|
@ -222,7 +222,7 @@ class MeshFairingContext : public FairingContext {
|
|||
}
|
||||
}
|
||||
|
||||
loop_to_poly_map_ = blender::mesh_topology::build_loop_to_poly_map(mpoly_, mloop_.size());
|
||||
loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(mpoly_, mloop_.size());
|
||||
}
|
||||
|
||||
~MeshFairingContext() override
|
||||
|
|
|
@ -36,18 +36,18 @@ void BKE_mesh_foreach_mapped_vert(
|
|||
void *userData,
|
||||
MeshForeachFlag flag)
|
||||
{
|
||||
if (mesh->edit_mesh != nullptr && mesh->runtime.edit_data != nullptr) {
|
||||
if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data != nullptr) {
|
||||
BMEditMesh *em = mesh->edit_mesh;
|
||||
BMesh *bm = em->bm;
|
||||
BMIter iter;
|
||||
BMVert *eve;
|
||||
int i;
|
||||
if (mesh->runtime.edit_data->vertexCos != nullptr) {
|
||||
const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
|
||||
if (mesh->runtime->edit_data->vertexCos != nullptr) {
|
||||
const float(*vertexCos)[3] = mesh->runtime->edit_data->vertexCos;
|
||||
const float(*vertexNos)[3];
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
BKE_editmesh_cache_ensure_vert_normals(em, mesh->runtime.edit_data);
|
||||
vertexNos = mesh->runtime.edit_data->vertexNos;
|
||||
BKE_editmesh_cache_ensure_vert_normals(em, mesh->runtime->edit_data);
|
||||
vertexNos = mesh->runtime->edit_data->vertexNos;
|
||||
}
|
||||
else {
|
||||
vertexNos = nullptr;
|
||||
|
@ -96,14 +96,14 @@ void BKE_mesh_foreach_mapped_edge(
|
|||
void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
|
||||
void *userData)
|
||||
{
|
||||
if (mesh->edit_mesh != nullptr && mesh->runtime.edit_data) {
|
||||
if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data) {
|
||||
BMEditMesh *em = mesh->edit_mesh;
|
||||
BMesh *bm = em->bm;
|
||||
BMIter iter;
|
||||
BMEdge *eed;
|
||||
int i;
|
||||
if (mesh->runtime.edit_data->vertexCos != nullptr) {
|
||||
const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
|
||||
if (mesh->runtime->edit_data->vertexCos != nullptr) {
|
||||
const float(*vertexCos)[3] = mesh->runtime->edit_data->vertexCos;
|
||||
BM_mesh_elem_index_ensure(bm, BM_VERT);
|
||||
|
||||
BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
|
||||
|
@ -154,13 +154,13 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
|
|||
/* We can't use `dm->getLoopDataLayout(dm)` here,
|
||||
* we want to always access `dm->loopData`, `EditDerivedBMesh` would
|
||||
* return loop data from BMesh itself. */
|
||||
if (mesh->edit_mesh != nullptr && mesh->runtime.edit_data) {
|
||||
if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data) {
|
||||
BMEditMesh *em = mesh->edit_mesh;
|
||||
BMesh *bm = em->bm;
|
||||
BMIter iter;
|
||||
BMFace *efa;
|
||||
|
||||
const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
|
||||
const float(*vertexCos)[3] = mesh->runtime->edit_data->vertexCos;
|
||||
|
||||
/* XXX: investigate using EditMesh data. */
|
||||
const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
|
||||
|
@ -231,7 +231,7 @@ void BKE_mesh_foreach_mapped_face_center(
|
|||
void *userData,
|
||||
MeshForeachFlag flag)
|
||||
{
|
||||
if (mesh->edit_mesh != nullptr && mesh->runtime.edit_data != nullptr) {
|
||||
if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data != nullptr) {
|
||||
BMEditMesh *em = mesh->edit_mesh;
|
||||
BMesh *bm = em->bm;
|
||||
const float(*polyCos)[3];
|
||||
|
@ -240,12 +240,12 @@ void BKE_mesh_foreach_mapped_face_center(
|
|||
BMIter iter;
|
||||
int i;
|
||||
|
||||
BKE_editmesh_cache_ensure_poly_centers(em, mesh->runtime.edit_data);
|
||||
polyCos = mesh->runtime.edit_data->polyCos; /* always set */
|
||||
BKE_editmesh_cache_ensure_poly_centers(em, mesh->runtime->edit_data);
|
||||
polyCos = mesh->runtime->edit_data->polyCos; /* always set */
|
||||
|
||||
if (flag & MESH_FOREACH_USE_NORMAL) {
|
||||
BKE_editmesh_cache_ensure_poly_normals(em, mesh->runtime.edit_data);
|
||||
polyNos = mesh->runtime.edit_data->polyNos; /* maybe nullptr */
|
||||
BKE_editmesh_cache_ensure_poly_normals(em, mesh->runtime->edit_data);
|
||||
polyNos = mesh->runtime->edit_data->polyNos; /* maybe nullptr */
|
||||
}
|
||||
else {
|
||||
polyNos = nullptr;
|
||||
|
@ -316,7 +316,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
|
|||
BKE_mesh_vertex_normals_ensure(mesh) :
|
||||
nullptr;
|
||||
const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX));
|
||||
const BLI_bitmap *facedot_tags = mesh->runtime.subsurf_face_dot_tags;
|
||||
const BLI_bitmap *facedot_tags = mesh->runtime->subsurf_face_dot_tags;
|
||||
BLI_assert(facedot_tags != nullptr);
|
||||
|
||||
if (index) {
|
||||
|
@ -361,7 +361,7 @@ struct MappedVCosData {
|
|||
static void get_vertexcos__mapFunc(void *user_data,
|
||||
int index,
|
||||
const float co[3],
|
||||
const float UNUSED(no[3]))
|
||||
const float /*no*/[3])
|
||||
{
|
||||
MappedVCosData *mapped_vcos_data = (MappedVCosData *)user_data;
|
||||
|
||||
|
|
|
@ -552,7 +552,7 @@ void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
|
|||
*r_mem = indices;
|
||||
}
|
||||
|
||||
namespace blender::mesh_topology {
|
||||
namespace blender::bke::mesh_topology {
|
||||
|
||||
Array<int> build_loop_to_poly_map(const Span<MPoly> polys, const int loops_num)
|
||||
{
|
||||
|
@ -585,7 +585,7 @@ Array<Vector<int>> build_vert_to_loop_map(const Span<MLoop> loops, const int ver
|
|||
return map;
|
||||
}
|
||||
|
||||
} // namespace blender::mesh_topology
|
||||
} // namespace blender::bke::mesh_topology
|
||||
|
||||
/** \} */
|
||||
|
||||
|
|
|
@ -96,72 +96,72 @@ static void add_v3_v3_atomic(float r[3], const float a[3])
|
|||
|
||||
void BKE_mesh_normals_tag_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime.vert_normals_dirty = true;
|
||||
mesh->runtime.poly_normals_dirty = true;
|
||||
mesh->runtime->vert_normals_dirty = true;
|
||||
mesh->runtime->poly_normals_dirty = true;
|
||||
}
|
||||
|
||||
float (*BKE_mesh_vertex_normals_for_write(Mesh *mesh))[3]
|
||||
{
|
||||
if (mesh->runtime.vert_normals == nullptr) {
|
||||
mesh->runtime.vert_normals = (float(*)[3])MEM_malloc_arrayN(
|
||||
if (mesh->runtime->vert_normals == nullptr) {
|
||||
mesh->runtime->vert_normals = (float(*)[3])MEM_malloc_arrayN(
|
||||
mesh->totvert, sizeof(float[3]), __func__);
|
||||
}
|
||||
|
||||
BLI_assert(MEM_allocN_len(mesh->runtime.vert_normals) >= sizeof(float[3]) * mesh->totvert);
|
||||
BLI_assert(MEM_allocN_len(mesh->runtime->vert_normals) >= sizeof(float[3]) * mesh->totvert);
|
||||
|
||||
return mesh->runtime.vert_normals;
|
||||
return mesh->runtime->vert_normals;
|
||||
}
|
||||
|
||||
float (*BKE_mesh_poly_normals_for_write(Mesh *mesh))[3]
|
||||
{
|
||||
if (mesh->runtime.poly_normals == nullptr) {
|
||||
mesh->runtime.poly_normals = (float(*)[3])MEM_malloc_arrayN(
|
||||
if (mesh->runtime->poly_normals == nullptr) {
|
||||
mesh->runtime->poly_normals = (float(*)[3])MEM_malloc_arrayN(
|
||||
mesh->totpoly, sizeof(float[3]), __func__);
|
||||
}
|
||||
|
||||
BLI_assert(MEM_allocN_len(mesh->runtime.poly_normals) >= sizeof(float[3]) * mesh->totpoly);
|
||||
BLI_assert(MEM_allocN_len(mesh->runtime->poly_normals) >= sizeof(float[3]) * mesh->totpoly);
|
||||
|
||||
return mesh->runtime.poly_normals;
|
||||
return mesh->runtime->poly_normals;
|
||||
}
|
||||
|
||||
void BKE_mesh_vertex_normals_clear_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime.vert_normals_dirty = false;
|
||||
mesh->runtime->vert_normals_dirty = false;
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
|
||||
}
|
||||
|
||||
void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime.poly_normals_dirty = false;
|
||||
mesh->runtime->poly_normals_dirty = false;
|
||||
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
|
||||
}
|
||||
|
||||
bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh)
|
||||
{
|
||||
return mesh->runtime.vert_normals_dirty;
|
||||
return mesh->runtime->vert_normals_dirty;
|
||||
}
|
||||
|
||||
bool BKE_mesh_poly_normals_are_dirty(const Mesh *mesh)
|
||||
{
|
||||
return mesh->runtime.poly_normals_dirty;
|
||||
return mesh->runtime->poly_normals_dirty;
|
||||
}
|
||||
|
||||
void BKE_mesh_clear_derived_normals(Mesh *mesh)
|
||||
{
|
||||
MEM_SAFE_FREE(mesh->runtime.vert_normals);
|
||||
MEM_SAFE_FREE(mesh->runtime.poly_normals);
|
||||
MEM_SAFE_FREE(mesh->runtime->vert_normals);
|
||||
MEM_SAFE_FREE(mesh->runtime->poly_normals);
|
||||
|
||||
mesh->runtime.vert_normals_dirty = true;
|
||||
mesh->runtime.poly_normals_dirty = true;
|
||||
mesh->runtime->vert_normals_dirty = true;
|
||||
mesh->runtime->poly_normals_dirty = true;
|
||||
}
|
||||
|
||||
void BKE_mesh_assert_normals_dirty_or_calculated(const Mesh *mesh)
|
||||
{
|
||||
if (!mesh->runtime.vert_normals_dirty) {
|
||||
BLI_assert(mesh->runtime.vert_normals || mesh->totvert == 0);
|
||||
if (!mesh->runtime->vert_normals_dirty) {
|
||||
BLI_assert(mesh->runtime->vert_normals || mesh->totvert == 0);
|
||||
}
|
||||
if (!mesh->runtime.poly_normals_dirty) {
|
||||
BLI_assert(mesh->runtime.poly_normals || mesh->totpoly == 0);
|
||||
if (!mesh->runtime->poly_normals_dirty) {
|
||||
BLI_assert(mesh->runtime->poly_normals || mesh->totpoly == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,20 +348,18 @@ void BKE_mesh_calc_normals_poly_and_vertex(const float (*positions)[3],
|
|||
const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
|
||||
{
|
||||
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime.vert_normals != nullptr || mesh->totvert == 0);
|
||||
return mesh->runtime.vert_normals;
|
||||
BLI_assert(mesh->runtime->vert_normals != nullptr || mesh->totvert == 0);
|
||||
return mesh->runtime->vert_normals;
|
||||
}
|
||||
|
||||
if (mesh->totvert == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ThreadMutex *normals_mutex = (ThreadMutex *)mesh->runtime.normals_mutex;
|
||||
BLI_mutex_lock(normals_mutex);
|
||||
std::lock_guard lock{mesh->runtime->normals_mutex};
|
||||
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime.vert_normals != nullptr);
|
||||
BLI_mutex_unlock(normals_mutex);
|
||||
return mesh->runtime.vert_normals;
|
||||
BLI_assert(mesh->runtime->vert_normals != nullptr);
|
||||
return mesh->runtime->vert_normals;
|
||||
}
|
||||
|
||||
float(*vert_normals)[3];
|
||||
|
@ -390,27 +388,24 @@ const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
|
|||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
});
|
||||
|
||||
BLI_mutex_unlock(normals_mutex);
|
||||
return vert_normals;
|
||||
}
|
||||
|
||||
const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
|
||||
{
|
||||
if (!BKE_mesh_poly_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime.poly_normals != nullptr || mesh->totpoly == 0);
|
||||
return mesh->runtime.poly_normals;
|
||||
BLI_assert(mesh->runtime->poly_normals != nullptr || mesh->totpoly == 0);
|
||||
return mesh->runtime->poly_normals;
|
||||
}
|
||||
|
||||
if (mesh->totpoly == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ThreadMutex *normals_mutex = (ThreadMutex *)mesh->runtime.normals_mutex;
|
||||
BLI_mutex_lock(normals_mutex);
|
||||
std::lock_guard lock{mesh->runtime->normals_mutex};
|
||||
if (!BKE_mesh_poly_normals_are_dirty(mesh)) {
|
||||
BLI_assert(mesh->runtime.poly_normals != nullptr);
|
||||
BLI_mutex_unlock(normals_mutex);
|
||||
return mesh->runtime.poly_normals;
|
||||
BLI_assert(mesh->runtime->poly_normals != nullptr);
|
||||
return mesh->runtime->poly_normals;
|
||||
}
|
||||
|
||||
float(*poly_normals)[3];
|
||||
|
@ -435,13 +430,12 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
|
|||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
});
|
||||
|
||||
BLI_mutex_unlock(normals_mutex);
|
||||
return poly_normals;
|
||||
}
|
||||
|
||||
void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
|
||||
{
|
||||
switch ((eMeshWrapperType)mesh->runtime.wrapper_type) {
|
||||
switch (mesh->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
BKE_mesh_vertex_normals_ensure(mesh);
|
||||
|
@ -449,7 +443,7 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
|
|||
break;
|
||||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
struct BMEditMesh *em = mesh->edit_mesh;
|
||||
EditMeshData *emd = mesh->runtime.edit_data;
|
||||
EditMeshData *emd = mesh->runtime->edit_data;
|
||||
if (emd->vertexCos) {
|
||||
BKE_editmesh_cache_ensure_vert_normals(em, emd);
|
||||
BKE_editmesh_cache_ensure_poly_normals(em, emd);
|
||||
|
|
|
@ -1530,7 +1530,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
|||
BLI_bitmap *looptri_active;
|
||||
|
||||
looptri_src = BKE_mesh_runtime_looptri_ensure(me_src);
|
||||
num_looptri_src = me_src->runtime.looptris.len;
|
||||
num_looptri_src = BKE_mesh_runtime_looptri_len(me_src);
|
||||
looptri_active = BLI_BITMAP_NEW((size_t)num_looptri_src, __func__);
|
||||
|
||||
for (tindex = 0; tindex < num_trees; tindex++) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "BLI_task.hh"
|
||||
|
||||
#include "BKE_bvhutils.h"
|
||||
#include "BKE_editmesh_cache.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
|
@ -31,81 +32,17 @@ using blender::Span;
|
|||
/** \name Mesh Runtime Struct Utils
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* \brief Initialize the runtime mutexes of the given mesh.
|
||||
*
|
||||
* Any existing mutexes will be overridden.
|
||||
*/
|
||||
static void mesh_runtime_init_mutexes(Mesh *mesh)
|
||||
{
|
||||
mesh->runtime.eval_mutex = MEM_new<ThreadMutex>("mesh runtime eval_mutex");
|
||||
BLI_mutex_init(static_cast<ThreadMutex *>(mesh->runtime.eval_mutex));
|
||||
mesh->runtime.normals_mutex = MEM_new<ThreadMutex>("mesh runtime normals_mutex");
|
||||
BLI_mutex_init(static_cast<ThreadMutex *>(mesh->runtime.normals_mutex));
|
||||
mesh->runtime.render_mutex = MEM_new<ThreadMutex>("mesh runtime render_mutex");
|
||||
BLI_mutex_init(static_cast<ThreadMutex *>(mesh->runtime.render_mutex));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief free the mutexes of the given mesh runtime.
|
||||
*/
|
||||
static void mesh_runtime_free_mutexes(Mesh *mesh)
|
||||
{
|
||||
if (mesh->runtime.eval_mutex != nullptr) {
|
||||
BLI_mutex_end(static_cast<ThreadMutex *>(mesh->runtime.eval_mutex));
|
||||
MEM_freeN(mesh->runtime.eval_mutex);
|
||||
mesh->runtime.eval_mutex = nullptr;
|
||||
}
|
||||
if (mesh->runtime.normals_mutex != nullptr) {
|
||||
BLI_mutex_end(static_cast<ThreadMutex *>(mesh->runtime.normals_mutex));
|
||||
MEM_freeN(mesh->runtime.normals_mutex);
|
||||
mesh->runtime.normals_mutex = nullptr;
|
||||
}
|
||||
if (mesh->runtime.render_mutex != nullptr) {
|
||||
BLI_mutex_end(static_cast<ThreadMutex *>(mesh->runtime.render_mutex));
|
||||
MEM_freeN(mesh->runtime.render_mutex);
|
||||
mesh->runtime.render_mutex = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_runtime_init_data(Mesh *mesh)
|
||||
{
|
||||
mesh_runtime_init_mutexes(mesh);
|
||||
}
|
||||
|
||||
void BKE_mesh_runtime_free_data(Mesh *mesh)
|
||||
{
|
||||
BKE_mesh_runtime_clear_cache(mesh);
|
||||
mesh_runtime_free_mutexes(mesh);
|
||||
}
|
||||
|
||||
void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int /*flag*/)
|
||||
{
|
||||
Mesh_Runtime *runtime = &mesh->runtime;
|
||||
|
||||
runtime->mesh_eval = nullptr;
|
||||
runtime->edit_data = nullptr;
|
||||
runtime->batch_cache = nullptr;
|
||||
runtime->subdiv_ccg = nullptr;
|
||||
runtime->looptris = blender::dna::shallow_zero_initialize();
|
||||
runtime->bvh_cache = nullptr;
|
||||
runtime->shrinkwrap_data = nullptr;
|
||||
runtime->subsurf_face_dot_tags = nullptr;
|
||||
|
||||
runtime->vert_normals_dirty = true;
|
||||
runtime->poly_normals_dirty = true;
|
||||
runtime->vert_normals = nullptr;
|
||||
runtime->poly_normals = nullptr;
|
||||
|
||||
mesh_runtime_init_mutexes(mesh);
|
||||
}
|
||||
|
||||
void BKE_mesh_runtime_clear_cache(Mesh *mesh)
|
||||
{
|
||||
if (mesh->runtime.mesh_eval != nullptr) {
|
||||
mesh->runtime.mesh_eval->edit_mesh = nullptr;
|
||||
BKE_id_free(nullptr, mesh->runtime.mesh_eval);
|
||||
mesh->runtime.mesh_eval = nullptr;
|
||||
if (mesh->runtime->mesh_eval != nullptr) {
|
||||
mesh->runtime->mesh_eval->edit_mesh = nullptr;
|
||||
BKE_id_free(nullptr, mesh->runtime->mesh_eval);
|
||||
mesh->runtime->mesh_eval = nullptr;
|
||||
}
|
||||
BKE_mesh_runtime_clear_geometry(mesh);
|
||||
BKE_mesh_batch_cache_free(mesh);
|
||||
|
@ -132,32 +69,32 @@ static void mesh_ensure_looptri_data(Mesh *mesh)
|
|||
const uint totpoly = mesh->totpoly;
|
||||
const int looptris_len = poly_to_tri_count(totpoly, mesh->totloop);
|
||||
|
||||
BLI_assert(mesh->runtime.looptris.array_wip == nullptr);
|
||||
BLI_assert(mesh->runtime->looptris.array_wip == nullptr);
|
||||
|
||||
SWAP(MLoopTri *, mesh->runtime.looptris.array, mesh->runtime.looptris.array_wip);
|
||||
SWAP(MLoopTri *, mesh->runtime->looptris.array, mesh->runtime->looptris.array_wip);
|
||||
|
||||
if ((looptris_len > mesh->runtime.looptris.len_alloc) ||
|
||||
(looptris_len < mesh->runtime.looptris.len_alloc * 2) || (totpoly == 0)) {
|
||||
MEM_SAFE_FREE(mesh->runtime.looptris.array_wip);
|
||||
mesh->runtime.looptris.len_alloc = 0;
|
||||
mesh->runtime.looptris.len = 0;
|
||||
if ((looptris_len > mesh->runtime->looptris.len_alloc) ||
|
||||
(looptris_len < mesh->runtime->looptris.len_alloc * 2) || (totpoly == 0)) {
|
||||
MEM_SAFE_FREE(mesh->runtime->looptris.array_wip);
|
||||
mesh->runtime->looptris.len_alloc = 0;
|
||||
mesh->runtime->looptris.len = 0;
|
||||
}
|
||||
|
||||
if (totpoly) {
|
||||
if (mesh->runtime.looptris.array_wip == nullptr) {
|
||||
mesh->runtime.looptris.array_wip = static_cast<MLoopTri *>(
|
||||
MEM_malloc_arrayN(looptris_len, sizeof(*mesh->runtime.looptris.array_wip), __func__));
|
||||
mesh->runtime.looptris.len_alloc = looptris_len;
|
||||
if (mesh->runtime->looptris.array_wip == nullptr) {
|
||||
mesh->runtime->looptris.array_wip = static_cast<MLoopTri *>(
|
||||
MEM_malloc_arrayN(looptris_len, sizeof(*mesh->runtime->looptris.array_wip), __func__));
|
||||
mesh->runtime->looptris.len_alloc = looptris_len;
|
||||
}
|
||||
|
||||
mesh->runtime.looptris.len = looptris_len;
|
||||
mesh->runtime->looptris.len = looptris_len;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
|
||||
{
|
||||
mesh_ensure_looptri_data(mesh);
|
||||
BLI_assert(mesh->totpoly == 0 || mesh->runtime.looptris.array_wip != nullptr);
|
||||
BLI_assert(mesh->totpoly == 0 || mesh->runtime->looptris.array_wip != nullptr);
|
||||
const Span<float3> positions = mesh->positions();
|
||||
const Span<MPoly> polys = mesh->polys();
|
||||
const Span<MLoop> loops = mesh->loops();
|
||||
|
@ -168,7 +105,7 @@ void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
|
|||
reinterpret_cast<const float(*)[3]>(positions.data()),
|
||||
mesh->totloop,
|
||||
mesh->totpoly,
|
||||
mesh->runtime.looptris.array_wip,
|
||||
mesh->runtime->looptris.array_wip,
|
||||
BKE_mesh_poly_normals_ensure(mesh));
|
||||
}
|
||||
else {
|
||||
|
@ -177,43 +114,40 @@ void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
|
|||
reinterpret_cast<const float(*)[3]>(positions.data()),
|
||||
mesh->totloop,
|
||||
mesh->totpoly,
|
||||
mesh->runtime.looptris.array_wip);
|
||||
mesh->runtime->looptris.array_wip);
|
||||
}
|
||||
|
||||
BLI_assert(mesh->runtime.looptris.array == nullptr);
|
||||
atomic_cas_ptr((void **)&mesh->runtime.looptris.array,
|
||||
mesh->runtime.looptris.array,
|
||||
mesh->runtime.looptris.array_wip);
|
||||
mesh->runtime.looptris.array_wip = nullptr;
|
||||
BLI_assert(mesh->runtime->looptris.array == nullptr);
|
||||
atomic_cas_ptr((void **)&mesh->runtime->looptris.array,
|
||||
mesh->runtime->looptris.array,
|
||||
mesh->runtime->looptris.array_wip);
|
||||
mesh->runtime->looptris.array_wip = nullptr;
|
||||
}
|
||||
|
||||
int BKE_mesh_runtime_looptri_len(const Mesh *mesh)
|
||||
{
|
||||
/* This is a ported copy of `dm_getNumLoopTri(dm)`. */
|
||||
const int looptri_len = poly_to_tri_count(mesh->totpoly, mesh->totloop);
|
||||
BLI_assert(ELEM(mesh->runtime.looptris.len, 0, looptri_len));
|
||||
BLI_assert(ELEM(mesh->runtime->looptris.len, 0, looptri_len));
|
||||
return looptri_len;
|
||||
}
|
||||
|
||||
const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh)
|
||||
{
|
||||
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
|
||||
BLI_mutex_lock(mesh_eval_mutex);
|
||||
std::lock_guard lock{mesh->runtime->eval_mutex};
|
||||
|
||||
MLoopTri *looptri = mesh->runtime.looptris.array;
|
||||
MLoopTri *looptri = mesh->runtime->looptris.array;
|
||||
|
||||
if (looptri != nullptr) {
|
||||
BLI_assert(BKE_mesh_runtime_looptri_len(mesh) == mesh->runtime.looptris.len);
|
||||
BLI_assert(BKE_mesh_runtime_looptri_len(mesh) == mesh->runtime->looptris.len);
|
||||
}
|
||||
else {
|
||||
/* Must isolate multithreaded tasks while holding a mutex lock. */
|
||||
blender::threading::isolate_task(
|
||||
[&]() { BKE_mesh_runtime_looptri_recalc(const_cast<Mesh *>(mesh)); });
|
||||
looptri = mesh->runtime.looptris.array;
|
||||
looptri = mesh->runtime->looptris.array;
|
||||
}
|
||||
|
||||
BLI_mutex_unlock(mesh_eval_mutex);
|
||||
|
||||
return looptri;
|
||||
}
|
||||
|
||||
|
@ -231,17 +165,17 @@ void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri,
|
|||
|
||||
bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh)
|
||||
{
|
||||
if (mesh->runtime.edit_data != nullptr) {
|
||||
if (mesh->runtime->edit_data != nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mesh->runtime.edit_data = MEM_cnew<EditMeshData>(__func__);
|
||||
mesh->runtime->edit_data = MEM_cnew<EditMeshData>(__func__);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BKE_mesh_runtime_reset_edit_data(Mesh *mesh)
|
||||
{
|
||||
EditMeshData *edit_data = mesh->runtime.edit_data;
|
||||
EditMeshData *edit_data = mesh->runtime->edit_data;
|
||||
if (edit_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
@ -256,13 +190,13 @@ bool BKE_mesh_runtime_reset_edit_data(Mesh *mesh)
|
|||
|
||||
bool BKE_mesh_runtime_clear_edit_data(Mesh *mesh)
|
||||
{
|
||||
if (mesh->runtime.edit_data == nullptr) {
|
||||
if (mesh->runtime->edit_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
BKE_mesh_runtime_reset_edit_data(mesh);
|
||||
|
||||
MEM_freeN(mesh->runtime.edit_data);
|
||||
mesh->runtime.edit_data = nullptr;
|
||||
MEM_freeN(mesh->runtime->edit_data);
|
||||
mesh->runtime->edit_data = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -272,22 +206,22 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
|
|||
BKE_mesh_tag_coords_changed(mesh);
|
||||
|
||||
/* TODO(sergey): Does this really belong here? */
|
||||
if (mesh->runtime.subdiv_ccg != nullptr) {
|
||||
BKE_subdiv_ccg_destroy(mesh->runtime.subdiv_ccg);
|
||||
mesh->runtime.subdiv_ccg = nullptr;
|
||||
if (mesh->runtime->subdiv_ccg != nullptr) {
|
||||
BKE_subdiv_ccg_destroy(mesh->runtime->subdiv_ccg);
|
||||
mesh->runtime->subdiv_ccg = nullptr;
|
||||
}
|
||||
BKE_shrinkwrap_discard_boundary_data(mesh);
|
||||
|
||||
MEM_SAFE_FREE(mesh->runtime.subsurf_face_dot_tags);
|
||||
MEM_SAFE_FREE(mesh->runtime->subsurf_face_dot_tags);
|
||||
}
|
||||
|
||||
void BKE_mesh_tag_coords_changed(Mesh *mesh)
|
||||
{
|
||||
BKE_mesh_normals_tag_dirty(mesh);
|
||||
MEM_SAFE_FREE(mesh->runtime.looptris.array);
|
||||
if (mesh->runtime.bvh_cache) {
|
||||
bvhcache_free(mesh->runtime.bvh_cache);
|
||||
mesh->runtime.bvh_cache = nullptr;
|
||||
MEM_SAFE_FREE(mesh->runtime->looptris.array);
|
||||
if (mesh->runtime->bvh_cache) {
|
||||
bvhcache_free(mesh->runtime->bvh_cache);
|
||||
mesh->runtime->bvh_cache = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,6 +240,16 @@ void BKE_mesh_tag_coords_changed_uniformly(Mesh *mesh)
|
|||
}
|
||||
}
|
||||
|
||||
bool BKE_mesh_is_deformed_only(const Mesh *mesh)
|
||||
{
|
||||
return mesh->runtime->deformed_only;
|
||||
}
|
||||
|
||||
eMeshWrapperType BKE_mesh_wrapper_type(const struct Mesh *mesh)
|
||||
{
|
||||
return mesh->runtime->wrapper_type;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -318,13 +262,13 @@ void (*BKE_mesh_batch_cache_free_cb)(Mesh *me) = nullptr;
|
|||
|
||||
void BKE_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
|
||||
{
|
||||
if (me->runtime.batch_cache) {
|
||||
if (me->runtime->batch_cache) {
|
||||
BKE_mesh_batch_cache_dirty_tag_cb(me, mode);
|
||||
}
|
||||
}
|
||||
void BKE_mesh_batch_cache_free(Mesh *me)
|
||||
{
|
||||
if (me->runtime.batch_cache) {
|
||||
if (me->runtime->batch_cache) {
|
||||
BKE_mesh_batch_cache_free_cb(me);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -570,8 +570,6 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
|
|||
const char (*tangent_names)[MAX_NAME],
|
||||
int tangent_names_len)
|
||||
{
|
||||
BKE_mesh_runtime_looptri_ensure(me_eval);
|
||||
|
||||
/* TODO(@campbellbarton): store in Mesh.runtime to avoid recalculation. */
|
||||
short tangent_mask = 0;
|
||||
BKE_mesh_calc_loop_tangent_ex(
|
||||
|
@ -579,8 +577,8 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
|
|||
BKE_mesh_polys(me_eval),
|
||||
uint(me_eval->totpoly),
|
||||
BKE_mesh_loops(me_eval),
|
||||
me_eval->runtime.looptris.array,
|
||||
uint(me_eval->runtime.looptris.len),
|
||||
BKE_mesh_runtime_looptri_ensure(me_eval),
|
||||
uint(BKE_mesh_runtime_looptri_len(me_eval)),
|
||||
&me_eval->ldata,
|
||||
calc_active_tangent,
|
||||
tangent_names,
|
||||
|
|
|
@ -58,13 +58,13 @@ Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
|
|||
BKE_mesh_copy_parameters_for_eval(me, me_settings);
|
||||
BKE_mesh_runtime_ensure_edit_data(me);
|
||||
|
||||
me->runtime.wrapper_type = ME_WRAPPER_TYPE_BMESH;
|
||||
me->runtime->wrapper_type = ME_WRAPPER_TYPE_BMESH;
|
||||
if (cd_mask_extra) {
|
||||
me->runtime.cd_mask_extra = *cd_mask_extra;
|
||||
me->runtime->cd_mask_extra = *cd_mask_extra;
|
||||
}
|
||||
|
||||
/* Use edit-mesh directly where possible. */
|
||||
me->runtime.is_original_bmesh = true;
|
||||
me->runtime->is_original_bmesh = true;
|
||||
|
||||
me->edit_mesh = static_cast<BMEditMesh *>(MEM_dupallocN(em));
|
||||
me->edit_mesh->is_shallow_copy = true;
|
||||
|
@ -82,7 +82,7 @@ Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
|
|||
me->totloop = 0;
|
||||
#endif
|
||||
|
||||
EditMeshData *edit_data = me->runtime.edit_data;
|
||||
EditMeshData *edit_data = me->runtime->edit_data;
|
||||
edit_data->vertexCos = vert_coords;
|
||||
return me;
|
||||
}
|
||||
|
@ -96,17 +96,14 @@ Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
|
|||
|
||||
void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
|
||||
{
|
||||
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)me->runtime.eval_mutex;
|
||||
BLI_mutex_lock(mesh_eval_mutex);
|
||||
|
||||
if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
|
||||
BLI_mutex_unlock(mesh_eval_mutex);
|
||||
std::lock_guard lock{me->runtime->eval_mutex};
|
||||
if (me->runtime->wrapper_type == ME_WRAPPER_TYPE_MDATA) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Must isolate multithreaded tasks while holding a mutex lock. */
|
||||
blender::threading::isolate_task([&]() {
|
||||
switch (static_cast<eMeshWrapperType>(me->runtime.wrapper_type)) {
|
||||
switch (static_cast<eMeshWrapperType>(me->runtime->wrapper_type)) {
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
case ME_WRAPPER_TYPE_SUBD: {
|
||||
break; /* Quiet warning. */
|
||||
|
@ -118,10 +115,10 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
|
|||
me->totloop = 0;
|
||||
|
||||
BLI_assert(me->edit_mesh != nullptr);
|
||||
BLI_assert(me->runtime.edit_data != nullptr);
|
||||
BLI_assert(me->runtime->edit_data != nullptr);
|
||||
|
||||
BMEditMesh *em = me->edit_mesh;
|
||||
BM_mesh_bm_to_me_for_eval(em->bm, me, &me->runtime.cd_mask_extra);
|
||||
BM_mesh_bm_to_me_for_eval(em->bm, me, &me->runtime->cd_mask_extra);
|
||||
|
||||
/* Adding original index layers assumes that all BMesh mesh wrappers are created from
|
||||
* original edit mode meshes (the only case where adding original indices makes sense).
|
||||
|
@ -133,32 +130,30 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
|
|||
* harmful. */
|
||||
BKE_mesh_ensure_default_orig_index_customdata_no_check(me);
|
||||
|
||||
EditMeshData *edit_data = me->runtime.edit_data;
|
||||
EditMeshData *edit_data = me->runtime->edit_data;
|
||||
if (edit_data->vertexCos) {
|
||||
BKE_mesh_vert_coords_apply(me, edit_data->vertexCos);
|
||||
me->runtime.is_original_bmesh = false;
|
||||
me->runtime->is_original_bmesh = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->runtime.wrapper_type_finalize) {
|
||||
BKE_mesh_wrapper_deferred_finalize_mdata(me, &me->runtime.cd_mask_extra);
|
||||
if (me->runtime->wrapper_type_finalize) {
|
||||
BKE_mesh_wrapper_deferred_finalize_mdata(me, &me->runtime->cd_mask_extra);
|
||||
}
|
||||
|
||||
/* Keep type assignment last, so that read-only access only uses the mdata code paths after all
|
||||
* the underlying data has been initialized. */
|
||||
me->runtime.wrapper_type = ME_WRAPPER_TYPE_MDATA;
|
||||
me->runtime->wrapper_type = ME_WRAPPER_TYPE_MDATA;
|
||||
});
|
||||
|
||||
BLI_mutex_unlock(mesh_eval_mutex);
|
||||
}
|
||||
|
||||
bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3])
|
||||
{
|
||||
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
|
||||
switch (me->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
return BKE_editmesh_cache_calc_minmax(me->edit_mesh, me->runtime.edit_data, min, max);
|
||||
return BKE_editmesh_cache_calc_minmax(me->edit_mesh, me->runtime->edit_data, min, max);
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
case ME_WRAPPER_TYPE_SUBD:
|
||||
return BKE_mesh_minmax(me, min, max);
|
||||
|
@ -175,11 +170,11 @@ void BKE_mesh_wrapper_vert_coords_copy(const Mesh *me,
|
|||
float (*vert_coords)[3],
|
||||
int vert_coords_len)
|
||||
{
|
||||
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
|
||||
switch (me->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
BMesh *bm = me->edit_mesh->bm;
|
||||
BLI_assert(vert_coords_len <= bm->totvert);
|
||||
EditMeshData *edit_data = me->runtime.edit_data;
|
||||
EditMeshData *edit_data = me->runtime->edit_data;
|
||||
if (edit_data->vertexCos != nullptr) {
|
||||
for (int i = 0; i < vert_coords_len; i++) {
|
||||
copy_v3_v3(vert_coords[i], edit_data->vertexCos[i]);
|
||||
|
@ -213,11 +208,11 @@ void BKE_mesh_wrapper_vert_coords_copy_with_mat4(const Mesh *me,
|
|||
int vert_coords_len,
|
||||
const float mat[4][4])
|
||||
{
|
||||
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
|
||||
switch (me->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
BMesh *bm = me->edit_mesh->bm;
|
||||
BLI_assert(vert_coords_len == bm->totvert);
|
||||
EditMeshData *edit_data = me->runtime.edit_data;
|
||||
EditMeshData *edit_data = me->runtime->edit_data;
|
||||
if (edit_data->vertexCos != nullptr) {
|
||||
for (int i = 0; i < vert_coords_len; i++) {
|
||||
mul_v3_m4v3(vert_coords[i], mat, edit_data->vertexCos[i]);
|
||||
|
@ -254,7 +249,7 @@ void BKE_mesh_wrapper_vert_coords_copy_with_mat4(const Mesh *me,
|
|||
|
||||
int BKE_mesh_wrapper_vert_len(const Mesh *me)
|
||||
{
|
||||
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
|
||||
switch (me->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
return me->edit_mesh->bm->totvert;
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
|
@ -267,7 +262,7 @@ int BKE_mesh_wrapper_vert_len(const Mesh *me)
|
|||
|
||||
int BKE_mesh_wrapper_edge_len(const Mesh *me)
|
||||
{
|
||||
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
|
||||
switch (me->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
return me->edit_mesh->bm->totedge;
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
|
@ -280,7 +275,7 @@ int BKE_mesh_wrapper_edge_len(const Mesh *me)
|
|||
|
||||
int BKE_mesh_wrapper_loop_len(const Mesh *me)
|
||||
{
|
||||
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
|
||||
switch (me->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
return me->edit_mesh->bm->totloop;
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
|
@ -293,7 +288,7 @@ int BKE_mesh_wrapper_loop_len(const Mesh *me)
|
|||
|
||||
int BKE_mesh_wrapper_poly_len(const Mesh *me)
|
||||
{
|
||||
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
|
||||
switch (me->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH:
|
||||
return me->edit_mesh->bm->totface;
|
||||
case ME_WRAPPER_TYPE_MDATA:
|
||||
|
@ -312,7 +307,7 @@ int BKE_mesh_wrapper_poly_len(const Mesh *me)
|
|||
|
||||
static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me)
|
||||
{
|
||||
SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)me->runtime.subsurf_runtime_data;
|
||||
SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)me->runtime->subsurf_runtime_data;
|
||||
if (runtime_data == nullptr || runtime_data->settings.level == 0) {
|
||||
return me;
|
||||
}
|
||||
|
@ -360,24 +355,22 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me)
|
|||
}
|
||||
|
||||
if (subdiv_mesh != me) {
|
||||
if (me->runtime.mesh_eval != nullptr) {
|
||||
BKE_id_free(nullptr, me->runtime.mesh_eval);
|
||||
if (me->runtime->mesh_eval != nullptr) {
|
||||
BKE_id_free(nullptr, me->runtime->mesh_eval);
|
||||
}
|
||||
me->runtime.mesh_eval = subdiv_mesh;
|
||||
me->runtime.wrapper_type = ME_WRAPPER_TYPE_SUBD;
|
||||
me->runtime->mesh_eval = subdiv_mesh;
|
||||
me->runtime->wrapper_type = ME_WRAPPER_TYPE_SUBD;
|
||||
}
|
||||
|
||||
return me->runtime.mesh_eval;
|
||||
return me->runtime->mesh_eval;
|
||||
}
|
||||
|
||||
Mesh *BKE_mesh_wrapper_ensure_subdivision(Mesh *me)
|
||||
{
|
||||
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)me->runtime.eval_mutex;
|
||||
BLI_mutex_lock(mesh_eval_mutex);
|
||||
std::lock_guard lock{me->runtime->eval_mutex};
|
||||
|
||||
if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_SUBD) {
|
||||
BLI_mutex_unlock(mesh_eval_mutex);
|
||||
return me->runtime.mesh_eval;
|
||||
if (me->runtime->wrapper_type == ME_WRAPPER_TYPE_SUBD) {
|
||||
return me->runtime->mesh_eval;
|
||||
}
|
||||
|
||||
Mesh *result;
|
||||
|
@ -385,7 +378,6 @@ Mesh *BKE_mesh_wrapper_ensure_subdivision(Mesh *me)
|
|||
/* Must isolate multithreaded tasks while holding a mutex lock. */
|
||||
blender::threading::isolate_task([&]() { result = mesh_wrapper_ensure_subdivision(me); });
|
||||
|
||||
BLI_mutex_unlock(mesh_eval_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -963,9 +963,9 @@ void BKE_modifier_path_init(char *path, int path_maxlen, const char *name)
|
|||
*/
|
||||
static void modwrap_dependsOnNormals(Mesh *me)
|
||||
{
|
||||
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
|
||||
switch (me->runtime->wrapper_type) {
|
||||
case ME_WRAPPER_TYPE_BMESH: {
|
||||
EditMeshData *edit_data = me->runtime.edit_data;
|
||||
EditMeshData *edit_data = me->runtime->edit_data;
|
||||
if (edit_data->vertexCos) {
|
||||
/* Note that 'ensure' is acceptable here since these values aren't modified in-place.
|
||||
* If that changes we'll need to recalculate. */
|
||||
|
@ -993,7 +993,7 @@ struct Mesh *BKE_modifier_modify_mesh(ModifierData *md,
|
|||
{
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type));
|
||||
|
||||
if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
||||
if (me->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
||||
if ((mti->flags & eModifierTypeFlag_AcceptsBMesh) == 0) {
|
||||
BKE_mesh_wrapper_ensure_mdata(me);
|
||||
}
|
||||
|
|
|
@ -397,7 +397,7 @@ void multires_mark_as_modified(Depsgraph *depsgraph, Object *object, MultiresMod
|
|||
* In a longer term maybe special dependency graph tag can help sanitizing this a bit. */
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
|
||||
Mesh *mesh = static_cast<Mesh *>(object_eval->data);
|
||||
SubdivCCG *subdiv_ccg = mesh->runtime.subdiv_ccg;
|
||||
SubdivCCG *subdiv_ccg = mesh->runtime->subdiv_ccg;
|
||||
if (subdiv_ccg == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1272,6 +1272,34 @@ float BKE_nlastrip_compute_frame_to_next_strip(NlaStrip *strip)
|
|||
return limit_next;
|
||||
}
|
||||
|
||||
NlaStrip *BKE_nlastrip_next_in_track(struct NlaStrip *strip, bool skip_transitions)
|
||||
{
|
||||
NlaStrip *next = strip->next;
|
||||
while (next != NULL) {
|
||||
if (skip_transitions && (next->type & NLASTRIP_TYPE_TRANSITION)) {
|
||||
next = next->next;
|
||||
}
|
||||
else {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NlaStrip *BKE_nlastrip_prev_in_track(struct NlaStrip *strip, bool skip_transitions)
|
||||
{
|
||||
NlaStrip *prev = strip->prev;
|
||||
while (prev != NULL) {
|
||||
if (skip_transitions && (prev->type & NLASTRIP_TYPE_TRANSITION)) {
|
||||
prev = prev->prev;
|
||||
}
|
||||
else {
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NlaStrip *BKE_nlastrip_find_active(NlaTrack *nlt)
|
||||
{
|
||||
if (nlt == NULL) {
|
||||
|
|
|
@ -1691,7 +1691,7 @@ static void object_update_from_subsurf_ccg(Object *object)
|
|||
if (mesh_eval == nullptr) {
|
||||
return;
|
||||
}
|
||||
SubdivCCG *subdiv_ccg = mesh_eval->runtime.subdiv_ccg;
|
||||
SubdivCCG *subdiv_ccg = mesh_eval->runtime->subdiv_ccg;
|
||||
if (subdiv_ccg == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
@ -1699,7 +1699,7 @@ static void object_update_from_subsurf_ccg(Object *object)
|
|||
if (!subdiv_ccg->dirty.coords && !subdiv_ccg->dirty.hidden) {
|
||||
return;
|
||||
}
|
||||
const int tot_level = mesh_eval->runtime.subdiv_ccg_tot_level;
|
||||
const int tot_level = mesh_eval->runtime->subdiv_ccg_tot_level;
|
||||
Object *object_orig = DEG_get_original_object(object);
|
||||
Mesh *mesh_orig = (Mesh *)object_orig->data;
|
||||
multiresModifier_reshapeFromCCG(tot_level, mesh_orig, subdiv_ccg);
|
||||
|
@ -3218,7 +3218,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
|
|||
int count = 0;
|
||||
int numVerts = me_eval->totvert;
|
||||
|
||||
if (em && me_eval->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
||||
if (em && me_eval->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
|
||||
numVerts = em->bm->totvert;
|
||||
if (em->bm->elem_table_dirty & BM_VERT) {
|
||||
#ifdef VPARENT_THREADING_HACK
|
||||
|
@ -3233,8 +3233,8 @@ static void give_parvert(Object *par, int nr, float vec[3])
|
|||
#endif
|
||||
}
|
||||
if (nr < numVerts) {
|
||||
if (me_eval && me_eval->runtime.edit_data && me_eval->runtime.edit_data->vertexCos) {
|
||||
add_v3_v3(vec, me_eval->runtime.edit_data->vertexCos[nr]);
|
||||
if (me_eval && me_eval->runtime->edit_data && me_eval->runtime->edit_data->vertexCos) {
|
||||
add_v3_v3(vec, me_eval->runtime->edit_data->vertexCos[nr]);
|
||||
}
|
||||
else {
|
||||
const BMVert *v = BM_vert_at_index(em->bm, nr);
|
||||
|
|
|
@ -57,10 +57,12 @@
|
|||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "BLI_hash.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "NOD_geometry_nodes_log.hh"
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_path.h"
|
||||
#include "RNA_prototypes.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
using blender::Array;
|
||||
|
@ -421,8 +423,8 @@ static const Mesh *mesh_data_from_duplicator_object(Object *ob,
|
|||
/* Note that this will only show deformation if #eModifierMode_OnCage is enabled.
|
||||
* We could change this but it matches 2.7x behavior. */
|
||||
me_eval = BKE_object_get_editmesh_eval_cage(ob);
|
||||
if ((me_eval == nullptr) || (me_eval->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
|
||||
EditMeshData *emd = me_eval ? me_eval->runtime.edit_data : nullptr;
|
||||
if ((me_eval == nullptr) || (me_eval->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
|
||||
EditMeshData *emd = me_eval ? me_eval->runtime->edit_data : nullptr;
|
||||
|
||||
/* Only assign edit-mesh in the case we can't use `me_eval`. */
|
||||
*r_em = em;
|
||||
|
@ -1926,4 +1928,30 @@ bool BKE_object_dupli_find_rgba_attribute(
|
|||
return false;
|
||||
}
|
||||
|
||||
bool BKE_view_layer_find_rgba_attribute(struct Scene *scene,
|
||||
struct ViewLayer *layer,
|
||||
const char *name,
|
||||
float r_value[4])
|
||||
{
|
||||
if (layer) {
|
||||
PointerRNA layer_ptr;
|
||||
RNA_pointer_create(&scene->id, &RNA_ViewLayer, layer, &layer_ptr);
|
||||
|
||||
if (find_rna_property_rgba(&layer_ptr, name, r_value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (find_rna_property_rgba(&scene->id, name, r_value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (scene->world && find_rna_property_rgba(&scene->world->id, name, r_value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
copy_v4_fl(r_value, 0.0f);
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -373,10 +373,8 @@ void BKE_object_select_update(Depsgraph *depsgraph, Object *object)
|
|||
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
|
||||
if (object->type == OB_MESH && !object->runtime.is_data_eval_owned) {
|
||||
Mesh *mesh_input = (Mesh *)object->runtime.data_orig;
|
||||
Mesh_Runtime *mesh_runtime = &mesh_input->runtime;
|
||||
BLI_mutex_lock(static_cast<ThreadMutex *>(mesh_runtime->eval_mutex));
|
||||
std::lock_guard lock{mesh_input->runtime->eval_mutex};
|
||||
BKE_object_data_select_update(depsgraph, static_cast<ID *>(object->data));
|
||||
BLI_mutex_unlock(static_cast<ThreadMutex *>(mesh_runtime->eval_mutex));
|
||||
}
|
||||
else {
|
||||
BKE_object_data_select_update(depsgraph, static_cast<ID *>(object->data));
|
||||
|
|
|
@ -1744,7 +1744,7 @@ static void sculpt_update_object(
|
|||
|
||||
ss->hide_poly = (bool *)CustomData_get_layer_named(&me->pdata, CD_PROP_BOOL, ".hide_poly");
|
||||
|
||||
ss->subdiv_ccg = me_eval->runtime.subdiv_ccg;
|
||||
ss->subdiv_ccg = me_eval->runtime->subdiv_ccg;
|
||||
|
||||
PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
|
||||
BLI_assert(pbvh == ss->pbvh);
|
||||
|
@ -2263,7 +2263,7 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) {
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *mesh_eval = static_cast<Mesh *>(object_eval->data);
|
||||
SubdivCCG *subdiv_ccg = mesh_eval->runtime.subdiv_ccg;
|
||||
SubdivCCG *subdiv_ccg = mesh_eval->runtime->subdiv_ccg;
|
||||
if (subdiv_ccg != nullptr) {
|
||||
BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg);
|
||||
}
|
||||
|
@ -2282,8 +2282,8 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
else {
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *mesh_eval = static_cast<Mesh *>(object_eval->data);
|
||||
if (mesh_eval->runtime.subdiv_ccg != nullptr) {
|
||||
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime.subdiv_ccg, respect_hide);
|
||||
if (mesh_eval->runtime->subdiv_ccg != nullptr) {
|
||||
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime->subdiv_ccg, respect_hide);
|
||||
}
|
||||
else if (ob->type == OB_MESH) {
|
||||
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;
|
||||
|
@ -2292,9 +2292,9 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
}
|
||||
|
||||
BKE_pbvh_pmap_set(pbvh, ob->sculpt->pmap);
|
||||
sculpt_attribute_update_refs(ob);
|
||||
|
||||
ob->sculpt->pbvh = pbvh;
|
||||
|
||||
sculpt_attribute_update_refs(ob);
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_legacy_convert.h"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
|
@ -1933,7 +1934,7 @@ int psys_particle_dm_face_lookup(Mesh *mesh_final,
|
|||
index_mf_to_mpoly_deformed = CustomData_get_layer(&mesh_original->fdata, CD_ORIGINDEX);
|
||||
}
|
||||
else {
|
||||
BLI_assert(mesh_final->runtime.deformed_only);
|
||||
BLI_assert(BKE_mesh_is_deformed_only(mesh_final));
|
||||
index_mf_to_mpoly_deformed = index_mf_to_mpoly;
|
||||
}
|
||||
BLI_assert(index_mf_to_mpoly_deformed);
|
||||
|
@ -2023,7 +2024,7 @@ static int psys_map_index_on_dm(Mesh *mesh,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (mesh->runtime.deformed_only || index_dmcache == DMCACHE_ISCHILD) {
|
||||
if (BKE_mesh_is_deformed_only(mesh) || index_dmcache == DMCACHE_ISCHILD) {
|
||||
/* for meshes that are either only deformed or for child particles, the
|
||||
* index and fw do not require any mapping, so we can directly use it */
|
||||
if (from == PART_FROM_VERT) {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_legacy_convert.h"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
|
||||
|
@ -907,7 +908,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!final_mesh->runtime.deformed_only &&
|
||||
if (!BKE_mesh_is_deformed_only(final_mesh) &&
|
||||
!CustomData_get_layer(&final_mesh->fdata, CD_ORIGINDEX)) {
|
||||
printf(
|
||||
"Can't create particles with the current modifier stack, disable destructive modifiers\n");
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_query.h"
|
||||
#include "BKE_mesh_legacy_convert.h"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_particle.h"
|
||||
|
||||
#include "BKE_bvhutils.h"
|
||||
|
@ -319,7 +320,7 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, Partic
|
|||
PARTICLE_P;
|
||||
|
||||
/* CACHE LOCATIONS */
|
||||
if (!mesh_final->runtime.deformed_only) {
|
||||
if (!BKE_mesh_is_deformed_only(mesh_final)) {
|
||||
/* Will use later to speed up subsurf/evaluated mesh. */
|
||||
LinkNode *node, *nodedmelem, **nodearray;
|
||||
int totdmelem, totelem, i;
|
||||
|
|
|
@ -2033,11 +2033,16 @@ void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *pro
|
|||
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
|
||||
int (**r_orco_tris)[3],
|
||||
int *r_orco_tris_num,
|
||||
float (**r_orco_coords)[3])
|
||||
float (**r_orco_coords)[3],
|
||||
BMVert ***r_orco_verts)
|
||||
{
|
||||
*r_orco_tris = node->bm_ortri;
|
||||
*r_orco_tris_num = node->bm_tot_ortri;
|
||||
*r_orco_coords = node->bm_orco;
|
||||
|
||||
if (r_orco_verts) {
|
||||
*r_orco_verts = node->bm_orvert;
|
||||
}
|
||||
}
|
||||
|
||||
bool BKE_pbvh_node_has_vert_with_normal_update_tag(PBVH *pbvh, PBVHNode *node)
|
||||
|
|
|
@ -493,7 +493,7 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
|
|||
BLI_gset_insert(node->bm_unique_verts, v);
|
||||
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, node_index);
|
||||
|
||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
|
||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_TopologyUpdated;
|
||||
|
||||
/* Log the new vertex */
|
||||
BM_log_vert_added(pbvh->bm_log, v, cd_vert_mask_offset);
|
||||
|
@ -519,7 +519,7 @@ static BMFace *pbvh_bmesh_face_create(
|
|||
BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, node_index);
|
||||
|
||||
/* mark node for update */
|
||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
|
||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_TopologyUpdated;
|
||||
node->flag &= ~PBVH_FullyHidden;
|
||||
|
||||
/* Log the new face */
|
||||
|
@ -594,7 +594,7 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *pbvh, PBVHNode *new_owner,
|
|||
{
|
||||
PBVHNode *current_owner = pbvh_bmesh_node_from_vert(pbvh, v);
|
||||
/* mark node for update */
|
||||
current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
|
||||
current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_TopologyUpdated;
|
||||
|
||||
BLI_assert(current_owner != new_owner);
|
||||
|
||||
|
@ -608,7 +608,7 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *pbvh, PBVHNode *new_owner,
|
|||
BLI_assert(!BLI_gset_haskey(new_owner->bm_other_verts, v));
|
||||
|
||||
/* mark node for update */
|
||||
new_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
|
||||
new_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_TopologyUpdated;
|
||||
}
|
||||
|
||||
static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v)
|
||||
|
@ -631,7 +631,7 @@ static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v)
|
|||
f_node_index_prev = f_node_index;
|
||||
|
||||
PBVHNode *f_node = &pbvh->nodes[f_node_index];
|
||||
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
|
||||
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_TopologyUpdated;
|
||||
|
||||
/* Remove current ownership */
|
||||
BLI_gset_remove(f_node->bm_other_verts, v, NULL);
|
||||
|
@ -680,7 +680,7 @@ static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f)
|
|||
BM_log_face_removed(pbvh->bm_log, f);
|
||||
|
||||
/* mark node for update */
|
||||
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
|
||||
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_TopologyUpdated;
|
||||
}
|
||||
|
||||
static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e)
|
||||
|
@ -701,14 +701,9 @@ static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e)
|
|||
|
||||
static void pbvh_bmesh_node_drop_orig(PBVHNode *node)
|
||||
{
|
||||
if (node->bm_orco) {
|
||||
MEM_freeN(node->bm_orco);
|
||||
}
|
||||
if (node->bm_ortri) {
|
||||
MEM_freeN(node->bm_ortri);
|
||||
}
|
||||
node->bm_orco = NULL;
|
||||
node->bm_ortri = NULL;
|
||||
MEM_SAFE_FREE(node->bm_orco);
|
||||
MEM_SAFE_FREE(node->bm_ortri);
|
||||
MEM_SAFE_FREE(node->bm_orvert);
|
||||
node->bm_tot_ortri = 0;
|
||||
}
|
||||
|
||||
|
@ -1507,29 +1502,51 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
|
|||
bool hit = false;
|
||||
float nearest_vertex_co[3] = {0.0f};
|
||||
|
||||
BLI_assert(!use_original || (BLI_gset_len(node->bm_faces) > 0 && node->bm_tot_ortri));
|
||||
|
||||
use_original = use_original && node->bm_tot_ortri;
|
||||
|
||||
GSetIterator gs_iter;
|
||||
|
||||
if (use_original && node->bm_tot_ortri) {
|
||||
for (int i = 0; i < node->bm_tot_ortri; i++) {
|
||||
const int *t = node->bm_ortri[i];
|
||||
hit |= ray_face_intersection_tri(ray_start,
|
||||
isect_precalc,
|
||||
node->bm_orco[t[0]],
|
||||
node->bm_orco[t[1]],
|
||||
node->bm_orco[t[2]],
|
||||
depth);
|
||||
float *cos[3];
|
||||
|
||||
cos[0] = node->bm_orco[node->bm_ortri[i][0]];
|
||||
cos[1] = node->bm_orco[node->bm_ortri[i][1]];
|
||||
cos[2] = node->bm_orco[node->bm_ortri[i][2]];
|
||||
|
||||
if (ray_face_intersection_tri(ray_start, isect_precalc, cos[0], cos[1], cos[2], depth)) {
|
||||
hit = true;
|
||||
|
||||
if (r_face_normal) {
|
||||
normal_tri_v3(r_face_normal, cos[0], cos[1], cos[2]);
|
||||
}
|
||||
|
||||
if (r_active_vertex) {
|
||||
float location[3] = {0.0f};
|
||||
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (len_squared_v3v3(location, cos[j]) <
|
||||
len_squared_v3v3(location, nearest_vertex_co)) {
|
||||
copy_v3_v3(nearest_vertex_co, cos[j]);
|
||||
r_active_vertex->i = (intptr_t)node->bm_orvert[node->bm_ortri[i][j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
GSetIterator gs_iter;
|
||||
|
||||
GSET_ITER (gs_iter, node->bm_faces) {
|
||||
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
|
||||
|
||||
BLI_assert(f->len == 3);
|
||||
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
BMVert *v_tri[3];
|
||||
|
||||
BM_face_as_array_vert_tri(f, v_tri);
|
||||
|
||||
if (ray_face_intersection_tri(
|
||||
ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth)) {
|
||||
hit = true;
|
||||
|
@ -2016,6 +2033,21 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
|||
BLI_buffer_free(&edge_loops);
|
||||
BLI_buffer_free(&deleted_faces);
|
||||
|
||||
/* Go over all changed nodes and check if anything needs to be updated. */
|
||||
for (int n = 0; n < pbvh->totnode; n++) {
|
||||
PBVHNode *node = &pbvh->nodes[n];
|
||||
|
||||
if (node->flag & PBVH_Leaf && node->flag & PBVH_TopologyUpdated) {
|
||||
node->flag &= ~PBVH_TopologyUpdated;
|
||||
|
||||
if (node->bm_ortri) {
|
||||
/* Reallocate original triangle data. */
|
||||
pbvh_bmesh_node_drop_orig(node);
|
||||
BKE_pbvh_bmesh_node_save_orig(pbvh->header.bm, pbvh->bm_log, node, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_VERIFY
|
||||
pbvh_bmesh_verify(pbvh);
|
||||
#endif
|
||||
|
@ -2023,7 +2055,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
|||
return modified;
|
||||
}
|
||||
|
||||
void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, PBVHNode *node)
|
||||
void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, BMLog *log, PBVHNode *node, bool use_original)
|
||||
{
|
||||
/* Skip if original coords/triangles are already saved */
|
||||
if (node->bm_orco) {
|
||||
|
@ -2036,19 +2068,38 @@ void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, PBVHNode *node)
|
|||
|
||||
node->bm_orco = MEM_mallocN(sizeof(*node->bm_orco) * totvert, __func__);
|
||||
node->bm_ortri = MEM_mallocN(sizeof(*node->bm_ortri) * tottri, __func__);
|
||||
node->bm_orvert = MEM_mallocN(sizeof(*node->bm_orvert) * totvert, __func__);
|
||||
|
||||
/* Copy out the vertices and assign a temporary index */
|
||||
int i = 0;
|
||||
GSetIterator gs_iter;
|
||||
GSET_ITER (gs_iter, node->bm_unique_verts) {
|
||||
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
|
||||
copy_v3_v3(node->bm_orco[i], v->co);
|
||||
const float *origco = BM_log_original_vert_co(log, v);
|
||||
|
||||
if (use_original && origco) {
|
||||
copy_v3_v3(node->bm_orco[i], origco);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(node->bm_orco[i], v->co);
|
||||
}
|
||||
|
||||
node->bm_orvert[i] = v;
|
||||
BM_elem_index_set(v, i); /* set_dirty! */
|
||||
i++;
|
||||
}
|
||||
GSET_ITER (gs_iter, node->bm_other_verts) {
|
||||
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
|
||||
copy_v3_v3(node->bm_orco[i], v->co);
|
||||
const float *origco = BM_log_original_vert_co(log, v);
|
||||
|
||||
if (use_original && origco) {
|
||||
copy_v3_v3(node->bm_orco[i], BM_log_original_vert_co(log, v));
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(node->bm_orco[i], v->co);
|
||||
}
|
||||
|
||||
node->bm_orvert[i] = v;
|
||||
BM_elem_index_set(v, i); /* set_dirty! */
|
||||
i++;
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ struct PBVHNode {
|
|||
|
||||
/* Indicates whether this node is a leaf or not; also used for
|
||||
* marking various updates that need to be applied. */
|
||||
PBVHNodeFlags flag : 16;
|
||||
PBVHNodeFlags flag : 32;
|
||||
|
||||
/* Used for raycasting: how close bb is to the ray point. */
|
||||
float tmin;
|
||||
|
@ -115,8 +115,11 @@ struct PBVHNode {
|
|||
GSet *bm_faces;
|
||||
GSet *bm_unique_verts;
|
||||
GSet *bm_other_verts;
|
||||
|
||||
/* Deprecated. Stores original coordinates of triangles. */
|
||||
float (*bm_orco)[3];
|
||||
int (*bm_ortri)[3];
|
||||
BMVert **bm_orvert;
|
||||
int bm_tot_ortri;
|
||||
|
||||
/* Used to store the brush color during a stroke and composite it over the original color */
|
||||
|
|
|
@ -239,12 +239,6 @@ PointCloud *BKE_pointcloud_new_nomain(const int totpoint)
|
|||
nullptr, ID_PT, BKE_idtype_idcode_to_name(ID_PT), LIB_ID_CREATE_LOCALIZE));
|
||||
|
||||
pointcloud_init_data(&pointcloud->id);
|
||||
CustomData_add_layer_named(&pointcloud->pdata,
|
||||
CD_PROP_FLOAT,
|
||||
CD_SET_DEFAULT,
|
||||
nullptr,
|
||||
pointcloud->totpoint,
|
||||
POINTCLOUD_ATTR_RADIUS);
|
||||
|
||||
CustomData_realloc(&pointcloud->pdata, 0, totpoint);
|
||||
pointcloud->totpoint = totpoint;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue