Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Eagar <joeedh@gmail.com>2022-10-23 02:33:47 +0300
committerJoseph Eagar <joeedh@gmail.com>2022-10-23 02:33:47 +0300
commitfe7088c99ff084f7218ab20136d49eb1a1dccd0b (patch)
tree3b3df4270110bbffa4a738e379dce5319fec9653
parentb5a69061e7d464914662ae0dd6fed46a999a56bb (diff)
parentb70bbfadfecec049ad1ac2de7a949198ca6c15bc (diff)
Merge remote-tracking branch 'origin' into temp-sculpt-brush-channel
-rw-r--r--CMakeLists.txt31
-rw-r--r--build_files/build_environment/CMakeLists.txt3
-rw-r--r--build_files/build_environment/cmake/aom.cmake6
-rw-r--r--build_files/build_environment/cmake/cve_check.cmake4
-rw-r--r--build_files/build_environment/cmake/cve_check.csv.in23
-rw-r--r--build_files/build_environment/cmake/download.cmake3
-rw-r--r--build_files/build_environment/cmake/ffmpeg.cmake6
-rw-r--r--build_files/build_environment/cmake/freetype.cmake4
-rw-r--r--build_files/build_environment/cmake/gmp.cmake1
-rw-r--r--build_files/build_environment/cmake/llvm.cmake1
-rw-r--r--build_files/build_environment/cmake/opencollada.cmake33
-rw-r--r--build_files/build_environment/cmake/options.cmake1
-rw-r--r--build_files/build_environment/cmake/osl.cmake3
-rw-r--r--build_files/build_environment/cmake/png.cmake8
-rw-r--r--build_files/build_environment/cmake/python.cmake17
-rw-r--r--build_files/build_environment/cmake/sndfile.cmake7
-rw-r--r--build_files/build_environment/cmake/sqlite.cmake1
-rw-r--r--build_files/build_environment/cmake/ssl.cmake1
-rw-r--r--build_files/build_environment/cmake/tiff.cmake1
-rw-r--r--build_files/build_environment/cmake/versions.cmake147
-rw-r--r--build_files/build_environment/cmake/wayland.cmake8
-rw-r--r--build_files/build_environment/cmake/xml2.cmake64
-rw-r--r--build_files/build_environment/dependencies.dot120
-rwxr-xr-xbuild_files/build_environment/install_deps.sh20
-rw-r--r--build_files/build_environment/patches/aom.diff18
-rw-r--r--build_files/build_environment/patches/ffmpeg.diff40
-rw-r--r--build_files/build_environment/patches/gmp.diff15
-rw-r--r--build_files/build_environment/patches/opencollada.diff25
-rw-r--r--build_files/build_environment/patches/osl.diff135
-rw-r--r--build_files/build_environment/patches/python_windows.diff24
-rw-r--r--build_files/build_environment/patches/sndfile.diff42
-rw-r--r--build_files/build_environment/patches/sqlite.diff14
-rw-r--r--build_files/build_environment/patches/ssl.diff10
-rw-r--r--build_files/cmake/Modules/FindOSL.cmake15
-rw-r--r--build_files/cmake/Modules/FindOpenSubdiv.cmake15
-rw-r--r--build_files/cmake/Modules/FindSYCL.cmake41
-rw-r--r--build_files/cmake/config/blender_full.cmake4
-rw-r--r--build_files/cmake/config/blender_release.cmake4
-rw-r--r--build_files/cmake/macros.cmake18
-rw-r--r--build_files/cmake/platform/platform_apple.cmake100
-rw-r--r--build_files/cmake/platform/platform_unix.cmake209
-rw-r--r--build_files/cmake/platform/platform_win32.cmake88
-rw-r--r--build_files/windows/svn_update.cmd24
-rw-r--r--intern/cycles/CMakeLists.txt6
-rw-r--r--intern/cycles/app/CMakeLists.txt5
-rw-r--r--intern/cycles/blender/addon/engine.py15
-rw-r--r--intern/cycles/blender/addon/properties.py1
-rw-r--r--intern/cycles/blender/sync.cpp206
-rw-r--r--intern/cycles/cmake/external_libs.cmake56
-rw-r--r--intern/cycles/device/CMakeLists.txt22
-rw-r--r--intern/cycles/device/metal/device_impl.mm8
-rw-r--r--intern/cycles/device/metal/kernel.mm6
-rw-r--r--intern/cycles/device/metal/util.mm6
-rw-r--r--intern/cycles/device/oneapi/device.cpp4
-rw-r--r--intern/cycles/device/oneapi/device_impl.cpp45
-rw-r--r--intern/cycles/device/oneapi/device_impl.h2
-rw-r--r--intern/cycles/kernel/CMakeLists.txt34
-rw-r--r--intern/cycles/kernel/bvh/shadow_all.h2
-rw-r--r--intern/cycles/kernel/bvh/util.h8
-rw-r--r--intern/cycles/kernel/device/cpu/bvh.h2
-rw-r--r--intern/cycles/kernel/device/gpu/parallel_active_index.h33
-rw-r--r--intern/cycles/kernel/device/metal/context_begin.h37
-rw-r--r--intern/cycles/kernel/device/metal/kernel.metal2
-rw-r--r--intern/cycles/kernel/device/oneapi/compat.h45
-rw-r--r--intern/cycles/kernel/device/oneapi/globals.h9
-rw-r--r--intern/cycles/kernel/device/oneapi/kernel.cpp17
-rw-r--r--intern/cycles/kernel/device/optix/bvh.h2
-rw-r--r--intern/ffmpeg/tests/ffmpeg_codecs.cc7
-rw-r--r--intern/ghost/CMakeLists.txt10
-rw-r--r--intern/ghost/GHOST_C-api.h2
-rw-r--r--intern/ghost/GHOST_ISystem.h2
-rw-r--r--intern/ghost/GHOST_Types.h12
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp2
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.h3
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm4
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp384
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h53
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerUnix.cpp16
-rw-r--r--intern/ghost/intern/GHOST_NDOFManagerUnix.h2
-rw-r--r--intern/ghost/intern/GHOST_System.cpp2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm5
-rw-r--r--intern/ghost/intern/GHOST_SystemHeadless.h3
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.cpp3
-rw-r--r--intern/ghost/intern/GHOST_SystemSDL.h1
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp1577
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.h14
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp3
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp4
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm4
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.cpp7
-rw-r--r--intern/ghost/test/gears/GHOST_Test.cpp21
-rw-r--r--intern/opensubdiv/CMakeLists.txt6
-rw-r--r--intern/wayland_dynload/extern/wayland_dynload_client.h1
-rw-r--r--make.bat10
-rw-r--r--release/scripts/modules/gpu_extras/batch.py4
-rw-r--r--release/scripts/modules/sys_info.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curves.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_output.py16
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py1
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py19
-rw-r--r--source/blender/blenkernel/BKE_attribute.hh2
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_brush.h2
-rw-r--r--source/blender/blenkernel/BKE_instances.hh2
-rw-r--r--source/blender/blenkernel/BKE_writeffmpeg.h2
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc17
-rw-r--r--source/blender/blenkernel/intern/blendfile_link_append.c6
-rw-r--r--source/blender/blenkernel/intern/curves.cc5
-rw-r--r--source/blender/blenkernel/intern/curves_geometry.cc19
-rw-r--r--source/blender/blenkernel/intern/image_format.cc7
-rw-r--r--source/blender/blenkernel/intern/image_save.cc2
-rw-r--r--source/blender/blenkernel/intern/instances.cc27
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c70
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.cc10
-rw-r--r--source/blender/blenkernel/intern/nla.c2
-rw-r--r--source/blender/blenkernel/intern/object.cc1
-rw-r--r--source/blender/blenkernel/intern/object_update.cc2
-rw-r--r--source/blender/blenkernel/intern/paint.cc2
-rw-r--r--source/blender/blenkernel/intern/volume.cc4
-rw-r--r--source/blender/blenkernel/intern/writeavi.c3
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c236
-rw-r--r--source/blender/blenlib/BLI_array_utils.hh5
-rw-r--r--source/blender/blenlib/BLI_string.h22
-rw-r--r--source/blender/blenlib/intern/array_utils.cc5
-rw-r--r--source/blender/blenlib/intern/string.c30
-rw-r--r--source/blender/blenlib/tests/BLI_string_test.cc97
-rw-r--r--source/blender/blenloader/intern/versioning_300.cc23
-rw-r--r--source/blender/compositor/realtime_compositor/CMakeLists.txt2
-rw-r--r--source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh45
-rw-r--r--source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc104
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc4
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c6
-rw-r--r--source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl6
-rw-r--r--source/blender/draw/intern/draw_curves.cc5
-rw-r--r--source/blender/draw/intern/draw_hair.cc5
-rw-r--r--source/blender/draw/intern/draw_manager.c18
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c3
-rw-r--r--source/blender/editors/include/ED_uvedit.h2
-rw-r--r--source/blender/editors/include/UI_interface.h4
-rw-r--r--source/blender/editors/include/UI_interface.hh1
-rw-r--r--source/blender/editors/include/UI_interface_icons.h12
-rw-r--r--source/blender/editors/interface/interface.cc5
-rw-r--r--source/blender/editors/interface/interface_context_path.cc14
-rw-r--r--source/blender/editors/interface/interface_icons.c117
-rw-r--r--source/blender/editors/interface/interface_intern.h4
-rw-r--r--source/blender/editors/interface/interface_layout.c4
-rw-r--r--source/blender/editors/interface/interface_panel.cc6
-rw-r--r--source/blender/editors/interface/interface_widgets.c15
-rw-r--r--source/blender/editors/object/object_add.cc197
-rw-r--r--source/blender/editors/screen/area.c3
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.cc29
-rw-r--r--source/blender/editors/space_file/file_draw.c65
-rw-r--r--source/blender/editors/space_info/textview.c3
-rw-r--r--source/blender/editors/space_node/node_draw.cc3
-rw-r--r--source/blender/editors/space_node/node_relationships.cc3
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.cc134
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_navigate_walk.c16
-rw-r--r--source/blender/editors/transform/transform.c35
-rw-r--r--source/blender/editors/transform/transform.h9
-rw-r--r--source/blender/editors/transform/transform_constraints.c15
-rw-r--r--source/blender/editors/transform/transform_convert_node.cc47
-rw-r--r--source/blender/editors/transform/transform_mode_curveshrinkfatten.c17
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c103
-rw-r--r--source/blender/editors/transform/transform_snap.c136
-rw-r--r--source/blender/editors/transform/transform_snap.h3
-rw-r--r--source/blender/editors/util/ed_viewer_path.cc3
-rw-r--r--source/blender/editors/uvedit/uvedit_islands.cc26
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c75
-rw-r--r--source/blender/geometry/intern/fillet_curves.cc6
-rw-r--r--source/blender/gpu/CMakeLists.txt9
-rw-r--r--source/blender/gpu/GPU_context.h2
-rw-r--r--source/blender/gpu/GPU_shader.h4
-rw-r--r--source/blender/gpu/intern/gpu_context.cc12
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer_private.hh5
-rw-r--r--source/blender/gpu/intern/gpu_immediate.cc11
-rw-r--r--source/blender/gpu/intern/gpu_immediate_private.hh8
-rw-r--r--source/blender/gpu/intern/gpu_shader_builder.cc49
-rw-r--r--source/blender/gpu/intern/gpu_shader_builder_stubs.cc9
-rw-r--r--source/blender/gpu/intern/gpu_shader_builtin.c5
-rw-r--r--source/blender/gpu/metal/mtl_batch.mm27
-rw-r--r--source/blender/gpu/metal/mtl_drawlist.mm14
-rw-r--r--source/blender/gpu/metal/mtl_texture.mm2
-rw-r--r--source/blender/gpu/opengl/gl_batch.cc4
-rw-r--r--source/blender/gpu/opengl/gl_shader_interface.cc10
-rw-r--r--source/blender/gpu/shaders/compositor/compositor_blur.glsl21
-rw-r--r--source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl21
-rw-r--r--source/blender/gpu/shaders/compositor/compositor_normalize.glsl10
-rw-r--r--source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl22
-rw-r--r--source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl26
-rw-r--r--source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh12
-rw-r--r--source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh81
-rw-r--r--source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh16
-rw-r--r--source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_icon_frag.glsl42
-rw-r--r--source/blender/gpu/shaders/gpu_shader_icon_vert.glsl37
-rw-r--r--source/blender/gpu/shaders/infos/gpu_interface_info.hh3
-rw-r--r--source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh22
-rw-r--r--source/blender/imbuf/intern/indexer.c12
-rw-r--r--source/blender/imbuf/intern/util_gpu.c1
-rw-r--r--source/blender/io/alembic/intern/abc_reader_mesh.cc6
-rw-r--r--source/blender/io/stl/CMakeLists.txt2
-rw-r--r--source/blender/io/usd/intern/usd_reader_mesh.cc6
-rw-r--r--source/blender/io/wavefront_obj/CMakeLists.txt4
-rw-r--r--source/blender/makesdna/DNA_node_types.h6
-rw-r--r--source/blender/makesdna/DNA_scene_types.h1
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesrna/intern/rna_brush.c4
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c14
-rw-r--r--source/blender/makesrna/intern/rna_internal.h4
-rw-r--r--source/blender/makesrna/intern/rna_scene.c3
-rw-r--r--source/blender/makesrna/intern/rna_space.c10
-rw-r--r--source/blender/makesrna/intern/rna_space_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_wm.c22
-rw-r--r--source/blender/makesrna/intern/rna_xr.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_normalize.cc47
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_tonemap.cc248
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc40
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc46
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc25
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc65
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc14
-rw-r--r--source/blender/nodes/texture/CMakeLists.txt2
-rw-r--r--source/blender/python/gpu/gpu_py_platform.c27
-rw-r--r--source/blender/render/intern/engine.cc55
-rw-r--r--source/blender/render/intern/render_result.cc87
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.cc3
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.cc2
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c5
-rw-r--r--source/blender/windowmanager/intern/wm_window.c27
-rw-r--r--source/blender/windowmanager/intern/wm_window_private.h5
-rw-r--r--source/blender/windowmanager/wm_event_types.h55
-rw-r--r--source/creator/creator_args.c44
240 files changed, 4971 insertions, 2498 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 408cf819ce8..f2f34ca3dd2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -336,11 +336,9 @@ if(APPLE)
else()
set(WITH_COREAUDIO OFF)
endif()
-if(NOT WIN32)
+if(UNIX AND NOT APPLE)
option(WITH_JACK "Enable JACK Support (http://www.jackaudio.org)" ON)
- if(UNIX AND NOT APPLE)
- option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF)
- endif()
+ option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF)
else()
set(WITH_JACK OFF)
endif()
@@ -489,13 +487,12 @@ endif()
if(NOT APPLE)
option(WITH_CYCLES_DEVICE_ONEAPI "Enable Cycles oneAPI compute support" OFF)
option(WITH_CYCLES_ONEAPI_BINARIES "Enable Ahead-Of-Time compilation for Cycles oneAPI device" OFF)
- option(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED "Enable use of SYCL host (CPU) device execution by oneAPI implementation. This option is for debugging purposes and impacts GPU execution." OFF)
# https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html
+ # acm-g10 is the architecture for the first Arc Alchemist GPUs but we'll keep using dg2 until IGC dependency is updated to support acm-g10.
set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "dg2" CACHE STRING "oneAPI Intel GPU architectures to build binaries for")
set(CYCLES_ONEAPI_SYCL_TARGETS spir64 spir64_gen CACHE STRING "oneAPI targets to build AOT binaries for")
- mark_as_advanced(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED)
mark_as_advanced(CYCLES_ONEAPI_SPIR64_GEN_DEVICES)
mark_as_advanced(CYCLES_ONEAPI_SYCL_TARGETS)
endif()
@@ -780,6 +777,8 @@ endif()
# -----------------------------------------------------------------------------
# Check for Conflicting/Unsupported Configurations
+option(WITH_STRICT_BUILD_OPTIONS "When requirements for a build option are not met, error instead of disabling the option" OFF)
+
if(NOT WITH_BLENDER AND NOT WITH_CYCLES_STANDALONE AND NOT WITH_CYCLES_HYDRA_RENDER_DELEGATE)
message(FATAL_ERROR
"At least one of WITH_BLENDER or WITH_CYCLES_STANDALONE "
@@ -895,10 +894,7 @@ endif()
if(WITH_BUILDINFO)
find_package(Git)
- if(NOT GIT_FOUND)
- message(WARNING "Git was not found, disabling WITH_BUILDINFO")
- set(WITH_BUILDINFO OFF)
- endif()
+ set_and_warn_library_found("Git" GIT_FOUND WITH_BUILDINFO)
endif()
if(WITH_AUDASPACE)
@@ -938,9 +934,10 @@ if(WITH_INTERNATIONAL)
WARNING
"Translation path '${CMAKE_SOURCE_DIR}/release/datafiles/locale' is missing, "
"This is a 'git submodule', which are known not to work with bridges to other version "
- "control systems, disabling 'WITH_INTERNATIONAL'."
+ "control systems."
)
- set(WITH_INTERNATIONAL OFF)
+ set(TRANSLATIONS_FOUND OFF)
+ set_and_warn_library_found("Translations" TRANSLATIONS_FOUND WITH_INTERNATIONAL)
endif()
endif()
@@ -1245,6 +1242,8 @@ if(WITH_OPENMP)
find_package(OpenMP)
endif()
+ set_and_warn_library_found("OpenMP" OPENMP_FOUND WITH_OPENMP)
+
if(OPENMP_FOUND)
if(NOT WITH_OPENMP_STATIC)
string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}")
@@ -1260,9 +1259,6 @@ if(WITH_OPENMP)
find_library_static(OpenMP_LIBRARIES gomp ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
endif()
- else()
- message(STATUS "OpenMP not found, disabling WITH_OPENMP")
- set(WITH_OPENMP OFF)
endif()
mark_as_advanced(
@@ -1277,10 +1273,7 @@ endif()
if(WITH_BULLET AND WITH_SYSTEM_BULLET)
find_package(Bullet)
- if(NOT BULLET_FOUND)
- message(STATUS "Bullet not found, disabling WITH_BULLET")
- set(WITH_BULLET OFF)
- endif()
+ set_and_warn_library_found("Bullet" BULLET_FOUND WITH_BULLET)
else()
set(BULLET_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/bullet2/src")
# set(BULLET_LIBRARIES "")
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt
index 4f40f44ad18..023d113b551 100644
--- a/build_files/build_environment/CMakeLists.txt
+++ b/build_files/build_environment/CMakeLists.txt
@@ -97,6 +97,8 @@ include(cmake/embree.cmake)
include(cmake/openpgl.cmake)
include(cmake/fmt.cmake)
include(cmake/robinmap.cmake)
+include(cmake/xml2.cmake)
+
if(NOT APPLE)
include(cmake/xr_openxr.cmake)
if(NOT WIN32 OR BUILD_MODE STREQUAL Release)
@@ -149,7 +151,6 @@ if(NOT WIN32 OR ENABLE_MINGW64)
endif()
if(UNIX)
include(cmake/flac.cmake)
- include(cmake/xml2.cmake)
if(NOT APPLE)
include(cmake/spnav.cmake)
include(cmake/jemalloc.cmake)
diff --git a/build_files/build_environment/cmake/aom.cmake b/build_files/build_environment/cmake/aom.cmake
index 9f64439771f..11c81c3f6e4 100644
--- a/build_files/build_environment/cmake/aom.cmake
+++ b/build_files/build_environment/cmake/aom.cmake
@@ -8,11 +8,6 @@ if(WIN32)
# building with mingw, it'll have an unhappy time with that and
# we need to clear them out.
set(AOM_CMAKE_FLAGS )
- # CMake will correctly identify phreads being available, however
- # we do not want to use them, as that gains a dependency on
- # libpthreadswin.dll which we do not want. when pthreads is not
- # available oam will use a pthreads emulation layer using win32 threads
- set(AOM_EXTRA_ARGS_WIN32 -DCMAKE_HAVE_PTHREAD_H=OFF)
else()
set(AOM_GENERATOR "Unix Makefiles")
set(AOM_CMAKE_FLAGS ${DEFAULT_CMAKE_FLAGS})
@@ -36,6 +31,7 @@ ExternalProject_Add(external_aom
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${AOM_HASH_TYPE}=${AOM_HASH}
PREFIX ${BUILD_DIR}/aom
+ PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/aom/src/external_aom < ${PATCH_DIR}/aom.diff
CONFIGURE_COMMAND ${CONFIGURE_ENV} &&
cd ${BUILD_DIR}/aom/src/external_aom-build/ &&
${CMAKE_COMMAND} -G "${AOM_GENERATOR}" -DCMAKE_INSTALL_PREFIX=${LIBDIR}/aom ${AOM_CMAKE_FLAGS} ${AOM_EXTRA_ARGS} ${BUILD_DIR}/aom/src/external_aom/
diff --git a/build_files/build_environment/cmake/cve_check.cmake b/build_files/build_environment/cmake/cve_check.cmake
index dfb190bcffa..ac42444aef1 100644
--- a/build_files/build_environment/cmake/cve_check.cmake
+++ b/build_files/build_environment/cmake/cve_check.cmake
@@ -27,10 +27,12 @@ get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
if(_variableName MATCHES "CPE$")
string(REPLACE ":" ";" CPE_LIST ${${_variableName}})
+ string(REPLACE "_CPE" "_ID" CPE_DEPNAME ${_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")
+ set(${CPE_DEPNAME} "${CPE_VENDOR},${CPE_NAME},${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)
diff --git a/build_files/build_environment/cmake/cve_check.csv.in b/build_files/build_environment/cmake/cve_check.csv.in
index 6e7e8db5609..734a24f8c77 100644
--- a/build_files/build_environment/cmake/cve_check.csv.in
+++ b/build_files/build_environment/cmake/cve_check.csv.in
@@ -1,2 +1,23 @@
-vendor,product,version
+vendor,product,version,cve_number,remarks,comment
+@OPENJPEG_ID@,CVE-2016-9675,Ignored,issue in convert command line tool not used by blender
+@PYTHON_ID@,CVE-2009-2940,Ignored,issue in pygresql not used by blender
+@PYTHON_ID@,CVE-2020-29396,Ignored,issue in odoo not used by blender
+@PYTHON_ID@,CVE-2021-32052,Ignored,issue in django not used by blender
+@PYTHON_ID@,CVE-2009-3720,Ignored,already fixed in libexpat version used
+@SSL_ID@,CVE-2009-1390,Ignored,issue in mutt not used by blender
+@SSL_ID@,CVE-2009-3765,Ignored,issue in mutt not used by blender
+@SSL_ID@,CVE-2009-3766,Ignored,issue in mutt not used by blender
+@SSL_ID@,CVE-2009-3767,Ignored,issue in ldap not used by blender
+@SSL_ID@,CVE-2019-0190,Ignored,issue in apache not used by blender
+@TIFF_ID@,CVE-2022-2056,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2057,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2058,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2519,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2520,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2521,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-2953,Ignored,issue in tiff command line tool not used by blender
+@TIFF_ID@,CVE-2022-34526,Ignored,issue in tiff command line tool not used by blender
+@XML2_ID@,CVE-2016-3709,Ignored,not affecting blender and not considered a security issue upstream
+@GMP_ID@,CVE-2021-43618,Mitigated,patched using upstream commit 561a9c25298e
+@SQLITE_ID@,CVE-2022-35737,Ignored,only affects SQLITE_ENABLE_STAT4 compile option not used by blender or python
@SBOMCONTENTS@
diff --git a/build_files/build_environment/cmake/download.cmake b/build_files/build_environment/cmake/download.cmake
index 35bc028a1e3..8d75f0ff0ed 100644
--- a/build_files/build_environment/cmake/download.cmake
+++ b/build_files/build_environment/cmake/download.cmake
@@ -62,7 +62,7 @@ function(download_source dep)
# since the actual build of the dep will notify the
# platform maintainer if there is a problem with the
# source package and refuse to build.
- if(NOT PACKAGE_USE_UPSTREAM_SOURCES)
+ if(NOT PACKAGE_USE_UPSTREAM_SOURCES OR FORCE_CHECK_HASH)
file(${TARGET_HASH_TYPE} ${TARGET_FILE} LOCAL_HASH)
if(NOT ${TARGET_HASH} STREQUAL ${LOCAL_HASH})
message(FATAL_ERROR "${TARGET_FILE} ${TARGET_HASH_TYPE} mismatch\nExpected\t: ${TARGET_HASH}\nActual\t: ${LOCAL_HASH}")
@@ -114,7 +114,6 @@ download_source(WEBP)
download_source(SPNAV)
download_source(JEMALLOC)
download_source(XML2)
-download_source(TINYXML)
download_source(YAMLCPP)
download_source(EXPAT)
download_source(PUGIXML)
diff --git a/build_files/build_environment/cmake/ffmpeg.cmake b/build_files/build_environment/cmake/ffmpeg.cmake
index 7730607c514..e2b60e161f2 100644
--- a/build_files/build_environment/cmake/ffmpeg.cmake
+++ b/build_files/build_environment/cmake/ffmpeg.cmake
@@ -16,12 +16,6 @@ if(WIN32)
--enable-libopenjpeg
--disable-mediafoundation
)
- if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4")
- set(FFMPEG_EXTRA_FLAGS
- ${FFMPEG_EXTRA_FLAGS}
- --x86asmexe=yasm
- )
- endif()
else()
set(FFMPEG_EXTRA_FLAGS
${FFMPEG_EXTRA_FLAGS}
diff --git a/build_files/build_environment/cmake/freetype.cmake b/build_files/build_environment/cmake/freetype.cmake
index b6f53ede2db..842e5c42e25 100644
--- a/build_files/build_environment/cmake/freetype.cmake
+++ b/build_files/build_environment/cmake/freetype.cmake
@@ -7,8 +7,11 @@ set(FREETYPE_EXTRA_ARGS
-DFT_DISABLE_HARFBUZZ=ON
-DFT_DISABLE_PNG=ON
-DFT_REQUIRE_BROTLI=ON
+ -DFT_REQUIRE_ZLIB=ON
-DPC_BROTLIDEC_INCLUDEDIR=${LIBDIR}/brotli/include
-DPC_BROTLIDEC_LIBDIR=${LIBDIR}/brotli/lib
+ -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
+ -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include
)
ExternalProject_Add(external_freetype
@@ -23,6 +26,7 @@ ExternalProject_Add(external_freetype
add_dependencies(
external_freetype
external_brotli
+ external_zlib
)
if(BUILD_MODE STREQUAL Release AND WIN32)
diff --git a/build_files/build_environment/cmake/gmp.cmake b/build_files/build_environment/cmake/gmp.cmake
index e624778869e..ddfdba6662d 100644
--- a/build_files/build_environment/cmake/gmp.cmake
+++ b/build_files/build_environment/cmake/gmp.cmake
@@ -27,6 +27,7 @@ ExternalProject_Add(external_gmp
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${GMP_HASH_TYPE}=${GMP_HASH}
PREFIX ${BUILD_DIR}/gmp
+ PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/gmp/src/external_gmp < ${PATCH_DIR}/gmp.diff
CONFIGURE_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/gmp ${GMP_OPTIONS} ${GMP_EXTRA_ARGS}
BUILD_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && make -j${MAKE_THREADS}
INSTALL_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && make install
diff --git a/build_files/build_environment/cmake/llvm.cmake b/build_files/build_environment/cmake/llvm.cmake
index e4ddc7db846..11f6bf7c218 100644
--- a/build_files/build_environment/cmake/llvm.cmake
+++ b/build_files/build_environment/cmake/llvm.cmake
@@ -9,6 +9,7 @@ endif()
if(APPLE)
set(LLVM_XML2_ARGS
-DLIBXML2_LIBRARY=${LIBDIR}/xml2/lib/libxml2.a
+ -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2
)
set(LLVM_BUILD_CLANG_TOOLS_EXTRA ^^clang-tools-extra)
set(BUILD_CLANG_TOOLS ON)
diff --git a/build_files/build_environment/cmake/opencollada.cmake b/build_files/build_environment/cmake/opencollada.cmake
index b2ae1a1a351..9473aafbe88 100644
--- a/build_files/build_environment/cmake/opencollada.cmake
+++ b/build_files/build_environment/cmake/opencollada.cmake
@@ -4,6 +4,16 @@ if(UNIX)
set(OPENCOLLADA_EXTRA_ARGS
-DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2
-DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2.a)
+else()
+ set(OPENCOLLADA_EXTRA_ARGS
+ -DCMAKE_DEBUG_POSTFIX=_d
+ -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2
+ )
+ if(BUILD_MODE STREQUAL Release)
+ list(APPEND OPENCOLLADA_EXTRA_ARGS -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2s.lib)
+ else()
+ list(APPEND OPENCOLLADA_EXTRA_ARGS -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2sd.lib)
+ endif()
endif()
ExternalProject_Add(external_opencollada
@@ -16,12 +26,11 @@ ExternalProject_Add(external_opencollada
INSTALL_DIR ${LIBDIR}/opencollada
)
-if(UNIX)
- add_dependencies(
- external_opencollada
- external_xml2
- )
-endif()
+
+add_dependencies(
+ external_opencollada
+ external_xml2
+)
if(WIN32)
if(BUILD_MODE STREQUAL Release)
@@ -32,17 +41,7 @@ if(WIN32)
endif()
if(BUILD_MODE STREQUAL Debug)
ExternalProject_Add_Step(external_opencollada after_install
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/buffer.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/buffer_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/ftoa.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/ftoa_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/GeneratedSaxParser.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/GeneratedSaxParser_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/MathMLSolver.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/MathMLSolver_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADABaseUtils.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADABaseUtils_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADAFramework.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADAFramework_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADASaxFrameworkLoader.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADASaxFrameworkLoader_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADAStreamWriter.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADAStreamWriter_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/pcre.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/pcre_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/UTF.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/UTF_d.lib
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/xml.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/xml_d.lib
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencollada/lib ${HARVEST_TARGET}/opencollada/lib
DEPENDEES install
)
endif()
diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake
index 6e5f9df20b4..9058e945f6d 100644
--- a/build_files/build_environment/cmake/options.cmake
+++ b/build_files/build_environment/cmake/options.cmake
@@ -3,6 +3,7 @@
if(WIN32)
option(ENABLE_MINGW64 "Enable building of ffmpeg/iconv/libsndfile/fftw3 by installing mingw64" ON)
endif()
+option(FORCE_CHECK_HASH "Force a check of all hashses during CMake the configure phase" OFF)
option(WITH_BOOST_PYTHON "Enable building of boost with python support" OFF)
cmake_host_system_information(RESULT NUM_CORES QUERY NUMBER_OF_LOGICAL_CORES)
set(MAKE_THREADS ${NUM_CORES} CACHE STRING "Number of threads to run make with")
diff --git a/build_files/build_environment/cmake/osl.cmake b/build_files/build_environment/cmake/osl.cmake
index 9719de94d47..a5d000e4f44 100644
--- a/build_files/build_environment/cmake/osl.cmake
+++ b/build_files/build_environment/cmake/osl.cmake
@@ -32,6 +32,8 @@ set(OSL_EXTRA_ARGS
-DUSE_Qt5=OFF
-DINSTALL_DOCS=OFF
-Dpugixml_ROOT=${LIBDIR}/pugixml
+ -DTIFF_ROOT=${LIBDIR}/tiff
+ -DJPEG_ROOT=${LIBDIR}/jpeg
-DUSE_PYTHON=OFF
-DCMAKE_CXX_STANDARD=14
-DImath_ROOT=${LIBDIR}/imath
@@ -81,6 +83,7 @@ if(WIN32)
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslcomp.lib ${HARVEST_TARGET}/osl/lib/oslcomp_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslexec.lib ${HARVEST_TARGET}/osl/lib/oslexec_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslquery.lib ${HARVEST_TARGET}/osl/lib/oslquery_d.lib
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslnoise.lib ${HARVEST_TARGET}/osl/lib/oslnoise_d.lib
DEPENDEES install
)
endif()
diff --git a/build_files/build_environment/cmake/png.cmake b/build_files/build_environment/cmake/png.cmake
index 890be673cb8..371f2608e2a 100644
--- a/build_files/build_environment/cmake/png.cmake
+++ b/build_files/build_environment/cmake/png.cmake
@@ -24,6 +24,14 @@ add_dependencies(
external_zlib
)
+if(WIN32 AND BUILD_MODE STREQUAL Release)
+ ExternalProject_Add_Step(external_png after_install
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static${LIBEXT} ${HARVEST_TARGET}/png/lib/libpng${LIBEXT}
+ DEPENDEES install
+ )
+endif()
+
if(WIN32 AND BUILD_MODE STREQUAL Debug)
ExternalProject_Add_Step(external_png after_install
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_staticd${LIBEXT} ${LIBDIR}/png/lib/libpng16${LIBEXT}
diff --git a/build_files/build_environment/cmake/python.cmake b/build_files/build_environment/cmake/python.cmake
index 8fed10e9d72..72ae27ddfdb 100644
--- a/build_files/build_environment/cmake/python.cmake
+++ b/build_files/build_environment/cmake/python.cmake
@@ -15,9 +15,11 @@ if(WIN32)
endmacro()
set(PYTHON_EXTERNALS_FOLDER ${BUILD_DIR}/python/src/external_python/externals)
+ set(ZLIB_SOURCE_FOLDER ${BUILD_DIR}/zlib/src/external_zlib)
set(DOWNLOADS_EXTERNALS_FOLDER ${DOWNLOAD_DIR}/externals)
cmake_to_dos_path(${PYTHON_EXTERNALS_FOLDER} PYTHON_EXTERNALS_FOLDER_DOS)
+ cmake_to_dos_path(${ZLIB_SOURCE_FOLDER} ZLIB_SOURCE_FOLDER_DOS)
cmake_to_dos_path(${DOWNLOADS_EXTERNALS_FOLDER} DOWNLOADS_EXTERNALS_FOLDER_DOS)
ExternalProject_Add(external_python
@@ -25,12 +27,21 @@ if(WIN32)
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${PYTHON_HASH_TYPE}=${PYTHON_HASH}
PREFIX ${BUILD_DIR}/python
- CONFIGURE_COMMAND ""
+ # Python will download its own deps and there's very little we can do about
+ # that beyond placing some code in their externals dir before it tries.
+ # the foldernames *HAVE* to match the ones inside pythons get_externals.cmd.
+ # python 3.10.8 still ships zlib 1.2.12, replace it with our 1.2.13
+ # copy until they update.
+ CONFIGURE_COMMAND mkdir ${PYTHON_EXTERNALS_FOLDER_DOS} &&
+ mklink /J ${PYTHON_EXTERNALS_FOLDER_DOS}\\zlib-1.2.12 ${ZLIB_SOURCE_FOLDER_DOS} &&
+ ${CMAKE_COMMAND} -E copy ${ZLIB_SOURCE_FOLDER}/../external_zlib-build/zconf.h ${PYTHON_EXTERNALS_FOLDER}/zlib-1.2.12/zconf.h
BUILD_COMMAND cd ${BUILD_DIR}/python/src/external_python/pcbuild/ && set IncludeTkinter=false && call build.bat -e -p x64 -c ${BUILD_MODE}
- PATCH_COMMAND ${PATCH_CMD} --verbose -p1 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_windows.diff
INSTALL_COMMAND ${PYTHON_BINARY_INTERNAL} ${PYTHON_SRC}/PC/layout/main.py -b ${PYTHON_SRC}/PCbuild/amd64 -s ${PYTHON_SRC} -t ${PYTHON_SRC}/tmp/ --include-stable --include-pip --include-dev --include-launchers --include-venv --include-symbols ${PYTHON_EXTRA_INSTLAL_FLAGS} --copy ${LIBDIR}/python
)
-
+ add_dependencies(
+ external_python
+ external_zlib
+ )
else()
if(APPLE)
# Disable functions that can be in 10.13 sdk but aren't available on 10.9 target.
diff --git a/build_files/build_environment/cmake/sndfile.cmake b/build_files/build_environment/cmake/sndfile.cmake
index 192c25f5ed1..a2ac2a33779 100644
--- a/build_files/build_environment/cmake/sndfile.cmake
+++ b/build_files/build_environment/cmake/sndfile.cmake
@@ -11,18 +11,11 @@ else()
set(SNDFILE_OPTIONS --enable-static --disable-shared )
endif()
-if(UNIX)
- set(SNDFILE_PATCH_CMD ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/sndfile/src/external_sndfile < ${PATCH_DIR}/sndfile.diff)
-else()
- set(SNDFILE_PATCH_CMD)
-endif()
-
ExternalProject_Add(external_sndfile
URL file://${PACKAGE_DIR}/${SNDFILE_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${SNDFILE_HASH_TYPE}=${SNDFILE_HASH}
PREFIX ${BUILD_DIR}/sndfile
- PATCH_COMMAND ${SNDFILE_PATCH_CMD}
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && ${SNDFILE_ENV} ${CONFIGURE_COMMAND} ${SNDFILE_OPTIONS} --prefix=${mingw_LIBDIR}/sndfile
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && make -j${MAKE_THREADS}
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && make install
diff --git a/build_files/build_environment/cmake/sqlite.cmake b/build_files/build_environment/cmake/sqlite.cmake
index c82d832574a..c151a495ff1 100644
--- a/build_files/build_environment/cmake/sqlite.cmake
+++ b/build_files/build_environment/cmake/sqlite.cmake
@@ -48,7 +48,6 @@ ExternalProject_Add(external_sqlite
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH ${SQLITE_HASH_TYPE}=${SQLITE_HASH}
PREFIX ${BUILD_DIR}/sqlite
- PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/sqlite/src/external_sqlite < ${PATCH_DIR}/sqlite.diff
CONFIGURE_COMMAND ${SQLITE_CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/sqlite ${SQLITE_CONFIGURATION_ARGS}
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && make -j${MAKE_THREADS}
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && make install
diff --git a/build_files/build_environment/cmake/ssl.cmake b/build_files/build_environment/cmake/ssl.cmake
index 21c4d2418c3..628187dc0ac 100644
--- a/build_files/build_environment/cmake/ssl.cmake
+++ b/build_files/build_environment/cmake/ssl.cmake
@@ -5,6 +5,7 @@ set(SSL_PATCH_CMD echo .)
if(APPLE)
set(SSL_OS_COMPILER "blender-darwin-${CMAKE_OSX_ARCHITECTURES}")
+ set(SSL_PATCH_CMD ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/ssl/src/external_ssl < ${PATCH_DIR}/ssl.diff)
else()
if(BLENDER_PLATFORM_ARM)
set(SSL_OS_COMPILER "blender-linux-aarch64")
diff --git a/build_files/build_environment/cmake/tiff.cmake b/build_files/build_environment/cmake/tiff.cmake
index 1f8e9442ae5..1ac2e4c6058 100644
--- a/build_files/build_environment/cmake/tiff.cmake
+++ b/build_files/build_environment/cmake/tiff.cmake
@@ -25,6 +25,7 @@ ExternalProject_Add(external_tiff
add_dependencies(
external_tiff
external_zlib
+ external_jpeg
)
if(WIN32)
if(BUILD_MODE STREQUAL Release)
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index bfc6d27f74d..06a923e5c22 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -8,9 +8,9 @@
# 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_VERSION 1.2.13)
set(ZLIB_URI https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz)
-set(ZLIB_HASH 5fc414a9726be31427b440b434d05f78)
+set(ZLIB_HASH 9b8aa094c4e5765dabf4da391f00d15c)
set(ZLIB_HASH_TYPE MD5)
set(ZLIB_FILE zlib-${ZLIB_VERSION}.tar.gz)
set(ZLIB_CPE "cpe:2.3:a:zlib:zlib:${ZLIB_VERSION}:*:*:*:*:*:*:*")
@@ -88,9 +88,9 @@ else()
set(OPENEXR_VERSION_POSTFIX)
endif()
-set(FREETYPE_VERSION 2.11.1)
+set(FREETYPE_VERSION 2.12.1)
set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz)
-set(FREETYPE_HASH bd4e3b007474319909a6b79d50908e85)
+set(FREETYPE_HASH 8bc5c9c9df7ac12c504f8918552a7cf2)
set(FREETYPE_HASH_TYPE MD5)
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)
SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*")
@@ -159,9 +159,9 @@ set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${
set(OPENMP_HASH_TYPE MD5)
set(OPENMP_FILE openmp-${OPENMP_VERSION}.src.tar.xz)
-set(OPENIMAGEIO_VERSION v2.3.13.0)
+set(OPENIMAGEIO_VERSION v2.3.20.0)
set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/refs/tags/${OPENIMAGEIO_VERSION}.tar.gz)
-set(OPENIMAGEIO_HASH de45fb38501c4581062b522b53b6141c)
+set(OPENIMAGEIO_HASH defb1fe7c8e64bac60eb3cacaf5c3736)
set(OPENIMAGEIO_HASH_TYPE MD5)
set(OPENIMAGEIO_FILE OpenImageIO-${OPENIMAGEIO_VERSION}.tar.gz)
@@ -189,17 +189,17 @@ 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)
-set(OSL_HASH 63265472ce14548839ace2e21e401544)
+set(OSL_VERSION 1.12.6.2)
+set(OSL_URI https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/archive/refs/tags/v${OSL_VERSION}.tar.gz)
+set(OSL_HASH 6fef11548adfdd3e5b25c49d2dae96ee)
set(OSL_HASH_TYPE MD5)
set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz)
-set(PYTHON_VERSION 3.10.2)
+set(PYTHON_VERSION 3.10.8)
set(PYTHON_SHORT_VERSION 3.10)
set(PYTHON_SHORT_VERSION_NO_DOTS 310)
set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
-set(PYTHON_HASH 14e8c22458ed7779a1957b26cde01db9)
+set(PYTHON_HASH e92356b012ed4d0e09675131d39b1bde)
set(PYTHON_HASH_TYPE MD5)
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
set(PYTHON_CPE "cpe:2.3:a:python:python:${PYTHON_VERSION}:-:*:*:*:*:*:*")
@@ -298,17 +298,17 @@ set(XVIDCORE_HASH abbdcbd39555691dd1c9b4d08f0a031376a3b211652c0d8b3b8aa9be1303ce
set(XVIDCORE_HASH_TYPE SHA256)
set(XVIDCORE_FILE xvidcore-${XVIDCORE_VERSION}.tar.gz)
-set(OPENJPEG_VERSION 2.4.0)
-set(OPENJPEG_SHORT_VERSION 2.4)
+set(OPENJPEG_VERSION 2.5.0)
+set(OPENJPEG_SHORT_VERSION 2.5)
set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz)
-set(OPENJPEG_HASH 8702ba68b442657f11aaeb2b338443ca8d5fb95b0d845757968a7be31ef7f16d)
+set(OPENJPEG_HASH 0333806d6adecc6f7a91243b2b839ff4d2053823634d4f6ed7a59bc87409122a)
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_VERSION 5.1.2)
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
-set(FFMPEG_HASH c0130b8db2c763430fd1c6905288d61bc44ee0548ad5fcd2dfd650b88432bed9)
+set(FFMPEG_HASH 39a0bcc8d98549f16c570624678246a6ac736c066cebdb409f9502e915b22f2b)
set(FFMPEG_HASH_TYPE SHA256)
set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2)
set(FFMPEG_CPE "cpe:2.3:a:ffmpeg:ffmpeg:${FFMPEG_VERSION}:*:*:*:*:*:*:*")
@@ -325,9 +325,9 @@ set(ICONV_HASH 7d2a800b952942bb2880efb00cfd524c)
set(ICONV_HASH_TYPE MD5)
set(ICONV_FILE libiconv-${ICONV_VERSION}.tar.gz)
-set(SNDFILE_VERSION 1.0.28)
-set(SNDFILE_URI http://www.mega-nerd.com/libsndfile/files/libsndfile-${SNDFILE_VERSION}.tar.gz)
-set(SNDFILE_HASH 646b5f98ce89ac60cdb060fcd398247c)
+set(SNDFILE_VERSION 1.1.0)
+set(SNDFILE_URI https://github.com/libsndfile/libsndfile/releases/download/1.1.0/libsndfile-${SNDFILE_VERSION}.tar.xz)
+set(SNDFILE_HASH e63dead2b4f0aaf323687619d007ee6a)
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}:*:*:*:*:*:*:*")
@@ -351,21 +351,13 @@ set(JEMALLOC_HASH 3d41fbf006e6ebffd489bdb304d009ae)
set(JEMALLOC_HASH_TYPE MD5)
set(JEMALLOC_FILE jemalloc-${JEMALLOC_VERSION}.tar.bz2)
-set(XML2_VERSION 2.9.10)
-set(XML2_URI http://xmlsoft.org/sources/libxml2-${XML2_VERSION}.tar.gz)
-set(XML2_HASH 10942a1dc23137a8aa07f0639cbfece5)
+set(XML2_VERSION 2.10.3)
+set(XML2_URI https://download.gnome.org/sources/libxml2/2.10/libxml2-${XML2_VERSION}.tar.xz)
+set(XML2_HASH f9edac7fac232b3657a003fd9a5bbe42)
set(XML2_HASH_TYPE MD5)
-set(XML2_FILE libxml2-${XML2_VERSION}.tar.gz)
+set(XML2_FILE libxml2-${XML2_VERSION}.tar.xz)
set(XML2_CPE "cpe:2.3:a:xmlsoft:libxml2:${XML2_VERSION}:*:*:*:*:*:*:*")
-set(TINYXML_VERSION 2_6_2)
-set(TINYXML_VERSION_DOTS 2.6.2)
-set(TINYXML_URI https://nchc.dl.sourceforge.net/project/tinyxml/tinyxml/${TINYXML_VERSION_DOTS}/tinyxml_${TINYXML_VERSION}.tar.gz)
-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)
@@ -379,10 +371,10 @@ set(PYSTRING_HASH f2c68786b359f5e4e62bed53bc4fb86d)
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_VERSION 2_4_9)
+set(EXPAT_VERSION_DOTS 2.4.9)
set(EXPAT_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz)
-set(EXPAT_HASH 2d3e81dee94b452369dc6394ff0f8f98)
+set(EXPAT_HASH b59a2aa796be1ee177bbab3b7231dfa5)
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}:*:*:*:*:*:*:*")
@@ -410,6 +402,10 @@ set(FLEX_FILE flex-${FLEX_VERSION}.tar.gz)
# NOTE: bzip.org domain does no longer belong to BZip 2 project, so we download
# sources from Debian packaging.
+#
+# NOTE 2: This will *HAVE* to match the version python ships on windows which
+# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there
+# can be no exceptions to this.
set(BZIP2_VERSION 1.0.8)
set(BZIP2_URI http://http.debian.net/debian/pool/main/b/bzip2/bzip2_${BZIP2_VERSION}.orig.tar.gz)
set(BZIP2_HASH ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269)
@@ -417,6 +413,9 @@ 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}:*:*:*:*:*:*:*")
+# NOTE: This will *HAVE* to match the version python ships on windows which
+# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there
+# can be no exceptions to this.
set(FFI_VERSION 3.3)
set(FFI_URI https://sourceware.org/pub/libffi/libffi-${FFI_VERSION}.tar.gz)
set(FFI_HASH 72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056)
@@ -430,27 +429,25 @@ set(LZMA_HASH 5117f930900b341493827d63aa910ff5e011e0b994197c3b71c08a20228a42df)
set(LZMA_HASH_TYPE SHA256)
set(LZMA_FILE xz-${LZMA_VERSION}.tar.bz2)
-if(BLENDER_PLATFORM_ARM)
- # Need at least 1.1.1i for aarch64 support (https://github.com/openssl/openssl/pull/13218)
- set(SSL_VERSION 1.1.1i)
- set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
- set(SSL_HASH e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242)
- set(SSL_HASH_TYPE SHA256)
- set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
-else()
- set(SSL_VERSION 1.1.1g)
- set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
- set(SSL_HASH ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46)
- set(SSL_HASH_TYPE SHA256)
- set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
-endif()
+# NOTE: This will *HAVE* to match the version python ships on windows which
+# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there
+# can be no exceptions to this.
+set(SSL_VERSION 1.1.1q)
+set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
+set(SSL_HASH d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca)
+set(SSL_HASH_TYPE SHA256)
+set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
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)
+# Note: This will *HAVE* to match the version python ships on windows which
+# is hardcoded in pythons PCbuild/get_externals.bat for compliance reasons there
+# can be no exceptions to this.
+set(SQLITE_VERSION 3.37.2)
+set(SQLLITE_LONG_VERSION 3370200)
+set(SQLITE_URI https://www.sqlite.org/2022/sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
+set(SQLITE_HASH e56faacadfb4154f8fbd0f2a3f827d13706b70a1)
set(SQLITE_HASH_TYPE SHA1)
-set(SQLITE_FILE sqlite-src-3240000.zip)
+set(SQLITE_FILE sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*")
set(EMBREE_VERSION 3.13.4)
@@ -564,19 +561,19 @@ set(BROTLI_CPE "cpe:2.3:a:google:brotli:${BROTLI_VERSION}:*:*:*:*:*:*:*")
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 58d5b65c533ce6cac3f7e1d51cf169a5411adf356abcd85f04049bbcaecc2e77)
+set(OPENPGL_HASH 1f090f88ab2bad028e8b3619aa926f4f97cf7b2c175b904704d2fec8593dd3cd)
set(OPENPGL_HASH_TYPE SHA256)
set(OPENPGL_FILE openpgl-${OPENPGL_VERSION}.tar.gz)
-set(LEVEL_ZERO_VERSION v1.7.15)
+set(LEVEL_ZERO_VERSION v1.8.5)
set(LEVEL_ZERO_URI https://github.com/oneapi-src/level-zero/archive/refs/tags/${LEVEL_ZERO_VERSION}.tar.gz)
-set(LEVEL_ZERO_HASH c39bb05a8e5898aa6c444e1704105b93d3f1888b9c333f8e7e73825ffbfb2617)
+set(LEVEL_ZERO_HASH b6e9663bbcc53c148d32376998298bec6f7c434ef2218c61fa708963e3a09394)
set(LEVEL_ZERO_HASH_TYPE SHA256)
set(LEVEL_ZERO_FILE level-zero-${LEVEL_ZERO_VERSION}.tar.gz)
-set(DPCPP_VERSION 20220812)
+set(DPCPP_VERSION 20221019)
set(DPCPP_URI https://github.com/intel/llvm/archive/refs/tags/sycl-nightly/${DPCPP_VERSION}.tar.gz)
-set(DPCPP_HASH 0e3c95346c295f5cf80f3a42d80b1c49481955898530242636ddc002627248d6)
+set(DPCPP_HASH 2f533946e91ce3829431758ea17b0b834b960c1a796e9e4563c86e03eb9603a2)
set(DPCPP_HASH_TYPE SHA256)
set(DPCPP_FILE DPCPP-${DPCPP_VERSION}.tar.gz)
@@ -589,9 +586,9 @@ set(DPCPP_FILE DPCPP-${DPCPP_VERSION}.tar.gz)
# will take care of building them, unpack is being done in dpcpp_deps.cmake
# Source llvm/lib/SYCLLowerIR/CMakeLists.txt
-set(VCINTRINSICS_VERSION 984bb27baacce6ee5c716c2e64845f2a1928025b)
+set(VCINTRINSICS_VERSION abce9184b7a3a7fe1b02289b9285610d9dc45465)
set(VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/${VCINTRINSICS_VERSION}.tar.gz)
-set(VCINTRINSICS_HASH abea415a15a0dd11fdc94dee8fb462910f2548311b787e02f42509789e1b0d7b)
+set(VCINTRINSICS_HASH 3e9fd471246b87633b26f7e15e17ab7733d357458c53d5c5881c03929d6c551f)
set(VCINTRINSICS_HASH_TYPE SHA256)
set(VCINTRINSICS_FILE vc-intrinsics-${VCINTRINSICS_VERSION}.tar.gz)
@@ -603,9 +600,9 @@ set(OPENCLHEADERS_HASH_TYPE SHA256)
set(OPENCLHEADERS_FILE opencl_headers-${OPENCLHEADERS_VERSION}.tar.gz)
# Source opencl/CMakeLists.txt
-set(ICDLOADER_VERSION aec3952654832211636fc4af613710f80e203b0a)
+set(ICDLOADER_VERSION 792682ad3d877ab38573b997808bab3b43902b70)
set(ICDLOADER_URI https://github.com/KhronosGroup/OpenCL-ICD-Loader/archive/${ICDLOADER_VERSION}.tar.gz)
-set(ICDLOADER_HASH e1880551d67bd8dc31d13de63b94bbfd6b1f315b6145dad1ffcd159b89bda93c)
+set(ICDLOADER_HASH b33a0320d94bf300efa1da97931ded506d27813bd1148da6858fe79d412d1ea2)
set(ICDLOADER_HASH_TYPE SHA256)
set(ICDLOADER_FILE icdloader-${ICDLOADER_VERSION}.tar.gz)
@@ -620,9 +617,9 @@ set(MP11_FILE mp11-${MP11_VERSION}.tar.gz)
# Source llvm-spirv/CMakeLists.txt (repo)
# Source llvm-spirv/spirv-headers-tag.conf (hash)
-set(SPIRV_HEADERS_VERSION 36c0c1596225e728bd49abb7ef56a3953e7ed468)
+set(SPIRV_HEADERS_VERSION 5a121866927a16ab9d49bed4788b532c7fcea766)
set(SPIRV_HEADERS_URI https://github.com/KhronosGroup/SPIRV-Headers/archive/${SPIRV_HEADERS_VERSION}.tar.gz)
-set(SPIRV_HEADERS_HASH 7a5c89633f8740456fe8adee052033e134476d267411d1336c0cb1e587a9229a)
+set(SPIRV_HEADERS_HASH ec8ecb471a62672697846c436501638ab25447ae9d4a6761e0bfe8a9a839502a)
set(SPIRV_HEADERS_HASH_TYPE SHA256)
set(SPIRV_HEADERS_FILE SPIR-V-Headers-${SPIRV_HEADERS_VERSION}.tar.gz)
@@ -637,9 +634,9 @@ set(SPIRV_HEADERS_FILE SPIR-V-Headers-${SPIRV_HEADERS_VERSION}.tar.gz)
# compiler, the versions used are taken from the following location
# https://github.com/intel/intel-graphics-compiler/releases
-set(IGC_VERSION 1.0.11222)
+set(IGC_VERSION 1.0.12149.1)
set(IGC_URI https://github.com/intel/intel-graphics-compiler/archive/refs/tags/igc-${IGC_VERSION}.tar.gz)
-set(IGC_HASH d92f0608dcbb52690855685f9447282e5c09c0ba98ae35fabf114fcf8b1e9fcf)
+set(IGC_HASH 44f67f24e3bc5130f9f062533abf8154782a9d0a992bc19b498639a8521ae836)
set(IGC_HASH_TYPE SHA256)
set(IGC_FILE igc-${IGC_VERSION}.tar.gz)
@@ -659,15 +656,15 @@ set(IGC_LLVM_FILE ${IGC_LLVM_VERSION}.tar.gz)
#
# WARNING WARNING WARNING
-set(IGC_OPENCL_CLANG_VERSION bbdd1587f577397a105c900be114b56755d1f7dc)
+set(IGC_OPENCL_CLANG_VERSION 363a5262d8c7cff3fb28f3bdb5d85c8d7e91c1bb)
set(IGC_OPENCL_CLANG_URI https://github.com/intel/opencl-clang/archive/${IGC_OPENCL_CLANG_VERSION}.tar.gz)
-set(IGC_OPENCL_CLANG_HASH d08315f1b0d8a6fef33de2b3e6aa7356534c324910634962c72523d970773efc)
+set(IGC_OPENCL_CLANG_HASH aa8cf72bb239722ce8ce44f79413c6887ecc8ca18477dd520aa5c4809756da9a)
set(IGC_OPENCL_CLANG_HASH_TYPE SHA256)
set(IGC_OPENCL_CLANG_FILE opencl-clang-${IGC_OPENCL_CLANG_VERSION}.tar.gz)
-set(IGC_VCINTRINSICS_VERSION v0.4.0)
+set(IGC_VCINTRINSICS_VERSION v0.5.0)
set(IGC_VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/refs/tags/${IGC_VCINTRINSICS_VERSION}.tar.gz)
-set(IGC_VCINTRINSICS_HASH c8b92682ad5031cf9d5b82a40e7d5c0e763cd9278660adbcaa69aab988e4b589)
+set(IGC_VCINTRINSICS_HASH 70bb47c5e32173cf61514941e83ae7c7eb4485e6d2fca60cfa1f50d4f42c41f2)
set(IGC_VCINTRINSICS_HASH_TYPE SHA256)
set(IGC_VCINTRINSICS_FILE vc-intrinsics-${IGC_VCINTRINSICS_VERSION}.tar.gz)
@@ -683,9 +680,9 @@ set(IGC_SPIRV_TOOLS_HASH 6e19900e948944243024aedd0a201baf3854b377b9cc7a386553bc1
set(IGC_SPIRV_TOOLS_HASH_TYPE SHA256)
set(IGC_SPIRV_TOOLS_FILE SPIR-V-Tools-${IGC_SPIRV_TOOLS_VERSION}.tar.gz)
-set(IGC_SPIRV_TRANSLATOR_VERSION 99420daab98998a7e36858befac9c5ed109d4920)
+set(IGC_SPIRV_TRANSLATOR_VERSION a31ffaeef77e23d500b3ea3d35e0c42ff5648ad9)
set(IGC_SPIRV_TRANSLATOR_URI https://github.com/KhronosGroup/SPIRV-LLVM-Translator/archive/${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz)
-set(IGC_SPIRV_TRANSLATOR_HASH 77dfb4ddb6bfb993535562c02ddea23f0a0d1c5a0258c1afe7e27c894ff783a8)
+set(IGC_SPIRV_TRANSLATOR_HASH 9e26c96a45341b8f8af521bacea20e752623346340addd02af95d669f6e89252)
set(IGC_SPIRV_TRANSLATOR_HASH_TYPE SHA256)
set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz)
@@ -693,15 +690,15 @@ set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.
### Intel Graphics Compiler DEPS END ###
########################################
-set(GMMLIB_VERSION intel-gmmlib-22.1.2)
+set(GMMLIB_VERSION intel-gmmlib-22.1.8)
set(GMMLIB_URI https://github.com/intel/gmmlib/archive/refs/tags/${GMMLIB_VERSION}.tar.gz)
-set(GMMLIB_HASH 3b9a6d5e7e3f5748b3d0a2fb0e980ae943907fece0980bd9c0508e71c838e334)
+set(GMMLIB_HASH bf23e9a3742b4fb98c7666c9e9b29f3219e4b2fb4d831aaf4eed71f5e2d17368)
set(GMMLIB_HASH_TYPE SHA256)
set(GMMLIB_FILE ${GMMLIB_VERSION}.tar.gz)
-set(OCLOC_VERSION 22.20.23198)
+set(OCLOC_VERSION 22.38.24278)
set(OCLOC_URI https://github.com/intel/compute-runtime/archive/refs/tags/${OCLOC_VERSION}.tar.gz)
-set(OCLOC_HASH ab22b8bf2560a57fdd3def0e35a62ca75991406f959c0263abb00cd6cd9ae998)
+set(OCLOC_HASH db0c542fccd651e6404b15a74d46027f1ce0eda8dc9e25a40cbb6c0faef257ee)
set(OCLOC_HASH_TYPE SHA256)
set(OCLOC_FILE ocloc-${OCLOC_VERSION}.tar.gz)
diff --git a/build_files/build_environment/cmake/wayland.cmake b/build_files/build_environment/cmake/wayland.cmake
index 799f2513da9..c73db1d10ff 100644
--- a/build_files/build_environment/cmake/wayland.cmake
+++ b/build_files/build_environment/cmake/wayland.cmake
@@ -7,10 +7,14 @@ ExternalProject_Add(external_wayland
PREFIX ${BUILD_DIR}/wayland
PATCH_COMMAND ${PATCH_CMD} -d ${BUILD_DIR}/wayland/src/external_wayland < ${PATCH_DIR}/wayland.diff
# Use `-E` so the `PKG_CONFIG_PATH` can be defined to link against our own LIBEXPAT & LIBXML2.
- # Note that passing link args "ffi/lib" should not be needed, but
+ #
+ # NOTE: passing link args "ffi/lib" should not be needed, but
# `pkgconfig` would incorrectly look in "ffi/lib/../lib64" otherwise.
+ #
+ # NOTE: `-lm` is needed for `libxml2` which is a static library that uses `libm.so`,
+ # without this, math symbols such as `floor` aren't found.
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/expat/lib/pkgconfig:${LIBDIR}/xml2/lib/pkgconfig:${LIBDIR}/ffi/lib/pkgconfig:$PKG_CONFIG_PATH
- meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -Dc_link_args=-L${LIBDIR}/ffi/lib . ../external_wayland
+ meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -D "c_link_args=-L${LIBDIR}/ffi/lib -lm" . ../external_wayland
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
)
diff --git a/build_files/build_environment/cmake/xml2.cmake b/build_files/build_environment/cmake/xml2.cmake
index cd24fd836b0..3d31ec131bb 100644
--- a/build_files/build_environment/cmake/xml2.cmake
+++ b/build_files/build_environment/cmake/xml2.cmake
@@ -1,20 +1,48 @@
# SPDX-License-Identifier: GPL-2.0-or-later
-ExternalProject_Add(external_xml2
- URL file://${PACKAGE_DIR}/${XML2_FILE}
- DOWNLOAD_DIR ${DOWNLOAD_DIR}
- URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH}
- PREFIX ${BUILD_DIR}/xml2
- CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && ${CONFIGURE_COMMAND}
- --prefix=${LIBDIR}/xml2
- --disable-shared
- --enable-static
- --with-pic
- --with-python=no
- --with-lzma=no
- --with-zlib=no
- --with-iconv=no
- BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make -j${MAKE_THREADS}
- INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make install
- INSTALL_DIR ${LIBDIR}/xml2
-)
+if(WIN32)
+ set(XML2_EXTRA_ARGS
+ -DLIBXML2_WITH_ZLIB=OFF
+ -DLIBXML2_WITH_LZMA=OFF
+ -DLIBXML2_WITH_PYTHON=OFF
+ -DLIBXML2_WITH_ICONV=OFF
+ -DLIBXML2_WITH_TESTS=OFF
+ -DLIBXML2_WITH_PROGRAMS=OFF
+ -DBUILD_SHARED_LIBS=OFF
+ )
+ ExternalProject_Add(external_xml2
+ URL file://${PACKAGE_DIR}/${XML2_FILE}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH}
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/xml2 ${DEFAULT_CMAKE_FLAGS} ${XML2_EXTRA_ARGS}
+ PREFIX ${BUILD_DIR}/xml2
+ INSTALL_DIR ${LIBDIR}/xml2
+ )
+else()
+ ExternalProject_Add(external_xml2
+ URL file://${PACKAGE_DIR}/${XML2_FILE}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH}
+ PREFIX ${BUILD_DIR}/xml2
+ CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && ${CONFIGURE_COMMAND}
+ --prefix=${LIBDIR}/xml2
+ --disable-shared
+ --enable-static
+ --with-pic
+ --with-python=no
+ --with-lzma=no
+ --with-zlib=no
+ --with-iconv=no
+ BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make -j${MAKE_THREADS}
+ INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make install
+ INSTALL_DIR ${LIBDIR}/xml2
+ )
+endif()
+
+if(WIN32 AND BUILD_MODE STREQUAL Release)
+ ExternalProject_Add_Step(external_xml2 after_install
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/xml2/include ${HARVEST_TARGET}/xml2/include
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/xml2/lib/libxml2s.lib ${HARVEST_TARGET}/xml2/lib/libxml2s.lib
+ DEPENDEES install
+ )
+endif()
diff --git a/build_files/build_environment/dependencies.dot b/build_files/build_environment/dependencies.dot
index 7e8637fbced..bb42856c3ac 100644
--- a/build_files/build_environment/dependencies.dot
+++ b/build_files/build_environment/dependencies.dot
@@ -1,96 +1,114 @@
strict graph {
-graph[autosize = false, size = "25.7,8.3!", resolution = 300, overlap = false, splines = false, outputorder=edgesfirst ];
- node [style=filled fillcolor=white];
- external_alembic -- external_boost;
- external_alembic -- external_zlib;
+graph[autosize = false, size = "25.7,8.3!", resolution = 300];
external_alembic -- external_openexr;
+ external_alembic -- external_imath;
external_blosc -- external_zlib;
external_blosc -- external_pthreads;
- external_boost -- Make_Python_Environment;
- external_clang -- ll;
+ external_boost -- external_python;
+ external_boost -- external_numpy;
+ external_dpcpp -- external_python;
+ external_dpcpp -- external_python_site_packages;
+ external_dpcpp -- external_vcintrinsics;
+ external_dpcpp -- external_openclheaders;
+ external_dpcpp -- external_icdloader;
+ external_dpcpp -- external_mp11;
+ external_dpcpp -- external_level_zero;
+ external_dpcpp -- external_spirvheaders;
+ external_embree -- external_tbb;
external_ffmpeg -- external_zlib;
- external_ffmpeg -- external_faad;
external_ffmpeg -- external_openjpeg;
external_ffmpeg -- external_xvidcore;
external_ffmpeg -- external_x264;
+ external_ffmpeg -- external_opus;
external_ffmpeg -- external_vpx;
external_ffmpeg -- external_theora;
external_ffmpeg -- external_vorbis;
external_ffmpeg -- external_ogg;
external_ffmpeg -- external_lame;
+ external_ffmpeg -- external_aom;
external_ffmpeg -- external_zlib_mingw;
- external_numpy -- Make_Python_Environment;
+ external_ffmpeg -- external_nasm;
+ external_freetype -- external_brotli;
+ external_freetype -- external_zlib;
+ external_gmpxx -- external_gmp;
+ external_igc_llvm -- external_igc_opencl_clang;
+ external_igc_spirv_translator -- external_igc_opencl_clang;
+ external_igc -- external_igc_vcintrinsics;
+ external_igc -- external_igc_llvm;
+ external_igc -- external_igc_opencl_clang;
+ external_igc -- external_igc_vcintrinsics;
+ external_igc -- external_igc_spirv_headers;
+ external_igc -- external_igc_spirv_tools;
+ external_igc -- external_igc_spirv_translator;
+ external_igc -- external_flex;
+ external_ispc -- ll;
+ external_ispc -- external_python;
+ external_ispc -- external_flexbison;
+ external_ispc -- external_flex;
+ ll -- external_xml2;
+ ll -- external_python;
+ external_mesa -- ll;
+ external_numpy -- external_python;
+ external_numpy -- external_python_site_packages;
+ external_ocloc -- external_igc;
+ external_ocloc -- external_gmmlib;
external_opencollada -- external_xml2;
- external_opencolorio -- external_boost;
- external_opencolorio -- external_tinyxml;
external_opencolorio -- external_yamlcpp;
+ external_opencolorio -- external_expat;
+ external_opencolorio -- external_imath;
+ external_opencolorio -- external_pystring;
external_openexr -- external_zlib;
+ external_openimagedenoise -- external_tbb;
+ external_openimagedenoise -- external_ispc;
+ external_openimagedenoise -- external_python;
external_openimageio -- external_png;
external_openimageio -- external_zlib;
external_openimageio -- external_openexr;
- external_openimageio -- external_openexr;
+ external_openimageio -- external_imath;
external_openimageio -- external_jpeg;
external_openimageio -- external_boost;
external_openimageio -- external_tiff;
- external_openimageio -- external_opencolorio;
+ external_openimageio -- external_pugixml;
+ external_openimageio -- external_fmt;
+ external_openimageio -- external_robinmap;
external_openimageio -- external_openjpeg;
external_openimageio -- external_webp;
- external_openimageio -- external_opencolorio_extra;
- external_openmp -- external_clang;
+ external_openmp -- ll;
+ external_openpgl -- external_tbb;
external_opensubdiv -- external_tbb;
openvdb -- external_tbb;
openvdb -- external_boost;
- openvdb -- external_openexr;
- openvdb -- external_openexr;
openvdb -- external_zlib;
openvdb -- external_blosc;
external_osl -- external_boost;
external_osl -- ll;
- external_osl -- external_clang;
- external_osl -- external_openexr;
external_osl -- external_openexr;
external_osl -- external_zlib;
- external_osl -- external_flexbison;
external_osl -- external_openimageio;
external_osl -- external_pugixml;
+ external_osl -- external_flexbison;
+ external_osl -- external_flex;
external_png -- external_zlib;
- external_python_site_packages -- Make_Python_Environment;
+ external_python -- external_bzip2;
+ external_python -- external_ffi;
+ external_python -- external_lzma;
+ external_python -- external_ssl;
+ external_python -- external_sqlite;
+ external_python -- external_zlib;
+ external_python_site_packages -- external_python;
external_sndfile -- external_ogg;
external_sndfile -- external_vorbis;
external_sndfile -- external_flac;
external_theora -- external_vorbis;
external_theora -- external_ogg;
external_tiff -- external_zlib;
+ external_usd -- external_tbb;
+ external_usd -- external_boost;
+ external_usd -- external_opensubdiv;
external_vorbis -- external_ogg;
- blender-- external_ffmpeg;
- blender-- external_alembic;
- blender-- external_openjpeg;
- blender-- external_opencolorio;
- blender-- external_openexr;
- blender-- external_opensubdiv;
- blender-- openvdb;
- blender-- external_osl;
- blender-- external_boost;
- blender-- external_jpeg;
- blender-- external_png;
- blender-- external_python;
- blender-- external_sndfile;
- blender-- external_iconv;
- blender-- external_fftw3;
- external_python-- external_python_site_packages;
- external_python_site_packages-- requests;
- external_python_site_packages-- idna;
- external_python_site_packages-- chardet;
- external_python_site_packages-- urllib3;
- external_python_site_packages-- certifi;
- external_python-- external_numpy;
- external_usd-- external_boost;
- external_usd-- external_tbb;
- blender-- external_opencollada;
- blender-- external_sdl;
- blender-- external_freetype;
- blender-- external_pthreads;
- blender-- external_zlib;
- blender-- external_openal;
- blender-- external_usd;
+ external_wayland -- external_expat;
+ external_wayland -- external_xml2;
+ external_wayland -- external_ffi;
+ external_wayland_protocols -- external_wayland;
+ external_x264 -- external_nasm;
}
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index f913ac5e73c..5a191f7669b 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -394,7 +394,7 @@ CLANG_FORMAT_VERSION="10.0"
CLANG_FORMAT_VERSION_MIN="6.0"
CLANG_FORMAT_VERSION_MEX="14.0"
-PYTHON_VERSION="3.10.2"
+PYTHON_VERSION="3.10.8"
PYTHON_VERSION_SHORT="3.10"
PYTHON_VERSION_MIN="3.10"
PYTHON_VERSION_MEX="3.12"
@@ -505,7 +505,7 @@ OPENEXR_FORCE_REBUILD=false
OPENEXR_SKIP=false
_with_built_openexr=false
-OIIO_VERSION="2.3.13.0"
+OIIO_VERSION="2.3.20.0"
OIIO_VERSION_SHORT="2.3"
OIIO_VERSION_MIN="2.1.12"
OIIO_VERSION_MEX="2.4.0"
@@ -523,8 +523,8 @@ LLVM_FORCE_REBUILD=false
LLVM_SKIP=false
# OSL needs to be compiled for now!
-OSL_VERSION="1.11.17.0"
-OSL_VERSION_SHORT="1.11"
+OSL_VERSION="1.12.6.2"
+OSL_VERSION_SHORT="1.12"
OSL_VERSION_MIN="1.11"
OSL_VERSION_MEX="2.0"
OSL_FORCE_BUILD=false
@@ -602,10 +602,10 @@ LEVEL_ZERO_FORCE_BUILD=false
LEVEL_ZERO_FORCE_REBUILD=false
LEVEL_ZERO_SKIP=false
-OPENPGL_VERSION="0.3.1"
-OPENPGL_VERSION_SHORT="0.3"
+OPENPGL_VERSION="0.4.0"
+OPENPGL_VERSION_SHORT="0.4"
OPENPGL_VERSION_MIN="0.3.1"
-OPENPGL_VERSION_MEX="0.3.2"
+OPENPGL_VERSION_MEX="0.5"
OPENPGL_FORCE_BUILD=false
OPENPGL_FORCE_REBUILD=false
OPENPGL_SKIP=false
@@ -618,8 +618,8 @@ XR_OPENXR_FORCE_BUILD=false
XR_OPENXR_FORCE_REBUILD=false
XR_OPENXR_SKIP=false
-FFMPEG_VERSION="5.0"
-FFMPEG_VERSION_SHORT="5.0"
+FFMPEG_VERSION="5.1.2"
+FFMPEG_VERSION_SHORT="5.1"
FFMPEG_VERSION_MIN="4.0"
FFMPEG_VERSION_MEX="6.0"
FFMPEG_FORCE_BUILD=false
@@ -1139,7 +1139,7 @@ LLVM_SOURCE=( "$_LLVM_SOURCE_ROOT/llvm-$LLVM_VERSION.src.tar.xz" )
LLVM_CLANG_SOURCE=( "$_LLVM_SOURCE_ROOT/clang-$LLVM_VERSION.src.tar.xz" "$_LLVM_SOURCE_ROOT/cfe-$LLVM_VERSION.src.tar.xz" )
OSL_USE_REPO=false
-OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/Release-$OSL_VERSION.tar.gz" )
+OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/v$OSL_VERSION.tar.gz" )
#~ OSL_SOURCE_REPO=( "https://github.com/imageworks/OpenShadingLanguage.git" )
#~ OSL_SOURCE_REPO_BRANCH="master"
#~ OSL_SOURCE_REPO_UID="85179714e1bc69cd25ecb6bb711c1a156685d395"
diff --git a/build_files/build_environment/patches/aom.diff b/build_files/build_environment/patches/aom.diff
new file mode 100644
index 00000000000..1611cff5dca
--- /dev/null
+++ b/build_files/build_environment/patches/aom.diff
@@ -0,0 +1,18 @@
+diff -Naur libaom-3.4.0/build/cmake/aom_configure.cmake external_aom/build/cmake/aom_configure.cmake
+--- libaom-3.4.0/build/cmake/aom_configure.cmake 2022-06-17 11:46:18 -0600
++++ external_aom/build/cmake/aom_configure.cmake 2022-10-16 15:35:54 -0600
+@@ -15,8 +15,12 @@
+
+ include(FindGit)
+ include(FindPerl)
+-include(FindThreads)
+-
++# Blender: This will drag in a dep on libwinpthreads which we prefer
++# not to have, aom will fallback on a native win32 thread wrapper
++# if pthreads are not found.
++if(NOT WIN32)
++ include(FindThreads)
++endif()
+ include("${AOM_ROOT}/build/cmake/aom_config_defaults.cmake")
+ include("${AOM_ROOT}/build/cmake/aom_experiment_deps.cmake")
+ include("${AOM_ROOT}/build/cmake/aom_optimization.cmake")
diff --git a/build_files/build_environment/patches/ffmpeg.diff b/build_files/build_environment/patches/ffmpeg.diff
index c255f7c37a3..ac104a20ffe 100644
--- a/build_files/build_environment/patches/ffmpeg.diff
+++ b/build_files/build_environment/patches/ffmpeg.diff
@@ -68,34 +68,18 @@
+
return ret;
}
---- a/libavcodec/rl.c
-+++ b/libavcodec/rl.c
-@@ -71,17 +71,19 @@
- av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size)
- {
- int i, q;
-- VLC_TYPE table[1500][2] = {{0}};
-+ VLC_TYPE (*table)[2] = av_calloc(sizeof(VLC_TYPE), 1500 * 2);
- VLC vlc = { .table = table, .table_allocated = static_size };
-- av_assert0(static_size <= FF_ARRAY_ELEMS(table));
-+ av_assert0(static_size < 1500);
- init_vlc(&vlc, 9, rl->n + 1, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC);
+diff --git a/libavcodec/x86/simple_idct.asm b/libavcodec/x86/simple_idct.asm
+index dcf0da6df121..982b2f0bbba1 100644
+--- a/libavcodec/x86/simple_idct.asm
++++ b/libavcodec/x86/simple_idct.asm
+@@ -25,9 +25,9 @@
- for (q = 0; q < 32; q++) {
- int qmul = q * 2;
- int qadd = (q - 1) | 1;
+ %include "libavutil/x86/x86util.asm"
-- if (!rl->rl_vlc[q])
-+ if (!rl->rl_vlc[q]){
-+ av_free(table);
- return;
-+ }
+-%if ARCH_X86_32
+ SECTION_RODATA
- if (q == 0) {
- qmul = 1;
-@@ -113,4 +115,5 @@
- rl->rl_vlc[q][i].run = run;
- }
- }
-+ av_free(table);
- }
++%if ARCH_X86_32
+ cextern pb_80
+
+ wm1010: dw 0, 0xffff, 0, 0xffff
diff --git a/build_files/build_environment/patches/gmp.diff b/build_files/build_environment/patches/gmp.diff
new file mode 100644
index 00000000000..bf22f93bc4f
--- /dev/null
+++ b/build_files/build_environment/patches/gmp.diff
@@ -0,0 +1,15 @@
+--- a/mpz/inp_raw.c Tue Dec 22 23:49:51 2020 +0100
++++ b/mpz/inp_raw.c Thu Oct 21 19:06:49 2021 +0200
+@@ -88,8 +88,11 @@
+
+ abs_csize = ABS (csize);
+
++ if (UNLIKELY (abs_csize > ~(mp_bitcnt_t) 0 / 8))
++ return 0; /* Bit size overflows */
++
+ /* round up to a multiple of limbs */
+- abs_xsize = BITS_TO_LIMBS (abs_csize*8);
++ abs_xsize = BITS_TO_LIMBS ((mp_bitcnt_t) abs_csize * 8);
+
+ if (abs_xsize != 0)
+ {
diff --git a/build_files/build_environment/patches/opencollada.diff b/build_files/build_environment/patches/opencollada.diff
index e8efc1a6909..02eab251a13 100644
--- a/build_files/build_environment/patches/opencollada.diff
+++ b/build_files/build_environment/patches/opencollada.diff
@@ -130,3 +130,28 @@ index 715d903..24423ce 100644
{
string id = node.attribute("id").value();
size_t line = node.line();
+diff -Naur a/CMakeLists.txt b/CMakeLists.txt
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -274,7 +274,7 @@
+ add_subdirectory(${EXTERNAL_LIBRARIES}/UTF)
+ add_subdirectory(common/libBuffer)
+ add_subdirectory(${EXTERNAL_LIBRARIES}/MathMLSolver)
+-add_subdirectory(${EXTERNAL_LIBRARIES}/zlib)
++#add_subdirectory(${EXTERNAL_LIBRARIES}/zlib)
+
+ # building OpenCOLLADA libs
+ add_subdirectory(COLLADABaseUtils)
+@@ -284,10 +284,10 @@
+ add_subdirectory(COLLADAStreamWriter)
+
+ # building COLLADAValidator app
+-add_subdirectory(COLLADAValidator)
++#add_subdirectory(COLLADAValidator)
+
+ # DAE validator app
+-add_subdirectory(DAEValidator)
++#add_subdirectory(DAEValidator)
+
+ # Library export
+ install(EXPORT LibraryExport DESTINATION ${OPENCOLLADA_INST_CMAKECONFIG} FILE OpenCOLLADATargets.cmake)
diff --git a/build_files/build_environment/patches/osl.diff b/build_files/build_environment/patches/osl.diff
index 28e1d6e101d..3f4a485b037 100644
--- a/build_files/build_environment/patches/osl.diff
+++ b/build_files/build_environment/patches/osl.diff
@@ -1,67 +1,53 @@
-diff -Naur OpenShadingLanguage-Release-1.9.9/src/include/OSL/llvm_util.h external_osl/src/include/OSL/llvm_util.h
---- OpenShadingLanguage-Release-1.9.9/src/include/OSL/llvm_util.h 2018-05-01 16:39:02 -0600
-+++ external_osl/src/include/OSL/llvm_util.h 2018-08-25 14:05:00 -0600
-@@ -33,6 +33,8 @@
-
- #include <vector>
-
-+#define OSL_HAS_BLENDER_CLEANUP_FIX
-+
- #ifdef LLVM_NAMESPACE
- namespace llvm = LLVM_NAMESPACE;
- #endif
-@@ -487,6 +489,7 @@
- std::string func_name (llvm::Function *f);
-
- static size_t total_jit_memory_held ();
-+ static void Cleanup ();
-
- private:
- class MemoryManager;
-diff -Naur OpenShadingLanguage-Release-1.9.9/src/liboslexec/llvm_util.cpp external_osl/src/liboslexec/llvm_util.cpp
---- OpenShadingLanguage-Release-1.9.9/src/liboslexec/llvm_util.cpp 2018-05-01 16:39:02 -0600
-+++ external_osl/src/liboslexec/llvm_util.cpp 2018-08-25 14:04:27 -0600
-@@ -140,7 +140,10 @@
- };
-
-
--
-+void LLVM_Util::Cleanup ()
-+{
-+ if(jitmm_hold) jitmm_hold->clear();
-+}
-
- size_t
- LLVM_Util::total_jit_memory_held ()
-diff -Naur org/CMakeLists.txt external_osl/CMakeLists.txt
---- org/CMakeLists.txt 2020-12-01 12:37:15 -0700
-+++ external_osl/CMakeLists.txt 2021-01-20 13:26:50 -0700
-@@ -84,6 +84,11 @@
+diff -Naur OpenShadingLanguage-1.12.6.2/CMakeLists.txt external_osl/CMakeLists.txt
+--- OpenShadingLanguage-1.12.6.2/CMakeLists.txt 2022-09-30 17:43:53 -0600
++++ external_osl/CMakeLists.txt 2022-10-15 14:49:26 -0600
+@@ -101,6 +101,11 @@
CACHE STRING "Directory where OptiX PTX files will be installed")
set (CMAKE_DEBUG_POSTFIX "" CACHE STRING "Library naming postfix for Debug builds (e.g., '_debug')")
-
+
+set (USE_OIIO_STATIC ON CACHE BOOL "If OIIO is built static")
+if (USE_OIIO_STATIC)
+ add_definitions ("-DOIIO_STATIC_BUILD=1")
+ add_definitions ("-DOIIO_STATIC_DEFINE=1")
+endif ()
-
+
set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem")
if (OSL_NO_DEFAULT_TEXTURESYSTEM)
-diff -Naur external_osl_orig/src/cmake/externalpackages.cmake external_osl/src/cmake/externalpackages.cmake
---- external_osl_orig/src/cmake/externalpackages.cmake 2021-06-01 13:44:18 -0600
-+++ external_osl/src/cmake/externalpackages.cmake 2021-06-28 07:44:32 -0600
-@@ -80,6 +80,7 @@
-
-
+diff -Naur OpenShadingLanguage-1.12.6.2/src/cmake/externalpackages.cmake external_osl/src/cmake/externalpackages.cmake
+--- OpenShadingLanguage-1.12.6.2/src/cmake/externalpackages.cmake 2022-09-30 17:43:53 -0600
++++ external_osl/src/cmake/externalpackages.cmake 2022-10-15 14:49:26 -0600
+@@ -77,6 +77,7 @@
+
+
checked_find_package (ZLIB REQUIRED) # Needed by several packages
+checked_find_package (PNG REQUIRED) # Needed since OIIO needs it
-
+
# IlmBase & OpenEXR
checked_find_package (OpenEXR REQUIRED
-diff -Naur external_osl_orig/src/liboslcomp/oslcomp.cpp external_osl/src/liboslcomp/oslcomp.cpp
---- external_osl_orig/src/liboslcomp/oslcomp.cpp 2021-06-01 13:44:18 -0600
-+++ external_osl/src/liboslcomp/oslcomp.cpp 2021-06-28 09:11:06 -0600
+diff -Naur OpenShadingLanguage-1.12.6.2/src/include/OSL/llvm_util.h external_osl/src/include/OSL/llvm_util.h
+--- OpenShadingLanguage-1.12.6.2/src/include/OSL/llvm_util.h 2022-09-30 17:43:53 -0600
++++ external_osl/src/include/OSL/llvm_util.h 2022-10-15 15:37:24 -0600
+@@ -9,6 +9,8 @@
+ #include <unordered_set>
+ #include <vector>
+
++#define OSL_HAS_BLENDER_CLEANUP_FIX
++
+ #ifdef LLVM_NAMESPACE
+ namespace llvm = LLVM_NAMESPACE;
+ #endif
+@@ -455,7 +457,7 @@
+ llvm::BasicBlock* masked_return_block() const;
+
+ bool is_masking_required() const { return m_is_masking_required; }
+-
++ static void Cleanup ();
+ struct ScopedMasking {
+ ScopedMasking() {}
+
+diff -Naur OpenShadingLanguage-1.12.6.2/src/liboslcomp/oslcomp.cpp external_osl/src/liboslcomp/oslcomp.cpp
+--- OpenShadingLanguage-1.12.6.2/src/liboslcomp/oslcomp.cpp 2022-09-30 17:43:53 -0600
++++ external_osl/src/liboslcomp/oslcomp.cpp 2022-10-15 14:49:26 -0600
@@ -21,6 +21,13 @@
#if !defined(__STDC_CONSTANT_MACROS)
# define __STDC_CONSTANT_MACROS 1
@@ -76,3 +62,50 @@ diff -Naur external_osl_orig/src/liboslcomp/oslcomp.cpp external_osl/src/liboslc
#include <clang/Basic/TargetInfo.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
+diff -Naur OpenShadingLanguage-1.12.6.2/src/liboslexec/llvm_util.cpp external_osl/src/liboslexec/llvm_util.cpp
+--- OpenShadingLanguage-1.12.6.2/src/liboslexec/llvm_util.cpp 2022-09-30 17:43:53 -0600
++++ external_osl/src/liboslexec/llvm_util.cpp 2022-10-15 15:53:11 -0600
+@@ -116,8 +116,6 @@
+ return { A.data(), size_t(A.size()) };
+ }
+
+-
+-
+ namespace pvt {
+
+ typedef llvm::SectionMemoryManager LLVMMemoryManager;
+@@ -182,6 +180,13 @@
+ ++jit_mem_hold_users;
+ }
+
++void
++LLVM_Util::Cleanup()
++{
++ if (jitmm_hold)
++ jitmm_hold->clear();
++}
++
+
+ LLVM_Util::ScopedJitMemoryUser::~ScopedJitMemoryUser()
+ {
+diff --git a/src/include/OSL/mask.h b/src/include/OSL/mask.h
+index 24197af..b9275f6 100644
+--- a/src/include/OSL/mask.h
++++ b/src/include/OSL/mask.h
+@@ -4,7 +4,6 @@
+
+ #pragma once
+
+-#include <immintrin.h>
+ #include <type_traits>
+
+ #include <OSL/oslconfig.h>
+@@ -23,6 +22,8 @@ using std::countr_zero;
+
+ #elif OSL_INTEL_CLASSIC_COMPILER_VERSION
+
++#include <immintrin.h>
++
+ OSL_FORCEINLINE int popcount(uint32_t x) noexcept { return _mm_popcnt_u32(x);}
+ OSL_FORCEINLINE int popcount(uint64_t x) noexcept { return _mm_popcnt_u64(x); }
+ OSL_FORCEINLINE int countr_zero(uint32_t x) noexcept { return _bit_scan_forward(x); }
diff --git a/build_files/build_environment/patches/python_windows.diff b/build_files/build_environment/patches/python_windows.diff
deleted file mode 100644
index f9c89a90fde..00000000000
--- a/build_files/build_environment/patches/python_windows.diff
+++ /dev/null
@@ -1,24 +0,0 @@
-diff -Naur orig/PCbuild/get_externals.bat Python-3.10.2/PCbuild/get_externals.bat
---- orig/PCbuild/get_externals.bat 2022-01-13 11:52:14 -0700
-+++ Python-3.10.2/PCbuild/get_externals.bat 2022-08-17 11:24:42 -0600
-@@ -51,7 +51,7 @@
- echo.Fetching external libraries...
-
- set libraries=
--set libraries=%libraries% bzip2-1.0.6
-+set libraries=%libraries% bzip2-1.0.8
- if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0
- if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1m
- set libraries=%libraries% sqlite-3.35.5.0
- diff -Naur orig/PCbuild/python.props external_python/PCbuild/python.props
---- orig/PCbuild/python.props 2022-01-13 11:52:14 -0700
-+++ external_python/PCbuild/python.props 2022-08-17 11:38:38 -0600
-@@ -58,7 +58,7 @@
- <ExternalsDir Condition="$(ExternalsDir) == ''">$([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`))</ExternalsDir>
- <ExternalsDir Condition="!HasTrailingSlash($(ExternalsDir))">$(ExternalsDir)\</ExternalsDir>
- <sqlite3Dir>$(ExternalsDir)sqlite-3.35.5.0\</sqlite3Dir>
-- <bz2Dir>$(ExternalsDir)bzip2-1.0.6\</bz2Dir>
-+ <bz2Dir>$(ExternalsDir)bzip2-1.0.8\</bz2Dir>
- <lzmaDir>$(ExternalsDir)xz-5.2.2\</lzmaDir>
- <libffiDir>$(ExternalsDir)libffi-3.3.0\</libffiDir>
- <libffiOutDir>$(ExternalsDir)libffi-3.3.0\$(ArchName)\</libffiOutDir>
diff --git a/build_files/build_environment/patches/sndfile.diff b/build_files/build_environment/patches/sndfile.diff
deleted file mode 100644
index ab43baa78df..00000000000
--- a/build_files/build_environment/patches/sndfile.diff
+++ /dev/null
@@ -1,42 +0,0 @@
---- src/Makefile.in 2017-09-26 01:28:47.000000000 +0300
-+++ src/Makefile.in 2017-09-26 01:19:06.000000000 +0300
-@@ -513,7 +513,7 @@
- libcommon_la_SOURCES = common.c file_io.c command.c pcm.c ulaw.c alaw.c \
- float32.c double64.c ima_adpcm.c ms_adpcm.c gsm610.c dwvw.c vox_adpcm.c \
- interleave.c strings.c dither.c cart.c broadcast.c audio_detect.c \
-- ima_oki_adpcm.c ima_oki_adpcm.h alac.c chunk.c ogg.c chanmap.c \
-+ ima_oki_adpcm.c ima_oki_adpcm.h alac.c chunk.c ogg.c chanmap.c \
- windows.c id3.c $(WIN_VERSION_FILE)
-
-
-@@ -719,10 +719,10 @@
- $(AM_V_CCLD)$(LINK) $(GSM610_libgsm_la_OBJECTS) $(GSM610_libgsm_la_LIBADD) $(LIBS)
-
- libcommon.la: $(libcommon_la_OBJECTS) $(libcommon_la_DEPENDENCIES) $(EXTRA_libcommon_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS)
-+ $(AM_V_CCLD)$(LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS) $(EXTERNAL_XIPH_LIBS)
-
- libsndfile.la: $(libsndfile_la_OBJECTS) $(libsndfile_la_DEPENDENCIES) $(EXTRA_libsndfile_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libsndfile_la_LINK) -rpath $(libdir) $(libsndfile_la_OBJECTS) $(libsndfile_la_LIBADD) $(LIBS)
-+ $(AM_V_CCLD)$(libsndfile_la_LINK) -rpath $(libdir) $(libsndfile_la_OBJECTS) $(libsndfile_la_LIBADD) $(LIBS) $(EXTERNAL_XIPH_LIBS)
-
- clean-checkPROGRAMS:
- @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
-@@ -924,7 +924,7 @@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -c -o libsndfile_la-dwd.lo `test -f 'dwd.c' || echo '$(srcdir)/'`dwd.c
-
- libsndfile_la-flac.lo: flac.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -MT libsndfile_la-flac.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-flac.Tpo -c -o libsndfile_la-flac.lo `test -f 'flac.c' || echo '$(srcdir)/'`flac.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) $(EXTERNAL_XIPH_CFLAGS) -MT libsndfile_la-flac.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-flac.Tpo -c -o libsndfile_la-flac.lo `test -f 'flac.c' || echo '$(srcdir)/'`flac.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsndfile_la-flac.Tpo $(DEPDIR)/libsndfile_la-flac.Plo
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='flac.c' object='libsndfile_la-flac.lo' libtool=yes @AMDEPBACKSLASH@
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@@ -1092,7 +1092,7 @@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -c -o libsndfile_la-rf64.lo `test -f 'rf64.c' || echo '$(srcdir)/'`rf64.c
-
- libsndfile_la-ogg_vorbis.lo: ogg_vorbis.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -MT libsndfile_la-ogg_vorbis.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo -c -o libsndfile_la-ogg_vorbis.lo `test -f 'ogg_vorbis.c' || echo '$(srcdir)/'`ogg_vorbis.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) $(EXTERNAL_XIPH_CFLAGS) -MT libsndfile_la-ogg_vorbis.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo -c -o libsndfile_la-ogg_vorbis.lo `test -f 'ogg_vorbis.c' || echo '$(srcdir)/'`ogg_vorbis.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo $(DEPDIR)/libsndfile_la-ogg_vorbis.Plo
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ogg_vorbis.c' object='libsndfile_la-ogg_vorbis.lo' libtool=yes @AMDEPBACKSLASH@
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
diff --git a/build_files/build_environment/patches/sqlite.diff b/build_files/build_environment/patches/sqlite.diff
deleted file mode 100644
index 80f1384f9cf..00000000000
--- a/build_files/build_environment/patches/sqlite.diff
+++ /dev/null
@@ -1,14 +0,0 @@
-Only in external_sqlite_orig: config.log
-diff -ru external_sqlite_orig/config.sub external_sqlite/config.sub
---- external_sqlite_orig/config.sub 2020-07-10 14:06:42.000000000 +0200
-+++ external_sqlite/config.sub 2020-07-10 14:10:24.000000000 +0200
-@@ -314,6 +314,7 @@
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
-+ | aarch64-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
-Only in external_sqlite: mksourceid
-Only in external_sqlite: sqlite3session.h
diff --git a/build_files/build_environment/patches/ssl.diff b/build_files/build_environment/patches/ssl.diff
new file mode 100644
index 00000000000..7bb4413952c
--- /dev/null
+++ b/build_files/build_environment/patches/ssl.diff
@@ -0,0 +1,10 @@
+--- ./test/v3ext.c 2022-07-05 11:08:33.000000000 +0200
++++ ./test/v3ext.c 2022-10-18 13:58:05.000000000 +0200
+@@ -8,6 +8,7 @@
+ */
+
+ #include <stdio.h>
++#include <string.h>
+ #include <openssl/x509.h>
+ #include <openssl/x509v3.h>
+ #include <openssl/pem.h>
diff --git a/build_files/cmake/Modules/FindOSL.cmake b/build_files/cmake/Modules/FindOSL.cmake
index ab5de53d3c9..a8d8344ae66 100644
--- a/build_files/cmake/Modules/FindOSL.cmake
+++ b/build_files/cmake/Modules/FindOSL.cmake
@@ -20,6 +20,7 @@ IF(NOT OSL_ROOT_DIR AND NOT $ENV{OSL_ROOT_DIR} STREQUAL "")
ENDIF()
SET(_osl_FIND_COMPONENTS
+ oslnoise
oslcomp
oslexec
oslquery
@@ -39,7 +40,6 @@ FIND_PATH(OSL_INCLUDE_DIR
include
)
-SET(_osl_LIBRARIES)
FOREACH(COMPONENT ${_osl_FIND_COMPONENTS})
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
@@ -51,9 +51,20 @@ FOREACH(COMPONENT ${_osl_FIND_COMPONENTS})
PATH_SUFFIXES
lib64 lib
)
- LIST(APPEND _osl_LIBRARIES "${OSL_${UPPERCOMPONENT}_LIBRARY}")
ENDFOREACH()
+# Note linking order matters, and oslnoise existence depends on version.
+SET(_osl_LIBRARIES ${OSL_OSLCOMP_LIBRARY})
+IF(APPLE)
+ list(APPEND _osl_LIBRARIES -force_load ${OSL_OSLEXEC_LIBRARY})
+ELSE()
+ list(APPEND _osl_LIBRARIES ${OSL_OSLEXEC_LIBRARY})
+ENDIF()
+list(APPEND _osl_LIBRARIES ${OSL_OSLQUERY_LIBRARY})
+IF(OSL_OSLNOISE_LIBRARY)
+ list(APPEND _osl_LIBRARIES ${OSL_OSLNOISE_LIBRARY})
+ENDIF()
+
FIND_PROGRAM(OSL_COMPILER oslc
HINTS ${_osl_SEARCH_DIRS}
PATH_SUFFIXES bin)
diff --git a/build_files/cmake/Modules/FindOpenSubdiv.cmake b/build_files/cmake/Modules/FindOpenSubdiv.cmake
index 37a2cddf3de..66d3b435c46 100644
--- a/build_files/cmake/Modules/FindOpenSubdiv.cmake
+++ b/build_files/cmake/Modules/FindOpenSubdiv.cmake
@@ -71,21 +71,6 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenSubdiv DEFAULT_MSG
IF(OPENSUBDIV_FOUND)
SET(OPENSUBDIV_LIBRARIES ${_opensubdiv_LIBRARIES})
SET(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR})
-
- # Find available compute controllers.
-
- FIND_PACKAGE(OpenMP)
- IF(OPENMP_FOUND)
- SET(OPENSUBDIV_HAS_OPENMP TRUE)
- ELSE()
- SET(OPENSUBDIV_HAS_OPENMP FALSE)
- ENDIF()
-
- OPENSUBDIV_CHECK_CONTROLLER("tbbEvaluator.h" OPENSUBDIV_HAS_TBB)
- OPENSUBDIV_CHECK_CONTROLLER("clEvaluator.h" OPENSUBDIV_HAS_OPENCL)
- OPENSUBDIV_CHECK_CONTROLLER("cudaEvaluator.h" OPENSUBDIV_HAS_CUDA)
- OPENSUBDIV_CHECK_CONTROLLER("glXFBEvaluator.h" OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK)
- OPENSUBDIV_CHECK_CONTROLLER("glComputeEvaluator.h" OPENSUBDIV_HAS_GLSL_COMPUTE)
ENDIF()
MARK_AS_ADVANCED(
diff --git a/build_files/cmake/Modules/FindSYCL.cmake b/build_files/cmake/Modules/FindSYCL.cmake
index 139ebad46b1..1ccbee179fb 100644
--- a/build_files/cmake/Modules/FindSYCL.cmake
+++ b/build_files/cmake/Modules/FindSYCL.cmake
@@ -30,6 +30,7 @@ SET(_sycl_search_dirs
# dpcpp binary.
FIND_PROGRAM(SYCL_COMPILER
NAMES
+ icpx
dpcpp
clang++
HINTS
@@ -45,6 +46,7 @@ FIND_PROGRAM(SYCL_COMPILER
if(NOT SYCL_COMPILER)
FIND_PROGRAM(SYCL_COMPILER
NAMES
+ icpx
dpcpp
HINTS
${_sycl_search_dirs}
@@ -55,6 +57,8 @@ endif()
FIND_LIBRARY(SYCL_LIBRARY
NAMES
+ sycl7
+ sycl6
sycl
HINTS
${_sycl_search_dirs}
@@ -63,34 +67,51 @@ FIND_LIBRARY(SYCL_LIBRARY
)
if(WIN32)
- string(REPLACE ".lib" "d.lib" SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY})
- set(SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY_DEBUG} CACHE FILEPATH "Path to SYCL debug library")
-else()
- set(SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY} CACHE FILEPATH "Path to SYCL debug library")
+ FIND_LIBRARY(SYCL_LIBRARY_DEBUG
+ NAMES
+ sycl7d
+ sycl6d
+ sycld
+ HINTS
+ ${_sycl_search_dirs}
+ PATH_SUFFIXES
+ lib64 lib
+ )
endif()
FIND_PATH(SYCL_INCLUDE_DIR
NAMES
- CL/sycl.hpp
+ sycl/sycl.hpp
HINTS
${_sycl_search_dirs}
PATH_SUFFIXES
include
- include/sycl
)
+IF(EXISTS "${SYCL_INCLUDE_DIR}/sycl/version.hpp")
+ FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_major_version REGEX "^#define __LIBSYCL_MAJOR_VERSION[ \t].*$")
+ STRING(REGEX MATCHALL "[0-9]+" _libsycl_major_version ${_libsycl_major_version})
+ FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_minor_version REGEX "^#define __LIBSYCL_MINOR_VERSION[ \t].*$")
+ STRING(REGEX MATCHALL "[0-9]+" _libsycl_minor_version ${_libsycl_minor_version})
+ FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_patch_version REGEX "^#define __LIBSYCL_PATCH_VERSION[ \t].*$")
+ STRING(REGEX MATCHALL "[0-9]+" _libsycl_patch_version ${_libsycl_patch_version})
+
+ SET(SYCL_VERSION "${_libsycl_major_version}.${_libsycl_minor_version}.${_libsycl_patch_version}")
+ENDIF()
+
INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL DEFAULT_MSG SYCL_LIBRARY SYCL_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL
+ REQUIRED_VARS SYCL_LIBRARY SYCL_INCLUDE_DIR
+ VERSION_VAR SYCL_VERSION
+)
IF(SYCL_FOUND)
- get_filename_component(_SYCL_INCLUDE_PARENT_DIR ${SYCL_INCLUDE_DIR} DIRECTORY)
- SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${_SYCL_INCLUDE_PARENT_DIR})
+ SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${SYCL_INCLUDE_DIR}/sycl)
ELSE()
SET(SYCL_SYCL_FOUND FALSE)
ENDIF()
MARK_AS_ADVANCED(
_SYCL_INCLUDE_PARENT_DIR
- SYCL_LIBRARY_DEBUG
)
diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake
index 958eb17522b..95304bd64c7 100644
--- a/build_files/cmake/config/blender_full.cmake
+++ b/build_files/cmake/config/blender_full.cmake
@@ -66,13 +66,11 @@ set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE)
if(APPLE)
set(WITH_COREAUDIO ON CACHE BOOL "" FORCE)
endif()
-if(NOT WIN32)
- set(WITH_JACK ON CACHE BOOL "" FORCE)
-endif()
if(WIN32)
set(WITH_WASAPI ON CACHE BOOL "" FORCE)
endif()
if(UNIX AND NOT APPLE)
+ set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE)
set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE)
set(WITH_PULSEAUDIO ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake
index d5f5230862b..74bbcb223c3 100644
--- a/build_files/cmake/config/blender_release.cmake
+++ b/build_files/cmake/config/blender_release.cmake
@@ -67,13 +67,11 @@ if(APPLE)
set(WITH_COREAUDIO ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_DEVICE_METAL ON CACHE BOOL "" FORCE)
endif()
-if(NOT WIN32)
- set(WITH_JACK ON CACHE BOOL "" FORCE)
-endif()
if(WIN32)
set(WITH_WASAPI ON CACHE BOOL "" FORCE)
endif()
if(UNIX AND NOT APPLE)
+ set(WITH_JACK ON CACHE BOOL "" FORCE)
set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE)
set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE)
set(WITH_PULSEAUDIO ON CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 3acea19079b..8af45690862 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -1205,11 +1205,27 @@ macro(set_and_warn_dependency
_dependency _setting _val)
# when $_dependency is disabled, forces $_setting = $_val
if(NOT ${${_dependency}} AND ${${_setting}})
- message(STATUS "'${_dependency}' is disabled: forcing 'set(${_setting} ${_val})'")
+ if(WITH_STRICT_BUILD_OPTIONS)
+ message(SEND_ERROR "${_dependency} disabled but required by ${_setting}")
+ else()
+ message(STATUS "${_dependency} is disabled, setting ${_setting}=${_val}")
+ endif()
set(${_setting} ${_val})
endif()
endmacro()
+macro(set_and_warn_library_found
+ _library_name _library_found _setting)
+ if(NOT ${${_library_found}} AND ${${_setting}})
+ if(WITH_STRICT_BUILD_OPTIONS)
+ message(SEND_ERROR "${_library_name} required but not found")
+ else()
+ message(STATUS "${_library_name} not found, disabling ${_setting}")
+ endif()
+ set(${_setting} OFF)
+ endif()
+endmacro()
+
macro(without_system_libs_begin)
set(CMAKE_IGNORE_PATH "${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES};${CMAKE_SYSTEM_INCLUDE_PATH};${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES};${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}")
endmacro()
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index 04f5a312030..c5fe3c908de 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -43,22 +43,18 @@ find_package(BZip2 REQUIRED)
list(APPEND ZLIB_LIBRARIES ${BZIP2_LIBRARIES})
if(WITH_OPENAL)
- find_package(OpenAL)
- if(NOT OPENAL_FOUND)
- message(WARNING "OpenAL not found, disabling WITH_OPENAL")
- set(WITH_OPENAL OFF)
- endif()
+ find_package(OpenAL REQUIRED)
endif()
if(WITH_JACK)
find_library(JACK_FRAMEWORK
NAMES jackmp
)
- if(NOT JACK_FRAMEWORK)
- message(STATUS "JACK not found, disabling WITH_JACK")
- set(WITH_JACK OFF)
- else()
+
+ if(JACK_FRAMEWORK)
set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers)
+ else()
+ set_and_warn_library_found("JACK" JACK_FRAMEWORK WITH_JACK)
endif()
endif()
@@ -101,11 +97,7 @@ if(WITH_ALEMBIC)
endif()
if(WITH_USD)
- find_package(USD)
- if(NOT USD_FOUND)
- message(STATUS "USD not found, disabling WITH_USD")
- set(WITH_USD OFF)
- endif()
+ find_package(USD REQUIRED)
endif()
if(WITH_OPENSUBDIV)
@@ -227,20 +219,12 @@ find_package(JPEG REQUIRED)
if(WITH_IMAGE_TIFF)
set(TIFF_ROOT ${LIBDIR}/tiff)
- find_package(TIFF)
- if(NOT TIFF_FOUND)
- message(WARNING "TIFF not found, disabling WITH_IMAGE_TIFF")
- set(WITH_IMAGE_TIFF OFF)
- endif()
+ find_package(TIFF REQUIRED)
endif()
if(WITH_IMAGE_WEBP)
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
- find_package(WebP)
- if(NOT WEBP_FOUND)
- message(WARNING "WebP not found, disabling WITH_IMAGE_WEBP")
- set(WITH_IMAGE_WEBP OFF)
- endif()
+ find_package(WebP REQUIRED)
endif()
if(WITH_BOOST)
@@ -270,11 +254,7 @@ if(WITH_INTERNATIONAL OR WITH_CODEC_FFMPEG)
endif()
if(WITH_PUGIXML)
- find_package(PugiXML)
- if(NOT PUGIXML_FOUND)
- message(WARNING "PugiXML not found, disabling WITH_PUGIXML")
- set(WITH_PUGIXML OFF)
- endif()
+ find_package(PugiXML REQUIRED)
endif()
if(WITH_OPENIMAGEIO)
@@ -292,12 +272,7 @@ if(WITH_OPENIMAGEIO)
endif()
if(WITH_OPENCOLORIO)
- find_package(OpenColorIO 2.0.0)
-
- if(NOT OPENCOLORIO_FOUND)
- set(WITH_OPENCOLORIO OFF)
- message(STATUS "OpenColorIO not found, disabling WITH_OPENCOLORIO")
- endif()
+ find_package(OpenColorIO 2.0.0 REQUIRED)
endif()
if(WITH_OPENVDB)
@@ -331,23 +306,7 @@ if(WITH_LLVM)
endif()
if(WITH_CYCLES AND WITH_CYCLES_OSL)
- set(CYCLES_OSL ${LIBDIR}/osl)
-
- find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
- find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib)
- find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
- # WARNING! depends on correct order of OSL libs linking
- list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -force_load ${OSL_LIB_EXEC} ${OSL_LIB_QUERY})
- find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
- find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
- find_path(OSL_SHADER_DIR NAMES stdosl.h PATHS ${CYCLES_OSL}/share/OSL/shaders)
-
- if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER AND OSL_SHADER_DIR)
- set(OSL_FOUND TRUE)
- else()
- message(WARNING "OSL not found, disabling WITH_CYCLES_OSL")
- set(WITH_CYCLES_OSL OFF)
- endif()
+ find_package(OSL REQUIRED)
endif()
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
@@ -365,28 +324,15 @@ if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
endif()
if(WITH_OPENIMAGEDENOISE)
- find_package(OpenImageDenoise)
-
- if(NOT OPENIMAGEDENOISE_FOUND)
- set(WITH_OPENIMAGEDENOISE OFF)
- message(STATUS "OpenImageDenoise not found, disabling WITH_OPENIMAGEDENOISE")
- endif()
+ find_package(OpenImageDenoise REQUIRED)
endif()
if(WITH_TBB)
- find_package(TBB)
- if(NOT TBB_FOUND)
- message(WARNING "TBB not found, disabling WITH_TBB")
- set(WITH_TBB OFF)
- endif()
+ find_package(TBB REQUIRED)
endif()
if(WITH_POTRACE)
- find_package(Potrace)
- if(NOT POTRACE_FOUND)
- message(WARNING "potrace not found, disabling WITH_POTRACE")
- set(WITH_POTRACE OFF)
- endif()
+ find_package(Potrace REQUIRED)
endif()
# CMake FindOpenMP doesn't know about AppleClang before 3.12, so provide custom flags.
@@ -406,27 +352,15 @@ if(WITH_OPENMP)
endif()
if(WITH_XR_OPENXR)
- find_package(XR_OpenXR_SDK)
- if(NOT XR_OPENXR_SDK_FOUND)
- message(WARNING "OpenXR-SDK was not found, disabling WITH_XR_OPENXR")
- set(WITH_XR_OPENXR OFF)
- endif()
+ find_package(XR_OpenXR_SDK REQUIRED)
endif()
if(WITH_GMP)
- find_package(GMP)
- if(NOT GMP_FOUND)
- message(WARNING "GMP not found, disabling WITH_GMP")
- set(WITH_GMP OFF)
- endif()
+ find_package(GMP REQUIRED)
endif()
if(WITH_HARU)
- find_package(Haru)
- if(NOT HARU_FOUND)
- message(WARNING "Haru not found, disabling WITH_HARU")
- set(WITH_HARU OFF)
- endif()
+ find_package(Haru REQUIRED)
endif()
if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING)
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake
index 695ea3d773e..424926afe39 100644
--- a/build_files/cmake/platform/platform_unix.cmake
+++ b/build_files/cmake/platform/platform_unix.cmake
@@ -174,32 +174,24 @@ endif()
if(WITH_IMAGE_OPENEXR)
find_package_wrapper(OpenEXR) # our own module
- if(NOT OPENEXR_FOUND)
- set(WITH_IMAGE_OPENEXR OFF)
- endif()
+ set_and_warn_library_found("OpenEXR" OPENEXR_FOUND WITH_IMAGE_OPENEXR)
endif()
if(WITH_IMAGE_OPENJPEG)
find_package_wrapper(OpenJPEG)
- if(NOT OPENJPEG_FOUND)
- set(WITH_IMAGE_OPENJPEG OFF)
- endif()
+ set_and_warn_library_found("OpenJPEG" OPENJPEG_FOUND WITH_IMAGE_OPENJPEG)
endif()
if(WITH_IMAGE_TIFF)
# XXX Linking errors with debian static tiff :/
# find_package_wrapper(TIFF)
find_package(TIFF)
- if(NOT TIFF_FOUND)
- set(WITH_IMAGE_TIFF OFF)
- endif()
+ set_and_warn_library_found("TIFF" TIFF_FOUND WITH_IMAGE_TIFF)
endif()
if(WITH_OPENAL)
find_package_wrapper(OpenAL)
- if(NOT OPENAL_FOUND)
- set(WITH_OPENAL OFF)
- endif()
+ set_and_warn_library_found("OpenAL" OPENAL_FOUND WITH_OPENAL)
endif()
if(WITH_SDL)
@@ -221,18 +213,14 @@ if(WITH_SDL)
SDL_LIBRARY
)
# unset(SDLMAIN_LIBRARY CACHE)
- if(NOT SDL_FOUND)
- set(WITH_SDL OFF)
- endif()
+ set_and_warn_library_found("SDL" SDL_FOUND WITH_SDL)
endif()
endif()
# Codecs
if(WITH_CODEC_SNDFILE)
find_package_wrapper(SndFile)
- if(NOT SNDFILE_FOUND)
- set(WITH_CODEC_SNDFILE OFF)
- endif()
+ set_and_warn_library_found("libsndfile" SNDFILE_FOUND WITH_CODEC_SNDFILE)
endif()
if(WITH_CODEC_FFMPEG)
@@ -260,17 +248,12 @@ if(WITH_CODEC_FFMPEG)
endif()
find_package(FFmpeg)
- if(NOT FFMPEG_FOUND)
- set(WITH_CODEC_FFMPEG OFF)
- message(STATUS "FFmpeg not found, disabling it")
- endif()
+ set_and_warn_library_found("FFmpeg" FFMPEG_FOUND WITH_CODEC_FFMPEG)
endif()
if(WITH_FFTW3)
find_package_wrapper(Fftw3)
- if(NOT FFTW3_FOUND)
- set(WITH_FFTW3 OFF)
- endif()
+ set_and_warn_library_found("fftw3" FFTW3_FOUND WITH_FFTW3)
endif()
if(WITH_OPENCOLLADA)
@@ -285,25 +268,23 @@ if(WITH_OPENCOLLADA)
endif()
find_package_wrapper(XML2)
else()
- set(WITH_OPENCOLLADA OFF)
+ set_and_warn_library_found("OpenCollada" OPENCOLLADA_FOUND WITH_OPENCOLLADA)
endif()
endif()
if(WITH_MEM_JEMALLOC)
find_package_wrapper(JeMalloc)
- if(NOT JEMALLOC_FOUND)
- set(WITH_MEM_JEMALLOC OFF)
- endif()
+ set_and_warn_library_found("JeMalloc" JEMALLOC_FOUND WITH_MEM_JEMALLOC)
endif()
if(WITH_INPUT_NDOF)
find_package_wrapper(Spacenav)
+ set_and_warn_library_found("SpaceNav" SPACENAV_FOUND WITH_INPUT_NDOF)
+
if(SPACENAV_FOUND)
# use generic names within blenders buildsystem.
set(NDOF_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIRS})
set(NDOF_LIBRARIES ${SPACENAV_LIBRARIES})
- else()
- set(WITH_INPUT_NDOF OFF)
endif()
endif()
@@ -313,6 +294,8 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
set(OSL_ROOT ${CYCLES_OSL})
endif()
find_package_wrapper(OSL)
+ set_and_warn_library_found("OSL" OSL_FOUND WITH_CYCLES_OSL)
+
if(OSL_FOUND)
if(${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6")
# Note: --whole-archive is needed to force loading of all symbols in liboslexec,
@@ -323,9 +306,6 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
-Wl,--no-whole-archive ${OSL_OSLQUERY_LIBRARY}
)
endif()
- else()
- message(STATUS "OSL not found, disabling it from Cycles")
- set(WITH_CYCLES_OSL OFF)
endif()
endif()
@@ -341,35 +321,27 @@ if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
endif()
file(GLOB _sycl_runtime_libraries
${SYCL_ROOT_DIR}/lib/libsycl.so
- ${SYCL_ROOT_DIR}/lib/libsycl.so.[0-9]
- ${SYCL_ROOT_DIR}/lib/libsycl.so.[0-9].[0-9].[0-9]-[0-9]
+ ${SYCL_ROOT_DIR}/lib/libsycl.so.*
${SYCL_ROOT_DIR}/lib/libpi_level_zero.so
)
+ list(FILTER _sycl_runtime_libraries EXCLUDE REGEX ".*\.py")
list(APPEND PLATFORM_BUNDLED_LIBRARIES ${_sycl_runtime_libraries})
unset(_sycl_runtime_libraries)
endif()
if(WITH_OPENVDB)
find_package_wrapper(OpenVDB)
- find_package_wrapper(Blosc)
-
- if(NOT OPENVDB_FOUND)
- set(WITH_OPENVDB OFF)
- set(WITH_OPENVDB_BLOSC OFF)
- message(STATUS "OpenVDB not found, disabling it")
- elseif(NOT BLOSC_FOUND)
- set(WITH_OPENVDB_BLOSC OFF)
- message(STATUS "Blosc not found, disabling it for OpenVBD")
+ set_and_warn_library_found("OpenVDB" OPENVDB_FOUND WITH_OPENVDB)
+
+ if(OPENVDB_FOUND)
+ find_package_wrapper(Blosc)
+ set_and_warn_library_found("Blosc" BLOSC_FOUND WITH_OPENVDB_BLOSC)
endif()
endif()
if(WITH_NANOVDB)
find_package_wrapper(NanoVDB)
-
- if(NOT NANOVDB_FOUND)
- set(WITH_NANOVDB OFF)
- message(STATUS "NanoVDB not found, disabling it")
- endif()
+ set_and_warn_library_found("NanoVDB" NANOVDB_FOUND WITH_NANOVDB)
endif()
if(WITH_CPU_SIMD AND SUPPORT_NEON_BUILD)
@@ -378,18 +350,12 @@ endif()
if(WITH_ALEMBIC)
find_package_wrapper(Alembic)
-
- if(NOT ALEMBIC_FOUND)
- set(WITH_ALEMBIC OFF)
- endif()
+ set_and_warn_library_found("Alembic" ALEMBIC_FOUND WITH_ALEMBIC)
endif()
if(WITH_USD)
find_package_wrapper(USD)
-
- if(NOT USD_FOUND)
- set(WITH_USD OFF)
- endif()
+ set_and_warn_library_found("USD" USD_FOUND WITH_USD)
endif()
if(WITH_BOOST)
@@ -442,20 +408,13 @@ endif()
if(WITH_PUGIXML)
find_package_wrapper(PugiXML)
-
- if(NOT PUGIXML_FOUND)
- set(WITH_PUGIXML OFF)
- message(STATUS "PugiXML not found, disabling WITH_PUGIXML")
- endif()
+ set_and_warn_library_found("PugiXML" PUGIXML_FOUND WITH_PUGIXML)
endif()
if(WITH_IMAGE_WEBP)
set(WEBP_ROOT_DIR ${LIBDIR}/webp)
find_package_wrapper(WebP)
- if(NOT WEBP_FOUND)
- set(WITH_IMAGE_WEBP OFF)
- message(WARNING "WebP not found, disabling WITH_IMAGE_WEBP")
- endif()
+ set_and_warn_library_found("WebP" WEBP_FOUND WITH_IMAGE_WEBP)
endif()
if(WITH_OPENIMAGEIO)
@@ -480,10 +439,7 @@ if(WITH_OPENIMAGEIO)
list(APPEND OPENIMAGEIO_LIBRARIES "${WEBP_LIBRARIES}")
endif()
- if(NOT OPENIMAGEIO_FOUND)
- set(WITH_OPENIMAGEIO OFF)
- message(STATUS "OpenImageIO not found, disabling WITH_CYCLES")
- endif()
+ set_and_warn_library_found("OPENIMAGEIO" OPENIMAGEIO_FOUND WITH_OPENIMAGEIO)
endif()
if(WITH_OPENCOLORIO)
@@ -493,10 +449,7 @@ if(WITH_OPENCOLORIO)
set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere
set(OPENCOLORIO_DEFINITIONS)
- if(NOT OPENCOLORIO_FOUND)
- set(WITH_OPENCOLORIO OFF)
- message(STATUS "OpenColorIO not found")
- endif()
+ set_and_warn_library_found("OpenColorIO" OPENCOLORIO_FOUND WITH_OPENCOLORIO)
endif()
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
@@ -505,11 +458,7 @@ endif()
if(WITH_OPENIMAGEDENOISE)
find_package_wrapper(OpenImageDenoise)
-
- if(NOT OPENIMAGEDENOISE_FOUND)
- set(WITH_OPENIMAGEDENOISE OFF)
- message(STATUS "OpenImageDenoise not found")
- endif()
+ set_and_warn_library_found("OpenImageDenoise" OPENIMAGEDENOISE_FOUND WITH_OPENIMAGEDENOISE)
endif()
if(WITH_LLVM)
@@ -518,24 +467,19 @@ if(WITH_LLVM)
endif()
find_package_wrapper(LLVM)
- if(WITH_CLANG)
- find_package_wrapper(Clang)
- endif()
- # Symbol conflicts with same UTF library used by OpenCollada
- if(EXISTS ${LIBDIR})
- if(WITH_OPENCOLLADA AND (${LLVM_VERSION} VERSION_LESS "4.0.0"))
- list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY})
+ set_and_warn_library_found("LLVM" LLVM_FOUND WITH_LLVM)
+
+ if(LLVM_FOUND)
+ if(WITH_CLANG)
+ find_package_wrapper(Clang)
+ set_and_warn_library_found("Clang" CLANG_FOUND WITH_CLANG)
endif()
- endif()
- if(NOT LLVM_FOUND)
- set(WITH_LLVM OFF)
- set(WITH_CLANG OFF)
- message(STATUS "LLVM not found")
- else()
- if(NOT CLANG_FOUND)
- set(WITH_CLANG OFF)
- message(STATUS "Clang not found")
+ # Symbol conflicts with same UTF library used by OpenCollada
+ if(EXISTS ${LIBDIR})
+ if(WITH_OPENCOLLADA AND (${LLVM_VERSION} VERSION_LESS "4.0.0"))
+ list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY})
+ endif()
endif()
endif()
endif()
@@ -546,50 +490,32 @@ if(WITH_OPENSUBDIV)
set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARIES})
set(OPENSUBDIV_LIBPATH) # TODO, remove and reference the absolute path everywhere
- if(NOT OPENSUBDIV_FOUND)
- set(WITH_OPENSUBDIV OFF)
- message(STATUS "OpenSubdiv not found")
- endif()
+ set_and_warn_library_found("OpenSubdiv" OPENSUBDIV_FOUND WITH_OPENSUBDIV)
endif()
if(WITH_TBB)
find_package_wrapper(TBB)
- if(NOT TBB_FOUND)
- message(WARNING "TBB not found, disabling WITH_TBB")
- set(WITH_TBB OFF)
- endif()
+ set_and_warn_library_found("TBB" TBB_FOUND WITH_TBB)
endif()
if(WITH_XR_OPENXR)
find_package(XR_OpenXR_SDK)
- if(NOT XR_OPENXR_SDK_FOUND)
- message(WARNING "OpenXR-SDK not found, disabling WITH_XR_OPENXR")
- set(WITH_XR_OPENXR OFF)
- endif()
+ set_and_warn_library_found("OpenXR-SDK" XR_OPENXR_SDK_FOUND WITH_XR_OPENXR)
endif()
if(WITH_GMP)
find_package_wrapper(GMP)
- if(NOT GMP_FOUND)
- message(WARNING "GMP not found, disabling WITH_GMP")
- set(WITH_GMP OFF)
- endif()
+ set_and_warn_library_found("GMP" GMP_FOUND WITH_GMP)
endif()
if(WITH_POTRACE)
find_package_wrapper(Potrace)
- if(NOT POTRACE_FOUND)
- message(WARNING "potrace not found, disabling WITH_POTRACE")
- set(WITH_POTRACE OFF)
- endif()
+ set_and_warn_library_found("Potrace" POTRACE_FOUND WITH_POTRACE)
endif()
if(WITH_HARU)
find_package_wrapper(Haru)
- if(NOT HARU_FOUND)
- message(WARNING "Haru not found, disabling WITH_HARU")
- set(WITH_HARU OFF)
- endif()
+ set_and_warn_library_found("Haru" HARU_FOUND WITH_HARU)
endif()
if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING)
@@ -676,25 +602,20 @@ endif()
# Jack is intended to use the system library.
if(WITH_JACK)
find_package_wrapper(Jack)
- if(NOT JACK_FOUND)
- set(WITH_JACK OFF)
- endif()
+ set_and_warn_library_found("JACK" JACK_FOUND WITH_JACK)
endif()
# Pulse is intended to use the system library.
if(WITH_PULSEAUDIO)
find_package_wrapper(Pulse)
- if(NOT PULSE_FOUND)
- set(WITH_PULSEAUDIO OFF)
- endif()
+ set_and_warn_library_found("PulseAudio" PULSE_FOUND WITH_PULSEAUDIO)
endif()
# Audio IO
if(WITH_SYSTEM_AUDASPACE)
find_package_wrapper(Audaspace)
- if(NOT AUDASPACE_FOUND OR NOT AUDASPACE_C_FOUND)
- message(FATAL_ERROR "Audaspace external library not found!")
- endif()
+ set(AUDASPACE_FOUND ${AUDASPACE_FOUND} AND ${AUDASPACE_C_FOUND})
+ set_and_warn_library_found("External Audaspace" AUDASPACE_FOUND WITH_SYSTEM_AUDASPACE)
endif()
if(WITH_GHOST_WAYLAND)
@@ -740,30 +661,12 @@ if(WITH_GHOST_WAYLAND)
set(wayland-cursor_FOUND ON)
endif()
- if (NOT wayland-client_FOUND)
- message(STATUS "wayland-client not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
- if (NOT wayland-egl_FOUND)
- message(STATUS "wayland-egl not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
- if (NOT wayland-scanner_FOUND)
- message(STATUS "wayland-scanner not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
- if (NOT wayland-cursor_FOUND)
- message(STATUS "wayland-cursor not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
- if (NOT wayland-protocols_FOUND)
- message(STATUS "wayland-protocols not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
- if (NOT xkbcommon_FOUND)
- message(STATUS "xkbcommon not found, disabling WITH_GHOST_WAYLAND")
- set(WITH_GHOST_WAYLAND OFF)
- endif()
+ set_and_warn_library_found("wayland-client" wayland-client_FOUND WITH_GHOST_WAYLAND)
+ set_and_warn_library_found("wayland-egl" wayland-egl_FOUND WITH_GHOST_WAYLAND)
+ set_and_warn_library_found("wayland-scanner" wayland-scanner_FOUND WITH_GHOST_WAYLAND)
+ set_and_warn_library_found("wayland-cursor" wayland-cursor_FOUND WITH_GHOST_WAYLAND)
+ set_and_warn_library_found("wayland-protocols" wayland-protocols_FOUND WITH_GHOST_WAYLAND)
+ set_and_warn_library_found("xkbcommon" xkbcommon_FOUND WITH_GHOST_WAYLAND)
if(WITH_GHOST_WAYLAND)
if(WITH_GHOST_WAYLAND_DBUS)
diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index cfb8bf34b81..3818076634a 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -326,18 +326,10 @@ if(WITH_FFTW3)
endif()
if(WITH_IMAGE_WEBP)
- windows_find_package(WebP)
- if(NOT WEBP_FOUND)
- if(EXISTS ${LIBDIR}/webp)
- set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include)
- set(WEBP_ROOT_DIR ${LIBDIR}/webp)
- set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib)
- set(WEBP_FOUND ON)
- else()
- message(STATUS "WITH_IMAGE_WEBP is ON but WEBP libraries are not found, setting WITH_IMAGE_WEBP=OFF")
- set(WITH_IMAGE_WEBP OFF)
- endif()
- endif()
+ set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include)
+ set(WEBP_ROOT_DIR ${LIBDIR}/webp)
+ set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib)
+ set(WEBP_FOUND ON)
endif()
if(WITH_OPENCOLLADA)
@@ -358,7 +350,6 @@ if(WITH_OPENCOLLADA)
optimized ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter.lib
optimized ${OPENCOLLADA}/lib/opencollada/MathMLSolver.lib
optimized ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser.lib
- optimized ${OPENCOLLADA}/lib/opencollada/xml.lib
optimized ${OPENCOLLADA}/lib/opencollada/buffer.lib
optimized ${OPENCOLLADA}/lib/opencollada/ftoa.lib
@@ -368,10 +359,14 @@ if(WITH_OPENCOLLADA)
debug ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter_d.lib
debug ${OPENCOLLADA}/lib/opencollada/MathMLSolver_d.lib
debug ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser_d.lib
- debug ${OPENCOLLADA}/lib/opencollada/xml_d.lib
debug ${OPENCOLLADA}/lib/opencollada/buffer_d.lib
debug ${OPENCOLLADA}/lib/opencollada/ftoa_d.lib
)
+ if(EXISTS ${LIBDIR}/xml2/lib/libxml2s.lib) # 3.4 libraries
+ list(APPEND OPENCOLLADA_LIBRARIES ${LIBDIR}/xml2/lib/libxml2s.lib)
+ else()
+ list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/xml.lib)
+ endif()
list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/UTF.lib)
@@ -679,11 +674,11 @@ endif()
if(WITH_IMAGE_OPENJPEG)
set(OPENJPEG ${LIBDIR}/openjpeg)
- set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.4)
+ set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.5)
if(NOT EXISTS "${OPENJPEG_INCLUDE_DIRS}")
- # when not found, could be an older lib folder with openjpeg 2.3
- # to ease the transition period, fall back if 2.4 is not found.
- set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.3)
+ # when not found, could be an older lib folder with openjpeg 2.4
+ # to ease the transition period, fall back if 2.5 is not found.
+ set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.4)
endif()
set(OPENJPEG_LIBRARIES ${OPENJPEG}/lib/openjp2.lib)
endif()
@@ -700,12 +695,6 @@ if(WITH_OPENSUBDIV)
debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
)
- set(OPENSUBDIV_HAS_OPENMP TRUE)
- set(OPENSUBDIV_HAS_TBB FALSE)
- set(OPENSUBDIV_HAS_OPENCL TRUE)
- set(OPENSUBDIV_HAS_CUDA FALSE)
- set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE)
- set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE)
endif()
endif()
@@ -773,9 +762,11 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
+ find_library(OSL_LIB_NOISE NAMES oslnoise PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_EXEC_DEBUG NAMES oslexec_d PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_COMP_DEBUG NAMES oslcomp_d PATHS ${CYCLES_OSL}/lib)
find_library(OSL_LIB_QUERY_DEBUG NAMES oslquery_d PATHS ${CYCLES_OSL}/lib)
+ find_library(OSL_LIB_NOISE_DEBUG NAMES oslnoise_d PATHS ${CYCLES_OSL}/lib)
list(APPEND OSL_LIBRARIES
optimized ${OSL_LIB_COMP}
optimized ${OSL_LIB_EXEC}
@@ -785,15 +776,14 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
debug ${OSL_LIB_QUERY_DEBUG}
${PUGIXML_LIBRARIES}
)
+ if(OSL_LIB_NOISE)
+ list(APPEND OSL_LIBRARIES optimized ${OSL_LIB_NOISE})
+ endif()
+ if(OSL_LIB_NOISE_DEBUG)
+ list(APPEND OSL_LIBRARIES debug ${OSL_LIB_NOISE_DEBUG})
+ endif()
find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
-
- if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER)
- set(OSL_FOUND TRUE)
- else()
- message(STATUS "OSL not found")
- set(WITH_CYCLES_OSL OFF)
- endif()
endif()
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
@@ -893,21 +883,16 @@ if(WINDOWS_PYTHON_DEBUG)
endif()
if(WITH_XR_OPENXR)
- if(EXISTS ${LIBDIR}/xr_openxr_sdk)
- set(XR_OPENXR_SDK ${LIBDIR}/xr_openxr_sdk)
- set(XR_OPENXR_SDK_LIBPATH ${LIBDIR}/xr_openxr_sdk/lib)
- set(XR_OPENXR_SDK_INCLUDE_DIR ${XR_OPENXR_SDK}/include)
- # This is the old name of this library, it is checked to
- # support the transition between the old and new lib versions
- # this can be removed after the next lib update.
- if(EXISTS ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib)
- set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib)
- else()
- set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loaderd.lib)
- endif()
+ set(XR_OPENXR_SDK ${LIBDIR}/xr_openxr_sdk)
+ set(XR_OPENXR_SDK_LIBPATH ${LIBDIR}/xr_openxr_sdk/lib)
+ set(XR_OPENXR_SDK_INCLUDE_DIR ${XR_OPENXR_SDK}/include)
+ # This is the old name of this library, it is checked to
+ # support the transition between the old and new lib versions
+ # this can be removed after the next lib update.
+ if(EXISTS ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib)
+ set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib)
else()
- message(WARNING "OpenXR-SDK was not found, disabling WITH_XR_OPENXR")
- set(WITH_XR_OPENXR OFF)
+ set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loaderd.lib)
endif()
endif()
@@ -925,15 +910,10 @@ if(WITH_POTRACE)
endif()
if(WITH_HARU)
- if(EXISTS ${LIBDIR}/haru)
- set(HARU_FOUND ON)
- set(HARU_ROOT_DIR ${LIBDIR}/haru)
- set(HARU_INCLUDE_DIRS ${HARU_ROOT_DIR}/include)
- set(HARU_LIBRARIES ${HARU_ROOT_DIR}/lib/libhpdfs.lib)
- else()
- message(WARNING "Haru was not found, disabling WITH_HARU")
- set(WITH_HARU OFF)
- endif()
+ set(HARU_FOUND ON)
+ set(HARU_ROOT_DIR ${LIBDIR}/haru)
+ set(HARU_INCLUDE_DIRS ${HARU_ROOT_DIR}/include)
+ set(HARU_LIBRARIES ${HARU_ROOT_DIR}/lib/libhpdfs.lib)
endif()
if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING)
diff --git a/build_files/windows/svn_update.cmd b/build_files/windows/svn_update.cmd
new file mode 100644
index 00000000000..f91f03f15b3
--- /dev/null
+++ b/build_files/windows/svn_update.cmd
@@ -0,0 +1,24 @@
+if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
+if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
+
+set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
+set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
+
+cd %BUILD_VS_LIBDIR%
+:RETRY
+"%SVN%" update
+if errorlevel 1 (
+ set /p LibRetry= "Error during update, retry? y/n"
+ if /I "!LibRetry!"=="Y" (
+ "%SVN%" cleanup
+ goto RETRY
+ )
+ echo.
+ echo Error: Download of external libraries failed.
+ echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in
+ echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successful blender build
+ echo.
+ exit /b 1
+)
+
+cd %BLENDER_DIR% \ No newline at end of file
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index f619e6b104e..329aa3990f6 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -263,8 +263,7 @@ if(WITH_CYCLES_DEVICE_OPTIX)
${OPTIX_INCLUDE_DIR}
)
else()
- message(STATUS "OptiX not found, disabling it from Cycles")
- set(WITH_CYCLES_DEVICE_OPTIX OFF)
+ set_and_warn_library_found("OptiX" OPTIX_FOUND WITH_CYCLES_DEVICE_OPTIX)
endif()
endif()
@@ -387,8 +386,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang")
endif()
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_USD))
- message(STATUS "USD not found, disabling WITH_CYCLES_HYDRA_RENDER_DELEGATE")
- set(WITH_CYCLES_HYDRA_RENDER_DELEGATE OFF)
+ set_and_warn_library_found("USD" WITH_USD WITH_CYCLES_HYDRA_RENDER_DELEGATE)
endif()
if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_BLENDER) AND (NOT WITH_CYCLES_STANDALONE))
set(CYCLES_INSTALL_PATH ${CYCLES_INSTALL_PATH}/hdCycles/resources)
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index 0988b1c0ac4..1c7a861ea93 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -43,7 +43,10 @@ else()
endif()
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
- list(APPEND INC_SYS ${Epoxy_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS})
+ list(APPEND INC_SYS
+ ${Epoxy_INCLUDE_DIRS}
+ ${SDL2_INCLUDE_DIRS}
+ )
list(APPEND LIB ${Epoxy_LIBRARIES} ${SDL2_LIBRARIES})
endif()
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 794338fe78e..e33891fa7a2 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -209,22 +209,25 @@ def list_render_passes(scene, srl):
yield ("Debug Sample Count", "X", 'VALUE')
# Cryptomatte passes.
- crypto_depth = (srl.pass_cryptomatte_depth + 1) // 2
+ # NOTE: Name channels are lowercase RGBA so that compression rules check in OpenEXR DWA code
+ # uses lossless compression. Reportedly this naming is the only one which works good from the
+ # interoperability point of view. Using XYZW naming is not portable.
+ crypto_depth = (min(16, srl.pass_cryptomatte_depth) + 1) // 2
if srl.use_pass_cryptomatte_object:
for i in range(0, crypto_depth):
- yield ("CryptoObject" + '{:02d}'.format(i), "RGBA", 'COLOR')
+ yield ("CryptoObject" + '{:02d}'.format(i), "rgba", 'COLOR')
if srl.use_pass_cryptomatte_material:
for i in range(0, crypto_depth):
- yield ("CryptoMaterial" + '{:02d}'.format(i), "RGBA", 'COLOR')
+ yield ("CryptoMaterial" + '{:02d}'.format(i), "rgba", 'COLOR')
if srl.use_pass_cryptomatte_asset:
for i in range(0, crypto_depth):
- yield ("CryptoAsset" + '{:02d}'.format(i), "RGBA", 'COLOR')
+ yield ("CryptoAsset" + '{:02d}'.format(i), "rgba", 'COLOR')
# Denoising passes.
if scene.cycles.use_denoising and crl.use_denoising:
yield ("Noisy Image", "RGBA", 'COLOR')
if crl.use_pass_shadow_catcher:
- yield ("Noisy Shadow Catcher", "RGBA", 'COLOR')
+ yield ("Noisy Shadow Catcher", "RGB", 'COLOR')
if crl.denoising_store_passes:
yield ("Denoising Normal", "XYZ", 'VECTOR')
yield ("Denoising Albedo", "RGB", 'COLOR')
@@ -232,6 +235,8 @@ def list_render_passes(scene, srl):
# Custom AOV passes.
for aov in srl.aovs:
+ if not aov.is_valid:
+ continue
if aov.type == 'VALUE':
yield (aov.name, "X", 'VALUE')
else:
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index b7ce76d8f44..425d123e9e6 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -1651,6 +1651,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
box.prop(
device, "use", text=device.name
.replace('(TM)', unicodedata.lookup('TRADE MARK SIGN'))
+ .replace('(tm)', unicodedata.lookup('TRADE MARK SIGN'))
.replace('(R)', unicodedata.lookup('REGISTERED SIGN'))
.replace('(C)', unicodedata.lookup('COPYRIGHT SIGN'))
)
diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp
index a69a94614d3..5251f0fee9c 100644
--- a/intern/cycles/blender/sync.cpp
+++ b/intern/cycles/blender/sync.cpp
@@ -575,68 +575,72 @@ void BlenderSync::sync_images()
/* Passes */
-static PassType get_blender_pass_type(BL::RenderPass &b_pass)
+static bool get_known_pass_type(BL::RenderPass &b_pass, PassType &type, PassMode &mode)
{
string name = b_pass.name();
-#define MAP_PASS(passname, passtype) \
+#define MAP_PASS(passname, passtype, noisy) \
if (name == passname) { \
- return passtype; \
+ type = passtype; \
+ mode = (noisy) ? PassMode::NOISY : PassMode::DENOISED; \
+ return true; \
} \
((void)0)
- /* NOTE: Keep in sync with defined names from DNA_scene_types.h */
+ /* NOTE: Keep in sync with defined names from engine.py */
- MAP_PASS("Combined", PASS_COMBINED);
- MAP_PASS("Noisy Image", PASS_COMBINED);
+ MAP_PASS("Combined", PASS_COMBINED, false);
+ MAP_PASS("Noisy Image", PASS_COMBINED, true);
- MAP_PASS("Depth", PASS_DEPTH);
- MAP_PASS("Mist", PASS_MIST);
- MAP_PASS("Position", PASS_POSITION);
- MAP_PASS("Normal", PASS_NORMAL);
- MAP_PASS("IndexOB", PASS_OBJECT_ID);
- MAP_PASS("UV", PASS_UV);
- MAP_PASS("Vector", PASS_MOTION);
- MAP_PASS("IndexMA", PASS_MATERIAL_ID);
+ MAP_PASS("Depth", PASS_DEPTH, false);
+ MAP_PASS("Mist", PASS_MIST, false);
+ MAP_PASS("Position", PASS_POSITION, false);
+ MAP_PASS("Normal", PASS_NORMAL, false);
+ MAP_PASS("IndexOB", PASS_OBJECT_ID, false);
+ MAP_PASS("UV", PASS_UV, false);
+ MAP_PASS("Vector", PASS_MOTION, false);
+ MAP_PASS("IndexMA", PASS_MATERIAL_ID, false);
- MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT);
- MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT);
- MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT);
- MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT);
+ MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT, false);
+ MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT, false);
+ MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT, false);
+ MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT, false);
- MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT);
- MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT);
- MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT);
- MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT);
+ MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT, false);
+ MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT, false);
+ MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT, false);
+ MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT, false);
- MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR);
- MAP_PASS("GlossCol", PASS_GLOSSY_COLOR);
- MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR);
+ MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR, false);
+ MAP_PASS("GlossCol", PASS_GLOSSY_COLOR, false);
+ MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR, false);
- MAP_PASS("Emit", PASS_EMISSION);
- MAP_PASS("Env", PASS_BACKGROUND);
- MAP_PASS("AO", PASS_AO);
- MAP_PASS("Shadow", PASS_SHADOW);
+ MAP_PASS("Emit", PASS_EMISSION, false);
+ MAP_PASS("Env", PASS_BACKGROUND, false);
+ MAP_PASS("AO", PASS_AO, false);
+ MAP_PASS("Shadow", PASS_SHADOW, false);
- MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE);
- MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL);
+ MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE, false);
+ MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL, false);
- MAP_PASS("Denoising Normal", PASS_DENOISING_NORMAL);
- MAP_PASS("Denoising Albedo", PASS_DENOISING_ALBEDO);
- MAP_PASS("Denoising Depth", PASS_DENOISING_DEPTH);
+ MAP_PASS("Denoising Normal", PASS_DENOISING_NORMAL, true);
+ MAP_PASS("Denoising Albedo", PASS_DENOISING_ALBEDO, true);
+ MAP_PASS("Denoising Depth", PASS_DENOISING_DEPTH, true);
- MAP_PASS("Shadow Catcher", PASS_SHADOW_CATCHER);
- MAP_PASS("Noisy Shadow Catcher", PASS_SHADOW_CATCHER);
+ MAP_PASS("Shadow Catcher", PASS_SHADOW_CATCHER, false);
+ MAP_PASS("Noisy Shadow Catcher", PASS_SHADOW_CATCHER, true);
- MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER);
- MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT);
+ MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER, false);
+ MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT, false);
if (string_startswith(name, cryptomatte_prefix)) {
- return PASS_CRYPTOMATTE;
+ type = PASS_CRYPTOMATTE;
+ mode = PassMode::DENOISED;
+ return true;
}
#undef MAP_PASS
- return PASS_NONE;
+ return false;
}
static Pass *pass_add(Scene *scene,
@@ -655,8 +659,6 @@ static Pass *pass_add(Scene *scene,
void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_view_layer)
{
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
-
/* Delete all existing passes. */
set<Pass *> clear_passes(scene->passes.begin(), scene->passes.end());
scene->delete_nodes(clear_passes);
@@ -664,103 +666,23 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
/* Always add combined pass. */
pass_add(scene, PASS_COMBINED, "Combined");
- /* Blender built-in data and light passes. */
- for (BL::RenderPass &b_pass : b_rlay.passes) {
- const PassType pass_type = get_blender_pass_type(b_pass);
-
- if (pass_type == PASS_NONE) {
- LOG(ERROR) << "Unknown pass " << b_pass.name();
- continue;
- }
-
- if (pass_type == PASS_MOTION &&
- (b_view_layer.use_motion_blur() && b_scene.render().use_motion_blur())) {
- continue;
- }
-
- pass_add(scene, pass_type, b_pass.name().c_str());
- }
-
- PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles");
-
- /* Debug passes. */
- if (get_boolean(crl, "pass_debug_sample_count")) {
- b_engine.add_pass("Debug Sample Count", 1, "X", b_view_layer.name().c_str());
- pass_add(scene, PASS_SAMPLE_COUNT, "Debug Sample Count");
- }
-
- /* Cycles specific passes. */
- if (get_boolean(crl, "use_pass_volume_direct")) {
- b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str());
- pass_add(scene, PASS_VOLUME_DIRECT, "VolumeDir");
- }
- if (get_boolean(crl, "use_pass_volume_indirect")) {
- b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str());
- pass_add(scene, PASS_VOLUME_INDIRECT, "VolumeInd");
- }
- if (get_boolean(crl, "use_pass_shadow_catcher")) {
- b_engine.add_pass("Shadow Catcher", 3, "RGB", b_view_layer.name().c_str());
- pass_add(scene, PASS_SHADOW_CATCHER, "Shadow Catcher");
- }
-
/* Cryptomatte stores two ID/weight pairs per RGBA layer.
- * User facing parameter is the number of pairs.
- *
- * NOTE: Name channels lowercase RGBA so that compression rules check in OpenEXR DWA code uses
- * lossless compression. Reportedly this naming is the only one which works good from the
- * interoperability point of view. Using XYZW naming is not portable. */
+ * User facing parameter is the number of pairs. */
int crypto_depth = divide_up(min(16, b_view_layer.pass_cryptomatte_depth()), 2);
scene->film->set_cryptomatte_depth(crypto_depth);
CryptomatteType cryptomatte_passes = CRYPT_NONE;
if (b_view_layer.use_pass_cryptomatte_object()) {
- for (int i = 0; i < crypto_depth; i++) {
- string passname = cryptomatte_prefix + string_printf("Object%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str());
- pass_add(scene, PASS_CRYPTOMATTE, passname.c_str());
- }
cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_OBJECT);
}
if (b_view_layer.use_pass_cryptomatte_material()) {
- for (int i = 0; i < crypto_depth; i++) {
- string passname = cryptomatte_prefix + string_printf("Material%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str());
- pass_add(scene, PASS_CRYPTOMATTE, passname.c_str());
- }
cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_MATERIAL);
}
if (b_view_layer.use_pass_cryptomatte_asset()) {
- for (int i = 0; i < crypto_depth; i++) {
- string passname = cryptomatte_prefix + string_printf("Asset%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str());
- pass_add(scene, PASS_CRYPTOMATTE, passname.c_str());
- }
cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ASSET);
}
scene->film->set_cryptomatte_passes(cryptomatte_passes);
- /* Denoising passes. */
- const bool use_denoising = get_boolean(cscene, "use_denoising") &&
- get_boolean(crl, "use_denoising");
- const bool store_denoising_passes = get_boolean(crl, "denoising_store_passes");
- if (use_denoising) {
- b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str());
- pass_add(scene, PASS_COMBINED, "Noisy Image", PassMode::NOISY);
- if (get_boolean(crl, "use_pass_shadow_catcher")) {
- b_engine.add_pass("Noisy Shadow Catcher", 3, "RGB", b_view_layer.name().c_str());
- pass_add(scene, PASS_SHADOW_CATCHER, "Noisy Shadow Catcher", PassMode::NOISY);
- }
- }
- if (store_denoising_passes) {
- b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str());
- pass_add(scene, PASS_DENOISING_NORMAL, "Denoising Normal", PassMode::NOISY);
-
- b_engine.add_pass("Denoising Albedo", 3, "RGB", b_view_layer.name().c_str());
- pass_add(scene, PASS_DENOISING_ALBEDO, "Denoising Albedo", PassMode::NOISY);
-
- b_engine.add_pass("Denoising Depth", 1, "Z", b_view_layer.name().c_str());
- pass_add(scene, PASS_DENOISING_DEPTH, "Denoising Depth", PassMode::NOISY);
- }
-
+ /* Path guiding debug passes. */
#ifdef WITH_CYCLES_DEBUG
b_engine.add_pass("Guiding Color", 3, "RGB", b_view_layer.name().c_str());
pass_add(scene, PASS_GUIDING_COLOR, "Guiding Color", PassMode::NOISY);
@@ -772,6 +694,8 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
pass_add(scene, PASS_GUIDING_AVG_ROUGHNESS, "Guiding Average Roughness", PassMode::NOISY);
#endif
+ unordered_set<string> expected_passes;
+
/* Custom AOV passes. */
BL::ViewLayer::aovs_iterator b_aov_iter;
for (b_view_layer.aovs.begin(b_aov_iter); b_aov_iter != b_view_layer.aovs.end(); ++b_aov_iter) {
@@ -781,16 +705,10 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
}
string name = b_aov.name();
- bool is_color = b_aov.type() == BL::AOV::type_COLOR;
+ PassType type = (b_aov.type() == BL::AOV::type_COLOR) ? PASS_AOV_COLOR : PASS_AOV_VALUE;
- if (is_color) {
- b_engine.add_pass(name.c_str(), 4, "RGBA", b_view_layer.name().c_str());
- pass_add(scene, PASS_AOV_COLOR, name.c_str());
- }
- else {
- b_engine.add_pass(name.c_str(), 1, "X", b_view_layer.name().c_str());
- pass_add(scene, PASS_AOV_VALUE, name.c_str());
- }
+ pass_add(scene, type, name.c_str());
+ expected_passes.insert(name);
}
/* Light Group passes. */
@@ -802,9 +720,29 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
string name = string_printf("Combined_%s", b_lightgroup.name().c_str());
- b_engine.add_pass(name.c_str(), 3, "RGB", b_view_layer.name().c_str());
Pass *pass = pass_add(scene, PASS_COMBINED, name.c_str(), PassMode::NOISY);
pass->set_lightgroup(ustring(b_lightgroup.name()));
+ expected_passes.insert(name);
+ }
+
+ /* Sync the passes that were defined in engine.py. */
+ for (BL::RenderPass &b_pass : b_rlay.passes) {
+ PassType pass_type = PASS_NONE;
+ PassMode pass_mode = PassMode::DENOISED;
+
+ if (!get_known_pass_type(b_pass, pass_type, pass_mode)) {
+ if (!expected_passes.count(b_pass.name())) {
+ LOG(ERROR) << "Unknown pass " << b_pass.name();
+ }
+ continue;
+ }
+
+ if (pass_type == PASS_MOTION &&
+ (b_view_layer.use_motion_blur() && b_scene.render().use_motion_blur())) {
+ continue;
+ }
+
+ pass_add(scene, pass_type, b_pass.name().c_str(), pass_mode);
}
scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold());
diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake
index 9524cda54f5..44542a08156 100644
--- a/intern/cycles/cmake/external_libs.cmake
+++ b/intern/cycles/cmake/external_libs.cmake
@@ -289,8 +289,7 @@ if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_PATH_GUIDING)
endif()
get_target_property(OPENPGL_INCLUDE_DIR openpgl::openpgl INTERFACE_INCLUDE_DIRECTORIES)
else()
- set(WITH_CYCLES_PATH_GUIDING OFF)
- message(STATUS "OpenPGL not found, disabling WITH_CYCLES_PATH_GUIDING")
+ set_and_warn_library_found("OpenPGL" openpgl_FOUND WITH_CYCLES_PATH_GUIDING)
endif()
endif()
@@ -588,16 +587,14 @@ if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
# We can't use the version from the Blender precompiled libraries because
# it does not include the video subsystem.
find_package(SDL2 REQUIRED)
+ set_and_warn_library_found("SDL" SDL2_FOUND WITH_CYCLES_STANDALONE_GUI)
- if(NOT SDL2_FOUND)
- set(WITH_CYCLES_STANDALONE_GUI OFF)
- message(STATUS "SDL not found, disabling Cycles standalone GUI")
+ if(SDL2_FOUND)
+ include_directories(
+ SYSTEM
+ ${SDL2_INCLUDE_DIRS}
+ )
endif()
-
- include_directories(
- SYSTEM
- ${SDL2_INCLUDE_DIRS}
- )
endif()
###########################################################################
@@ -606,11 +603,11 @@ endif()
if(WITH_CYCLES_DEVICE_CUDA AND (WITH_CYCLES_CUDA_BINARIES OR NOT WITH_CUDA_DYNLOAD))
find_package(CUDA) # Try to auto locate CUDA toolkit
+ set_and_warn_library_found("CUDA compiler" CUDA_FOUND WITH_CYCLES_CUDA_BINARIES)
+
if(CUDA_FOUND)
message(STATUS "Found CUDA ${CUDA_NVCC_EXECUTABLE} (${CUDA_VERSION})")
else()
- message(STATUS "CUDA compiler not found, disabling WITH_CYCLES_CUDA_BINARIES")
- set(WITH_CYCLES_CUDA_BINARIES OFF)
if(NOT WITH_CUDA_DYNLOAD)
message(STATUS "Additionally falling back to dynamic CUDA load")
set(WITH_CUDA_DYNLOAD ON)
@@ -624,11 +621,10 @@ endif()
if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP)
find_package(HIP)
+ set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES)
+
if(HIP_FOUND)
message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})")
- else()
- message(STATUS "HIP compiler not found, disabling WITH_CYCLES_HIP_BINARIES")
- set(WITH_CYCLES_HIP_BINARIES OFF)
endif()
endif()
@@ -644,13 +640,17 @@ if(WITH_CYCLES_DEVICE_METAL)
find_library(METAL_LIBRARY Metal)
# This file was added in the 12.0 SDK, use it as a way to detect the version.
- if(METAL_LIBRARY AND NOT EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h")
- message(STATUS "Metal version too old, must be SDK 12.0 or newer, disabling WITH_CYCLES_DEVICE_METAL")
- set(WITH_CYCLES_DEVICE_METAL OFF)
- elseif(NOT METAL_LIBRARY)
- message(STATUS "Metal not found, disabling WITH_CYCLES_DEVICE_METAL")
- set(WITH_CYCLES_DEVICE_METAL OFF)
- else()
+ if(METAL_LIBRARY)
+ if(EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h")
+ set(METAL_FOUND ON)
+ else()
+ message(STATUS "Metal version too old, must be SDK 12.0 or newer")
+ set(METAL_FOUND OFF)
+ endif()
+ endif()
+
+ set_and_warn_library_found("Metal" METAL_FOUND WITH_CYCLES_DEVICE_METAL)
+ if(METAL_FOUND)
message(STATUS "Found Metal: ${METAL_LIBRARY}")
endif()
endif()
@@ -662,9 +662,10 @@ endif()
if(WITH_CYCLES_DEVICE_ONEAPI)
find_package(SYCL)
find_package(LevelZero)
+ set_and_warn_library_found("oneAPI" SYCL_FOUND WITH_CYCLES_DEVICE_ONEAPI)
+ set_and_warn_library_found("Level Zero" LEVEL_ZERO_FOUND WITH_CYCLES_DEVICE_ONEAPI)
- if(SYCL_FOUND AND LEVEL_ZERO_FOUND)
- message(STATUS "Found oneAPI: ${SYCL_LIBRARY}")
+ if(SYCL_FOUND AND SYCL_VERSION VERSION_GREATER_EQUAL 6.0 AND LEVEL_ZERO_FOUND)
message(STATUS "Found Level Zero: ${LEVEL_ZERO_LIBRARY}")
if(WITH_CYCLES_ONEAPI_BINARIES)
@@ -675,13 +676,14 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
endif()
if(NOT EXISTS ${OCLOC_INSTALL_DIR})
- message(STATUS "oneAPI ocloc not found in ${OCLOC_INSTALL_DIR}, disabling WITH_CYCLES_ONEAPI_BINARIES."
+ set(OCLOC_FOUND OFF)
+ message(STATUS "oneAPI ocloc not found in ${OCLOC_INSTALL_DIR}."
" A different ocloc directory can be set using OCLOC_INSTALL_DIR cmake variable.")
- set(WITH_CYCLES_ONEAPI_BINARIES OFF)
+ set_and_warn_library_found("ocloc" OCLOC_FOUND WITH_CYCLES_ONEAPI_BINARIES)
endif()
endif()
else()
- message(STATUS "oneAPI or Level Zero not found, disabling WITH_CYCLES_DEVICE_ONEAPI")
+ message(STATUS "SYCL 6.0+ or Level Zero not found, disabling WITH_CYCLES_DEVICE_ONEAPI")
set(WITH_CYCLES_DEVICE_ONEAPI OFF)
endif()
endif()
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index 5516e97f34f..5296d819e42 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -187,18 +187,22 @@ if(WITH_CYCLES_DEVICE_METAL)
)
endif()
if (WITH_CYCLES_DEVICE_ONEAPI)
+ if(WITH_CYCLES_ONEAPI_BINARIES)
+ set(cycles_kernel_oneapi_lib_suffix "_aot")
+ else()
+ set(cycles_kernel_oneapi_lib_suffix "_jit")
+ endif()
if(WIN32)
- set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/cycles_kernel_oneapi.lib)
+ set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.lib)
else()
- set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi.so)
+ set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so)
+ endif()
+ list(APPEND LIB ${cycles_kernel_oneapi_lib})
+ if(WIN32)
+ list(APPEND LIB debug ${SYCL_LIBRARY_DEBUG} optimized ${SYCL_LIBRARY})
+ else()
+ list(APPEND LIB ${SYCL_LIBRARY})
endif()
- list(APPEND LIB
- ${cycles_kernel_oneapi_lib}
- "$<$<CONFIG:Debug>:${SYCL_LIBRARY_DEBUG}>"
- "$<$<CONFIG:Release>:${SYCL_LIBRARY}>"
- "$<$<CONFIG:RelWithDebInfo>:${SYCL_LIBRARY}>"
- "$<$<CONFIG:MinSizeRel>:${SYCL_LIBRARY}>"
- )
add_definitions(-DWITH_ONEAPI)
list(APPEND SRC
${SRC_ONEAPI}
diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm
index 6a16d4bb3b4..4b929b6bc0a 100644
--- a/intern/cycles/device/metal/device_impl.mm
+++ b/intern/cycles/device/metal/device_impl.mm
@@ -339,6 +339,14 @@ bool MetalDevice::compile_and_load(MetalPipelineType pso_type)
MTLCompileOptions *options = [[MTLCompileOptions alloc] init];
+# if defined(MAC_OS_VERSION_13_0)
+ if (@available(macos 13.0, *)) {
+ if (device_vendor == METAL_GPU_INTEL) {
+ [options setOptimizationLevel:MTLLibraryOptimizationLevelSize];
+ }
+ }
+# endif
+
options.fastMathEnabled = YES;
if (@available(macOS 12.0, *)) {
options.languageVersion = MTLLanguageVersion2_4;
diff --git a/intern/cycles/device/metal/kernel.mm b/intern/cycles/device/metal/kernel.mm
index 5e0cb6d18f4..8ccc50e57a3 100644
--- a/intern/cycles/device/metal/kernel.mm
+++ b/intern/cycles/device/metal/kernel.mm
@@ -317,6 +317,12 @@ bool MetalKernelPipeline::should_use_binary_archive() const
}
}
+ /* Workaround for Intel GPU having issue using Binary Archives */
+ MetalGPUVendor gpu_vendor = MetalInfo::get_device_vendor(mtlDevice);
+ if (gpu_vendor == METAL_GPU_INTEL) {
+ return false;
+ }
+
if (pso_type == PSO_GENERIC) {
/* Archive the generic kernels. */
return true;
diff --git a/intern/cycles/device/metal/util.mm b/intern/cycles/device/metal/util.mm
index 65c67c400fe..f47638fac15 100644
--- a/intern/cycles/device/metal/util.mm
+++ b/intern/cycles/device/metal/util.mm
@@ -110,6 +110,12 @@ vector<id<MTLDevice>> const &MetalInfo::get_usable_devices()
usable |= (vendor == METAL_GPU_AMD);
}
+# if defined(MAC_OS_VERSION_13_0)
+ if (@available(macos 13.0, *)) {
+ usable |= (vendor == METAL_GPU_INTEL);
+ }
+# endif
+
if (usable) {
metal_printf("- %s\n", device_name.c_str());
[device retain];
diff --git a/intern/cycles/device/oneapi/device.cpp b/intern/cycles/device/oneapi/device.cpp
index f303ab41627..66d6f749e30 100644
--- a/intern/cycles/device/oneapi/device.cpp
+++ b/intern/cycles/device/oneapi/device.cpp
@@ -39,7 +39,7 @@ bool device_oneapi_init()
_putenv_s("SYCL_CACHE_THRESHOLD", "0");
}
if (getenv("SYCL_DEVICE_FILTER") == nullptr) {
- _putenv_s("SYCL_DEVICE_FILTER", "host,level_zero");
+ _putenv_s("SYCL_DEVICE_FILTER", "level_zero");
}
if (getenv("SYCL_ENABLE_PCI") == nullptr) {
_putenv_s("SYCL_ENABLE_PCI", "1");
@@ -50,7 +50,7 @@ bool device_oneapi_init()
# elif __linux__
setenv("SYCL_CACHE_PERSISTENT", "1", false);
setenv("SYCL_CACHE_THRESHOLD", "0", false);
- setenv("SYCL_DEVICE_FILTER", "host,level_zero", false);
+ setenv("SYCL_DEVICE_FILTER", "level_zero", false);
setenv("SYCL_ENABLE_PCI", "1", false);
setenv("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_IN_ORDER_QUEUE", "0", false);
# endif
diff --git a/intern/cycles/device/oneapi/device_impl.cpp b/intern/cycles/device/oneapi/device_impl.cpp
index 91f53fd1eae..3588b75713b 100644
--- a/intern/cycles/device/oneapi/device_impl.cpp
+++ b/intern/cycles/device/oneapi/device_impl.cpp
@@ -430,9 +430,9 @@ void OneapiDevice::check_usm(SyclQueue *queue_, const void *usm_ptr, bool allow_
sycl::usm::alloc usm_type = get_pointer_type(usm_ptr, queue->get_context());
(void)usm_type;
assert(usm_type == sycl::usm::alloc::device ||
- ((device_type == sycl::info::device_type::host ||
- device_type == sycl::info::device_type::cpu || allow_host) &&
- usm_type == sycl::usm::alloc::host));
+ ((device_type == sycl::info::device_type::cpu || allow_host) &&
+ usm_type == sycl::usm::alloc::host ||
+ usm_type == sycl::usm::alloc::unknown));
# else
/* Silence warning about unused arguments. */
(void)queue_;
@@ -671,14 +671,6 @@ std::vector<sycl::device> OneapiDevice::available_devices()
if (getenv("CYCLES_ONEAPI_ALL_DEVICES") != nullptr)
allow_all_devices = true;
- /* Host device is useful only for debugging at the moment
- * so we hide this device with default build settings. */
-# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
- bool allow_host = true;
-# else
- bool allow_host = false;
-# endif
-
const std::vector<sycl::platform> &oneapi_platforms = sycl::platform::get_platforms();
std::vector<sycl::device> available_devices;
@@ -690,17 +682,11 @@ std::vector<sycl::device> OneapiDevice::available_devices()
}
const std::vector<sycl::device> &oneapi_devices =
- (allow_all_devices || allow_host) ? platform.get_devices(sycl::info::device_type::all) :
- platform.get_devices(sycl::info::device_type::gpu);
+ (allow_all_devices) ? platform.get_devices(sycl::info::device_type::all) :
+ platform.get_devices(sycl::info::device_type::gpu);
for (const sycl::device &device : oneapi_devices) {
- if (allow_all_devices) {
- /* still filter out host device if build doesn't support it. */
- if (allow_host || !device.is_host()) {
- available_devices.push_back(device);
- }
- }
- else {
+ if (!allow_all_devices) {
bool filter_out = false;
/* For now we support all Intel(R) Arc(TM) devices and likely any future GPU,
@@ -712,11 +698,11 @@ std::vector<sycl::device> OneapiDevice::available_devices()
int number_of_eus = 96;
int threads_per_eu = 7;
if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) {
- number_of_eus = device.get_info<sycl::info::device::ext_intel_gpu_eu_count>();
+ number_of_eus = device.get_info<sycl::ext::intel::info::device::gpu_eu_count>();
}
if (device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) {
threads_per_eu =
- device.get_info<sycl::info::device::ext_intel_gpu_hw_threads_per_eu>();
+ device.get_info<sycl::ext::intel::info::device::gpu_hw_threads_per_eu>();
}
/* This filters out all Level-Zero supported GPUs from older generation than Arc. */
if (number_of_eus <= 96 && threads_per_eu == 7) {
@@ -732,9 +718,6 @@ std::vector<sycl::device> OneapiDevice::available_devices()
}
}
}
- else if (!allow_host && device.is_host()) {
- filter_out = true;
- }
else if (!allow_all_devices) {
filter_out = true;
}
@@ -797,9 +780,7 @@ char *OneapiDevice::device_capabilities()
GET_NUM_ATTR(native_vector_width_double)
GET_NUM_ATTR(native_vector_width_half)
- size_t max_clock_frequency =
- (size_t)(device.is_host() ? (size_t)0 :
- device.get_info<sycl::info::device::max_clock_frequency>());
+ size_t max_clock_frequency = device.get_info<sycl::info::device::max_clock_frequency>();
WRITE_ATTR("max_clock_frequency", max_clock_frequency)
GET_NUM_ATTR(address_bits)
@@ -837,7 +818,7 @@ void OneapiDevice::iterate_devices(OneAPIDeviceIteratorCallback cb, void *user_p
std::string name = device.get_info<sycl::info::device::name>();
std::string id = "ONEAPI_" + platform_name + "_" + name;
if (device.has(sycl::aspect::ext_intel_pci_address)) {
- id.append("_" + device.get_info<sycl::info::device::ext_intel_pci_address>());
+ id.append("_" + device.get_info<sycl::ext::intel::info::device::pci_address>());
}
(cb)(id.c_str(), name.c_str(), num, user_ptr);
num++;
@@ -855,7 +836,7 @@ int OneapiDevice::get_num_multiprocessors()
{
const sycl::device &device = reinterpret_cast<sycl::queue *>(device_queue_)->get_device();
if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) {
- return device.get_info<sycl::info::device::ext_intel_gpu_eu_count>();
+ return device.get_info<sycl::ext::intel::info::device::gpu_eu_count>();
}
else
return 0;
@@ -866,8 +847,8 @@ int OneapiDevice::get_max_num_threads_per_multiprocessor()
const sycl::device &device = reinterpret_cast<sycl::queue *>(device_queue_)->get_device();
if (device.has(sycl::aspect::ext_intel_gpu_eu_simd_width) &&
device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) {
- return device.get_info<sycl::info::device::ext_intel_gpu_eu_simd_width>() *
- device.get_info<sycl::info::device::ext_intel_gpu_hw_threads_per_eu>();
+ return device.get_info<sycl::ext::intel::info::device::gpu_eu_simd_width>() *
+ device.get_info<sycl::ext::intel::info::device::gpu_hw_threads_per_eu>();
}
else
return 0;
diff --git a/intern/cycles/device/oneapi/device_impl.h b/intern/cycles/device/oneapi/device_impl.h
index 62034150eac..197cf03d60d 100644
--- a/intern/cycles/device/oneapi/device_impl.h
+++ b/intern/cycles/device/oneapi/device_impl.h
@@ -3,7 +3,7 @@
#ifdef WITH_ONEAPI
-# include <CL/sycl.hpp>
+# include <sycl/sycl.hpp>
# include "device/device.h"
# include "device/oneapi/device.h"
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 36c8b23d983..81c5f593974 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -713,10 +713,17 @@ endif()
# oneAPI module
if(WITH_CYCLES_DEVICE_ONEAPI)
+ if(WITH_CYCLES_ONEAPI_BINARIES)
+ set(cycles_kernel_oneapi_lib_suffix "_aot")
+ else()
+ set(cycles_kernel_oneapi_lib_suffix "_jit")
+ endif()
+
if(WIN32)
- set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.dll)
+ set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.dll)
+ set(cycles_kernel_oneapi_linker_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.lib)
else()
- set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi.so)
+ set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so)
endif()
set(cycles_oneapi_kernel_sources
@@ -751,10 +758,6 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
${SYCL_CPP_FLAGS}
)
- if (WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED)
- list(APPEND sycl_compiler_flags -DWITH_ONEAPI_SYCL_HOST_ENABLED)
- endif()
-
# Set defaults for spir64 and spir64_gen options
if (NOT DEFINED CYCLES_ONEAPI_SYCL_OPTIONS_spir64)
set(CYCLES_ONEAPI_SYCL_OPTIONS_spir64 "-options '-ze-opt-large-register-file -ze-opt-regular-grf-kernel integrator_intersect'")
@@ -767,6 +770,8 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
string(PREPEND CYCLES_ONEAPI_SYCL_OPTIONS_spir64_gen "-device ${CYCLES_ONEAPI_SPIR64_GEN_DEVICES} ")
if (WITH_CYCLES_ONEAPI_BINARIES)
+ # AoT binaries aren't currently reused when calling sycl::build.
+ list (APPEND sycl_compiler_flags -DSYCL_SKIP_KERNELS_PRELOAD)
# Iterate over all targest and their options
list (JOIN CYCLES_ONEAPI_SYCL_TARGETS "," targets_string)
list (APPEND sycl_compiler_flags -fsycl-targets=${targets_string})
@@ -819,12 +824,17 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
-DONEAPI_EXPORT)
string(REPLACE /Redist/ /Tools/ MSVC_TOOLS_DIR ${MSVC_REDIST_DIR})
- if(NOT CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) # case for Ninja on Windows
+ # Version Folder between Redist and Tools can mismatch sometimes
+ if(NOT EXISTS ${MSVC_TOOLS_DIR})
+ get_filename_component(cmake_ar_dir ${CMAKE_AR} DIRECTORY)
+ get_filename_component(MSVC_TOOLS_DIR "${cmake_ar_dir}/../../../" ABSOLUTE)
+ endif()
+ if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION)
+ set(WINDOWS_KIT_DIR ${WINDOWS_KITS_DIR}/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION})
+ else() # case for Ninja on Windows
get_filename_component(cmake_mt_dir ${CMAKE_MT} DIRECTORY)
string(REPLACE /bin/ /Lib/ WINDOWS_KIT_DIR ${cmake_mt_dir})
get_filename_component(WINDOWS_KIT_DIR "${WINDOWS_KIT_DIR}/../" ABSOLUTE)
- else()
- set(WINDOWS_KIT_DIR ${WINDOWS_KITS_DIR}/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION})
endif()
list(APPEND sycl_compiler_flags
-L "${MSVC_TOOLS_DIR}/lib/x64"
@@ -836,15 +846,13 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
set(sycl_compiler_flags_RelWithDebInfo ${sycl_compiler_flags})
set(sycl_compiler_flags_MinSizeRel ${sycl_compiler_flags})
list(APPEND sycl_compiler_flags_RelWithDebInfo -g)
- get_filename_component(sycl_library_debug_name ${SYCL_LIBRARY_DEBUG} NAME_WE)
list(APPEND sycl_compiler_flags_Debug
-g
-D_DEBUG
- -nostdlib -Xclang --dependent-lib=msvcrtd
- -Xclang --dependent-lib=${sycl_library_debug_name})
+ -nostdlib -Xclang --dependent-lib=msvcrtd)
add_custom_command(
- OUTPUT ${cycles_kernel_oneapi_lib}
+ OUTPUT ${cycles_kernel_oneapi_lib} ${cycles_kernel_oneapi_linker_lib}
COMMAND ${CMAKE_COMMAND} -E env
"LIB=${sycl_compiler_root}/../lib" # for compiler to find sycl.lib
"PATH=${OCLOC_INSTALL_DIR}\;${sycl_compiler_root}"
diff --git a/intern/cycles/kernel/bvh/shadow_all.h b/intern/cycles/kernel/bvh/shadow_all.h
index 2ffe1496c72..b31ba479e4f 100644
--- a/intern/cycles/kernel/bvh/shadow_all.h
+++ b/intern/cycles/kernel/bvh/shadow_all.h
@@ -229,7 +229,7 @@ ccl_device_inline
/* Always use baked shadow transparency for curves. */
if (isect.type & PRIMITIVE_CURVE) {
*r_throughput *= intersection_curve_shadow_transparency(
- kg, isect.object, isect.prim, isect.u);
+ kg, isect.object, isect.prim, isect.type, isect.u);
if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
return true;
diff --git a/intern/cycles/kernel/bvh/util.h b/intern/cycles/kernel/bvh/util.h
index a57703a8b8c..9ba787550c5 100644
--- a/intern/cycles/kernel/bvh/util.h
+++ b/intern/cycles/kernel/bvh/util.h
@@ -190,10 +190,8 @@ ccl_device_inline int intersection_find_attribute(KernelGlobals kg,
/* Cut-off value to stop transparent shadow tracing when practically opaque. */
#define CURVE_SHADOW_TRANSPARENCY_CUTOFF 0.001f
-ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg,
- const int object,
- const int prim,
- const float u)
+ccl_device_inline float intersection_curve_shadow_transparency(
+ KernelGlobals kg, const int object, const int prim, const int type, const float u)
{
/* Find attribute. */
const int offset = intersection_find_attribute(kg, object, ATTR_STD_SHADOW_TRANSPARENCY);
@@ -204,7 +202,7 @@ ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg,
/* Interpolate transparency between curve keys. */
const KernelCurve kcurve = kernel_data_fetch(curves, prim);
- const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(kcurve.type);
+ const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(type);
const int k1 = k0 + 1;
const float f0 = kernel_data_fetch(attributes_float, offset + k0);
diff --git a/intern/cycles/kernel/device/cpu/bvh.h b/intern/cycles/kernel/device/cpu/bvh.h
index d9267e1cd6d..2d7d8c2d704 100644
--- a/intern/cycles/kernel/device/cpu/bvh.h
+++ b/intern/cycles/kernel/device/cpu/bvh.h
@@ -252,7 +252,7 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum
/* Always use baked shadow transparency for curves. */
if (current_isect.type & PRIMITIVE_CURVE) {
ctx->throughput *= intersection_curve_shadow_transparency(
- kg, current_isect.object, current_isect.prim, current_isect.u);
+ kg, current_isect.object, current_isect.prim, current_isect.type, current_isect.u);
if (ctx->throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
ctx->opaque_hit = true;
diff --git a/intern/cycles/kernel/device/gpu/parallel_active_index.h b/intern/cycles/kernel/device/gpu/parallel_active_index.h
index c1df49c4f49..38cdcb572eb 100644
--- a/intern/cycles/kernel/device/gpu/parallel_active_index.h
+++ b/intern/cycles/kernel/device/gpu/parallel_active_index.h
@@ -23,22 +23,6 @@ CCL_NAMESPACE_BEGIN
* and keep device specific code in compat.h */
#ifdef __KERNEL_ONEAPI__
-# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
-template<typename IsActiveOp>
-void cpu_serial_active_index_array_impl(const uint num_states,
- ccl_global int *ccl_restrict indices,
- ccl_global int *ccl_restrict num_indices,
- IsActiveOp is_active_op)
-{
- int write_index = 0;
- for (int state_index = 0; state_index < num_states; state_index++) {
- if (is_active_op(state_index))
- indices[write_index++] = state_index;
- }
- *num_indices = write_index;
- return;
-}
-# endif /* WITH_ONEAPI_SYCL_HOST_ENABLED */
template<typename IsActiveOp>
void gpu_parallel_active_index_array_impl(const uint num_states,
@@ -182,18 +166,11 @@ __device__
num_simd_groups, \
simdgroup_offset)
#elif defined(__KERNEL_ONEAPI__)
-# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
-# define gpu_parallel_active_index_array( \
- blocksize, num_states, indices, num_indices, is_active_op) \
- if (ccl_gpu_global_size_x() == 1) \
- cpu_serial_active_index_array_impl(num_states, indices, num_indices, is_active_op); \
- else \
- gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op);
-# else
-# define gpu_parallel_active_index_array( \
- blocksize, num_states, indices, num_indices, is_active_op) \
- gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op)
-# endif
+
+# define gpu_parallel_active_index_array( \
+ blocksize, num_states, indices, num_indices, is_active_op) \
+ gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op)
+
#else
# define gpu_parallel_active_index_array( \
diff --git a/intern/cycles/kernel/device/metal/context_begin.h b/intern/cycles/kernel/device/metal/context_begin.h
index 99cb1e3826e..e75ec9cadec 100644
--- a/intern/cycles/kernel/device/metal/context_begin.h
+++ b/intern/cycles/kernel/device/metal/context_begin.h
@@ -34,21 +34,48 @@ class MetalKernelContext {
kernel_assert(0);
return 0;
}
-
+
+#ifdef __KERNEL_METAL_INTEL__
+ template<typename TextureType, typename CoordsType>
+ inline __attribute__((__always_inline__))
+ auto ccl_gpu_tex_object_read_intel_workaround(TextureType texture_array,
+ const uint tid, const uint sid,
+ CoordsType coords) const
+ {
+ switch(sid) {
+ default:
+ case 0: return texture_array[tid].tex.sample(sampler(address::repeat, filter::nearest), coords);
+ case 1: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::nearest), coords);
+ case 2: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::nearest), coords);
+ case 3: return texture_array[tid].tex.sample(sampler(address::repeat, filter::linear), coords);
+ case 4: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::linear), coords);
+ case 5: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::linear), coords);
+ }
+ }
+#endif
+
// texture2d
template<>
inline __attribute__((__always_inline__))
float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const {
const uint tid(tex);
const uint sid(tex >> 32);
+#ifndef __KERNEL_METAL_INTEL__
return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y));
+#else
+ return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_2d, tid, sid, float2(x, y));
+#endif
}
template<>
inline __attribute__((__always_inline__))
float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const {
const uint tid(tex);
const uint sid(tex >> 32);
+#ifndef __KERNEL_METAL_INTEL__
return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)).x;
+#else
+ return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_2d, tid, sid, float2(x, y)).x;
+#endif
}
// texture3d
@@ -57,14 +84,22 @@ class MetalKernelContext {
float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const {
const uint tid(tex);
const uint sid(tex >> 32);
+#ifndef __KERNEL_METAL_INTEL__
return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z));
+#else
+ return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_3d, tid, sid, float3(x, y, z));
+#endif
}
template<>
inline __attribute__((__always_inline__))
float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const {
const uint tid(tex);
const uint sid(tex >> 32);
+#ifndef __KERNEL_METAL_INTEL__
return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)).x;
+#else
+ return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_3d, tid, sid, float3(x, y, z)).x;
+#endif
}
# include "kernel/device/gpu/image.h"
diff --git a/intern/cycles/kernel/device/metal/kernel.metal b/intern/cycles/kernel/device/metal/kernel.metal
index 5646c7446db..8b69ee025cd 100644
--- a/intern/cycles/kernel/device/metal/kernel.metal
+++ b/intern/cycles/kernel/device/metal/kernel.metal
@@ -228,7 +228,7 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal,
/* Always use baked shadow transparency for curves. */
if (type & PRIMITIVE_CURVE) {
float throughput = payload.throughput;
- throughput *= context.intersection_curve_shadow_transparency(nullptr, object, prim, u);
+ throughput *= context.intersection_curve_shadow_transparency(nullptr, object, prim, type, u);
payload.throughput = throughput;
payload.num_hits += 1;
diff --git a/intern/cycles/kernel/device/oneapi/compat.h b/intern/cycles/kernel/device/oneapi/compat.h
index 8ae40b0612e..dfaec65130c 100644
--- a/intern/cycles/kernel/device/oneapi/compat.h
+++ b/intern/cycles/kernel/device/oneapi/compat.h
@@ -55,18 +55,6 @@
#define ccl_gpu_kernel(block_num_threads, thread_num_registers)
#define ccl_gpu_kernel_threads(block_num_threads)
-#ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
-# define KG_ND_ITEMS \
- kg->nd_item_local_id_0 = item.get_local_id(0); \
- kg->nd_item_local_range_0 = item.get_local_range(0); \
- kg->nd_item_group_0 = item.get_group(0); \
- kg->nd_item_group_range_0 = item.get_group_range(0); \
- kg->nd_item_global_id_0 = item.get_global_id(0); \
- kg->nd_item_global_range_0 = item.get_global_range(0);
-#else
-# define KG_ND_ITEMS
-#endif
-
#define ccl_gpu_kernel_signature(name, ...) \
void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \
size_t kernel_global_size, \
@@ -76,8 +64,7 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \
(kg); \
cgh.parallel_for<class kernel_##name>( \
sycl::nd_range<1>(kernel_global_size, kernel_local_size), \
- [=](sycl::nd_item<1> item) { \
- KG_ND_ITEMS
+ [=](sycl::nd_item<1> item) {
#define ccl_gpu_kernel_postfix \
}); \
@@ -95,31 +82,17 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \
} ccl_gpu_kernel_lambda_pass((ONEAPIKernelContext *)kg)
/* GPU thread, block, grid size and index */
-#ifndef WITH_ONEAPI_SYCL_HOST_ENABLED
-# define ccl_gpu_thread_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_id(0))
-# define ccl_gpu_block_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_range(0))
-# define ccl_gpu_block_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group(0))
-# define ccl_gpu_grid_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group_range(0))
-# define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0])
-# define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp))
-
-# define ccl_gpu_global_id_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_id(0))
-# define ccl_gpu_global_size_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_range(0))
-#else
-# define ccl_gpu_thread_idx_x (kg->nd_item_local_id_0)
-# define ccl_gpu_block_dim_x (kg->nd_item_local_range_0)
-# define ccl_gpu_block_idx_x (kg->nd_item_group_0)
-# define ccl_gpu_grid_dim_x (kg->nd_item_group_range_0)
-# define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0])
-# define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp))
-
-# define ccl_gpu_global_id_x() (kg->nd_item_global_id_0)
-# define ccl_gpu_global_size_x() (kg->nd_item_global_range_0)
-#endif
+#define ccl_gpu_thread_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_id(0))
+#define ccl_gpu_block_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_range(0))
+#define ccl_gpu_block_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group(0))
+#define ccl_gpu_grid_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group_range(0))
+#define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0])
+#define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp))
+#define ccl_gpu_global_id_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_id(0))
+#define ccl_gpu_global_size_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_range(0))
/* GPU warp synchronization */
-
#define ccl_gpu_syncthreads() sycl::ext::oneapi::experimental::this_nd_item<1>().barrier()
#define ccl_gpu_local_syncthreads() sycl::ext::oneapi::experimental::this_nd_item<1>().barrier(sycl::access::fence_space::local_space)
#ifdef __SYCL_DEVICE_ONLY__
diff --git a/intern/cycles/kernel/device/oneapi/globals.h b/intern/cycles/kernel/device/oneapi/globals.h
index d60f4f135ba..116620eb725 100644
--- a/intern/cycles/kernel/device/oneapi/globals.h
+++ b/intern/cycles/kernel/device/oneapi/globals.h
@@ -23,15 +23,6 @@ typedef struct KernelGlobalsGPU {
#undef KERNEL_DATA_ARRAY
IntegratorStateGPU *integrator_state;
const KernelData *__data;
-#ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
- size_t nd_item_local_id_0;
- size_t nd_item_local_range_0;
- size_t nd_item_group_0;
- size_t nd_item_group_range_0;
-
- size_t nd_item_global_id_0;
- size_t nd_item_global_range_0;
-#endif
} KernelGlobalsGPU;
typedef ccl_global KernelGlobalsGPU *ccl_restrict KernelGlobals;
diff --git a/intern/cycles/kernel/device/oneapi/kernel.cpp b/intern/cycles/kernel/device/oneapi/kernel.cpp
index 40e0b1f0b2b..525ae288f0c 100644
--- a/intern/cycles/kernel/device/oneapi/kernel.cpp
+++ b/intern/cycles/kernel/device/oneapi/kernel.cpp
@@ -8,7 +8,7 @@
# include <map>
# include <set>
-# include <CL/sycl.hpp>
+# include <sycl/sycl.hpp>
# include "kernel/device/oneapi/compat.h"
# include "kernel/device/oneapi/globals.h"
@@ -144,6 +144,10 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue,
bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features)
{
+# ifdef SYCL_SKIP_KERNELS_PRELOAD
+ (void)queue_;
+ (void)requested_features;
+# else
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
@@ -175,7 +179,7 @@ bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features)
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());
+ sycl::build(one_kernel_bundle);
}
}
catch (sycl::exception const &e) {
@@ -184,7 +188,7 @@ bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features)
}
return false;
}
-
+# endif
return true;
}
@@ -226,13 +230,6 @@ bool oneapi_enqueue_kernel(KernelContext *kernel_context,
/* NOTE(@nsirgien): As for now non-uniform work-groups don't work on most oneAPI devices,
* we extend work size to fit uniformity requirements. */
global_size = groups_count * local_size;
-
-# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED
- if (queue->get_device().is_host()) {
- global_size = 1;
- local_size = 1;
- }
-# endif
}
/* Let the compiler throw an error if there are any kernels missing in this implementation. */
diff --git a/intern/cycles/kernel/device/optix/bvh.h b/intern/cycles/kernel/device/optix/bvh.h
index fb9907709ce..6d81b44660c 100644
--- a/intern/cycles/kernel/device/optix/bvh.h
+++ b/intern/cycles/kernel/device/optix/bvh.h
@@ -202,7 +202,7 @@ extern "C" __global__ void __anyhit__kernel_optix_shadow_all_hit()
/* Always use baked shadow transparency for curves. */
if (type & PRIMITIVE_CURVE) {
float throughput = __uint_as_float(optixGetPayload_1());
- throughput *= intersection_curve_shadow_transparency(nullptr, object, prim, u);
+ throughput *= intersection_curve_shadow_transparency(nullptr, object, prim, type, u);
optixSetPayload_1(__float_as_uint(throughput));
optixSetPayload_2(uint16_pack_to_uint(num_recorded_hits, num_hits + 1));
diff --git a/intern/ffmpeg/tests/ffmpeg_codecs.cc b/intern/ffmpeg/tests/ffmpeg_codecs.cc
index d0c40736884..e5c33202417 100644
--- a/intern/ffmpeg/tests/ffmpeg_codecs.cc
+++ b/intern/ffmpeg/tests/ffmpeg_codecs.cc
@@ -130,6 +130,7 @@ FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_DVVIDEO, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG1VIDEO, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG2VIDEO, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_FLV1, AV_PIX_FMT_YUV420P)
+FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_AV1, AV_PIX_FMT_YUV420P)
/* Audio codecs */
@@ -149,6 +150,12 @@ FFMPEG_TEST_VCODEC_NAME(libx264, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_NAME(libvpx, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_NAME(libopenjpeg, AV_PIX_FMT_YUV420P)
FFMPEG_TEST_VCODEC_NAME(libxvid, AV_PIX_FMT_YUV420P)
+/* aom's AV1 encoder is "libaom-av1". FFMPEG_TEST_VCODEC_NAME(libaom-av1, ...)
+ * will not work because the dash will not work with the test macro. */
+TEST(ffmpeg, libaom_av1_AV_PIX_FMT_YUV420P)
+{
+ EXPECT_TRUE(test_codec_video_by_name("libaom-av1", AV_PIX_FMT_YUV420P));
+}
FFMPEG_TEST_ACODEC_NAME(libvorbis, AV_SAMPLE_FMT_FLTP)
FFMPEG_TEST_ACODEC_NAME(libopus, AV_SAMPLE_FMT_FLT)
FFMPEG_TEST_ACODEC_NAME(libmp3lame, AV_SAMPLE_FMT_FLTP)
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 2f8ea1f9065..fb10530bfae 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -268,7 +268,7 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
if(WITH_GHOST_WAYLAND_DYNLOAD)
list(APPEND INC_SYS
- ../../intern/wayland_dynload/extern
+ ../wayland_dynload/extern
)
list(APPEND LIB
bf_intern_wayland_dynload
@@ -372,10 +372,18 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
)
+ # Pointer-gestures (multi-touch).
+ generate_protocol_bindings(
+ "${WAYLAND_PROTOCOLS_DIR}/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml"
+ )
# Tablet.
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/unstable/tablet/tablet-unstable-v2.xml"
)
+ # Primary-selection.
+ generate_protocol_bindings(
+ "${WAYLAND_PROTOCOLS_DIR}/unstable/primary-selection/primary-selection-unstable-v1.xml"
+ )
add_definitions(-DWITH_GHOST_WAYLAND)
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 7fda535a7ac..62984c762c1 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -162,7 +162,6 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
* \param height: The height the window.
* \param state: The state of the window when opened.
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
- * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL options.
* \return A handle to the new window ( == NULL if creation failed).
*/
@@ -175,7 +174,6 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings);
/**
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 9fb94ed1525..64b5f4ee496 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -232,7 +232,6 @@ class GHOST_ISystem {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
- * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized.
@@ -245,7 +244,6 @@ class GHOST_ISystem {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 2645ce448b0..db4eeff3122 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -60,10 +60,6 @@ typedef struct {
int hot_spot[2];
} GHOST_CursorBitmapRef;
-typedef struct {
- int flags;
-} GHOST_GLSettings;
-
typedef enum {
GHOST_glStereoVisual = (1 << 0),
GHOST_glDebugContext = (1 << 1),
@@ -157,6 +153,9 @@ typedef enum {
#ifdef WIN32
GHOST_kDrawingContextTypeD3D,
#endif
+#ifdef __APPLE__
+ GHOST_kDrawingContextTypeMetal,
+#endif
} GHOST_TDrawingContextType;
typedef enum {
@@ -598,6 +597,11 @@ typedef struct {
uint32_t frequency;
} GHOST_DisplaySetting;
+typedef struct {
+ int flags;
+ GHOST_TDrawingContextType context_type;
+} GHOST_GLSettings;
+
typedef enum {
/** Axis that cursor grab will wrap. */
GHOST_kDebugDefault = (1 << 1),
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 158e979cdf2..aa2363c10b3 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -161,7 +161,6 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
uint32_t height,
GHOST_TWindowState state,
bool is_dialog,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings)
{
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
@@ -172,7 +171,6 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
width,
height,
state,
- type,
glSettings,
false,
is_dialog,
diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h
index 130b926f25c..d19fffffb43 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.h
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -30,7 +30,8 @@ class GHOST_ContextCGL : public GHOST_Context {
GHOST_ContextCGL(bool stereoVisual,
NSView *metalView,
CAMetalLayer *metalLayer,
- NSOpenGLView *openglView);
+ NSOpenGLView *openglView,
+ GHOST_TDrawingContextType type);
/**
* Destructor.
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index ff53ecdbbba..9dad337a5d6 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -46,8 +46,10 @@ int GHOST_ContextCGL::s_sharedCount = 0;
GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual,
NSView *metalView,
CAMetalLayer *metalLayer,
- NSOpenGLView *openGLView)
+ NSOpenGLView *openGLView,
+ GHOST_TDrawingContextType type)
: GHOST_Context(stereoVisual),
+ m_useMetalForRendering(type == GHOST_kDrawingContextTypeMetal),
m_metalView(metalView),
m_metalLayer(metalLayer),
m_metalCmdQueue(nil),
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index f4c726c7450..9e9b9f14c43 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -12,11 +12,14 @@
#include <climits>
#include <cmath>
-#include <cstdio> /* For error/info reporting. */
#include <cstring> /* For memory functions. */
-/* Printable version of each GHOST_TProgress value. */
-static const char *progress_string[] = {
+/* -------------------------------------------------------------------- */
+/** \name NDOF Enum Strings
+ * \{ */
+
+/* Printable values for #GHOST_TProgress enum (keep aligned). */
+static const char *ndof_progress_string[] = {
"not started",
"starting",
"in progress",
@@ -24,41 +27,30 @@ static const char *progress_string[] = {
"finished",
};
+/* Printable values for #NDOF_ButtonT enum (keep aligned) */
static const char *ndof_button_names[] = {
- /* used internally, never sent */
- "NDOF_BUTTON_NONE",
- /* these two are available from any 3Dconnexion device */
+ /* Exclude `NDOF_BUTTON_NONE` (-1). */
"NDOF_BUTTON_MENU",
"NDOF_BUTTON_FIT",
- /* standard views */
"NDOF_BUTTON_TOP",
"NDOF_BUTTON_BOTTOM",
"NDOF_BUTTON_LEFT",
"NDOF_BUTTON_RIGHT",
"NDOF_BUTTON_FRONT",
"NDOF_BUTTON_BACK",
- /* more views */
"NDOF_BUTTON_ISO1",
"NDOF_BUTTON_ISO2",
- /* 90 degree rotations */
"NDOF_BUTTON_ROLL_CW",
"NDOF_BUTTON_ROLL_CCW",
"NDOF_BUTTON_SPIN_CW",
"NDOF_BUTTON_SPIN_CCW",
"NDOF_BUTTON_TILT_CW",
"NDOF_BUTTON_TILT_CCW",
- /* device control */
"NDOF_BUTTON_ROTATE",
"NDOF_BUTTON_PANZOOM",
"NDOF_BUTTON_DOMINANT",
"NDOF_BUTTON_PLUS",
"NDOF_BUTTON_MINUS",
- /* keyboard emulation */
- "NDOF_BUTTON_ESC",
- "NDOF_BUTTON_ALT",
- "NDOF_BUTTON_SHIFT",
- "NDOF_BUTTON_CTRL",
- /* general-purpose buttons */
"NDOF_BUTTON_1",
"NDOF_BUTTON_2",
"NDOF_BUTTON_3",
@@ -69,18 +61,47 @@ static const char *ndof_button_names[] = {
"NDOF_BUTTON_8",
"NDOF_BUTTON_9",
"NDOF_BUTTON_10",
- /* more general-purpose buttons */
"NDOF_BUTTON_A",
"NDOF_BUTTON_B",
"NDOF_BUTTON_C",
- /* the end */
- "NDOF_BUTTON_LAST",
+ "NDOF_BUTTON_V1",
+ "NDOF_BUTTON_V2",
+ "NDOF_BUTTON_V3",
+ /* Keyboard emulation. */
+ "NDOF_BUTTON_ESC",
+ "NDOF_BUTTON_ENTER",
+ "NDOF_BUTTON_DELETE",
+ "NDOF_BUTTON_TAB",
+ "NDOF_BUTTON_SPACE",
+ "NDOF_BUTTON_ALT",
+ "NDOF_BUTTON_SHIFT",
+ "NDOF_BUTTON_CTRL",
};
+static const char *ndof_device_names[] = {
+ "UnknownDevice",
+ "SpaceNavigator",
+ "SpaceExplorer",
+ "SpacePilotPro",
+ "SpaceMousePro",
+ "SpaceMouseWireless",
+ "SpaceMouseProWireless",
+ "SpaceMouseEnterprise",
+ "SpacePilot",
+ "Spaceball5000",
+ "SpaceTraveler",
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name NDOF Button Maps
+ * \{ */
+
/* Shared by the latest 3Dconnexion hardware
* SpacePilotPro uses all of these
* smaller devices use only some, based on button mask. */
-static const NDOF_ButtonT Modern3Dx_HID_map[] = {
+static const NDOF_ButtonT ndof_HID_map_Modern3Dx[] = {
NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, NDOF_BUTTON_TOP, NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, NDOF_BUTTON_BOTTOM, NDOF_BUTTON_BACK,
NDOF_BUTTON_ROLL_CW, NDOF_BUTTON_ROLL_CCW, NDOF_BUTTON_ISO1, NDOF_BUTTON_ISO2,
@@ -90,7 +111,7 @@ static const NDOF_ButtonT Modern3Dx_HID_map[] = {
NDOF_BUTTON_SHIFT, NDOF_BUTTON_CTRL, NDOF_BUTTON_ROTATE, NDOF_BUTTON_PANZOOM,
NDOF_BUTTON_DOMINANT, NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS};
-static const NDOF_ButtonT SpaceExplorer_HID_map[] = {
+static const NDOF_ButtonT ndof_HID_map_SpaceExplorer[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_TOP,
@@ -108,9 +129,8 @@ static const NDOF_ButtonT SpaceExplorer_HID_map[] = {
NDOF_BUTTON_ROTATE,
};
-/* This is the older SpacePilot (sans Pro)
- * thanks to polosson for info about this device. */
-static const NDOF_ButtonT SpacePilot_HID_map[] = {
+/* This is the older SpacePilot (sans Pro). */
+static const NDOF_ButtonT ndof_HID_map_SpacePilot[] = {
NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, NDOF_BUTTON_4,
NDOF_BUTTON_5, NDOF_BUTTON_6, NDOF_BUTTON_TOP, NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, NDOF_BUTTON_ESC, NDOF_BUTTON_ALT,
@@ -119,7 +139,7 @@ static const NDOF_ButtonT SpacePilot_HID_map[] = {
NDOF_BUTTON_NONE /* the CONFIG button -- what does it do? */
};
-static const NDOF_ButtonT Generic_HID_map[] = {
+static const NDOF_ButtonT ndof_HID_map_Generic[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_3,
@@ -134,27 +154,70 @@ static const NDOF_ButtonT Generic_HID_map[] = {
NDOF_BUTTON_C,
};
-static const int genericButtonCount = ARRAY_SIZE(Generic_HID_map);
+/* Values taken from: https://github.com/FreeSpacenav/spacenavd/wiki/Device-button-names */
+static const NDOF_ButtonT ndof_HID_map_SpaceMouseEnterprise[] = {
+ NDOF_BUTTON_1, /* (0) */
+ NDOF_BUTTON_2, /* (1) */
+ NDOF_BUTTON_3, /* (2) */
+ NDOF_BUTTON_4, /* (3) */
+ NDOF_BUTTON_5, /* (4) */
+ NDOF_BUTTON_6, /* (5) */
+ NDOF_BUTTON_7, /* (6) */
+ NDOF_BUTTON_8, /* (7) */
+ NDOF_BUTTON_9, /* (8) */
+ NDOF_BUTTON_A, /* Labeled "10" (9). */
+ NDOF_BUTTON_B, /* Labeled "11" (10). */
+ NDOF_BUTTON_C, /* Labeled "12" (11). */
+ NDOF_BUTTON_MENU, /* (12). */
+ NDOF_BUTTON_FIT, /* (13). */
+ NDOF_BUTTON_TOP, /* (14). */
+ NDOF_BUTTON_RIGHT, /* (15). */
+ NDOF_BUTTON_FRONT, /* (16). */
+ NDOF_BUTTON_ROLL_CW, /* (17). */
+ NDOF_BUTTON_ESC, /* (18). */
+ NDOF_BUTTON_ALT, /* (19). */
+ NDOF_BUTTON_SHIFT, /* (20). */
+ NDOF_BUTTON_CTRL, /* (21). */
+ NDOF_BUTTON_ROTATE, /* Labeled "Lock Rotate" (22). */
+ NDOF_BUTTON_ENTER, /* Labeled "Enter" (23). */
+ NDOF_BUTTON_DELETE, /* (24). */
+ NDOF_BUTTON_TAB, /* (25). */
+ NDOF_BUTTON_SPACE, /* (26). */
+ NDOF_BUTTON_V1, /* Labeled "V1" (27). */
+ NDOF_BUTTON_V2, /* Labeled "V2" (28). */
+ NDOF_BUTTON_V3, /* Labeled "V3" (29). */
+ NDOF_BUTTON_ISO1, /* Labeled "ISO1" (30). */
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name NDOF Manager Class
+ * \{ */
+
+static const int genericButtonCount = ARRAY_SIZE(ndof_HID_map_Generic);
GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys)
- : m_system(sys),
- m_deviceType(NDOF_UnknownDevice), /* Each platform has its own device detection code. */
- m_buttonCount(genericButtonCount),
- m_buttonMask(0),
- m_hidMap(Generic_HID_map),
- m_buttons(0),
- m_motionTime(0),
- m_prevMotionTime(0),
- m_motionState(GHOST_kNotStarted),
- m_motionEventPending(false),
- m_deadZone(0.0f)
+ : system_(sys),
+ device_type_(NDOF_UnknownDevice), /* Each platform has its own device detection code. */
+ hid_map_button_num_(genericButtonCount),
+ hid_map_button_mask_(0),
+ hid_map_(ndof_HID_map_Generic),
+ button_depressed_(0),
+ motion_time_(0),
+ motion_time_prev_(0),
+ motion_state_(GHOST_kNotStarted),
+ motion_event_pending_(false),
+ motion_dead_zone_(0.0f)
{
/* To avoid the rare situation where one triple is updated and
* the other is not, initialize them both here: */
- memset(m_translation, 0, sizeof(m_translation));
- memset(m_rotation, 0, sizeof(m_rotation));
+ memset(translation_, 0, sizeof(translation_));
+ memset(rotation_, 0, sizeof(rotation_));
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name NDOF Device Setup
* \{ */
@@ -166,16 +229,16 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
{
/* Call this function until it returns true
* it's a good idea to stop calling it after that, as it will "forget"
- * whichever device it already found */
+ * whichever device it already found. */
/* Default to safe generic behavior for "unknown" devices
* unidentified devices will emit motion events like normal
* rogue buttons do nothing by default, but can be customized by the user. */
- m_deviceType = NDOF_UnknownDevice;
- m_hidMap = Generic_HID_map;
- m_buttonCount = genericButtonCount;
- m_buttonMask = 0;
+ device_type_ = NDOF_UnknownDevice;
+ hid_map_ = ndof_HID_map_Generic;
+ hid_map_button_num_ = genericButtonCount;
+ hid_map_button_mask_ = 0;
/* "mystery device" owners can help build a HID_map for their hardware
* A few users have already contributed information about several older devices
@@ -185,96 +248,101 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
case 0x046D: /* Logitech (3Dconnexion was a subsidiary). */
switch (product_id) {
/* -- current devices -- */
- case 0xC626: /* full-size SpaceNavigator */
- case 0xC628: /* the "for Notebooks" one */
- puts("ndof: using SpaceNavigator");
- m_deviceType = NDOF_SpaceNavigator;
- m_buttonCount = 2;
- m_hidMap = Modern3Dx_HID_map;
+ case 0xC626: /* Full-size SpaceNavigator. */
+ case 0xC628: /* The "for Notebooks" one. */
+ {
+ device_type_ = NDOF_SpaceNavigator;
+ hid_map_button_num_ = 2;
+ hid_map_ = ndof_HID_map_Modern3Dx;
break;
- case 0xC627:
- puts("ndof: using SpaceExplorer");
- m_deviceType = NDOF_SpaceExplorer;
- m_buttonCount = 15;
- m_hidMap = SpaceExplorer_HID_map;
+ }
+ case 0xC627: {
+ device_type_ = NDOF_SpaceExplorer;
+ hid_map_button_num_ = 15;
+ hid_map_ = ndof_HID_map_SpaceExplorer;
break;
- case 0xC629:
- puts("ndof: using SpacePilot Pro");
- m_deviceType = NDOF_SpacePilotPro;
- m_buttonCount = 31;
- m_hidMap = Modern3Dx_HID_map;
+ }
+ case 0xC629: {
+ device_type_ = NDOF_SpacePilotPro;
+ hid_map_button_num_ = 31;
+ hid_map_ = ndof_HID_map_Modern3Dx;
break;
- case 0xC62B:
- puts("ndof: using SpaceMouse Pro");
- m_deviceType = NDOF_SpaceMousePro;
- m_buttonCount = 27;
- /* ^^ actually has 15 buttons, but their HID codes range from 0 to 26 */
- m_buttonMask = 0x07C0F137;
- m_hidMap = Modern3Dx_HID_map;
+ }
+ case 0xC62B: {
+ device_type_ = NDOF_SpaceMousePro;
+ hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */
+ hid_map_button_mask_ = 0x07C0F137;
+ hid_map_ = ndof_HID_map_Modern3Dx;
break;
+ }
/* -- older devices -- */
- case 0xC625:
- puts("ndof: using SpacePilot");
- m_deviceType = NDOF_SpacePilot;
- m_buttonCount = 21;
- m_hidMap = SpacePilot_HID_map;
+ case 0xC625: {
+ device_type_ = NDOF_SpacePilot;
+ hid_map_button_num_ = 21;
+ hid_map_ = ndof_HID_map_SpacePilot;
break;
- case 0xC621:
- puts("ndof: using Spaceball 5000");
- m_deviceType = NDOF_Spaceball5000;
- m_buttonCount = 12;
+ }
+ case 0xC621: {
+ device_type_ = NDOF_Spaceball5000;
+ hid_map_button_num_ = 12;
break;
- case 0xC623:
- puts("ndof: using SpaceTraveler");
- m_deviceType = NDOF_SpaceTraveler;
- m_buttonCount = 8;
+ }
+ case 0xC623: {
+ device_type_ = NDOF_SpaceTraveler;
+ hid_map_button_num_ = 8;
break;
-
- default:
- printf("ndof: unknown Logitech product %04hx\n", product_id);
+ }
+ default: {
+ CLOG_INFO(LOG, 2, "unknown Logitech product %04hx", product_id);
+ }
}
break;
- case 0x256F: /* 3Dconnexion */
+ case 0x256F: /* 3Dconnexion. */
switch (product_id) {
case 0xC62E: /* Plugged in. */
case 0xC62F: /* Wireless. */
- puts("ndof: using SpaceMouse Wireless");
- m_deviceType = NDOF_SpaceMouseWireless;
- m_buttonCount = 2;
- m_hidMap = Modern3Dx_HID_map;
+ {
+ device_type_ = NDOF_SpaceMouseWireless;
+ hid_map_button_num_ = 2;
+ hid_map_ = ndof_HID_map_Modern3Dx;
break;
+ }
case 0xC631: /* Plugged in. */
case 0xC632: /* Wireless. */
- puts("ndof: using SpaceMouse Pro Wireless");
- m_deviceType = NDOF_SpaceMouseProWireless;
- m_buttonCount = 27;
- /* ^^ actually has 15 buttons, but their HID codes range from 0 to 26. */
- m_buttonMask = 0x07C0F137;
- m_hidMap = Modern3Dx_HID_map;
+ {
+ device_type_ = NDOF_SpaceMouseProWireless;
+ hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */
+ hid_map_button_mask_ = 0x07C0F137;
+ hid_map_ = ndof_HID_map_Modern3Dx;
break;
- case 0xC633:
- puts("ndof: using SpaceMouse Enterprise");
- m_deviceType = NDOF_SpaceMouseEnterprise;
- m_buttonCount = 31;
- m_hidMap = Modern3Dx_HID_map;
+ }
+ case 0xC633: {
+ device_type_ = NDOF_SpaceMouseEnterprise;
+ hid_map_button_num_ = 31;
+ hid_map_ = ndof_HID_map_SpaceMouseEnterprise;
break;
-
- default:
- printf("ndof: unknown 3Dconnexion product %04hx\n", product_id);
+ }
+ default: {
+ CLOG_INFO(LOG, 2, "unknown 3Dconnexion product %04hx", product_id);
+ }
}
break;
default:
- printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id);
+ CLOG_INFO(LOG, 2, "unknown device %04hx:%04hx", vendor_id, product_id);
+ }
+
+ if (device_type_ != NDOF_UnknownDevice) {
+ CLOG_INFO(LOG, 2, "using %s", ndof_device_names[device_type_]);
}
- if (m_buttonMask == 0) {
- m_buttonMask = int(~(UINT_MAX << m_buttonCount));
+ if (hid_map_button_mask_ == 0) {
+ hid_map_button_mask_ = int(~(UINT_MAX << hid_map_button_num_));
}
- CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", m_buttonCount, (uint)m_buttonMask);
+ CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", hid_map_button_num_, (uint)hid_map_button_mask_);
- return m_deviceType != NDOF_UnknownDevice;
+ return device_type_ != NDOF_UnknownDevice;
}
#undef LOG
@@ -287,16 +355,16 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
void GHOST_NDOFManager::updateTranslation(const int t[3], uint64_t time)
{
- memcpy(m_translation, t, sizeof(m_translation));
- m_motionTime = time;
- m_motionEventPending = true;
+ memcpy(translation_, t, sizeof(translation_));
+ motion_time_ = time;
+ motion_event_pending_ = true;
}
void GHOST_NDOFManager::updateRotation(const int r[3], uint64_t time)
{
- memcpy(m_rotation, r, sizeof(m_rotation));
- m_motionTime = time;
- m_motionEventPending = true;
+ memcpy(rotation_, r, sizeof(rotation_));
+ motion_time_ = time;
+ motion_event_pending_ = true;
}
/** \} */
@@ -314,6 +382,18 @@ static GHOST_TKey ghost_map_keyboard_from_ndof_buttom(const NDOF_ButtonT button)
case NDOF_BUTTON_ESC: {
return GHOST_kKeyEsc;
}
+ case NDOF_BUTTON_ENTER: {
+ return GHOST_kKeyEnter;
+ }
+ case NDOF_BUTTON_DELETE: {
+ return GHOST_kKeyDelete;
+ }
+ case NDOF_BUTTON_TAB: {
+ return GHOST_kKeyTab;
+ }
+ case NDOF_BUTTON_SPACE: {
+ return GHOST_kKeySpace;
+ }
case NDOF_BUTTON_ALT: {
return GHOST_kKeyLeftAlt;
}
@@ -334,7 +414,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button,
uint64_t time,
GHOST_IWindow *window)
{
- GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_LAST,
+ GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_NUM,
"rogue button trying to escape NDOF manager");
GHOST_EventNDOFButton *event = new GHOST_EventNDOFButton(time, window);
@@ -343,7 +423,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button,
data->action = press ? GHOST_kPress : GHOST_kRelease;
data->button = button;
- m_system.pushEvent(event);
+ system_.pushEvent(event);
}
void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key,
@@ -354,21 +434,21 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key,
GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key, false);
- m_system.pushEvent(event);
+ system_.pushEvent(event);
}
void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t time)
{
- if (button_number >= m_buttonCount) {
+ if (button_number >= hid_map_button_num_) {
CLOG_INFO(LOG,
2,
"button=%d, press=%d (out of range %d, ignoring!)",
button_number,
(int)press,
- m_buttonCount);
+ hid_map_button_num_);
return;
}
- const NDOF_ButtonT button = m_hidMap[button_number];
+ const NDOF_ButtonT button = hid_map_[button_number];
if (button == NDOF_BUTTON_NONE) {
CLOG_INFO(
LOG, 2, "button=%d, press=%d (mapped to none, ignoring!)", button_number, (int)press);
@@ -382,7 +462,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim
(int)press,
ndof_button_names[button]);
- GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow();
+ GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow();
const GHOST_TKey key = ghost_map_keyboard_from_ndof_buttom(button);
if (key != GHOST_kKeyUnknown) {
sendKeyEvent(key, press, time, window);
@@ -393,20 +473,20 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim
int mask = 1 << button_number;
if (press) {
- m_buttons |= mask; /* Set this button's bit. */
+ button_depressed_ |= mask; /* Set this button's bit. */
}
else {
- m_buttons &= ~mask; /* Clear this button's bit. */
+ button_depressed_ &= ~mask; /* Clear this button's bit. */
}
}
void GHOST_NDOFManager::updateButtons(int button_bits, uint64_t time)
{
- button_bits &= m_buttonMask; /* Discard any "garbage" bits. */
+ button_bits &= hid_map_button_mask_; /* Discard any "garbage" bits. */
- int diff = m_buttons ^ button_bits;
+ int diff = button_depressed_ ^ button_bits;
- for (int button_number = 0; button_number < m_buttonCount; ++button_number) {
+ for (int button_number = 0; button_number < hid_map_button_num_; ++button_number) {
int mask = 1 << button_number;
if (diff & mask) {
@@ -433,7 +513,7 @@ void GHOST_NDOFManager::setDeadZone(float dz)
/* Negative values don't make sense, so clamp at zero. */
dz = 0.0f;
}
- m_deadZone = dz;
+ motion_dead_zone_ = dz;
/* Warn the rogue user/developer about high dead-zone, but allow it. */
CLOG_INFO(LOG, 2, "dead zone set to %.2f%s", dz, (dz > 0.5f) ? " (unexpectedly high)" : "");
@@ -458,20 +538,20 @@ static bool nearHomePosition(GHOST_TEventNDOFMotionData *ndof, float threshold)
bool GHOST_NDOFManager::sendMotionEvent()
{
- if (!m_motionEventPending) {
+ if (!motion_event_pending_) {
return false;
}
- m_motionEventPending = false; /* Any pending motion is handled right now. */
+ motion_event_pending_ = false; /* Any pending motion is handled right now. */
- GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow();
+ GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow();
if (window == nullptr) {
- m_motionState = GHOST_kNotStarted; /* Avoid large `dt` times when changing windows. */
+ motion_state_ = GHOST_kNotStarted; /* Avoid large `dt` times when changing windows. */
return false; /* Delivery will fail, so don't bother sending. */
}
- GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(m_motionTime, window);
+ GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(motion_time_, window);
GHOST_TEventNDOFMotionData *data = (GHOST_TEventNDOFMotionData *)event->getData();
/* Scale axis values here to normalize them to around +/- 1
@@ -479,26 +559,26 @@ bool GHOST_NDOFManager::sendMotionEvent()
const float scale = 1.0f / 350.0f; /* 3Dconnexion devices send +/- 350 usually */
- data->tx = scale * m_translation[0];
- data->ty = scale * m_translation[1];
- data->tz = scale * m_translation[2];
+ data->tx = scale * translation_[0];
+ data->ty = scale * translation_[1];
+ data->tz = scale * translation_[2];
- data->rx = scale * m_rotation[0];
- data->ry = scale * m_rotation[1];
- data->rz = scale * m_rotation[2];
- data->dt = 0.001f * (m_motionTime - m_prevMotionTime); /* In seconds. */
- m_prevMotionTime = m_motionTime;
+ data->rx = scale * rotation_[0];
+ data->ry = scale * rotation_[1];
+ data->rz = scale * rotation_[2];
+ data->dt = 0.001f * (motion_time_ - motion_time_prev_); /* In seconds. */
+ motion_time_prev_ = motion_time_;
- bool weHaveMotion = !nearHomePosition(data, m_deadZone);
+ bool weHaveMotion = !nearHomePosition(data, motion_dead_zone_);
/* Determine what kind of motion event to send `(Starting, InProgress, Finishing)`
* and where that leaves this NDOF manager `(NotStarted, InProgress, Finished)`. */
- switch (m_motionState) {
+ switch (motion_state_) {
case GHOST_kNotStarted:
case GHOST_kFinished: {
if (weHaveMotion) {
data->progress = GHOST_kStarting;
- m_motionState = GHOST_kInProgress;
+ motion_state_ = GHOST_kInProgress;
/* Previous motion time will be ancient, so just make up a reasonable time delta. */
data->dt = 0.0125f;
}
@@ -517,7 +597,7 @@ bool GHOST_NDOFManager::sendMotionEvent()
}
else {
data->progress = GHOST_kFinishing;
- m_motionState = GHOST_kFinished;
+ motion_state_ = GHOST_kFinished;
}
break;
}
@@ -538,21 +618,21 @@ bool GHOST_NDOFManager::sendMotionEvent()
data->ry,
data->rz,
data->dt,
- progress_string[data->progress]);
+ ndof_progress_string[data->progress]);
#else
/* Raw values, may be useful for debugging. */
CLOG_INFO(LOG,
2,
"motion sent, T=(%d,%d,%d) R=(%d,%d,%d) status=%s",
- m_translation[0],
- m_translation[1],
- m_translation[2],
- m_rotation[0],
- m_rotation[1],
- m_rotation[2],
- progress_string[data->progress]);
+ translation_[0],
+ translation_[1],
+ translation_[2],
+ rotation_[0],
+ rotation_[1],
+ rotation_[2],
+ ndof_progress_string[data->progress]);
#endif
- m_system.pushEvent(event);
+ system_.pushEvent(event);
return true;
}
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index 73c1b17f891..2d5bba14aa4 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -9,7 +9,7 @@
#include "GHOST_System.h"
typedef enum {
- NDOF_UnknownDevice,
+ NDOF_UnknownDevice = 0,
/* Current devices. */
NDOF_SpaceNavigator,
@@ -29,8 +29,8 @@ typedef enum {
/* NDOF device button event types */
typedef enum {
- /* Used internally, never sent. */
- NDOF_BUTTON_NONE = 0,
+ /* Used internally, never sent or used as an index. */
+ NDOF_BUTTON_NONE = -1,
/* These two are available from any 3Dconnexion device. */
NDOF_BUTTON_MENU,
NDOF_BUTTON_FIT,
@@ -58,11 +58,6 @@ typedef enum {
NDOF_BUTTON_DOMINANT,
NDOF_BUTTON_PLUS,
NDOF_BUTTON_MINUS,
- /* Keyboard emulation. */
- NDOF_BUTTON_ESC,
- NDOF_BUTTON_ALT,
- NDOF_BUTTON_SHIFT,
- NDOF_BUTTON_CTRL,
/* General-purpose buttons.
* Users can assign functions via keymap editor. */
NDOF_BUTTON_1,
@@ -79,8 +74,20 @@ typedef enum {
NDOF_BUTTON_A,
NDOF_BUTTON_B,
NDOF_BUTTON_C,
- /* The end. */
- NDOF_BUTTON_LAST
+ /* Store Views. */
+ NDOF_BUTTON_V1,
+ NDOF_BUTTON_V2,
+ NDOF_BUTTON_V3,
+ /* Keyboard emulation. */
+ NDOF_BUTTON_ESC,
+ NDOF_BUTTON_ENTER,
+ NDOF_BUTTON_DELETE,
+ NDOF_BUTTON_TAB,
+ NDOF_BUTTON_SPACE,
+ NDOF_BUTTON_ALT,
+ NDOF_BUTTON_SHIFT,
+ NDOF_BUTTON_CTRL,
+#define NDOF_BUTTON_NUM (NDOF_BUTTON_CTRL + 1)
} NDOF_ButtonT;
class GHOST_NDOFManager {
@@ -140,25 +147,25 @@ class GHOST_NDOFManager {
bool sendMotionEvent();
protected:
- GHOST_System &m_system;
+ GHOST_System &system_;
private:
void sendButtonEvent(NDOF_ButtonT, bool press, uint64_t time, GHOST_IWindow *);
void sendKeyEvent(GHOST_TKey, bool press, uint64_t time, GHOST_IWindow *);
- NDOF_DeviceT m_deviceType;
- int m_buttonCount;
- int m_buttonMask;
- const NDOF_ButtonT *m_hidMap;
+ NDOF_DeviceT device_type_;
+ int hid_map_button_num_;
+ int hid_map_button_mask_;
+ const NDOF_ButtonT *hid_map_;
- int m_translation[3];
- int m_rotation[3];
- int m_buttons; /* Bit field. */
+ int translation_[3];
+ int rotation_[3];
+ int button_depressed_; /* Bit field. */
- uint64_t m_motionTime; /* In milliseconds. */
- uint64_t m_prevMotionTime; /* Time of most recent motion event sent. */
+ uint64_t motion_time_; /* In milliseconds. */
+ uint64_t motion_time_prev_; /* Time of most recent motion event sent. */
- GHOST_TProgress m_motionState;
- bool m_motionEventPending;
- float m_deadZone; /* Discard motion with each component < this. */
+ GHOST_TProgress motion_state_;
+ bool motion_event_pending_;
+ float motion_dead_zone_; /* Discard motion with each component < this. */
};
diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp
index 94bf0337371..0ccf4dc9bfb 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp
@@ -10,7 +10,7 @@
#define SPNAV_SOCK_PATH "/var/run/spnav.sock"
GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys)
- : GHOST_NDOFManager(sys), m_available(false)
+ : GHOST_NDOFManager(sys), available_(false)
{
if (access(SPNAV_SOCK_PATH, F_OK) != 0) {
#ifdef DEBUG
@@ -20,7 +20,7 @@ GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys)
#endif
}
else if (spnav_open() != -1) {
- m_available = true;
+ available_ = true;
/* determine exactly which device (if any) is plugged in */
@@ -45,14 +45,14 @@ GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys)
GHOST_NDOFManagerUnix::~GHOST_NDOFManagerUnix()
{
- if (m_available) {
+ if (available_) {
spnav_close();
}
}
bool GHOST_NDOFManagerUnix::available()
{
- return m_available;
+ return available_;
}
/*
@@ -74,7 +74,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
{
bool anyProcessed = false;
- if (m_available) {
+ if (available_) {
spnav_event e;
#ifdef USE_FINISH_GLITCH_WORKAROUND
@@ -85,7 +85,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
switch (e.type) {
case SPNAV_EVENT_MOTION: {
/* convert to blender view coords */
- uint64_t now = m_system.getMilliSeconds();
+ uint64_t now = system_.getMilliSeconds();
const int t[3] = {int(e.motion.x), int(e.motion.y), int(-e.motion.z)};
const int r[3] = {int(-e.motion.rx), int(-e.motion.ry), int(e.motion.rz)};
@@ -97,7 +97,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
break;
}
case SPNAV_EVENT_BUTTON:
- uint64_t now = m_system.getMilliSeconds();
+ uint64_t now = system_.getMilliSeconds();
updateButton(e.button.bnum, e.button.press, now);
break;
}
@@ -106,7 +106,7 @@ bool GHOST_NDOFManagerUnix::processEvents()
#ifdef USE_FINISH_GLITCH_WORKAROUND
if (motion_test_prev == true && motion_test == false) {
- uint64_t now = m_system.getMilliSeconds();
+ uint64_t now = system_.getMilliSeconds();
const int v[3] = {0, 0, 0};
updateTranslation(v, now);
diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.h b/intern/ghost/intern/GHOST_NDOFManagerUnix.h
index fd603e3cb54..2b98fad974f 100644
--- a/intern/ghost/intern/GHOST_NDOFManagerUnix.h
+++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.h
@@ -15,5 +15,5 @@ class GHOST_NDOFManagerUnix : public GHOST_NDOFManager {
bool processEvents();
private:
- bool m_available;
+ bool available_;
};
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 94d021fd822..670ede35989 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -384,6 +384,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
if (stereoVisual) {
glSettings.flags |= GHOST_glStereoVisual;
}
+ glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
/* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may
* be zoomed in and the desktop may be bigger than the viewport. */
GHOST_ASSERT(m_displayManager,
@@ -395,7 +396,6 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
settings.xPixels,
settings.yPixels,
GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL,
glSettings,
true /* exclusive */);
return (*window == nullptr) ? GHOST_kFailure : GHOST_kSuccess;
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index dbb41c7fddf..0211694aad4 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -77,7 +77,6 @@ class GHOST_SystemCocoa : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
- * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent (embedder) window.
@@ -89,7 +88,6 @@ class GHOST_SystemCocoa : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index bfa90114e4c..a1016dd4843 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -689,7 +689,6 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
const bool is_dialog,
@@ -719,7 +718,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
width,
height,
state,
- type,
+ glSettings.context_type,
glSettings.flags & GHOST_glStereoVisual,
glSettings.flags & GHOST_glDebugContext,
is_dialog,
@@ -751,7 +750,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
*/
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings)
{
- GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL);
+ GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, glSettings.context_type);
if (context->initializeDrawingContext())
return context;
else
diff --git a/intern/ghost/intern/GHOST_SystemHeadless.h b/intern/ghost/intern/GHOST_SystemHeadless.h
index b02a82fc9eb..66af65f763d 100644
--- a/intern/ghost/intern/GHOST_SystemHeadless.h
+++ b/intern/ghost/intern/GHOST_SystemHeadless.h
@@ -142,7 +142,6 @@ class GHOST_SystemHeadless : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool /*exclusive*/,
const bool /*is_dialog*/,
@@ -155,7 +154,7 @@ class GHOST_SystemHeadless : public GHOST_System {
height,
state,
parentWindow,
- type,
+ glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0));
}
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp
index ad5c4dc85fb..9174664adc4 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.cpp
+++ b/intern/ghost/intern/GHOST_SystemSDL.cpp
@@ -42,7 +42,6 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
const bool /* is_dialog */,
@@ -57,7 +56,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
width,
height,
state,
- type,
+ glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
exclusive,
parentWindow);
diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h
index bee277ba674..385bfb841e3 100644
--- a/intern/ghost/intern/GHOST_SystemSDL.h
+++ b/intern/ghost/intern/GHOST_SystemSDL.h
@@ -71,7 +71,6 @@ class GHOST_SystemSDL : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 04c7e103bde..442e51d4f7c 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -10,6 +10,7 @@
#include "GHOST_EventCursor.h"
#include "GHOST_EventDragnDrop.h"
#include "GHOST_EventKey.h"
+#include "GHOST_EventTrackpad.h"
#include "GHOST_EventWheel.h"
#include "GHOST_PathUtils.h"
#include "GHOST_TimerManager.h"
@@ -50,6 +51,8 @@
/* Generated by `wayland-scanner`. */
#include <pointer-constraints-unstable-v1-client-protocol.h>
+#include <pointer-gestures-unstable-v1-client-protocol.h>
+#include <primary-selection-unstable-v1-client-protocol.h>
#include <relative-pointer-unstable-v1-client-protocol.h>
#include <tablet-unstable-v2-client-protocol.h>
#include <xdg-output-unstable-v1-client-protocol.h>
@@ -82,6 +85,10 @@ static void keyboard_handle_key_repeat_cancel(struct GWL_Seat *seat);
static void output_handle_done(void *data, struct wl_output *wl_output);
+static void gwl_seat_capability_pointer_disable(GWL_Seat *seat);
+static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat);
+static void gwl_seat_capability_touch_disable(GWL_Seat *seat);
+
/* -------------------------------------------------------------------- */
/** \name Local Defines
*
@@ -116,6 +123,8 @@ static bool use_gnome_confine_hack = false;
* This define could be removed without changing any functionality,
* it just means GNOME users will see verbose warning messages that alert them about
* a known problem that needs to be fixed up-stream.
+ *
+ * This has been fixed for GNOME 43. Keep the workaround until support for gnome 42 is dropped.
* See: https://gitlab.gnome.org/GNOME/mutter/-/issues/2457
*/
#define USE_GNOME_KEYBOARD_SUPPRESS_WARNING
@@ -140,8 +149,7 @@ static bool use_gnome_confine_hack = false;
* \{ */
/**
- * The event codes are used to
- * to differentiate from which mouse button an event comes from.
+ * The event codes are used to differentiate from which mouse button an event comes from.
*/
#define BTN_LEFT 0x110
#define BTN_RIGHT 0x111
@@ -190,48 +198,93 @@ struct GWL_ModifierInfo {
};
static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM] = {
- [MOD_INDEX_SHIFT] =
- {
- .display_name = "Shift",
- .xkb_id = XKB_MOD_NAME_SHIFT,
- .key_l = GHOST_kKeyLeftShift,
- .key_r = GHOST_kKeyRightShift,
- .mod_l = GHOST_kModifierKeyLeftShift,
- .mod_r = GHOST_kModifierKeyRightShift,
- },
- [MOD_INDEX_ALT] =
- {
- .display_name = "Alt",
- .xkb_id = XKB_MOD_NAME_ALT,
- .key_l = GHOST_kKeyLeftAlt,
- .key_r = GHOST_kKeyRightAlt,
- .mod_l = GHOST_kModifierKeyLeftAlt,
- .mod_r = GHOST_kModifierKeyRightAlt,
- },
- [MOD_INDEX_CTRL] =
- {
- .display_name = "Control",
- .xkb_id = XKB_MOD_NAME_CTRL,
- .key_l = GHOST_kKeyLeftControl,
- .key_r = GHOST_kKeyRightControl,
- .mod_l = GHOST_kModifierKeyLeftControl,
- .mod_r = GHOST_kModifierKeyRightControl,
- },
- [MOD_INDEX_OS] =
- {
- .display_name = "OS",
- .xkb_id = XKB_MOD_NAME_LOGO,
- .key_l = GHOST_kKeyLeftOS,
- .key_r = GHOST_kKeyRightOS,
- .mod_l = GHOST_kModifierKeyLeftOS,
- .mod_r = GHOST_kModifierKeyRightOS,
- },
+ /* MOD_INDEX_SHIFT */
+ {
+ /* display_name */ "Shift",
+ /* xkb_id */ XKB_MOD_NAME_SHIFT,
+ /* key_l */ GHOST_kKeyLeftShift,
+ /* key_r */ GHOST_kKeyRightShift,
+ /* mod_l */ GHOST_kModifierKeyLeftShift,
+ /* mod_r */ GHOST_kModifierKeyRightShift,
+ },
+ /* MOD_INDEX_ALT */
+ {
+ /* display_name */ "Alt",
+ /* xkb_id */ XKB_MOD_NAME_ALT,
+ /* key_l */ GHOST_kKeyLeftAlt,
+ /* key_r */ GHOST_kKeyRightAlt,
+ /* mod_l */ GHOST_kModifierKeyLeftAlt,
+ /* mod_r */ GHOST_kModifierKeyRightAlt,
+ },
+ /* MOD_INDEX_CTRL */
+ {
+ /* display_name */ "Control",
+ /* xkb_id */ XKB_MOD_NAME_CTRL,
+ /* key_l */ GHOST_kKeyLeftControl,
+ /* key_r */ GHOST_kKeyRightControl,
+ /* mod_l */ GHOST_kModifierKeyLeftControl,
+ /* mod_r */ GHOST_kModifierKeyRightControl,
+ },
+ /* MOD_INDEX_OS */
+ {
+ /* display_name */ "OS",
+ /* xkb_id */ XKB_MOD_NAME_LOGO,
+ /* key_l */ GHOST_kKeyLeftOS,
+ /* key_r */ GHOST_kKeyRightOS,
+ /* mod_l */ GHOST_kModifierKeyLeftOS,
+ /* mod_r */ GHOST_kModifierKeyRightOS,
+ },
};
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Private Types & Defines
+/** \name Internal #GWL_SimpleBuffer Type
+ * \{ */
+
+struct GWL_SimpleBuffer {
+ /** Constant data, but may be freed. */
+ const char *data = nullptr;
+ size_t data_size = 0;
+};
+
+static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer)
+{
+ free(const_cast<char *>(buffer->data));
+ buffer->data = nullptr;
+ buffer->data_size = 0;
+}
+
+static void gwl_simple_buffer_set_and_take_ownership(GWL_SimpleBuffer *buffer,
+ const char *data,
+ size_t data_size)
+{
+ free(const_cast<char *>(buffer->data));
+ buffer->data = data;
+ buffer->data_size = data_size;
+}
+
+static void gwl_simple_buffer_set_from_string(GWL_SimpleBuffer *buffer, const char *str)
+{
+ free(const_cast<char *>(buffer->data));
+ buffer->data_size = strlen(str);
+ char *data = static_cast<char *>(malloc(buffer->data_size));
+ std::memcpy(data, str, buffer->data_size);
+ buffer->data = data;
+}
+
+static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer)
+{
+ char *buffer_str = static_cast<char *>(malloc(buffer->data_size + 1));
+ memcpy(buffer_str, buffer->data, buffer->data_size);
+ buffer_str[buffer->data_size] = '\0';
+ return buffer_str;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_Cursor Type
* \{ */
/**
@@ -249,16 +302,26 @@ struct GWL_Cursor {
* the hardware cursor is used.
*/
bool is_hardware = true;
+ /** When true, a custom image is used to display the cursor (stored in `wl_image`). */
bool is_custom = false;
struct wl_surface *wl_surface = nullptr;
struct wl_buffer *wl_buffer = nullptr;
struct wl_cursor_image wl_image = {0};
struct wl_cursor_theme *wl_theme = nullptr;
void *custom_data = nullptr;
+ /** The size of `custom_data` in bytes. */
size_t custom_data_size = 0;
- int size = 0;
+ /**
+ * The name of the theme (loaded by DBUS, depends on #WITH_GHOST_WAYLAND_DBUS).
+ * When disabled, leave as an empty string and the default theme will be used.
+ */
std::string theme_name;
-
+ /**
+ * The size of the cursor (when looking up a cursor theme).
+ * This must be scaled by the maximum output scale when passing to wl_cursor_theme_load.
+ * See #update_cursor_scale.
+ * */
+ int theme_size = 0;
int custom_scale = 1;
};
@@ -269,6 +332,7 @@ struct GWL_Cursor {
*/
struct GWL_TabletTool {
struct GWL_Seat *seat = nullptr;
+ /** Tablets have a separate cursor to the 'pointer', this surface is used for cursor drawing. */
struct wl_surface *wl_surface_cursor = nullptr;
/** Used to delay clearing tablet focused wl_surface until the frame is handled. */
bool proximity = false;
@@ -276,23 +340,51 @@ struct GWL_TabletTool {
GHOST_TabletData data = GHOST_TABLET_DATA_NONE;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_DataOffer Type
+ * \{ */
+
+/**
+ * Data storage used for clipboard paste & drag-and-drop.
+ */
struct GWL_DataOffer {
- std::unordered_set<std::string> types;
- uint32_t source_actions = 0;
- uint32_t dnd_action = 0;
struct wl_data_offer *id = nullptr;
+ std::unordered_set<std::string> types;
std::atomic<bool> in_use = false;
+
struct {
+ /**
+ * Bit-mask with available drop options.
+ * #WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, #WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE.. etc.
+ * The application that initializes the drag may set these depending on modifiers held
+ * \note when dragging begins. Currently ghost doesn't make use of these.
+ */
+ enum wl_data_device_manager_dnd_action source_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+ enum wl_data_device_manager_dnd_action action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
/** Compatible with #GWL_Seat.xy coordinates. */
wl_fixed_t xy[2] = {0, 0};
} dnd;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_DataSource Type
+ * \{ */
+
struct GWL_DataSource {
- struct wl_data_source *data_source = nullptr;
- char *buffer_out = nullptr;
+ struct wl_data_source *wl_source = nullptr;
+ GWL_SimpleBuffer buffer_out;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_Seat Type (#wl_seat wrapper & associated types)
+ * \{ */
+
/**
* Data used to implement client-side key-repeat.
*
@@ -358,6 +450,52 @@ struct GWL_SeatStatePointer {
};
/**
+ * Scroll state, applying to pointer (not tablet) events.
+ * Otherwise this would be part of #GWL_SeatStatePointer.
+ */
+struct GWL_SeatStatePointerScroll {
+ /** Smooth scrolling (handled & reset with pointer "frame" callback). */
+ wl_fixed_t smooth_xy[2] = {0, 0};
+ /** Discrete scrolling (handled & reset with pointer "frame" callback). */
+ int32_t discrete_xy[2] = {0, 0};
+ /** The source of scroll event. */
+ enum wl_pointer_axis_source axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
+};
+
+/**
+ * Utility struct to access rounded values from a scaled `wl_fixed_t`,
+ * without loosing information.
+ *
+ * As the rounded result is rounded to a lower precision integer,
+ * the high precision value is accumulated and converted to an integer to
+ * prevent the accumulation of rounded values giving an inaccurate result.
+ *
+ * \note This is simple but doesn't read well when expanded multiple times inline.
+ */
+struct GWL_ScaledFixedT {
+ wl_fixed_t value = 0;
+ wl_fixed_t factor = 1;
+};
+
+static int gwl_scaled_fixed_t_add_and_calc_rounded_delta(GWL_ScaledFixedT *sf,
+ const wl_fixed_t add)
+{
+ const int result_prev = wl_fixed_to_int(sf->value * sf->factor);
+ sf->value += add;
+ const int result_curr = wl_fixed_to_int(sf->value * sf->factor);
+ return result_curr - result_prev;
+}
+
+/**
+ * Gesture state.
+ * This is needed so the gesture values can be converted to deltas.
+ */
+struct GWL_SeatStatePointerGesture_Pinch {
+ GWL_ScaledFixedT scale;
+ GWL_ScaledFixedT rotation;
+};
+
+/**
* State of the keyboard (in #GWL_Seat).
*/
struct GWL_SeatStateKeyboard {
@@ -376,16 +514,16 @@ struct GWL_SeatStateKeyboard {
*
* Needed as #GWL_Seat.xkb_state doesn't store which modifier keys are held.
*/
-struct WGL_KeyboardDepressedState {
+struct GWL_KeyboardDepressedState {
int16_t mods[GHOST_KEY_MODIFIER_NUM] = {0};
};
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
-struct WGL_LibDecor_System {
+struct GWL_LibDecor_System {
struct libdecor *context = nullptr;
};
-static void wgl_libdecor_system_destroy(WGL_LibDecor_System *decor)
+static void gwl_libdecor_system_destroy(GWL_LibDecor_System *decor)
{
if (decor->context) {
libdecor_unref(decor->context);
@@ -394,12 +532,12 @@ static void wgl_libdecor_system_destroy(WGL_LibDecor_System *decor)
}
#endif
-struct WGL_XDG_Decor_System {
+struct GWL_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)
+static void gwl_xdg_decor_system_destroy(GWL_XDG_Decor_System *decor)
{
if (decor->manager) {
zxdg_decoration_manager_v1_destroy(decor->manager);
@@ -410,14 +548,65 @@ static void wgl_xdg_decor_system_destroy(WGL_XDG_Decor_System *decor)
delete decor;
}
+struct GWL_PrimarySelection_DataOffer {
+ struct zwp_primary_selection_offer_v1 *id = nullptr;
+ std::atomic<bool> in_use = false;
+
+ std::unordered_set<std::string> types;
+};
+
+struct GWL_PrimarySelection_DataSource {
+ struct zwp_primary_selection_source_v1 *wp_source = nullptr;
+ GWL_SimpleBuffer buffer_out;
+};
+
+/** Primary selection support. */
+struct GWL_PrimarySelection {
+
+ GWL_PrimarySelection_DataSource *data_source = nullptr;
+ std::mutex data_source_mutex;
+
+ GWL_PrimarySelection_DataOffer *data_offer = nullptr;
+ std::mutex data_offer_mutex;
+};
+
+static void gwl_primary_selection_discard_offer(GWL_PrimarySelection *primary)
+{
+ if (primary->data_offer == nullptr) {
+ return;
+ }
+ zwp_primary_selection_offer_v1_destroy(primary->data_offer->id);
+ delete primary->data_offer;
+ primary->data_offer = nullptr;
+}
+
+static void gwl_primary_selection_discard_source(GWL_PrimarySelection *primary)
+{
+ GWL_PrimarySelection_DataSource *data_source = primary->data_source;
+ if (data_source == nullptr) {
+ return;
+ }
+ gwl_simple_buffer_free_data(&data_source->buffer_out);
+ if (data_source->wp_source) {
+ zwp_primary_selection_source_v1_destroy(data_source->wp_source);
+ }
+ delete primary->data_source;
+ primary->data_source = nullptr;
+}
+
struct GWL_Seat {
GHOST_SystemWayland *system = nullptr;
std::string name;
struct wl_seat *wl_seat = nullptr;
struct wl_pointer *wl_pointer = nullptr;
+ struct wl_touch *wl_touch = nullptr;
struct wl_keyboard *wl_keyboard = nullptr;
- struct zwp_tablet_seat_v2 *tablet_seat = nullptr;
+ struct zwp_tablet_seat_v2 *wp_tablet_seat = nullptr;
+
+ struct zwp_pointer_gesture_hold_v1 *wp_pointer_gesture_hold = nullptr;
+ struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch = nullptr;
+ struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe = nullptr;
/** All currently active tablet tools (needed for changing the cursor). */
std::unordered_set<zwp_tablet_tool_v2 *> tablet_tools;
@@ -426,6 +615,8 @@ struct GWL_Seat {
uint32_t cursor_source_serial = 0;
GWL_SeatStatePointer pointer;
+ GWL_SeatStatePointerScroll pointer_scroll;
+ GWL_SeatStatePointerGesture_Pinch pointer_gesture_pinch;
/** Mostly this can be interchanged with `pointer` however it can't be locked/confined. */
GWL_SeatStatePointer tablet;
@@ -440,9 +631,9 @@ struct GWL_Seat {
struct GWL_Cursor cursor;
- struct zwp_relative_pointer_v1 *relative_pointer = nullptr;
- struct zwp_locked_pointer_v1 *locked_pointer = nullptr;
- struct zwp_confined_pointer_v1 *confined_pointer = nullptr;
+ struct zwp_relative_pointer_v1 *wp_relative_pointer = nullptr;
+ struct zwp_locked_pointer_v1 *wp_locked_pointer = nullptr;
+ struct zwp_confined_pointer_v1 *wp_confined_pointer = nullptr;
struct xkb_context *xkb_context = nullptr;
@@ -458,7 +649,7 @@ struct GWL_Seat {
struct xkb_state *xkb_state_empty_with_numlock = nullptr;
/** Keys held matching `xkb_state`. */
- struct WGL_KeyboardDepressedState key_depressed;
+ struct GWL_KeyboardDepressedState key_depressed;
#ifdef USE_GNOME_KEYBOARD_SUPPRESS_WARNING
struct {
@@ -485,7 +676,7 @@ struct GWL_Seat {
struct wl_surface *wl_surface_focus_dnd = nullptr;
- struct wl_data_device *data_device = nullptr;
+ struct wl_data_device *wl_data_device = nullptr;
/** Drag & Drop. */
struct GWL_DataOffer *data_offer_dnd = nullptr;
std::mutex data_offer_dnd_mutex;
@@ -497,10 +688,19 @@ struct GWL_Seat {
struct GWL_DataSource *data_source = nullptr;
std::mutex data_source_mutex;
+ struct zwp_primary_selection_device_v1 *wp_primary_selection_device = nullptr;
+ struct GWL_PrimarySelection primary_selection;
+
/** Last device that was active. */
uint32_t data_source_serial = 0;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_Display Type (#wl_display & #wl_compositor wrapper)
+ * \{ */
+
struct GWL_Display {
GHOST_SystemWayland *system = nullptr;
@@ -508,23 +708,27 @@ struct GWL_Display {
struct wl_compositor *wl_compositor = nullptr;
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- WGL_LibDecor_System *libdecor = nullptr;
+ GWL_LibDecor_System *libdecor = nullptr;
bool libdecor_required = false;
#endif
- WGL_XDG_Decor_System *xdg_decor = nullptr;
+ GWL_XDG_Decor_System *xdg_decor = nullptr;
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
struct wl_shm *wl_shm = nullptr;
std::vector<GWL_Output *> outputs;
std::vector<GWL_Seat *> seats;
- struct wl_data_device_manager *data_device_manager = nullptr;
- struct zwp_tablet_manager_v2 *tablet_manager = nullptr;
- struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr;
- struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr;
-};
+ struct wl_data_device_manager *wl_data_device_manager = nullptr;
+ struct zwp_tablet_manager_v2 *wp_tablet_manager = nullptr;
+ struct zwp_relative_pointer_manager_v1 *wp_relative_pointer_manager = nullptr;
+ struct zwp_pointer_constraints_v1 *wp_pointer_constraints = nullptr;
+ struct zwp_pointer_gestures_v1 *wp_pointer_gestures = nullptr;
-#undef LOG
+ struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr;
+
+ GWL_SimpleBuffer clipboard;
+ GWL_SimpleBuffer clipboard_primary;
+};
/** \} */
@@ -580,12 +784,12 @@ static GWL_SeatStatePointer *seat_state_pointer_from_cursor_surface(GWL_Seat *se
static void display_destroy(GWL_Display *display)
{
- if (display->data_device_manager) {
- wl_data_device_manager_destroy(display->data_device_manager);
+ if (display->wl_data_device_manager) {
+ wl_data_device_manager_destroy(display->wl_data_device_manager);
}
- if (display->tablet_manager) {
- zwp_tablet_manager_v2_destroy(display->tablet_manager);
+ if (display->wp_tablet_manager) {
+ zwp_tablet_manager_v2_destroy(display->wp_tablet_manager);
}
for (GWL_Output *output : display->outputs) {
@@ -600,9 +804,9 @@ static void display_destroy(GWL_Display *display)
{
std::lock_guard lock{seat->data_source_mutex};
if (seat->data_source) {
- free(seat->data_source->buffer_out);
- if (seat->data_source->data_source) {
- wl_data_source_destroy(seat->data_source->data_source);
+ gwl_simple_buffer_free_data(&seat->data_source->buffer_out);
+ if (seat->data_source->wl_source) {
+ wl_data_source_destroy(seat->data_source->wl_source);
}
delete seat->data_source;
}
@@ -624,32 +828,39 @@ static void display_destroy(GWL_Display *display)
}
}
- if (seat->data_device) {
- wl_data_device_release(seat->data_device);
+ {
+ GWL_PrimarySelection *primary = &seat->primary_selection;
+ std::lock_guard lock{primary->data_offer_mutex};
+ gwl_primary_selection_discard_offer(primary);
}
- if (seat->cursor.custom_data) {
- munmap(seat->cursor.custom_data, seat->cursor.custom_data_size);
+ {
+ GWL_PrimarySelection *primary = &seat->primary_selection;
+ std::lock_guard lock{primary->data_source_mutex};
+ gwl_primary_selection_discard_source(primary);
}
- if (seat->wl_pointer) {
- if (seat->cursor.wl_surface) {
- wl_surface_destroy(seat->cursor.wl_surface);
- }
- if (seat->cursor.wl_theme) {
- wl_cursor_theme_destroy(seat->cursor.wl_theme);
- }
- if (seat->wl_pointer) {
- wl_pointer_destroy(seat->wl_pointer);
- }
+ if (seat->wp_primary_selection_device) {
+ zwp_primary_selection_device_v1_destroy(seat->wp_primary_selection_device);
}
- if (seat->wl_keyboard) {
- if (seat->key_repeat.timer) {
- keyboard_handle_key_repeat_cancel(seat);
- }
- wl_keyboard_destroy(seat->wl_keyboard);
+
+ if (seat->wl_data_device) {
+ wl_data_device_release(seat->wl_data_device);
+ }
+
+ if (seat->cursor.custom_data) {
+ munmap(seat->cursor.custom_data, seat->cursor.custom_data_size);
}
+ /* Disable all capabilities as a way to free:
+ * - `seat.wl_pointer` (and related cursor variables).
+ * - `seat.wl_touch`.
+ * - `seat.wl_keyboard`.
+ */
+ gwl_seat_capability_pointer_disable(seat);
+ gwl_seat_capability_keyboard_disable(seat);
+ gwl_seat_capability_touch_disable(seat);
+
/* Un-referencing checks for NULL case. */
xkb_state_unref(seat->xkb_state);
xkb_state_unref(seat->xkb_state_empty);
@@ -665,12 +876,16 @@ static void display_destroy(GWL_Display *display)
wl_shm_destroy(display->wl_shm);
}
- if (display->relative_pointer_manager) {
- zwp_relative_pointer_manager_v1_destroy(display->relative_pointer_manager);
+ if (display->wp_relative_pointer_manager) {
+ zwp_relative_pointer_manager_v1_destroy(display->wp_relative_pointer_manager);
}
- if (display->pointer_constraints) {
- zwp_pointer_constraints_v1_destroy(display->pointer_constraints);
+ if (display->wp_pointer_constraints) {
+ zwp_pointer_constraints_v1_destroy(display->wp_pointer_constraints);
+ }
+
+ if (display->wp_pointer_gestures) {
+ zwp_pointer_gestures_v1_destroy(display->wp_pointer_gestures);
}
if (display->wl_compositor) {
@@ -680,14 +895,14 @@ static void display_destroy(GWL_Display *display)
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (use_libdecor) {
if (display->libdecor) {
- wgl_libdecor_system_destroy(display->libdecor);
+ gwl_libdecor_system_destroy(display->libdecor);
}
}
else
#endif
{
if (display->xdg_decor) {
- wgl_xdg_decor_system_destroy(display->xdg_decor);
+ gwl_xdg_decor_system_destroy(display->xdg_decor);
}
}
@@ -699,6 +914,12 @@ static void display_destroy(GWL_Display *display)
wl_display_disconnect(display->wl_display);
}
+ {
+ std::lock_guard lock{system_clipboard_mutex};
+ gwl_simple_buffer_free_data(&display->clipboard);
+ gwl_simple_buffer_free_data(&display->clipboard_primary);
+ }
+
delete display;
}
@@ -837,9 +1058,24 @@ static GHOST_TKey xkb_map_gkey_or_scan_code(const xkb_keysym_t sym, const uint32
return gkey;
}
-static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wl_tablet_tool_type)
+static int pointer_axis_as_index(const uint32_t axis)
+{
+ switch (axis) {
+ case WL_POINTER_AXIS_HORIZONTAL_SCROLL: {
+ return 0;
+ }
+ case WL_POINTER_AXIS_VERTICAL_SCROLL: {
+ return 1;
+ }
+ default: {
+ return -1;
+ }
+ }
+}
+
+static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wp_tablet_tool_type)
{
- switch (wl_tablet_tool_type) {
+ switch (wp_tablet_tool_type) {
case ZWP_TABLET_TOOL_V2_TYPE_ERASER: {
return GHOST_kTabletModeEraser;
}
@@ -1045,7 +1281,7 @@ static void keyboard_depressed_state_key_event(GWL_Seat *seat,
}
static void keyboard_depressed_state_push_events_from_change(
- GWL_Seat *seat, const WGL_KeyboardDepressedState &key_depressed_prev)
+ GWL_Seat *seat, const GWL_KeyboardDepressedState &key_depressed_prev)
{
GHOST_IWindow *win = ghost_wl_surface_user_data(seat->keyboard.wl_surface);
GHOST_SystemWayland *system = seat->system;
@@ -1183,15 +1419,81 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event)
}
}
-static std::string read_pipe(GWL_DataOffer *data_offer,
- const std::string mime_receive,
- std::mutex *mutex)
+/**
+ * Read from `fd` into a buffer which is returned.
+ * \return the buffer or null on failure.
+ */
+static const char *read_file_as_buffer(const int fd, size_t *r_len)
+{
+ struct ByteChunk {
+ ByteChunk *next;
+ char data[4096 - sizeof(ByteChunk *)];
+ };
+ ByteChunk *chunk_first = nullptr, **chunk_link_p = &chunk_first;
+ bool ok = true;
+ size_t len = 0;
+ while (true) {
+ ByteChunk *chunk = static_cast<typeof(chunk)>(malloc(sizeof(*chunk)));
+ if (UNLIKELY(chunk == nullptr)) {
+ CLOG_WARN(LOG, "unable to allocate chunk for file buffer");
+ ok = false;
+ break;
+ }
+ chunk->next = nullptr;
+ const ssize_t len_chunk = read(fd, chunk->data, sizeof(chunk->data));
+ if (len_chunk <= 0) {
+ if (UNLIKELY(len_chunk < 0)) {
+ CLOG_WARN(LOG, "error reading from pipe: %s", std::strerror(errno));
+ ok = false;
+ }
+ free(chunk);
+ break;
+ }
+ if (chunk_first == nullptr) {
+ chunk_first = chunk;
+ }
+ *chunk_link_p = chunk;
+ chunk_link_p = &chunk->next;
+ len += len_chunk;
+ }
+
+ char *buf = nullptr;
+ if (ok) {
+ buf = static_cast<char *>(malloc(len));
+ if (UNLIKELY(buf == nullptr)) {
+ CLOG_WARN(LOG, "unable to allocate file buffer: %zu bytes", len);
+ ok = false;
+ }
+ }
+
+ *r_len = ok ? len : 0;
+ char *buf_stride = buf;
+ while (chunk_first) {
+ if (ok) {
+ const size_t len_chunk = std::min(len, sizeof(chunk_first->data));
+ memcpy(buf_stride, chunk_first->data, len_chunk);
+ buf_stride += len_chunk;
+ len -= len_chunk;
+ }
+ ByteChunk *chunk = chunk_first->next;
+ free(chunk_first);
+ chunk_first = chunk;
+ }
+
+ return buf;
+}
+
+static const char *read_buffer_from_data_offer(GWL_DataOffer *data_offer,
+ const char *mime_receive,
+ std::mutex *mutex,
+ size_t *r_len)
{
int pipefd[2];
if (UNLIKELY(pipe(pipefd) != 0)) {
- return {};
+ CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno));
+ return nullptr;
}
- wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]);
+ wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]);
close(pipefd[1]);
data_offer->in_use.store(false);
@@ -1201,15 +1503,34 @@ static std::string read_pipe(GWL_DataOffer *data_offer,
}
/* WARNING: `data_offer` may be freed from now on. */
- std::string data;
- ssize_t len;
- char buffer[4096];
- while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
- data.insert(data.end(), buffer, buffer + len);
- }
+ const char *buf = read_file_as_buffer(pipefd[0], r_len);
close(pipefd[0]);
+ return buf;
+}
+
+static const char *read_buffer_from_primary_selection_offer(
+ GWL_PrimarySelection_DataOffer *data_offer,
+ const char *mime_receive,
+ std::mutex *mutex,
+ size_t *r_len)
+{
+ int pipefd[2];
+ if (UNLIKELY(pipe(pipefd) != 0)) {
+ CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno));
+ return nullptr;
+ }
+ zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]);
+ close(pipefd[1]);
+
+ data_offer->in_use.store(false);
- return data;
+ if (mutex) {
+ mutex->unlock();
+ }
+ /* WARNING: `data_offer` may be freed from now on. */
+ const char *buf = read_file_as_buffer(pipefd[0], r_len);
+ close(pipefd[0]);
+ return buf;
}
/**
@@ -1235,16 +1556,22 @@ static void data_source_handle_send(void *data,
CLOG_INFO(LOG, 2, "send");
- const char *const buffer = seat->data_source->buffer_out;
- if (write(fd, buffer, strlen(buffer)) < 0) {
- GHOST_PRINT("error writing to clipboard: " << std::strerror(errno) << std::endl);
+ const char *const buffer = seat->data_source->buffer_out.data;
+ if (UNLIKELY(write(fd, buffer, seat->data_source->buffer_out.data_size) < 0)) {
+ CLOG_WARN(LOG, "error writing to clipboard: %s", std::strerror(errno));
}
close(fd);
}
-static void data_source_handle_cancelled(void * /*data*/, struct wl_data_source *wl_data_source)
+static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_data_source)
{
CLOG_INFO(LOG, 2, "cancelled");
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ GWL_DataSource *data_source = seat->data_source;
+ if (seat->data_source->wl_source == wl_data_source) {
+ data_source->wl_source = nullptr;
+ }
+
wl_data_source_destroy(wl_data_source);
}
@@ -1313,7 +1640,8 @@ static void data_offer_handle_offer(void *data,
const char *mime_type)
{
CLOG_INFO(LOG, 2, "offer (mime_type=%s)", mime_type);
- static_cast<GWL_DataOffer *>(data)->types.insert(mime_type);
+ GWL_DataOffer *data_offer = static_cast<GWL_DataOffer *>(data);
+ data_offer->types.insert(mime_type);
}
static void data_offer_handle_source_actions(void *data,
@@ -1321,7 +1649,8 @@ static void data_offer_handle_source_actions(void *data,
const uint32_t source_actions)
{
CLOG_INFO(LOG, 2, "source_actions (%u)", source_actions);
- static_cast<GWL_DataOffer *>(data)->source_actions = source_actions;
+ GWL_DataOffer *data_offer = static_cast<GWL_DataOffer *>(data);
+ data_offer->dnd.source_actions = (enum wl_data_device_manager_dnd_action)source_actions;
}
static void data_offer_handle_action(void *data,
@@ -1329,7 +1658,8 @@ static void data_offer_handle_action(void *data,
const uint32_t dnd_action)
{
CLOG_INFO(LOG, 2, "actions (%u)", dnd_action);
- static_cast<GWL_DataOffer *>(data)->dnd_action = dnd_action;
+ GWL_DataOffer *data_offer = static_cast<GWL_DataOffer *>(data);
+ data_offer->dnd.action = (enum wl_data_device_manager_dnd_action)dnd_action;
}
static const struct wl_data_offer_listener data_offer_listener = {
@@ -1452,7 +1782,11 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
const std::string mime_receive) {
const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)};
- const std::string data = read_pipe(data_offer, mime_receive, nullptr);
+ size_t data_buf_len = 0;
+ const char *data_buf = read_buffer_from_data_offer(
+ data_offer, mime_receive.c_str(), nullptr, &data_buf_len);
+ std::string data = data_buf ? std::string(data_buf, data_buf_len) : "";
+ free(const_cast<char *>(data_buf));
CLOG_INFO(
LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive.c_str(), data.c_str());
@@ -1567,12 +1901,15 @@ static void data_device_handle_selection(void *data,
break;
}
}
- const std::string data = read_pipe(
- data_offer, mime_receive, &seat->data_offer_copy_paste_mutex);
+
+ size_t data_len = 0;
+ const char *data = read_buffer_from_data_offer(
+ data_offer, mime_receive.c_str(), &seat->data_offer_copy_paste_mutex, &data_len);
{
std::lock_guard lock{system_clipboard_mutex};
- system->clipboard_set(data);
+ GWL_SimpleBuffer *buf = system->clipboard_data(false);
+ gwl_simple_buffer_set_and_take_ownership(buf, data, data_len);
}
};
@@ -1646,7 +1983,8 @@ static bool update_cursor_scale(GWL_Cursor &cursor,
wl_surface_set_buffer_scale(wl_cursor_surface, scale);
}
wl_cursor_theme_destroy(cursor.wl_theme);
- cursor.wl_theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm);
+ cursor.wl_theme = wl_cursor_theme_load(
+ cursor.theme_name.c_str(), scale * cursor.theme_size, shm);
return true;
}
return false;
@@ -1726,6 +2064,15 @@ static void pointer_handle_enter(void *data,
seat->pointer.serial = serial;
seat->pointer.xy[0] = surface_x;
seat->pointer.xy[1] = surface_y;
+
+ /* Resetting scroll events is likely unnecessary,
+ * do this to avoid any possible problems as it's harmless. */
+ seat->pointer_scroll.smooth_xy[0] = 0;
+ seat->pointer_scroll.smooth_xy[1] = 0;
+ seat->pointer_scroll.discrete_xy[0] = 0;
+ seat->pointer_scroll.discrete_xy[1] = 0;
+ seat->pointer_scroll.axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
+
seat->pointer.wl_surface = wl_surface;
win->setCursorShape(win->getCursorShape());
@@ -1837,24 +2184,91 @@ static void pointer_handle_button(void *data,
}
}
-static void pointer_handle_axis(void * /*data*/,
+static void pointer_handle_axis(void *data,
struct wl_pointer * /*wl_pointer*/,
const uint32_t /*time*/,
const uint32_t axis,
const wl_fixed_t value)
{
+ /* NOTE: this is used for touch based scrolling - or other input that doesn't scroll with
+ * discrete "steps". This allows supporting smooth-scrolling without "touch" gesture support. */
CLOG_INFO(LOG, 2, "axis (axis=%u, value=%d)", axis, value);
+ const int index = pointer_axis_as_index(axis);
+ if (UNLIKELY(index == -1)) {
+ return;
+ }
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->pointer_scroll.smooth_xy[index] = value;
}
-static void pointer_handle_frame(void * /*data*/, struct wl_pointer * /*wl_pointer*/)
+static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/)
{
CLOG_INFO(LOG, 2, "frame");
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+
+ /* Both discrete and smooth events may be set at once, never generate events for both
+ * as this will be handling the same event in to different ways.
+ * Prioritize discrete axis events for the mouse wheel, otherwise smooth scroll. */
+ if (seat->pointer_scroll.axis_source == WL_POINTER_AXIS_SOURCE_WHEEL) {
+ if (seat->pointer_scroll.discrete_xy[0]) {
+ seat->pointer_scroll.smooth_xy[0] = 0;
+ }
+ if (seat->pointer_scroll.discrete_xy[1]) {
+ seat->pointer_scroll.smooth_xy[1] = 0;
+ }
+ }
+ else {
+ if (seat->pointer_scroll.smooth_xy[0]) {
+ seat->pointer_scroll.discrete_xy[0] = 0;
+ }
+ if (seat->pointer_scroll.smooth_xy[1]) {
+ seat->pointer_scroll.discrete_xy[1] = 0;
+ }
+ }
+
+ /* Discrete X axis currently unsupported. */
+ if (seat->pointer_scroll.discrete_xy[1]) {
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ const int32_t discrete = seat->pointer_scroll.discrete_xy[1];
+ seat->system->pushEvent(new GHOST_EventWheel(
+ seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1));
+ }
+ seat->pointer_scroll.discrete_xy[0] = 0;
+ seat->pointer_scroll.discrete_xy[1] = 0;
+ }
+
+ if (seat->pointer_scroll.smooth_xy[0] || seat->pointer_scroll.smooth_xy[1]) {
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
+ const wl_fixed_t scale = win->scale();
+ seat->system->pushEvent(new GHOST_EventTrackpad(
+ seat->system->getMilliSeconds(),
+ win,
+ GHOST_kTrackpadEventScroll,
+ wl_fixed_to_int(scale * seat->pointer.xy[0]),
+ wl_fixed_to_int(scale * seat->pointer.xy[1]),
+ /* NOTE: scaling the delta doesn't seem necessary.
+ * NOTE: inverting delta gives correct results, see: QTBUG-85767. */
+ -wl_fixed_to_int(seat->pointer_scroll.smooth_xy[0]),
+ -wl_fixed_to_int(seat->pointer_scroll.smooth_xy[1]),
+ /* TODO: investigate a way to request this configuration from the system. */
+ false));
+ }
+
+ seat->pointer_scroll.smooth_xy[0] = 0;
+ seat->pointer_scroll.smooth_xy[1] = 0;
+ }
+
+ seat->pointer_scroll.axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
}
-static void pointer_handle_axis_source(void * /*data*/,
+static void pointer_handle_axis_source(void *data,
struct wl_pointer * /*wl_pointer*/,
uint32_t axis_source)
{
CLOG_INFO(LOG, 2, "axis_source (axis_source=%u)", axis_source);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->pointer_scroll.axis_source = (enum wl_pointer_axis_source)axis_source;
}
static void pointer_handle_axis_stop(void * /*data*/,
struct wl_pointer * /*wl_pointer*/,
@@ -1868,18 +2282,15 @@ static void pointer_handle_axis_discrete(void *data,
uint32_t axis,
int32_t discrete)
{
+ /* NOTE: a discrete axis are typically mouse wheel events.
+ * The non-discrete version of this function is used for touch-pad. */
CLOG_INFO(LOG, 2, "axis_discrete (axis=%u, discrete=%d)", axis, discrete);
-
- GWL_Seat *seat = static_cast<GWL_Seat *>(data);
- if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) {
+ const int index = pointer_axis_as_index(axis);
+ if (UNLIKELY(index == -1)) {
return;
}
-
- if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
- GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
- seat->system->pushEvent(new GHOST_EventWheel(
- seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1));
- }
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ seat->pointer_scroll.discrete_xy[index] = discrete;
}
static const struct wl_pointer_listener pointer_listener = {
@@ -1899,6 +2310,306 @@ static const struct wl_pointer_listener pointer_listener = {
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Listener (Pointer Gesture: Hold), #zwp_pointer_gesture_hold_v1_listener
+ * \{ */
+
+static CLG_LogRef LOG_WL_POINTER_GESTURE_HOLD = {"ghost.wl.handle.pointer_gesture.hold"};
+#define LOG (&LOG_WL_POINTER_GESTURE_HOLD)
+
+static void gesture_hold_handle_begin(
+ void * /*data*/,
+ struct zwp_pointer_gesture_hold_v1 * /*zwp_pointer_gesture_hold_v1*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ struct wl_surface * /*surface*/,
+ uint32_t fingers)
+{
+ CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers);
+}
+
+static void gesture_hold_handle_end(
+ void * /*data*/,
+ struct zwp_pointer_gesture_hold_v1 * /*zwp_pointer_gesture_hold_v1*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ int32_t cancelled)
+{
+ CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled);
+}
+
+static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_listener = {
+ gesture_hold_handle_begin,
+ gesture_hold_handle_end,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (Pointer Gesture: Pinch), #zwp_pointer_gesture_pinch_v1_listener
+ * \{ */
+
+static CLG_LogRef LOG_WL_POINTER_GESTURE_PINCH = {"ghost.wl.handle.pointer_gesture.pinch"};
+#define LOG (&LOG_WL_POINTER_GESTURE_PINCH)
+
+static void gesture_pinch_handle_begin(void *data,
+ struct zwp_pointer_gesture_pinch_v1 * /*pinch*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ struct wl_surface * /*surface*/,
+ uint32_t fingers)
+{
+ CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers);
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+ /* Reset defaults. */
+ seat->pointer_gesture_pinch = GWL_SeatStatePointerGesture_Pinch{};
+
+ GHOST_WindowWayland *win = nullptr;
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ win = ghost_wl_surface_user_data(wl_surface_focus);
+ }
+ const wl_fixed_t win_scale = win ? win->scale() : 1;
+
+ /* NOTE(@campbellbarton): Scale factors match Blender's operators & default preferences.
+ * For these values to work correctly, operator logic will need to be changed not to scale input
+ * by the region size (as with 3D view zoom) or preference for 3D view orbit sensitivity.
+ *
+ * By working "correctly" I mean that a rotation action where the users fingers rotate to
+ * opposite locations should always rotate the viewport 180d, since users will expect the
+ * physical location of their fingers to match the viewport.
+ * Similarly with zoom, the scale value from the pinch action can be mapped to a zoom level
+ * although unlike rotation, an inexact mapping is less noticeable.
+ * Users may even prefer the zoom level to be scaled - which could be a preference. */
+ seat->pointer_gesture_pinch.scale.value = wl_fixed_from_int(1);
+ /* The value 300 matches a value used in clip & image zoom operators.
+ * It seems OK for the 3D view too. */
+ seat->pointer_gesture_pinch.scale.factor = 300 * win_scale;
+ /* The value 5 is used on macOS and roughly maps 1:1 with turntable rotation,
+ * although preferences can scale the sensitivity (which would be skipped ideally). */
+ seat->pointer_gesture_pinch.rotation.factor = 5 * win_scale;
+}
+
+static void gesture_pinch_handle_update(void *data,
+ struct zwp_pointer_gesture_pinch_v1 * /*pinch*/,
+ uint32_t /*time*/,
+ wl_fixed_t dx,
+ wl_fixed_t dy,
+ wl_fixed_t scale,
+ wl_fixed_t rotation)
+{
+ CLOG_INFO(LOG,
+ 2,
+ "update (dx=%.3f, dy=%.3f, scale=%.3f, rotation=%.3f)",
+ wl_fixed_to_double(dx),
+ wl_fixed_to_double(dy),
+ wl_fixed_to_double(scale),
+ wl_fixed_to_double(rotation));
+
+ GWL_Seat *seat = static_cast<GWL_Seat *>(data);
+
+ GHOST_WindowWayland *win = nullptr;
+
+ if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) {
+ win = ghost_wl_surface_user_data(wl_surface_focus);
+ }
+
+ /* Scale defaults to `wl_fixed_from_int(1)` which may change while pinching.
+ * This needs to be converted to a delta. */
+ const wl_fixed_t scale_delta = scale - seat->pointer_gesture_pinch.scale.value;
+ const int scale_as_delta_px = gwl_scaled_fixed_t_add_and_calc_rounded_delta(
+ &seat->pointer_gesture_pinch.scale, scale_delta);
+
+ /* Rotation in degrees, unlike scale this is a delta. */
+ const int rotation_as_delta_px = gwl_scaled_fixed_t_add_and_calc_rounded_delta(
+ &seat->pointer_gesture_pinch.rotation, rotation);
+
+ if (win) {
+ const wl_fixed_t win_scale = win->scale();
+ const int32_t event_xy[2] = {
+ wl_fixed_to_int(win_scale * seat->pointer.xy[0]),
+ wl_fixed_to_int(win_scale * seat->pointer.xy[1]),
+ };
+ if (scale_as_delta_px) {
+ seat->system->pushEvent(new GHOST_EventTrackpad(seat->system->getMilliSeconds(),
+ win,
+ GHOST_kTrackpadEventMagnify,
+ event_xy[0],
+ event_xy[1],
+ scale_as_delta_px,
+ 0,
+ false));
+ }
+
+ if (rotation_as_delta_px) {
+ seat->system->pushEvent(new GHOST_EventTrackpad(seat->system->getMilliSeconds(),
+ win,
+ GHOST_kTrackpadEventRotate,
+ event_xy[0],
+ event_xy[1],
+ rotation_as_delta_px,
+ 0,
+ false));
+ }
+ }
+}
+
+static void gesture_pinch_handle_end(void * /*data*/,
+ struct zwp_pointer_gesture_pinch_v1 * /*pinch*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ int32_t cancelled)
+{
+ CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled);
+}
+
+static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener = {
+ gesture_pinch_handle_begin,
+ gesture_pinch_handle_update,
+ gesture_pinch_handle_end,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (Pointer Gesture: Swipe), #zwp_pointer_gesture_swipe_v1
+ *
+ * \note In both Gnome-Shell & KDE this gesture isn't emitted at time of writing,
+ * instead, high resolution 2D #wl_pointer_listener.axis data is generated which works well.
+ * There may be some situations where WAYLAND compositors generate this gesture
+ * (swiping with 3+ fingers, for e.g.). So keep this to allow logging & testing gestures.
+ * \{ */
+
+static CLG_LogRef LOG_WL_POINTER_GESTURE_SWIPE = {"ghost.wl.handle.pointer_gesture.swipe"};
+#define LOG (&LOG_WL_POINTER_GESTURE_SWIPE)
+
+static void gesture_swipe_handle_begin(
+ void * /*data*/,
+ struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ struct wl_surface * /*surface*/,
+ uint32_t fingers)
+{
+ CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers);
+}
+
+static void gesture_swipe_handle_update(
+ void * /*data*/,
+ struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/,
+ uint32_t /*time*/,
+ wl_fixed_t dx,
+ wl_fixed_t dy)
+{
+ CLOG_INFO(LOG, 2, "update (dx=%.3f, dy=%.3f)", wl_fixed_to_double(dx), wl_fixed_to_double(dy));
+}
+
+static void gesture_swipe_handle_end(
+ void * /*data*/,
+ struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ int32_t cancelled)
+{
+ CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled);
+}
+
+static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener = {
+ gesture_swipe_handle_begin,
+ gesture_swipe_handle_update,
+ gesture_swipe_handle_end,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (Touch Seat), #wl_touch_listener
+ *
+ * TODO(@campbellbarton): Only setup the callbacks for now as I don't have
+ * hardware that generates touch events.
+ * \{ */
+
+static CLG_LogRef LOG_WL_TOUCH = {"ghost.wl.handle.touch"};
+#define LOG (&LOG_WL_TOUCH)
+
+static void touch_seat_handle_down(void * /*data*/,
+ struct wl_touch * /*wl_touch*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ struct wl_surface * /*wl_surface*/,
+ int32_t /*id*/,
+ wl_fixed_t /*x*/,
+ wl_fixed_t /*y*/)
+{
+ CLOG_INFO(LOG, 2, "down");
+}
+
+static void touch_seat_handle_up(void * /*data*/,
+ struct wl_touch * /*wl_touch*/,
+ uint32_t /*serial*/,
+ uint32_t /*time*/,
+ int32_t /*id*/)
+{
+ CLOG_INFO(LOG, 2, "up");
+}
+
+static void touch_seat_handle_motion(void * /*data*/,
+ struct wl_touch * /*wl_touch*/,
+ uint32_t /*time*/,
+ int32_t /*id*/,
+ wl_fixed_t /*x*/,
+ wl_fixed_t /*y*/)
+{
+ CLOG_INFO(LOG, 2, "motion");
+}
+
+static void touch_seat_handle_frame(void * /*data*/, struct wl_touch * /*wl_touch*/)
+{
+ CLOG_INFO(LOG, 2, "frame");
+}
+
+static void touch_seat_handle_cancel(void * /*data*/, struct wl_touch * /*wl_touch*/)
+{
+
+ CLOG_INFO(LOG, 2, "cancel");
+}
+
+static void touch_seat_handle_shape(void * /*data*/,
+ struct wl_touch * /*touch*/,
+ int32_t /*id*/,
+ wl_fixed_t /*major*/,
+ wl_fixed_t /*minor*/)
+{
+ CLOG_INFO(LOG, 2, "shape");
+}
+
+static void touch_seat_handle_orientation(void * /*data*/,
+ struct wl_touch * /*touch*/,
+ int32_t /*id*/,
+ wl_fixed_t /*orientation*/)
+{
+ CLOG_INFO(LOG, 2, "orientation");
+}
+
+static const struct wl_touch_listener touch_seat_listener = {
+ touch_seat_handle_down,
+ touch_seat_handle_up,
+ touch_seat_handle_motion,
+ touch_seat_handle_frame,
+ touch_seat_handle_cancel,
+ touch_seat_handle_shape,
+ touch_seat_handle_orientation,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Listener (Tablet Tool), #zwp_tablet_tool_v2_listener
* \{ */
@@ -2377,7 +3088,7 @@ static void keyboard_handle_enter(void *data,
/* If there are any keys held when activating the window,
* modifiers will be compared against the seat state,
* only enabling modifiers that were previously disabled. */
- WGL_KeyboardDepressedState key_depressed_prev = seat->key_depressed;
+ GWL_KeyboardDepressedState key_depressed_prev = seat->key_depressed;
keyboard_depressed_state_reset(seat);
uint32_t *key;
@@ -2587,11 +3298,10 @@ static void keyboard_handle_key(void *data,
/* Start timer for repeating key, if applicable. */
if ((seat->key_repeat.rate > 0) && (etype == GHOST_kEventKeyDown) &&
xkb_keymap_key_repeats(xkb_state_get_keymap(seat->xkb_state), key_code)) {
- key_repeat_payload = new GWL_KeyRepeatPlayload({
- .seat = seat,
- .key_code = key_code,
- .key_data = {.gkey = gkey},
- });
+ key_repeat_payload = new GWL_KeyRepeatPlayload();
+ key_repeat_payload->seat = seat;
+ key_repeat_payload->key_code = key_code;
+ key_repeat_payload->key_data.gkey = gkey;
}
}
@@ -2681,12 +3391,294 @@ static const struct wl_keyboard_listener keyboard_listener = {
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Listener (Primary Selection Offer), #zwp_primary_selection_offer_v1_listener
+ * \{ */
+
+static CLG_LogRef LOG_WL_PRIMARY_SELECTION_OFFER = {"ghost.wl.handle.primary_selection_offer"};
+#define LOG (&LOG_WL_PRIMARY_SELECTION_OFFER)
+
+static void primary_selection_offer_offer(void *data,
+ struct zwp_primary_selection_offer_v1 *id,
+ const char *type)
+{
+ GWL_PrimarySelection_DataOffer *data_offer = static_cast<GWL_PrimarySelection_DataOffer *>(data);
+ if (data_offer->id != id) {
+ CLOG_INFO(LOG, 2, "offer: %p: offer for unknown selection %p of %s (skipped)", data, id, type);
+ return;
+ }
+
+ data_offer->types.insert(std::string(type));
+}
+
+static const struct zwp_primary_selection_offer_v1_listener primary_selection_offer_listener = {
+ primary_selection_offer_offer,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (Primary Selection Device), #zwp_primary_selection_device_v1_listener
+ * \{ */
+
+static CLG_LogRef LOG_WL_PRIMARY_SELECTION_DEVICE = {"ghost.wl.handle.primary_selection_device"};
+#define LOG (&LOG_WL_PRIMARY_SELECTION_DEVICE)
+
+static void primary_selection_device_handle_data_offer(
+ void * /*data*/,
+ struct zwp_primary_selection_device_v1 * /*zwp_primary_selection_device_v1*/,
+ struct zwp_primary_selection_offer_v1 *id)
+{
+ CLOG_INFO(LOG, 2, "data_offer");
+
+ GWL_PrimarySelection_DataOffer *data_offer = new GWL_PrimarySelection_DataOffer;
+ data_offer->id = id;
+ zwp_primary_selection_offer_v1_add_listener(id, &primary_selection_offer_listener, data_offer);
+}
+
+static void primary_selection_device_handle_selection(
+ void *data,
+ struct zwp_primary_selection_device_v1 * /*zwp_primary_selection_device_v1*/,
+ struct zwp_primary_selection_offer_v1 *id)
+{
+ GWL_PrimarySelection *primary = static_cast<GWL_PrimarySelection *>(data);
+
+ std::lock_guard lock{primary->data_offer_mutex};
+
+ /* Delete old data offer. */
+ if (primary->data_offer != nullptr) {
+ gwl_primary_selection_discard_offer(primary);
+ }
+
+ if (id == nullptr) {
+ CLOG_INFO(LOG, 2, "selection: (skipped)");
+ return;
+ }
+ CLOG_INFO(LOG, 2, "selection");
+ /* Get new data offer. */
+ GWL_PrimarySelection_DataOffer *data_offer = static_cast<GWL_PrimarySelection_DataOffer *>(
+ zwp_primary_selection_offer_v1_get_user_data(id));
+ primary->data_offer = data_offer;
+
+ auto read_selection_fn = [](GWL_PrimarySelection *primary) {
+ GHOST_SystemWayland *system = static_cast<GHOST_SystemWayland *>(GHOST_ISystem::getSystem());
+ primary->data_offer_mutex.lock();
+
+ GWL_PrimarySelection_DataOffer *data_offer = primary->data_offer;
+ std::string mime_receive;
+ for (const std::string type : {mime_text_utf8, mime_text_plain}) {
+ if (data_offer->types.count(type)) {
+ mime_receive = type;
+ break;
+ }
+ }
+ size_t data_len = 0;
+ const char *data = read_buffer_from_primary_selection_offer(
+ data_offer, mime_receive.c_str(), &primary->data_offer_mutex, &data_len);
+
+ {
+ std::lock_guard lock{system_clipboard_mutex};
+ GWL_SimpleBuffer *buf = system->clipboard_data(true);
+ gwl_simple_buffer_set_and_take_ownership(buf, data, data_len);
+ }
+ };
+
+ std::thread read_thread(read_selection_fn, primary);
+ read_thread.detach();
+}
+
+static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = {
+ primary_selection_device_handle_data_offer,
+ primary_selection_device_handle_selection,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (Primary Selection Source), #zwp_primary_selection_source_v1_listener
+ * \{ */
+
+static CLG_LogRef LOG_WL_PRIMARY_SELECTION_SOURCE = {"ghost.wl.handle.primary_selection_source"};
+#define LOG (&LOG_WL_PRIMARY_SELECTION_SOURCE)
+
+static void primary_selection_source_send(void *data,
+ struct zwp_primary_selection_source_v1 * /*source*/,
+ const char * /*mime_type*/,
+ int32_t fd)
+{
+ CLOG_INFO(LOG, 2, "send");
+
+ GWL_PrimarySelection *primary = static_cast<GWL_PrimarySelection *>(data);
+
+ std::lock_guard lock{primary->data_source_mutex};
+ GWL_PrimarySelection_DataSource *data_source = primary->data_source;
+
+ const char *const buffer = data_source->buffer_out.data;
+ if (UNLIKELY(write(fd, buffer, data_source->buffer_out.data_size) < 0)) {
+ CLOG_WARN(LOG, "error writing to primary clipboard: %s", std::strerror(errno));
+ }
+ close(fd);
+}
+
+static void primary_selection_source_cancelled(void *data,
+ struct zwp_primary_selection_source_v1 *source)
+{
+ CLOG_INFO(LOG, 2, "cancelled");
+
+ GWL_PrimarySelection *primary = static_cast<GWL_PrimarySelection *>(data);
+
+ if (source == primary->data_source->wp_source) {
+ gwl_primary_selection_discard_source(primary);
+ }
+}
+
+static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = {
+ primary_selection_source_send,
+ primary_selection_source_cancelled,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Listener (Seat), #wl_seat_listener
* \{ */
static CLG_LogRef LOG_WL_SEAT = {"ghost.wl.handle.seat"};
#define LOG (&LOG_WL_SEAT)
+static void gwl_seat_capability_pointer_enable(GWL_Seat *seat)
+{
+ if (seat->wl_pointer) {
+ return;
+ }
+ seat->wl_pointer = wl_seat_get_pointer(seat->wl_seat);
+ seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor());
+ seat->cursor.visible = true;
+ seat->cursor.wl_buffer = nullptr;
+ if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.theme_size)) {
+ seat->cursor.theme_name = std::string();
+ seat->cursor.theme_size = default_cursor_size;
+ }
+ wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat);
+
+ wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, seat);
+ ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface);
+
+ zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures();
+ if (pointer_gestures) {
+ { /* Hold gesture. */
+ struct zwp_pointer_gesture_hold_v1 *gesture = zwp_pointer_gestures_v1_get_hold_gesture(
+ pointer_gestures, seat->wl_pointer);
+ zwp_pointer_gesture_hold_v1_set_user_data(gesture, seat);
+ zwp_pointer_gesture_hold_v1_add_listener(gesture, &gesture_hold_listener, seat);
+ seat->wp_pointer_gesture_hold = gesture;
+ }
+ { /* Pinch gesture. */
+ struct zwp_pointer_gesture_pinch_v1 *gesture = zwp_pointer_gestures_v1_get_pinch_gesture(
+ pointer_gestures, seat->wl_pointer);
+ zwp_pointer_gesture_pinch_v1_set_user_data(gesture, seat);
+ zwp_pointer_gesture_pinch_v1_add_listener(gesture, &gesture_pinch_listener, seat);
+ seat->wp_pointer_gesture_pinch = gesture;
+ }
+ { /* Swipe gesture. */
+ struct zwp_pointer_gesture_swipe_v1 *gesture = zwp_pointer_gestures_v1_get_swipe_gesture(
+ pointer_gestures, seat->wl_pointer);
+ zwp_pointer_gesture_swipe_v1_set_user_data(gesture, seat);
+ zwp_pointer_gesture_swipe_v1_add_listener(gesture, &gesture_swipe_listener, seat);
+ seat->wp_pointer_gesture_swipe = gesture;
+ }
+ }
+}
+
+static void gwl_seat_capability_pointer_disable(GWL_Seat *seat)
+{
+ if (!seat->wl_pointer) {
+ return;
+ }
+
+ zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures();
+ if (pointer_gestures) {
+ { /* Hold gesture. */
+ struct zwp_pointer_gesture_hold_v1 **gesture_p = &seat->wp_pointer_gesture_hold;
+ if (*gesture_p) {
+ zwp_pointer_gesture_hold_v1_destroy(*gesture_p);
+ *gesture_p = nullptr;
+ }
+ }
+ { /* Pinch gesture. */
+ struct zwp_pointer_gesture_pinch_v1 **gesture_p = &seat->wp_pointer_gesture_pinch;
+ if (*gesture_p) {
+ zwp_pointer_gesture_pinch_v1_destroy(*gesture_p);
+ *gesture_p = nullptr;
+ }
+ }
+ { /* Swipe gesture. */
+ struct zwp_pointer_gesture_swipe_v1 **gesture_p = &seat->wp_pointer_gesture_swipe;
+ if (*gesture_p) {
+ zwp_pointer_gesture_swipe_v1_destroy(*gesture_p);
+ *gesture_p = nullptr;
+ }
+ }
+ }
+
+ if (seat->cursor.wl_surface) {
+ wl_surface_destroy(seat->cursor.wl_surface);
+ seat->cursor.wl_surface = nullptr;
+ }
+ if (seat->cursor.wl_theme) {
+ wl_cursor_theme_destroy(seat->cursor.wl_theme);
+ seat->cursor.wl_theme = nullptr;
+ }
+
+ wl_pointer_destroy(seat->wl_pointer);
+ seat->wl_pointer = nullptr;
+}
+
+static void gwl_seat_capability_keyboard_enable(GWL_Seat *seat)
+{
+ if (seat->wl_keyboard) {
+ return;
+ }
+ seat->wl_keyboard = wl_seat_get_keyboard(seat->wl_seat);
+ wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, seat);
+}
+
+static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat)
+{
+ if (!seat->wl_keyboard) {
+ return;
+ }
+ if (seat->key_repeat.timer) {
+ keyboard_handle_key_repeat_cancel(seat);
+ }
+ wl_keyboard_destroy(seat->wl_keyboard);
+ seat->wl_keyboard = nullptr;
+}
+
+static void gwl_seat_capability_touch_enable(GWL_Seat *seat)
+{
+ if (seat->wl_touch) {
+ return;
+ }
+ seat->wl_touch = wl_seat_get_touch(seat->wl_seat);
+ wl_touch_set_user_data(seat->wl_touch, seat);
+ wl_touch_add_listener(seat->wl_touch, &touch_seat_listener, seat);
+}
+
+static void gwl_seat_capability_touch_disable(GWL_Seat *seat)
+{
+ if (!seat->wl_touch) {
+ return;
+ }
+ wl_touch_destroy(seat->wl_touch);
+ seat->wl_touch = nullptr;
+}
+
static void seat_handle_capabilities(void *data,
struct wl_seat *wl_seat,
const uint32_t capabilities)
@@ -2699,27 +3691,43 @@ static void seat_handle_capabilities(void *data,
(capabilities & WL_SEAT_CAPABILITY_TOUCH) != 0);
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
- seat->wl_pointer = nullptr;
- seat->wl_keyboard = nullptr;
+ GHOST_ASSERT(seat->wl_seat == wl_seat, "Seat mismatch");
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
- seat->wl_pointer = wl_seat_get_pointer(wl_seat);
- seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor());
- seat->cursor.visible = true;
- seat->cursor.wl_buffer = nullptr;
- if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.size)) {
- seat->cursor.theme_name = std::string();
- seat->cursor.size = default_cursor_size;
- }
- wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, data);
-
- wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, data);
- ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface);
+ gwl_seat_capability_pointer_enable(seat);
+ }
+ else {
+ gwl_seat_capability_pointer_disable(seat);
}
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
- seat->wl_keyboard = wl_seat_get_keyboard(wl_seat);
- wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, data);
+ gwl_seat_capability_keyboard_enable(seat);
+ }
+ else {
+ gwl_seat_capability_keyboard_disable(seat);
+ }
+
+ if (capabilities & WL_SEAT_CAPABILITY_TOUCH) {
+ gwl_seat_capability_touch_enable(seat);
+ }
+ else {
+ gwl_seat_capability_touch_disable(seat);
+ }
+
+ /* TODO(@campbellbarton): this could be moved out elsewhere. */
+ if (seat->system) {
+ zwp_primary_selection_device_manager_v1 *primary_selection_device_manager =
+ seat->system->wp_primary_selection_manager();
+ if (primary_selection_device_manager) {
+ if (seat->wp_primary_selection_device == nullptr) {
+ seat->wp_primary_selection_device = zwp_primary_selection_device_manager_v1_get_device(
+ primary_selection_device_manager, seat->wl_seat);
+
+ zwp_primary_selection_device_v1_add_listener(seat->wp_primary_selection_device,
+ &primary_selection_device_listener,
+ &seat->primary_selection);
+ }
+ }
}
}
@@ -3026,13 +4034,13 @@ static void global_handle_add(void *data,
wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3));
}
else if (STREQ(interface, xdg_wm_base_interface.name)) {
- WGL_XDG_Decor_System &decor = *display->xdg_decor;
+ GWL_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(decor.shell, &shell_listener, nullptr);
}
else if (STREQ(interface, zxdg_decoration_manager_v1_interface.name)) {
- WGL_XDG_Decor_System &decor = *display->xdg_decor;
+ GWL_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));
}
@@ -3076,21 +4084,32 @@ static void global_handle_add(void *data,
wl_registry_bind(wl_registry, name, &wl_shm_interface, 1));
}
else if (STREQ(interface, wl_data_device_manager_interface.name)) {
- display->data_device_manager = static_cast<wl_data_device_manager *>(
+ display->wl_data_device_manager = static_cast<wl_data_device_manager *>(
wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3));
}
else if (STREQ(interface, zwp_tablet_manager_v2_interface.name)) {
- display->tablet_manager = static_cast<zwp_tablet_manager_v2 *>(
+ display->wp_tablet_manager = static_cast<zwp_tablet_manager_v2 *>(
wl_registry_bind(wl_registry, name, &zwp_tablet_manager_v2_interface, 1));
}
else if (STREQ(interface, zwp_relative_pointer_manager_v1_interface.name)) {
- display->relative_pointer_manager = static_cast<zwp_relative_pointer_manager_v1 *>(
+ display->wp_relative_pointer_manager = static_cast<zwp_relative_pointer_manager_v1 *>(
wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1));
}
else if (STREQ(interface, zwp_pointer_constraints_v1_interface.name)) {
- display->pointer_constraints = static_cast<zwp_pointer_constraints_v1 *>(
+ display->wp_pointer_constraints = static_cast<zwp_pointer_constraints_v1 *>(
wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1));
}
+ else if (STREQ(interface, zwp_pointer_gestures_v1_interface.name)) {
+ display->wp_pointer_gestures = static_cast<zwp_pointer_gestures_v1 *>(
+ wl_registry_bind(wl_registry, name, &zwp_pointer_gestures_v1_interface, 3));
+ }
+
+ else if (!strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name)) {
+ display->wp_primary_selection_device_manager =
+ static_cast<zwp_primary_selection_device_manager_v1 *>(wl_registry_bind(
+ wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1));
+ }
+
else {
found = false;
@@ -3156,7 +4175,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di
}
/* This may be removed later if decorations are required, needed as part of registration. */
- display_->xdg_decor = new WGL_XDG_Decor_System;
+ display_->xdg_decor = new GWL_XDG_Decor_System;
/* Register interfaces. */
struct wl_registry *registry = wl_display_get_registry(display_->wl_display);
@@ -3169,7 +4188,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (display_->libdecor_required) {
- wgl_xdg_decor_system_destroy(display_->xdg_decor);
+ gwl_xdg_decor_system_destroy(display_->xdg_decor);
display_->xdg_decor = nullptr;
if (!has_libdecor) {
@@ -3190,8 +4209,8 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (use_libdecor) {
- display_->libdecor = new WGL_LibDecor_System;
- WGL_LibDecor_System &decor = *display_->libdecor;
+ display_->libdecor = new GWL_LibDecor_System;
+ GWL_LibDecor_System &decor = *display_->libdecor;
decor.context = libdecor_new(display_->wl_display, &libdecor_interface);
if (!decor.context) {
display_destroy(display_);
@@ -3201,7 +4220,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di
else
#endif
{
- WGL_XDG_Decor_System &decor = *display_->xdg_decor;
+ GWL_XDG_Decor_System &decor = *display_->xdg_decor;
if (!decor.shell) {
display_destroy(display_);
throw std::runtime_error("Wayland: unable to access xdg_shell!");
@@ -3209,19 +4228,19 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di
}
/* Register data device per seat for IPC between Wayland clients. */
- if (display_->data_device_manager) {
+ if (display_->wl_data_device_manager) {
for (GWL_Seat *seat : display_->seats) {
- seat->data_device = wl_data_device_manager_get_data_device(display_->data_device_manager,
- seat->wl_seat);
- wl_data_device_add_listener(seat->data_device, &data_device_listener, seat);
+ seat->wl_data_device = wl_data_device_manager_get_data_device(
+ display_->wl_data_device_manager, seat->wl_seat);
+ wl_data_device_add_listener(seat->wl_data_device, &data_device_listener, seat);
}
}
- if (display_->tablet_manager) {
+ if (display_->wp_tablet_manager) {
for (GWL_Seat *seat : display_->seats) {
- seat->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display_->tablet_manager,
- seat->wl_seat);
- zwp_tablet_seat_v2_add_listener(seat->tablet_seat, &tablet_seat_listener, seat);
+ seat->wp_tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display_->wp_tablet_manager,
+ seat->wl_seat);
+ zwp_tablet_seat_v2_add_listener(seat->wp_tablet_seat, &tablet_seat_listener, seat);
}
}
}
@@ -3300,7 +4319,7 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co
}
#endif
- /* Use local #WGL_KeyboardDepressedState to check which key is pressed.
+ /* Use local #GWL_KeyboardDepressedState to check which key is pressed.
* Use XKB as the source of truth, if there is any discrepancy. */
for (int i = 0; i < MOD_INDEX_NUM; i++) {
if (UNLIKELY(seat->xkb_keymap_mod_index[i] == XKB_MOD_INVALID)) {
@@ -3358,43 +4377,86 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const
return GHOST_kSuccess;
}
-char *GHOST_SystemWayland::getClipboard(bool /*selection*/) const
+char *GHOST_SystemWayland::getClipboard(bool selection) const
{
- char *clipboard = static_cast<char *>(malloc(clipboard_.size() + 1));
- memcpy(clipboard, clipboard_.data(), clipboard_.size() + 1);
- return clipboard;
+ const GWL_SimpleBuffer *buf = clipboard_data(selection);
+ if (buf->data == nullptr) {
+ return nullptr;
+ }
+ return gwl_simple_buffer_as_string(buf);
}
-void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) const
+static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer)
{
- if (UNLIKELY(!display_->data_device_manager || display_->seats.empty())) {
+ if (!display->wp_primary_selection_device_manager) {
return;
}
+ GWL_Seat *seat = display->seats[0];
+ GWL_PrimarySelection *primary = &seat->primary_selection;
- GWL_Seat *seat = display_->seats[0];
+ std::lock_guard lock{primary->data_source_mutex};
+
+ gwl_primary_selection_discard_source(primary);
+
+ GWL_PrimarySelection_DataSource *data_source = new GWL_PrimarySelection_DataSource;
+ primary->data_source = data_source;
+
+ /* Copy buffer. */
+ gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer);
+
+ data_source->wp_source = zwp_primary_selection_device_manager_v1_create_source(
+ display->wp_primary_selection_device_manager);
+
+ zwp_primary_selection_source_v1_add_listener(
+ data_source->wp_source, &primary_selection_source_listener, primary);
+
+ for (const std::string &type : mime_send) {
+ zwp_primary_selection_source_v1_offer(data_source->wp_source, type.c_str());
+ }
+
+ if (seat->wp_primary_selection_device) {
+ zwp_primary_selection_device_v1_set_selection(
+ seat->wp_primary_selection_device, data_source->wp_source, seat->data_source_serial);
+ }
+}
+
+static void system_clipboard_put(GWL_Display *display, const char *buffer)
+{
+ GWL_Seat *seat = display->seats[0];
std::lock_guard lock{seat->data_source_mutex};
GWL_DataSource *data_source = seat->data_source;
/* Copy buffer. */
- free(data_source->buffer_out);
- const size_t buffer_size = strlen(buffer) + 1;
- data_source->buffer_out = static_cast<char *>(malloc(buffer_size));
- std::memcpy(data_source->buffer_out, buffer, buffer_size);
+ gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer);
- data_source->data_source = wl_data_device_manager_create_data_source(
- display_->data_device_manager);
+ data_source->wl_source = wl_data_device_manager_create_data_source(
+ display->wl_data_device_manager);
- wl_data_source_add_listener(data_source->data_source, &data_source_listener, seat);
+ wl_data_source_add_listener(data_source->wl_source, &data_source_listener, seat);
for (const std::string &type : mime_send) {
- wl_data_source_offer(data_source->data_source, type.c_str());
+ wl_data_source_offer(data_source->wl_source, type.c_str());
}
- if (seat->data_device) {
+ if (seat->wl_data_device) {
wl_data_device_set_selection(
- seat->data_device, data_source->data_source, seat->data_source_serial);
+ seat->wl_data_device, data_source->wl_source, seat->data_source_serial);
+ }
+}
+
+void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const
+{
+ if (UNLIKELY(!display_->wl_data_device_manager || display_->seats.empty())) {
+ return;
+ }
+
+ if (selection) {
+ system_clipboard_put_primary_selection(display_, buffer);
+ }
+ else {
+ system_clipboard_put(display_, buffer);
}
}
@@ -3423,7 +4485,7 @@ static GHOST_TSuccess setCursorPositionClientRelative_impl(GWL_Seat *seat,
/* NOTE: WAYLAND doesn't support warping the cursor.
* However when grab is enabled, we already simulate a cursor location
* so that can be set to a new location. */
- if (!seat->relative_pointer) {
+ if (!seat->wp_relative_pointer) {
return GHOST_kFailure;
}
const wl_fixed_t scale = win->scale();
@@ -3616,7 +4678,6 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
const uint32_t width,
const uint32_t height,
const GHOST_TWindowState state,
- const GHOST_TDrawingContextType type,
const GHOST_GLSettings glSettings,
const bool exclusive,
const bool is_dialog,
@@ -3636,7 +4697,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
height,
state,
parentWindow,
- type,
+ glSettings.context_type,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
exclusive);
@@ -3664,22 +4725,22 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
*/
static void cursor_buffer_show(const GWL_Seat *seat)
{
- const GWL_Cursor *c = &seat->cursor;
+ const GWL_Cursor *cursor = &seat->cursor;
if (seat->wl_pointer) {
- const int scale = c->is_custom ? c->custom_scale : seat->pointer.theme_scale;
- const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale;
- const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale;
+ const int scale = cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale;
+ const int32_t hotspot_x = int32_t(cursor->wl_image.hotspot_x) / scale;
+ const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale;
if (seat->wl_pointer) {
wl_pointer_set_cursor(
- seat->wl_pointer, seat->pointer.serial, c->wl_surface, hotspot_x, hotspot_y);
+ seat->wl_pointer, seat->pointer.serial, cursor->wl_surface, hotspot_x, hotspot_y);
}
}
if (!seat->tablet_tools.empty()) {
- const int scale = c->is_custom ? c->custom_scale : seat->tablet.theme_scale;
- const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale;
- const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale;
+ const int scale = cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale;
+ const int32_t hotspot_x = int32_t(cursor->wl_image.hotspot_x) / scale;
+ const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale;
for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
@@ -3742,21 +4803,21 @@ static void cursor_buffer_set_surface_impl(const GWL_Seat *seat,
static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer)
{
- const GWL_Cursor *c = &seat->cursor;
+ const GWL_Cursor *cursor = &seat->cursor;
const wl_cursor_image *wl_image = &seat->cursor.wl_image;
- const bool visible = (c->visible && c->is_hardware);
+ const bool visible = (cursor->visible && cursor->is_hardware);
/* This is a requirement of WAYLAND, when this isn't the case,
* it causes Blender's window to close intermittently. */
if (seat->wl_pointer) {
const int scale = cursor_buffer_compatible_scale_from_image(
- wl_image, c->is_custom ? c->custom_scale : seat->pointer.theme_scale);
+ wl_image, cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale);
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
- cursor_buffer_set_surface_impl(seat, buffer, c->wl_surface, scale);
+ cursor_buffer_set_surface_impl(seat, buffer, cursor->wl_surface, scale);
wl_pointer_set_cursor(seat->wl_pointer,
seat->pointer.serial,
- visible ? c->wl_surface : nullptr,
+ visible ? cursor->wl_surface : nullptr,
hotspot_x,
hotspot_y);
}
@@ -3764,7 +4825,7 @@ static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer)
/* Set the cursor for all tablet tools as well. */
if (!seat->tablet_tools.empty()) {
const int scale = cursor_buffer_compatible_scale_from_image(
- wl_image, c->is_custom ? c->custom_scale : seat->tablet.theme_scale);
+ wl_image, cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale);
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
@@ -3851,31 +4912,31 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s
(*cursor_find).second;
GWL_Seat *seat = display_->seats[0];
- GWL_Cursor *c = &seat->cursor;
+ GWL_Cursor *cursor = &seat->cursor;
- if (!c->wl_theme) {
+ if (!cursor->wl_theme) {
/* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */
- c->wl_theme = wl_cursor_theme_load(
- c->theme_name.c_str(), c->size, display_->seats[0]->system->wl_shm());
+ cursor->wl_theme = wl_cursor_theme_load(
+ cursor->theme_name.c_str(), cursor->theme_size, wl_shm());
}
- wl_cursor *cursor = wl_cursor_theme_get_cursor(c->wl_theme, cursor_name);
+ wl_cursor *wl_cursor = wl_cursor_theme_get_cursor(cursor->wl_theme, cursor_name);
- if (!cursor) {
+ if (!wl_cursor) {
GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl);
return GHOST_kFailure;
}
- struct wl_cursor_image *image = cursor->images[0];
+ struct wl_cursor_image *image = wl_cursor->images[0];
struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
if (!buffer) {
return GHOST_kFailure;
}
- c->visible = true;
- c->is_custom = false;
- c->wl_buffer = buffer;
- c->wl_image = *image;
+ cursor->visible = true;
+ cursor->is_custom = false;
+ cursor->wl_buffer = buffer;
+ cursor->wl_image = *image;
cursor_buffer_set(seat, buffer);
@@ -4062,11 +5123,10 @@ static GWL_SeatStateGrab seat_grab_state_from_mode(const GHOST_TGrabCursorMode m
const bool use_software_confine)
{
/* Initialize all members. */
- const struct GWL_SeatStateGrab grab_state = {
- /* Warping happens to require software cursor which also hides. */
- .use_lock = ELEM(mode, GHOST_kGrabWrap, GHOST_kGrabHide) || use_software_confine,
- .use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false),
- };
+ GWL_SeatStateGrab grab_state;
+ /* Warping happens to require software cursor which also hides. */
+ grab_state.use_lock = ELEM(mode, GHOST_kGrabWrap, GHOST_kGrabHide) || use_software_confine;
+ grab_state.use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false);
return grab_state;
}
@@ -4140,6 +5200,16 @@ wl_compositor *GHOST_SystemWayland::wl_compositor()
return display_->wl_compositor;
}
+struct zwp_primary_selection_device_manager_v1 *GHOST_SystemWayland::wp_primary_selection_manager()
+{
+ return display_->wp_primary_selection_device_manager;
+}
+
+struct zwp_pointer_gestures_v1 *GHOST_SystemWayland::wp_pointer_gestures()
+{
+ return display_->wp_pointer_gestures;
+}
+
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor *GHOST_SystemWayland::libdecor_context()
@@ -4202,11 +5272,6 @@ GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *wl_surface)
* Functionality only used for the WAYLAND implementation.
* \{ */
-void GHOST_SystemWayland::clipboard_set(const std::string &clipboard)
-{
- clipboard_ = clipboard;
-}
-
void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface)
{
#define SURFACE_CLEAR_PTR(surface_test) \
@@ -4234,7 +5299,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
const int scale)
{
/* Ignore, if the required protocols are not supported. */
- if (UNLIKELY(!display_->relative_pointer_manager || !display_->pointer_constraints)) {
+ if (UNLIKELY(!display_->wp_relative_pointer_manager || !display_->wp_pointer_constraints)) {
return GHOST_kFailure;
}
@@ -4273,11 +5338,11 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
* in this case disable the current locks as it makes logic confusing,
* postpone changing the cursor to avoid flickering. */
if (!grab_state_next.use_lock) {
- if (seat->relative_pointer) {
- zwp_relative_pointer_v1_destroy(seat->relative_pointer);
- seat->relative_pointer = nullptr;
+ if (seat->wp_relative_pointer) {
+ zwp_relative_pointer_v1_destroy(seat->wp_relative_pointer);
+ seat->wp_relative_pointer = nullptr;
}
- if (seat->locked_pointer) {
+ if (seat->wp_locked_pointer) {
/* Potentially add a motion event so the application has updated X/Y coordinates. */
int32_t xy_motion[2] = {0, 0};
bool xy_motion_create_event = false;
@@ -4306,7 +5371,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
seat->pointer.xy[0] = xy_next[0];
seat->pointer.xy[1] = xy_next[1];
- zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, UNPACK2(xy_next));
+ zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer, UNPACK2(xy_next));
wl_surface_commit(wl_surface);
}
else if (mode_current == GHOST_kGrabHide) {
@@ -4316,7 +5381,8 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
wl_fixed_from_int(init_grab_xy[0]) / scale,
wl_fixed_from_int(init_grab_xy[1]) / scale,
};
- zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, UNPACK2(xy_next));
+ zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer,
+ UNPACK2(xy_next));
wl_surface_commit(wl_surface);
/* NOTE(@campbellbarton): The new cursor position is a hint,
@@ -4330,7 +5396,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
#ifdef USE_GNOME_CONFINE_HACK
else if (mode_current == GHOST_kGrabNormal) {
if (was_software_confine) {
- zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer,
+ zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer,
UNPACK2(seat->pointer.xy));
wl_surface_commit(wl_surface);
}
@@ -4346,15 +5412,15 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
GHOST_TABLET_DATA_NONE));
}
- zwp_locked_pointer_v1_destroy(seat->locked_pointer);
- seat->locked_pointer = nullptr;
+ zwp_locked_pointer_v1_destroy(seat->wp_locked_pointer);
+ seat->wp_locked_pointer = nullptr;
}
}
if (!grab_state_next.use_confine) {
- if (seat->confined_pointer) {
- zwp_confined_pointer_v1_destroy(seat->confined_pointer);
- seat->confined_pointer = nullptr;
+ if (seat->wp_confined_pointer) {
+ zwp_confined_pointer_v1_destroy(seat->wp_confined_pointer);
+ seat->wp_confined_pointer = nullptr;
}
}
@@ -4365,12 +5431,12 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
* possible to support #GHOST_kGrabWrap by pragmatically settings it's coordinates.
* An alternative could be to draw the cursor in software (and hide the real cursor),
* or just accept a locked cursor on WAYLAND. */
- seat->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
- display_->relative_pointer_manager, seat->wl_pointer);
+ seat->wp_relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
+ display_->wp_relative_pointer_manager, seat->wl_pointer);
zwp_relative_pointer_v1_add_listener(
- seat->relative_pointer, &relative_pointer_listener, seat);
- seat->locked_pointer = zwp_pointer_constraints_v1_lock_pointer(
- display_->pointer_constraints,
+ seat->wp_relative_pointer, &relative_pointer_listener, seat);
+ seat->wp_locked_pointer = zwp_pointer_constraints_v1_lock_pointer(
+ display_->wp_pointer_constraints,
wl_surface,
seat->wl_pointer,
nullptr,
@@ -4387,8 +5453,8 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
}
else if (grab_state_next.use_confine) {
if (!grab_state_prev.use_confine) {
- seat->confined_pointer = zwp_pointer_constraints_v1_confine_pointer(
- display_->pointer_constraints,
+ seat->wp_confined_pointer = zwp_pointer_constraints_v1_confine_pointer(
+ display_->wp_pointer_constraints,
wl_surface,
seat->wl_pointer,
nullptr,
@@ -4407,6 +5473,11 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
return GHOST_kSuccess;
}
+struct GWL_SimpleBuffer *GHOST_SystemWayland::clipboard_data(bool selection) const
+{
+ return selection ? &display_->clipboard_primary : &display_->clipboard;
+}
+
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
bool GHOST_SystemWayland::use_libdecor_runtime()
{
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index 5d2cfe45582..f08e9fdcf9c 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -88,7 +88,7 @@ class GHOST_SystemWayland : public GHOST_System {
~GHOST_SystemWayland() override;
- GHOST_TSuccess init();
+ GHOST_TSuccess init() override;
bool processEvents(bool waitForEvent) override;
@@ -128,7 +128,6 @@ class GHOST_SystemWayland : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
const bool is_dialog,
@@ -150,8 +149,8 @@ class GHOST_SystemWayland : public GHOST_System {
GHOST_TSuccess setCursorVisibility(bool visible);
- bool supportsCursorWarp();
- bool supportsWindowPosition();
+ bool supportsCursorWarp() override;
+ bool supportsWindowPosition() override;
bool getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode);
@@ -159,6 +158,8 @@ class GHOST_SystemWayland : public GHOST_System {
struct wl_display *wl_display();
struct wl_compositor *wl_compositor();
+ struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_manager();
+ struct zwp_pointer_gestures_v1 *wp_pointer_gestures();
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor *libdecor_context();
@@ -173,8 +174,6 @@ class GHOST_SystemWayland : public GHOST_System {
/* WAYLAND utility functions. */
- void clipboard_set(const std::string &clipboard);
-
/** Clear all references to this surface to prevent accessing NULL pointers. */
void window_surface_unref(const wl_surface *wl_surface);
@@ -186,11 +185,12 @@ class GHOST_SystemWayland : public GHOST_System {
wl_surface *wl_surface,
int scale);
+ struct GWL_SimpleBuffer *clipboard_data(bool selection) const;
+
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
static bool use_libdecor_runtime();
#endif
private:
struct GWL_Display *display_;
- std::string clipboard_;
};
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 667198241f0..54c892d296e 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -213,7 +213,6 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
const bool is_dialog,
@@ -227,7 +226,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
width,
height,
state,
- type,
+ glSettings.context_type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
false,
(GHOST_WindowWin32 *)parentWindow,
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index f5cd0055b34..98a7e5dfb35 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -103,7 +103,6 @@ class GHOST_SystemWin32 : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
- * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent window.
@@ -115,7 +114,6 @@ class GHOST_SystemWin32 : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 4523f6fa37c..5c89febe97c 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -308,7 +308,6 @@ void GHOST_SystemX11::getAllDisplayDimensions(uint32_t &width, uint32_t &height)
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
- * \param type: The type of drawing context installed in this window.
* \param glSettings: Misc OpenGL settings.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent window.
@@ -320,7 +319,6 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
const bool is_dialog,
@@ -341,7 +339,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
height,
state,
(GHOST_WindowX11 *)parentWindow,
- type,
+ glSettings.context_type,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
exclusive,
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 572be30174d..1f071da6da7 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -113,7 +113,6 @@ class GHOST_SystemX11 : public GHOST_System {
* \param width: The width the window.
* \param height: The height the window.
* \param state: The state of the window when opened.
- * \param type: The type of drawing context installed in this window.
* \param stereoVisual: Create a stereo visual for quad buffered stereo.
* \param exclusive: Use to show the window on top and ignore others (used full-screen).
* \param parentWindow: Parent (embedder) window.
@@ -125,7 +124,6 @@ class GHOST_SystemX11 : public GHOST_System {
uint32_t width,
uint32_t height,
GHOST_TWindowState state,
- GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const bool is_dialog = false,
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 737fd64bdf0..bc1f1e99a3a 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -803,10 +803,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type)
{
- if (type == GHOST_kDrawingContextTypeOpenGL) {
+ if (type == GHOST_kDrawingContextTypeOpenGL || type == GHOST_kDrawingContextTypeMetal) {
GHOST_Context *context = new GHOST_ContextCGL(
- m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView);
+ m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView, type);
if (context->initializeDrawingContext())
return context;
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index b29c5efd8d4..986e18d7a87 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -946,7 +946,12 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType
EGL_OPENGL_API);
}
- return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr;
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+
+ delete context;
+ return nullptr;
}
/** \} */
diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp
index 1891f1eca77..3c9206b2010 100644
--- a/intern/ghost/test/gears/GHOST_Test.cpp
+++ b/intern/ghost/test/gears/GHOST_Test.cpp
@@ -407,17 +407,12 @@ Application::Application(GHOST_ISystem *system)
stereo(false)
{
GHOST_GLSettings glSettings = {0};
+ glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
fApp = this;
// Create the main window
- m_mainWindow = system->createWindow("gears - main window",
- 10,
- 64,
- 320,
- 200,
- GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL,
- glSettings);
+ m_mainWindow = system->createWindow(
+ "gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
if (!m_mainWindow) {
std::cout << "could not create main window\n";
@@ -425,14 +420,8 @@ Application::Application(GHOST_ISystem *system)
}
// Create a secondary window
- m_secondaryWindow = system->createWindow("gears - secondary window",
- 340,
- 64,
- 320,
- 200,
- GHOST_kWindowStateNormal,
- GHOST_kDrawingContextTypeOpenGL,
- glSettings);
+ m_secondaryWindow = system->createWindow(
+ "gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, glSettings);
if (!m_secondaryWindow) {
std::cout << "could not create secondary window\n";
exit(-1);
diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt
index 1dddd70928a..920b8d5c542 100644
--- a/intern/opensubdiv/CMakeLists.txt
+++ b/intern/opensubdiv/CMakeLists.txt
@@ -81,12 +81,6 @@ if(WITH_OPENSUBDIV)
)
endif()
- opensubdiv_define_component(OPENSUBDIV_HAS_OPENMP)
- opensubdiv_define_component(OPENSUBDIV_HAS_OPENCL)
- opensubdiv_define_component(OPENSUBDIV_HAS_CUDA)
- opensubdiv_define_component(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK)
- opensubdiv_define_component(OPENSUBDIV_HAS_GLSL_COMPUTE)
-
if(WIN32)
add_definitions(-DNOMINMAX)
add_definitions(-D_USE_MATH_DEFINES)
diff --git a/intern/wayland_dynload/extern/wayland_dynload_client.h b/intern/wayland_dynload/extern/wayland_dynload_client.h
index 8e9dddd91a3..d80ef5c9f0c 100644
--- a/intern/wayland_dynload/extern/wayland_dynload_client.h
+++ b/intern/wayland_dynload/extern/wayland_dynload_client.h
@@ -41,6 +41,7 @@ WAYLAND_DYNLOAD_IFACE(wl_seat_interface)
WAYLAND_DYNLOAD_IFACE(wl_shm_interface)
WAYLAND_DYNLOAD_IFACE(wl_shm_pool_interface)
WAYLAND_DYNLOAD_IFACE(wl_surface_interface)
+WAYLAND_DYNLOAD_IFACE(wl_touch_interface)
#else
/* Header guard. */
diff --git a/make.bat b/make.bat
index ff8059b0754..0be70053ce1 100644
--- a/make.bat
+++ b/make.bat
@@ -62,9 +62,17 @@ if "%SVN_FIX%" == "1" (
)
if "%BUILD_UPDATE%" == "1" (
+ REM First see if the SVN libs are there and check them out if they are not.
call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd"
if errorlevel 1 goto EOF
-
+ REM Then update SVN platform libraries, since updating python while python is
+ REM running tends to be problematic. The python script that update_sources
+ REM calls later on may still try to switch branches and run into trouble,
+ REM but for *most* people this will side step the problem.
+ call "%BLENDER_DIR%\build_files\windows\svn_update.cmd"
+ REM Finally call the python script shared between all platforms that updates git
+ REM and does any other SVN work like update the tests or branch switches
+ REM if required.
call "%BLENDER_DIR%\build_files\windows\update_sources.cmd"
goto EOF
)
diff --git a/release/scripts/modules/gpu_extras/batch.py b/release/scripts/modules/gpu_extras/batch.py
index ba8e3879a8e..6c9ab52c1a3 100644
--- a/release/scripts/modules/gpu_extras/batch.py
+++ b/release/scripts/modules/gpu_extras/batch.py
@@ -34,13 +34,13 @@ def batch_for_shader(shader, type, content, *, indices=None):
return 'I32'
def recommended_attr_len(attr_name):
- item = content[attr_name][0]
attr_len = 1
try:
+ item = content[attr_name][0]
while True:
attr_len *= len(item)
item = item[0]
- except TypeError:
+ except (TypeError, IndexError):
pass
return attr_len
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index 7f6d0b1e9bf..5bd38acb19c 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -184,6 +184,7 @@ def write_sysinfo(filepath):
output.write("vendor:\t\t%r\n" % gpu.platform.vendor_get())
output.write("version:\t%r\n" % gpu.platform.version_get())
output.write("device type:\t%r\n" % gpu.platform.device_type_get())
+ output.write("backend type:\t%r\n" % gpu.platform.backend_type_get())
output.write("extensions:\n")
glext = sorted(gpu.capabilities.extensions_get())
diff --git a/release/scripts/startup/bl_ui/properties_data_curves.py b/release/scripts/startup/bl_ui/properties_data_curves.py
index ff0eabeb7d9..df80bdb4552 100644
--- a/release/scripts/startup/bl_ui/properties_data_curves.py
+++ b/release/scripts/startup/bl_ui/properties_data_curves.py
@@ -44,7 +44,13 @@ class DATA_PT_curves_surface(DataButtonsPanel, Panel):
layout.use_property_split = True
layout.prop(ob.data, "surface")
- layout.prop(ob.data, "surface_uv_map", text="UV Map")
+ has_surface = ob.data.surface is not None
+ if has_surface:
+ layout.prop_search(ob.data, "surface_uv_map", ob.data.surface.data, "uv_layers", text="UV Map")
+ else:
+ row = layout.row()
+ row.prop(ob.data, "surface_uv_map", text="UV Map")
+ row.enabled = has_surface
class CURVES_MT_add_attribute(Menu):
diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py
index ca0e698500e..61384f25afb 100644
--- a/release/scripts/startup/bl_ui/properties_output.py
+++ b/release/scripts/startup/bl_ui/properties_output.py
@@ -380,7 +380,14 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel):
layout = self.layout
ffmpeg = context.scene.render.ffmpeg
- needs_codec = ffmpeg.format in {'AVI', 'QUICKTIME', 'MKV', 'OGG', 'MPEG4', 'WEBM'}
+ needs_codec = ffmpeg.format in {
+ 'AVI',
+ 'QUICKTIME',
+ 'MKV',
+ 'OGG',
+ 'MPEG4',
+ 'WEBM'
+ }
if needs_codec:
layout.prop(ffmpeg, "codec")
@@ -391,7 +398,12 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel):
layout.prop(ffmpeg, "use_lossless_output")
# Output quality
- use_crf = needs_codec and ffmpeg.codec in {'H264', 'MPEG4', 'WEBM'}
+ use_crf = needs_codec and ffmpeg.codec in {
+ 'H264',
+ 'MPEG4',
+ 'WEBM',
+ 'AV1'
+ }
if use_crf:
layout.prop(ffmpeg, "constant_rate_factor")
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 92beba2c032..b16983c1492 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -3030,6 +3030,7 @@ class VIEW3D_MT_brush_paint_modes(Menu):
layout.prop(brush, "use_paint_vertex", text="Vertex Paint")
layout.prop(brush, "use_paint_weight", text="Weight Paint")
layout.prop(brush, "use_paint_image", text="Texture Paint")
+ layout.prop(brush, "use_paint_sculpt_curves", text="Sculpt Curves")
class VIEW3D_MT_paint_vertex(Menu):
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index dfe92f64341..0157f01a0e5 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -53,6 +53,8 @@ class VIEW3D_MT_brush_context_menu(Menu):
elif context.sculpt_object:
layout.prop_menu_enum(brush, "sculpt_tool")
layout.operator("brush.reset")
+ elif context.tool_settings.curves_sculpt:
+ layout.prop_menu_enum(brush, "curves_sculpt_tool")
class VIEW3D_MT_brush_gpencil_context_menu(Menu):
@@ -82,22 +84,6 @@ class VIEW3D_MT_brush_gpencil_context_menu(Menu):
layout.operator("gpencil.brush_reset_all")
-class VIEW3D_MT_brush_context_menu_paint_modes(Menu):
- bl_label = "Enabled Modes"
-
- def draw(self, context):
- layout = self.layout
-
- settings = UnifiedPaintPanel.paint_settings(context)
- brush = settings.brush
-
- layout.prop(brush, "use_paint_sculpt", text="Sculpt")
- layout.prop(brush, "use_paint_uv_sculpt", text="UV Sculpt")
- layout.prop(brush, "use_paint_vertex", text="Vertex Paint")
- layout.prop(brush, "use_paint_weight", text="Weight Paint")
- layout.prop(brush, "use_paint_image", text="Texture Paint")
-
-
class View3DPanel:
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -2448,7 +2434,6 @@ class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel):
classes = (
VIEW3D_MT_brush_context_menu,
VIEW3D_MT_brush_gpencil_context_menu,
- VIEW3D_MT_brush_context_menu_paint_modes,
VIEW3D_PT_tools_object_options,
VIEW3D_PT_tools_object_options_transform,
VIEW3D_PT_tools_meshedit_options,
diff --git a/source/blender/blenkernel/BKE_attribute.hh b/source/blender/blenkernel/BKE_attribute.hh
index 7b13b8a2b09..a4f9d73c31e 100644
--- a/source/blender/blenkernel/BKE_attribute.hh
+++ b/source/blender/blenkernel/BKE_attribute.hh
@@ -793,7 +793,9 @@ class CustomDataAttributes {
~CustomDataAttributes();
CustomDataAttributes(const CustomDataAttributes &other);
CustomDataAttributes(CustomDataAttributes &&other);
+
CustomDataAttributes &operator=(const CustomDataAttributes &other);
+ CustomDataAttributes &operator=(CustomDataAttributes &&other);
void reallocate(int size);
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 96df8f7a443..806fff2099e 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -25,7 +25,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 4
+#define BLENDER_FILE_SUBVERSION 5
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 38bf30a773c..ed75a69b81f 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -130,7 +130,7 @@ float BKE_brush_sample_masktex(const struct Scene *scene,
* Get the mask texture for this given object mode.
*
* This is preferred above using mtex/mask_mtex attributes directly as due to legacy these
- * attributes got switched in sculpt mode.
+ * attributes got switched in sculpt mode.
*/
const struct MTex *BKE_brush_mask_texture_get(const struct Brush *brush,
const eObjectMode object_mode);
diff --git a/source/blender/blenkernel/BKE_instances.hh b/source/blender/blenkernel/BKE_instances.hh
index 6502fefec88..f17ebba0dfa 100644
--- a/source/blender/blenkernel/BKE_instances.hh
+++ b/source/blender/blenkernel/BKE_instances.hh
@@ -5,7 +5,7 @@
/** \file
* \ingroup bke
*
- * #Instances is a container for geometry instances. It fullfills some key requirements:
+ * #Instances is a container for geometry instances. It fulfills some key requirements:
* - Support nested instances.
* - Support instance attributes.
* - Support referencing different kinds of instances (objects, collections, geometry sets).
diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h
index 736f7548bb4..cfe246eb470 100644
--- a/source/blender/blenkernel/BKE_writeffmpeg.h
+++ b/source/blender/blenkernel/BKE_writeffmpeg.h
@@ -27,6 +27,7 @@ enum {
FFMPEG_OGG = 10,
FFMPEG_INVALID = 11,
FFMPEG_WEBM = 12,
+ FFMPEG_AV1 = 13,
};
enum {
@@ -38,6 +39,7 @@ enum {
FFMPEG_PRESET_H264 = 5,
FFMPEG_PRESET_THEORA = 6,
FFMPEG_PRESET_XVID = 7,
+ FFMPEG_PRESET_AV1 = 8,
};
struct RenderData;
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index b86353bdb74..544427cfdd3 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -642,15 +642,26 @@ CustomDataAttributes::CustomDataAttributes(CustomDataAttributes &&other)
size_ = other.size_;
data = other.data;
CustomData_reset(&other.data);
+ other.size_ = 0;
}
CustomDataAttributes &CustomDataAttributes::operator=(const CustomDataAttributes &other)
{
- if (this != &other) {
- CustomData_copy(&other.data, &data, CD_MASK_ALL, CD_DUPLICATE, other.size_);
- size_ = other.size_;
+ if (this == &other) {
+ return *this;
}
+ this->~CustomDataAttributes();
+ new (this) CustomDataAttributes(other);
+ return *this;
+}
+CustomDataAttributes &CustomDataAttributes::operator=(CustomDataAttributes &&other)
+{
+ if (this == &other) {
+ return *this;
+ }
+ this->~CustomDataAttributes();
+ new (this) CustomDataAttributes(std::move(other));
return *this;
}
diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c
index 394469e19a4..4dd225c09ec 100644
--- a/source/blender/blenkernel/intern/blendfile_link_append.c
+++ b/source/blender/blenkernel/intern/blendfile_link_append.c
@@ -1494,6 +1494,7 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
* code is wrong, we need to redo it here after adding them back to main. */
BKE_main_id_refcount_recompute(bmain, false);
+ BKE_layer_collection_resync_forbid();
/* Note that in reload case, we also want to replace indirect usages. */
const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE |
(do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
@@ -1523,6 +1524,8 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
id_us_plus_no_lib(&old_key->id);
}
}
+ BKE_layer_collection_resync_allow();
+ BKE_main_collection_sync_remap(bmain);
BKE_main_unlock(bmain);
@@ -1614,6 +1617,9 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
(id->tag & LIB_TAG_PRE_EXISTING) == 0) {
continue;
}
+ if ((id->override_library->reference->tag & LIB_TAG_MISSING) == 0) {
+ id->tag &= ~LIB_TAG_MISSING;
+ }
if ((id->override_library->reference->tag & LIB_TAG_PRE_EXISTING) == 0) {
BKE_lib_override_library_update(bmain, id);
}
diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc
index 01be22a57b0..72e53023d6d 100644
--- a/source/blender/blenkernel/intern/curves.cc
+++ b/source/blender/blenkernel/intern/curves.cc
@@ -287,7 +287,10 @@ static void curves_evaluate_modifiers(struct Depsgraph *depsgraph,
{
/* Modifier evaluation modes. */
const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
- const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
+ int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
+ if (BKE_object_is_in_editmode(object)) {
+ required_mode = (ModifierMode)(int(required_mode) | eModifierMode_Editmode);
+ }
ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 29f8d62545f..7c338480c71 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -9,6 +9,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array_utils.hh"
#include "BLI_bounds.hh"
#include "BLI_index_mask_ops.hh"
#include "BLI_length_parameterize.hh"
@@ -1111,21 +1112,11 @@ static void copy_between_buffers(const CPPType &type,
src_range.size());
}
-template<typename T>
-static void copy_with_map(const Span<T> src, const Span<int> map, MutableSpan<T> dst)
-{
- threading::parallel_for(map.index_range(), 1024, [&](const IndexRange range) {
- for (const int i : range) {
- dst[i] = src[map[i]];
- }
- });
-}
-
static void copy_with_map(const GSpan src, const Span<int> map, GMutableSpan dst)
{
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
using T = decltype(dummy);
- copy_with_map(src.typed<T>(), map, dst.typed<T>());
+ array_utils::gather(src.typed<T>(), map, dst.typed<T>());
});
}
@@ -1233,6 +1224,10 @@ static CurvesGeometry copy_with_removed_points(const CurvesGeometry &curves,
attribute.dst.finish();
}
+ if (new_curves.curves_num() != curves.curves_num()) {
+ new_curves.remove_attributes_based_on_types();
+ }
+
return new_curves;
}
@@ -1338,6 +1333,8 @@ static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
attribute.dst.finish();
}
+ new_curves.remove_attributes_based_on_types();
+
return new_curves;
}
diff --git a/source/blender/blenkernel/intern/image_format.cc b/source/blender/blenkernel/intern/image_format.cc
index 8d1aeac76fb..5b861eff166 100644
--- a/source/blender/blenkernel/intern/image_format.cc
+++ b/source/blender/blenkernel/intern/image_format.cc
@@ -201,6 +201,7 @@ bool BKE_imtype_is_movie(const char imtype)
case R_IMF_IMTYPE_H264:
case R_IMF_IMTYPE_THEORA:
case R_IMF_IMTYPE_XVID:
+ case R_IMF_IMTYPE_AV1:
return true;
}
return false;
@@ -433,7 +434,8 @@ static bool do_add_image_extension(char *string,
R_IMF_IMTYPE_FFMPEG,
R_IMF_IMTYPE_H264,
R_IMF_IMTYPE_THEORA,
- R_IMF_IMTYPE_XVID)) {
+ R_IMF_IMTYPE_XVID,
+ R_IMF_IMTYPE_AV1)) {
if (!BLI_path_extension_check(string, extension_test = ".png")) {
extension = extension_test;
}
@@ -627,7 +629,8 @@ void BKE_image_format_to_imbuf(ImBuf *ibuf, const ImageFormatData *imf)
R_IMF_IMTYPE_FFMPEG,
R_IMF_IMTYPE_H264,
R_IMF_IMTYPE_THEORA,
- R_IMF_IMTYPE_XVID)) {
+ R_IMF_IMTYPE_XVID,
+ R_IMF_IMTYPE_AV1)) {
ibuf->ftype = IMB_FTYPE_PNG;
if (imtype == R_IMF_IMTYPE_PNG) {
diff --git a/source/blender/blenkernel/intern/image_save.cc b/source/blender/blenkernel/intern/image_save.cc
index 4e47e71fb2b..003211e6288 100644
--- a/source/blender/blenkernel/intern/image_save.cc
+++ b/source/blender/blenkernel/intern/image_save.cc
@@ -968,6 +968,7 @@ bool BKE_image_render_write(ReportList *reports,
/* optional preview images for exr */
if (ok && (image_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
image_format.imtype = R_IMF_IMTYPE_JPEG90;
+ image_format.depth = R_IMF_CHAN_DEPTH_8;
if (BLI_path_extension_check(filepath, ".exr")) {
filepath[strlen(filepath) - 4] = 0;
@@ -1025,6 +1026,7 @@ bool BKE_image_render_write(ReportList *reports,
/* optional preview images for exr */
if (ok && is_exr_rr && (image_format.flag & R_IMF_FLAG_PREVIEW_JPG)) {
image_format.imtype = R_IMF_IMTYPE_JPEG90;
+ image_format.depth = R_IMF_CHAN_DEPTH_8;
if (BLI_path_extension_check(filepath, ".exr")) {
filepath[strlen(filepath) - 4] = 0;
diff --git a/source/blender/blenkernel/intern/instances.cc b/source/blender/blenkernel/intern/instances.cc
index dd759453630..4675562e927 100644
--- a/source/blender/blenkernel/intern/instances.cc
+++ b/source/blender/blenkernel/intern/instances.cc
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "BLI_array_utils.hh"
#include "BLI_cpp_type_make.hh"
#include "BLI_rand.hh"
#include "BLI_task.hh"
@@ -107,18 +108,6 @@ blender::Span<InstanceReference> Instances::references() const
return references_;
}
-template<typename T>
-static void copy_data_based_on_mask(Span<T> src, MutableSpan<T> dst, IndexMask mask)
-{
- BLI_assert(src.data() != dst.data());
- using namespace blender;
- threading::parallel_for(mask.index_range(), 1024, [&](IndexRange range) {
- for (const int i : range) {
- dst[i] = src[mask[i]];
- }
- });
-}
-
void Instances::remove(const IndexMask mask)
{
using namespace blender;
@@ -129,11 +118,14 @@ void Instances::remove(const IndexMask mask)
return;
}
+ const Span<int> old_handles = this->reference_handles();
Vector<int> new_handles(mask.size());
- copy_data_based_on_mask<int>(this->reference_handles(), new_handles, mask);
+ array_utils::gather(old_handles, mask.indices(), new_handles.as_mutable_span());
reference_handles_ = std::move(new_handles);
+
+ const Span<float4x4> old_tansforms = this->transforms();
Vector<float4x4> new_transforms(mask.size());
- copy_data_based_on_mask<float4x4>(this->transforms(), new_transforms, mask);
+ array_utils::gather(old_tansforms, mask.indices(), new_transforms.as_mutable_span());
transforms_ = std::move(new_transforms);
const bke::CustomDataAttributes &src_attributes = attributes_;
@@ -150,11 +142,8 @@ void Instances::remove(const IndexMask mask)
GSpan src = *src_attributes.get_for_read(id);
dst_attributes.create(id, meta_data.data_type);
GMutableSpan dst = *dst_attributes.get_for_write(id);
+ array_utils::gather(src, mask.indices(), dst);
- attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
- using T = decltype(dummy);
- copy_data_based_on_mask<T>(src.typed<T>(), dst.typed<T>(), mask);
- });
return true;
},
ATTR_DOMAIN_INSTANCE);
@@ -266,7 +255,7 @@ bool Instances::owns_direct_data() const
void Instances::ensure_owns_direct_data()
{
for (const InstanceReference &const_reference : references_) {
- /* Const cast is fine because we are not changing anything that would change the hash of the
+ /* `const` cast is fine because we are not changing anything that would change the hash of the
* reference. */
InstanceReference &reference = const_cast<InstanceReference &>(const_reference);
reference.ensure_owns_direct_data();
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
index f4f5ca7a1d7..1a80376f482 100644
--- a/source/blender/blenkernel/intern/lib_id_delete.c
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -16,6 +16,7 @@
#include "BLI_utildefines.h"
+#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BKE_anim_data.h"
@@ -23,10 +24,10 @@
#include "BKE_idprop.h"
#include "BKE_idtype.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_lib_remap.h"
-#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_main_namemap.h"
@@ -202,7 +203,6 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
{
const int tag = LIB_TAG_DOIT;
ListBase *lbarray[INDEX_ID_MAX];
- Link dummy_link = {0};
int base_count, i;
/* Used by batch tagged deletion, when we call BKE_id_free then, id is no more in Main database,
@@ -217,6 +217,9 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
BKE_main_lock(bmain);
if (do_tagged_deletion) {
+ struct IDRemapper *id_remapper = BKE_id_remapper_create();
+ BKE_layer_collection_resync_forbid();
+
/* Main idea of batch deletion is to remove all IDs to be deleted from Main database.
* This means that we won't have to loop over all deleted IDs to remove usages
* of other deleted IDs.
@@ -227,7 +230,6 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
bool keep_looping = true;
while (keep_looping) {
ID *id, *id_next;
- ID *last_remapped_id = tagged_deleted_ids.last;
keep_looping = false;
/* First tag and remove from Main all datablocks directly from target lib.
@@ -243,6 +245,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
BLI_remlink(lb, id);
BKE_main_namemap_remove_name(bmain, id, id->name + 2);
BLI_addtail(&tagged_deleted_ids, id);
+ BKE_id_remapper_add(id_remapper, id, NULL);
/* Do not tag as no_main now, we want to unlink it first (lower-level ID management
* code has some specific handling of 'no main' IDs that would be a problem in that
* case). */
@@ -251,33 +254,38 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
}
}
}
- if (last_remapped_id == NULL) {
- dummy_link.next = tagged_deleted_ids.first;
- last_remapped_id = (ID *)(&dummy_link);
- }
- for (id = last_remapped_id->next; id; id = id->next) {
- /* Will tag 'never NULL' users of this ID too.
- *
- * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
- * links, this can lead to nasty crashing here in second, actual deleting loop.
- * Also, this will also flag users of deleted data that cannot be unlinked
- * (object using deleted obdata, etc.), so that they also get deleted. */
- BKE_libblock_remap_locked(bmain,
- id,
- NULL,
- (ID_REMAP_FLAG_NEVER_NULL_USAGE |
- ID_REMAP_FORCE_NEVER_NULL_USAGE |
- ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS));
- /* Since we removed ID from Main,
- * we also need to unlink its own other IDs usages ourself. */
- BKE_libblock_relink_ex(
- bmain,
- id,
- NULL,
- NULL,
- (ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | ID_REMAP_SKIP_USER_CLEAR));
- }
+
+ /* Will tag 'never NULL' users of this ID too.
+ *
+ * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
+ * links, this can lead to nasty crashing here in second, actual deleting loop.
+ * Also, this will also flag users of deleted data that cannot be unlinked
+ * (object using deleted obdata, etc.), so that they also get deleted. */
+ BKE_libblock_remap_multiple_locked(bmain,
+ id_remapper,
+ ID_REMAP_FLAG_NEVER_NULL_USAGE |
+ ID_REMAP_FORCE_NEVER_NULL_USAGE |
+ ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS);
+ BKE_id_remapper_clear(id_remapper);
+ }
+
+ /* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */
+ LinkNode *cleanup_ids = NULL;
+ for (ID *id = tagged_deleted_ids.first; id; id = id->next) {
+ BLI_linklist_prepend(&cleanup_ids, id);
}
+ BKE_libblock_relink_multiple(bmain,
+ cleanup_ids,
+ ID_REMAP_TYPE_CLEANUP,
+ id_remapper,
+ ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS |
+ ID_REMAP_SKIP_USER_CLEAR);
+
+ BKE_id_remapper_free(id_remapper);
+ BLI_linklist_free(cleanup_ids, NULL);
+
+ BKE_layer_collection_resync_allow();
+ BKE_main_collection_sync_remap(bmain);
/* Now we can safely mark that ID as not being in Main database anymore. */
/* NOTE: This needs to be done in a separate loop than above, otherwise some user-counts of
@@ -285,6 +293,10 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
* is never affected). */
for (ID *id = tagged_deleted_ids.first; id; id = id->next) {
id->tag |= LIB_TAG_NO_MAIN;
+ /* Usercount needs to be reset artificially, since some usages may not be cleared in batch
+ * deletion (typically, if one deleted ID uses another deleted ID, this may not be cleared by
+ * remapping code, depending on order in which these are handled). */
+ id->us = ID_FAKE_USERS(id);
}
}
else {
diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc
index 027423f5774..784d35a8d65 100644
--- a/source/blender/blenkernel/intern/mesh_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_convert.cc
@@ -1313,6 +1313,7 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
CustomData_duplicate_referenced_layers(&mesh_src->pdata, mesh_src->totpoly);
CustomData_duplicate_referenced_layers(&mesh_src->ldata, mesh_src->totloop);
+ const bool verts_num_changed = mesh_dst->totvert != mesh_src->totvert;
mesh_dst->totvert = mesh_src->totvert;
mesh_dst->totedge = mesh_src->totedge;
mesh_dst->totpoly = mesh_src->totpoly;
@@ -1339,11 +1340,10 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
const int uid_active = ob ? find_object_active_key_uid(*key_dst, *ob) : -1;
move_shapekey_layers_to_keyblocks(*mesh_dst, mesh_src->vdata, *key_dst, uid_active);
}
- else if (mesh_src->totvert != mesh_dst->totvert) {
- CLOG_ERROR(&LOG, "Mesh in Main '%s' lost shape keys", mesh_src->id.name);
- if (mesh_src->key) {
- id_us_min(&mesh_src->key->id);
- }
+ else if (verts_num_changed) {
+ CLOG_WARN(&LOG, "Shape key data lost when replacing mesh '%s' in Main", mesh_src->id.name);
+ id_us_min(&mesh_dst->key->id);
+ mesh_dst->key = nullptr;
}
}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index ba63cdff917..24663d6db05 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -1918,7 +1918,7 @@ bool BKE_nla_action_stash(AnimData *adt, const bool is_liboverride)
* NOTE: this must be done *after* adding the strip to the track, or else
* the strip locking will prevent the strip from getting added
*/
- nlt->flag = (NLATRACK_MUTED | NLATRACK_PROTECTED);
+ nlt->flag |= (NLATRACK_MUTED | NLATRACK_PROTECTED);
strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
/* also mark the strip for auto syncing the length, so that the strips accurately
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index 2d949fb5c65..d98f5e85028 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -1902,6 +1902,7 @@ bool BKE_object_is_in_editmode(const Object *ob)
/* Grease Pencil object has no edit mode data. */
return GPENCIL_EDIT_MODE((bGPdata *)ob->data);
case OB_CURVES:
+ /* Curves object has no edit mode data. */
return ob->mode == OB_MODE_EDIT;
default:
return false;
diff --git a/source/blender/blenkernel/intern/object_update.cc b/source/blender/blenkernel/intern/object_update.cc
index ceef6404bf0..e53090bcffe 100644
--- a/source/blender/blenkernel/intern/object_update.cc
+++ b/source/blender/blenkernel/intern/object_update.cc
@@ -292,6 +292,8 @@ void BKE_object_batch_cache_dirty_tag(Object *ob)
BKE_lattice_batch_cache_dirty_tag((struct Lattice *)ob->data, BKE_LATTICE_BATCH_DIRTY_ALL);
break;
case OB_CURVES_LEGACY:
+ case OB_SURF:
+ case OB_FONT:
BKE_curve_batch_cache_dirty_tag((struct Curve *)ob->data, BKE_CURVE_BATCH_DIRTY_ALL);
break;
case OB_MBALL: {
diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc
index 13243925b28..408cd117e32 100644
--- a/source/blender/blenkernel/intern/paint.cc
+++ b/source/blender/blenkernel/intern/paint.cc
@@ -1043,6 +1043,8 @@ eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode)
return OB_MODE_TEXTURE_PAINT;
case PAINT_MODE_SCULPT_UV:
return OB_MODE_EDIT;
+ case PAINT_MODE_SCULPT_CURVES:
+ return OB_MODE_SCULPT_CURVES;
case PAINT_MODE_INVALID:
default:
return OB_MODE_OBJECT;
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index 7c54b4d3f2f..e81657f9ef0 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -445,7 +445,7 @@ struct VolumeGrid {
* may actually be loaded by another user while this is false. But only after
* calling load() and is_loaded changes to true is it safe to access.
*
- * Const write access to this must be protected by `entry->mutex`.
+ * `const` write access to this must be protected by `entry->mutex`.
*/
mutable bool is_loaded;
};
@@ -480,7 +480,7 @@ struct VolumeGridVector : public std::list<VolumeGrid> {
metadata.reset();
}
- /* Mutex for file loading of grids list. Const write access to the fields after this must be
+ /* Mutex for file loading of grids list. `const` write access to the fields after this must be
* protected by locking with this mutex. */
mutable std::mutex mutex;
/* Absolute file path that grids have been loaded from. */
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index dbdf8cc395d..de2e196c163 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -122,7 +122,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
R_IMF_IMTYPE_FFMPEG,
R_IMF_IMTYPE_H264,
R_IMF_IMTYPE_XVID,
- R_IMF_IMTYPE_THEORA)) {
+ R_IMF_IMTYPE_THEORA,
+ R_IMF_IMTYPE_AV1)) {
mh.start_movie = BKE_ffmpeg_start;
mh.append_movie = BKE_ffmpeg_append;
mh.end_movie = BKE_ffmpeg_end;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 99df07b6105..0d3a790ba00 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -299,6 +299,10 @@ static const char **get_file_extensions(int format)
static const char *rv[] = {".webm", NULL};
return rv;
}
+ case FFMPEG_AV1: {
+ static const char *rv[] = {".mp4", ".mkv", NULL};
+ return rv;
+ }
default:
return NULL;
}
@@ -455,6 +459,204 @@ static AVRational calc_time_base(uint den, double num, int codec_id)
return time_base;
}
+static const AVCodec *get_av1_encoder(
+ FFMpegContext *context, RenderData *rd, AVDictionary **opts, int rectx, int recty)
+{
+ /* There are three possible encoders for AV1: libaom-av1, librav1e, and libsvtav1. librav1e tends
+ * to give the best compression quality while libsvtav1 tends to be the fastest encoder. One of
+ * each will be picked based on the preset setting, and if a particular encoder is not available,
+ * then use the default returned by FFMpeg. */
+ const AVCodec *codec = NULL;
+ switch (context->ffmpeg_preset) {
+ case FFM_PRESET_BEST:
+ /* Default to libaom-av1 for BEST preset due to it performing better than rav1e in terms of
+ * video quality (VMAF scores). Fallback to rav1e if libaom-av1 isn't available. */
+ codec = avcodec_find_encoder_by_name("libaom-av1");
+ if (!codec) {
+ codec = avcodec_find_encoder_by_name("librav1e");
+ }
+ break;
+ case FFM_PRESET_REALTIME:
+ codec = avcodec_find_encoder_by_name("libsvtav1");
+ break;
+ case FFM_PRESET_GOOD:
+ default:
+ codec = avcodec_find_encoder_by_name("libaom-av1");
+ break;
+ }
+
+ /* Use the default AV1 encoder if the specified encoder wasn't found. */
+ if (!codec) {
+ codec = avcodec_find_encoder(AV_CODEC_ID_AV1);
+ }
+
+ /* Apply AV1 encoder specific settings. */
+ if (codec) {
+ if (strcmp(codec->name, "librav1e") == 0) {
+ /* Set "tiles" to 8 to enable multi-threaded encoding. */
+ if (rd->threads > 8) {
+ ffmpeg_dict_set_int(opts, "tiles", rd->threads);
+ }
+ else {
+ ffmpeg_dict_set_int(opts, "tiles", 8);
+ }
+
+ /* Use a reasonable speed setting based on preset. Speed ranges from 0-10.
+ * Must check context->ffmpeg_preset again in case this encoder was selected due to the
+ * absence of another. */
+ switch (context->ffmpeg_preset) {
+ case FFM_PRESET_BEST:
+ ffmpeg_dict_set_int(opts, "speed", 4);
+ break;
+ case FFM_PRESET_REALTIME:
+ ffmpeg_dict_set_int(opts, "speed", 10);
+ break;
+ case FFM_PRESET_GOOD:
+ default:
+ ffmpeg_dict_set_int(opts, "speed", 6);
+ break;
+ }
+ if (context->ffmpeg_crf >= 0) {
+ /* librav1e does not use -crf, but uses -qp in the range of 0-255. Calculates the roughly
+ * equivalent float, and truncates it to an integer. */
+ unsigned int qp_value = ((float)context->ffmpeg_crf) * 255.0F / 51.0F;
+ if (qp_value > 255) {
+ qp_value = 255;
+ }
+ ffmpeg_dict_set_int(opts, "qp", qp_value);
+ }
+ /* Set gop_size as rav1e's "--keyint". */
+ char buffer[64];
+ BLI_snprintf(buffer, sizeof(buffer), "keyint=%d", context->ffmpeg_gop_size);
+ av_dict_set(opts, "rav1e-params", buffer, 0);
+ }
+ else if (strcmp(codec->name, "libsvtav1") == 0) {
+ /* Set preset value based on ffmpeg_preset.
+ * Must check context->ffmpeg_preset again in case this encoder was selected due to the
+ * absence of another. */
+ switch (context->ffmpeg_preset) {
+ case FFM_PRESET_REALTIME:
+ ffmpeg_dict_set_int(opts, "preset", 8);
+ break;
+ case FFM_PRESET_BEST:
+ ffmpeg_dict_set_int(opts, "preset", 3);
+ break;
+ case FFM_PRESET_GOOD:
+ default:
+ ffmpeg_dict_set_int(opts, "preset", 5);
+ break;
+ }
+ if (context->ffmpeg_crf >= 0) {
+ /* libsvtav1 does not support crf until FFmpeg builds since 2022-02-24, use qp as fallback.
+ */
+ ffmpeg_dict_set_int(opts, "qp", context->ffmpeg_crf);
+ }
+ }
+ else if (strcmp(codec->name, "libaom-av1") == 0) {
+ /* Speed up libaom-av1 encoding by enabling multithreading and setting tiles. */
+ ffmpeg_dict_set_int(opts, "row-mt", 1);
+ const char *tiles_string = NULL;
+ bool tiles_string_is_dynamic = false;
+ if (rd->threads > 0) {
+ /* See if threads is a square. */
+ int threads_sqrt = sqrtf(rd->threads);
+ if (threads_sqrt < 4) {
+ /* Ensure a default minimum. */
+ threads_sqrt = 4;
+ }
+ if (is_power_of_2_i(threads_sqrt) && threads_sqrt * threads_sqrt == rd->threads) {
+ /* Is a square num, therefore just do "sqrt x sqrt" for tiles parameter. */
+ int digits = 0;
+ for (int t_sqrt_copy = threads_sqrt; t_sqrt_copy > 0; t_sqrt_copy /= 10) {
+ ++digits;
+ }
+ /* A char array need only an alignment of 1. */
+ char *tiles_string_mut = (char *)calloc(digits * 2 + 2, 1);
+ BLI_snprintf(tiles_string_mut, digits * 2 + 2, "%dx%d", threads_sqrt, threads_sqrt);
+ tiles_string_is_dynamic = true;
+ tiles_string = tiles_string_mut;
+ }
+ else {
+ /* Is not a square num, set greater side based on longer side, or use a square if both
+ sides are equal. */
+ int sqrt_p2 = power_of_2_min_i(threads_sqrt);
+ if (sqrt_p2 < 2) {
+ /* Ensure a default minimum. */
+ sqrt_p2 = 2;
+ }
+ int sqrt_p2_next = power_of_2_min_i((int)rd->threads / sqrt_p2);
+ if (sqrt_p2_next < 1) {
+ sqrt_p2_next = 1;
+ }
+ if (sqrt_p2 > sqrt_p2_next) {
+ /* Ensure sqrt_p2_next is greater or equal to sqrt_p2. */
+ int temp = sqrt_p2;
+ sqrt_p2 = sqrt_p2_next;
+ sqrt_p2_next = temp;
+ }
+ int combined_digits = 0;
+ for (int sqrt_p2_copy = sqrt_p2; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) {
+ ++combined_digits;
+ }
+ for (int sqrt_p2_copy = sqrt_p2_next; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) {
+ ++combined_digits;
+ }
+ /* A char array need only an alignment of 1. */
+ char *tiles_string_mut = (char *)calloc(combined_digits + 2, 1);
+ if (rectx > recty) {
+ BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2_next, sqrt_p2);
+ }
+ else if (rectx < recty) {
+ BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2_next);
+ }
+ else {
+ BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2);
+ }
+ tiles_string_is_dynamic = true;
+ tiles_string = tiles_string_mut;
+ }
+ }
+ else {
+ /* Thread count unknown, default to 8. */
+ if (rectx > recty) {
+ tiles_string = "4x2";
+ }
+ else if (rectx < recty) {
+ tiles_string = "2x4";
+ }
+ else {
+ tiles_string = "2x2";
+ }
+ }
+ av_dict_set(opts, "tiles", tiles_string, 0);
+ if (tiles_string_is_dynamic) {
+ free((void *)tiles_string);
+ }
+ /* libaom-av1 uses "cpu-used" instead of "preset" for defining compression quality.
+ * This value is in a range from 0-8. 0 and 8 are extremes, but we will allow 8.
+ * Must check context->ffmpeg_preset again in case this encoder was selected due to the
+ * absence of another. */
+ switch (context->ffmpeg_preset) {
+ case FFM_PRESET_REALTIME:
+ ffmpeg_dict_set_int(opts, "cpu-used", 8);
+ break;
+ case FFM_PRESET_BEST:
+ ffmpeg_dict_set_int(opts, "cpu-used", 4);
+ break;
+ case FFM_PRESET_GOOD:
+ default:
+ ffmpeg_dict_set_int(opts, "cpu-used", 6);
+ break;
+ }
+
+ /* CRF related settings is similar to H264 for libaom-av1, so we will rely on those settings
+ * applied later. */
+ }
+ }
+
+ return codec;
+}
+
/* prepare a video stream for the output file */
static AVStream *alloc_video_stream(FFMpegContext *context,
@@ -480,7 +682,14 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
/* Set up the codec context */
- codec = avcodec_find_encoder(codec_id);
+ if (codec_id == AV_CODEC_ID_AV1) {
+ /* Use get_av1_encoder() to get the ideal (hopefully) encoder for AV1 based
+ * on given parameters, and also set up opts. */
+ codec = get_av1_encoder(context, rd, &opts, rectx, recty);
+ }
+ else {
+ codec = avcodec_find_encoder(codec_id);
+ }
if (!codec) {
fprintf(stderr, "Couldn't find valid video codec\n");
context->video_codec = NULL;
@@ -568,7 +777,9 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
default:
printf("Unknown preset number %i, ignoring.\n", context->ffmpeg_preset);
}
- if (preset_name != NULL) {
+ /* "codec_id != AV_CODEC_ID_AV1" is required due to "preset" already being set by an AV1 codec.
+ */
+ if (preset_name != NULL && codec_id != AV_CODEC_ID_AV1) {
av_dict_set(&opts, "preset", preset_name, 0);
}
if (deadline_name != NULL) {
@@ -951,6 +1162,9 @@ static int start_ffmpeg_impl(FFMpegContext *context,
case FFMPEG_FLV:
video_codec = AV_CODEC_ID_FLV1;
break;
+ case FFMPEG_AV1:
+ video_codec = AV_CODEC_ID_AV1;
+ break;
default:
/* These containers are not restricted to any specific codec types.
* Currently we expect these to be .avi, .mov, .mkv, and .mp4.
@@ -1482,6 +1696,18 @@ void BKE_ffmpeg_preset_set(RenderData *rd, int preset)
rd->ffcodecdata.mux_packet_size = 2048;
rd->ffcodecdata.mux_rate = 10080000;
break;
+ case FFMPEG_PRESET_AV1:
+ rd->ffcodecdata.type = FFMPEG_AV1;
+ rd->ffcodecdata.codec = AV_CODEC_ID_AV1;
+ rd->ffcodecdata.video_bitrate = 6000;
+ rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15;
+ rd->ffcodecdata.rc_max_rate = 9000;
+ rd->ffcodecdata.rc_min_rate = 0;
+ rd->ffcodecdata.rc_buffer_size = 224 * 8;
+ rd->ffcodecdata.mux_packet_size = 2048;
+ rd->ffcodecdata.mux_rate = 10080000;
+
+ break;
}
}
@@ -1521,6 +1747,12 @@ void BKE_ffmpeg_image_type_verify(RenderData *rd, const ImageFormatData *imf)
audio = 1;
}
}
+ else if (imf->imtype == R_IMF_IMTYPE_AV1) {
+ if (rd->ffcodecdata.codec != AV_CODEC_ID_AV1) {
+ BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_AV1);
+ audio = 1;
+ }
+ }
if (audio && rd->ffcodecdata.audio_codec < 0) {
rd->ffcodecdata.audio_codec = AV_CODEC_ID_NONE;
diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh
index 95b3bde10f4..264ac00e034 100644
--- a/source/blender/blenlib/BLI_array_utils.hh
+++ b/source/blender/blenlib/BLI_array_utils.hh
@@ -42,6 +42,11 @@ void gather(const GVArray &src, IndexMask indices, GMutableSpan dst, int64_t gra
/**
* Fill the destination span by gathering indexed values from the `src` array.
*/
+void gather(GSpan src, IndexMask indices, GMutableSpan dst, int64_t grain_size = 4096);
+
+/**
+ * Fill the destination span by gathering indexed values from the `src` array.
+ */
template<typename T>
inline void gather(const VArray<T> &src,
const IndexMask indices,
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 15926e8f2d2..17abcf52ecc 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -309,6 +309,28 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, bool base_10) A
*/
void BLI_str_format_decimal_unit(char dst[7], int number_to_format) ATTR_NONNULL();
/**
+ * Format a count to up to 3 places (plus minus sign, plus '\0' terminator) string using long
+ * number names abbreviations. Used to produce a compact representation of large numbers as
+ * integers.
+ *
+ * It shows a lower bound instead of rounding the number.
+ *
+ * 1 -> 1
+ * 15 -> 15
+ * 155 -> 155
+ * 1555 -> 1K
+ * 15555 -> 15K
+ * 155555 -> .1M
+ * 1555555 -> 1M
+ * 15555555 -> 15M
+ * 155555555 -> .1B
+ * 1000000000 -> 1B
+ * ...
+ *
+ * Length of 5 is the maximum of the resulting string, for example, `-15K\0`.
+ */
+void BLI_str_format_integer_unit(char dst[5], int number_to_format) ATTR_NONNULL();
+/**
* Compare two strings without regard to case.
*
* \retval True if the strings are equal, false otherwise.
diff --git a/source/blender/blenlib/intern/array_utils.cc b/source/blender/blenlib/intern/array_utils.cc
index a837d6aceec..2a231228dcb 100644
--- a/source/blender/blenlib/intern/array_utils.cc
+++ b/source/blender/blenlib/intern/array_utils.cc
@@ -28,4 +28,9 @@ void gather(const GVArray &src,
});
}
+void gather(const GSpan src, const IndexMask indices, GMutableSpan dst, const int64_t grain_size)
+{
+ gather(GVArray::ForSpan(src), indices, dst, grain_size);
+}
+
} // namespace blender::array_utils
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 89d31c5e93f..755d2dbd55d 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -1176,4 +1176,34 @@ void BLI_str_format_decimal_unit(char dst[7], int number_to_format)
BLI_snprintf(dst, dst_len, "%.*f%s", decimals, number_to_format_converted, units[order]);
}
+void BLI_str_format_integer_unit(char dst[5], const int number_to_format)
+{
+ float number_to_format_converted = number_to_format;
+ int order = 0;
+ const float base = 1000;
+ const char *units[] = {"", "K", "M", "B"};
+ const int units_num = ARRAY_SIZE(units);
+
+ while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < units_num)) {
+ number_to_format_converted /= base;
+ order++;
+ }
+
+ const bool add_dot = (abs(number_to_format) > 99999) && fabsf(number_to_format_converted) > 99;
+
+ if (add_dot) {
+ number_to_format_converted /= 100;
+ order++;
+ }
+
+ const size_t dst_len = 5;
+ BLI_snprintf(dst,
+ dst_len,
+ "%s%s%d%s",
+ number_to_format < 0 ? "-" : "",
+ add_dot ? "." : "",
+ (int)floorf(fabsf(number_to_format_converted)),
+ units[order]);
+}
+
/** \} */
diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc
index 9bdf6075c70..d726fbccf20 100644
--- a/source/blender/blenlib/tests/BLI_string_test.cc
+++ b/source/blender/blenlib/tests/BLI_string_test.cc
@@ -515,6 +515,103 @@ TEST(string, StrFormatDecimalUnits)
EXPECT_STREQ("-2.1B", size_str);
}
+/* BLI_str_format_integer_unit */
+TEST(string, StrFormatIntegerUnits)
+{
+ char size_str[7];
+ int size;
+
+ BLI_str_format_integer_unit(size_str, size = 0);
+ EXPECT_STREQ("0", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1);
+ EXPECT_STREQ("1", size_str);
+ BLI_str_format_integer_unit(size_str, size = 10);
+ EXPECT_STREQ("10", size_str);
+ BLI_str_format_integer_unit(size_str, size = 15);
+ EXPECT_STREQ("15", size_str);
+ BLI_str_format_integer_unit(size_str, size = 100);
+ EXPECT_STREQ("100", size_str);
+ BLI_str_format_integer_unit(size_str, size = 155);
+ EXPECT_STREQ("155", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1000);
+ EXPECT_STREQ("1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1555);
+ EXPECT_STREQ("1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 10000);
+ EXPECT_STREQ("10K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 15555);
+ EXPECT_STREQ("15K", size_str);
+ BLI_str_format_integer_unit(size_str, size = 100000);
+ EXPECT_STREQ(".1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 155555);
+ EXPECT_STREQ(".1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1000000);
+ EXPECT_STREQ("1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1555555);
+ EXPECT_STREQ("1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 2555555);
+ EXPECT_STREQ("2M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 10000000);
+ EXPECT_STREQ("10M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 15555555);
+ EXPECT_STREQ("15M", size_str);
+ BLI_str_format_integer_unit(size_str, size = 100000000);
+ EXPECT_STREQ(".1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = 155555555);
+ EXPECT_STREQ(".1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = 255555555);
+ EXPECT_STREQ(".2B", size_str);
+ BLI_str_format_integer_unit(size_str, size = 1000000000);
+ EXPECT_STREQ("1B", size_str);
+
+ /* Largest possible value. */
+ BLI_str_format_integer_unit(size_str, size = INT32_MAX);
+ EXPECT_STREQ("2B", size_str);
+
+ BLI_str_format_integer_unit(size_str, size = -0);
+ EXPECT_STREQ("0", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1);
+ EXPECT_STREQ("-1", size_str);
+ BLI_str_format_integer_unit(size_str, size = -10);
+ EXPECT_STREQ("-10", size_str);
+ BLI_str_format_integer_unit(size_str, size = -15);
+ EXPECT_STREQ("-15", size_str);
+ BLI_str_format_integer_unit(size_str, size = -100);
+ EXPECT_STREQ("-100", size_str);
+ BLI_str_format_integer_unit(size_str, size = -155);
+ EXPECT_STREQ("-155", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1000);
+ EXPECT_STREQ("-1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1555);
+ EXPECT_STREQ("-1K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -10000);
+ EXPECT_STREQ("-10K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -15555);
+ EXPECT_STREQ("-15K", size_str);
+ BLI_str_format_integer_unit(size_str, size = -100000);
+ EXPECT_STREQ("-.1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -155555);
+ EXPECT_STREQ("-.1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1000000);
+ EXPECT_STREQ("-1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1555555);
+ EXPECT_STREQ("-1M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -10000000);
+ EXPECT_STREQ("-10M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -15555555);
+ EXPECT_STREQ("-15M", size_str);
+ BLI_str_format_integer_unit(size_str, size = -100000000);
+ EXPECT_STREQ("-.1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = -155555555);
+ EXPECT_STREQ("-.1B", size_str);
+ BLI_str_format_integer_unit(size_str, size = -1000000000);
+ EXPECT_STREQ("-1B", size_str);
+
+ /* Smallest possible value. */
+ BLI_str_format_integer_unit(size_str, size = -INT32_MAX);
+ EXPECT_STREQ("-2B", size_str);
+}
+
struct WordInfo {
WordInfo() = default;
WordInfo(int start, int end) : start(start), end(end)
diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc
index e2b98b2283f..a2bd7fd2fd1 100644
--- a/source/blender/blenloader/intern/versioning_300.cc
+++ b/source/blender/blenloader/intern/versioning_300.cc
@@ -3630,6 +3630,29 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 304, 5)) {
+ /* Fix for T101622 - update flags of sequence editor regions that were not initialized
+ * properly. */
+ LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
+ ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
+ &sl->regionbase;
+ if (sl->spacetype == SPACE_SEQ) {
+ LISTBASE_FOREACH (ARegion *, region, regionbase) {
+ if (region->regiontype == RGN_TYPE_TOOLS) {
+ region->v2d.flag &= ~V2D_VIEWSYNC_AREA_VERTICAL;
+ }
+ if (region->regiontype == RGN_TYPE_CHANNELS) {
+ region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt
index 90cbe0988ad..bab0b5385ec 100644
--- a/source/blender/compositor/realtime_compositor/CMakeLists.txt
+++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt
@@ -2,7 +2,7 @@
set(INC
.
- ./algorithms
+ algorithms
../../blenkernel
../../blenlib
../../gpu
diff --git a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh
index 9d0851eff84..f6d479f9bbe 100644
--- a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh
+++ b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh
@@ -27,6 +27,13 @@ float sum_blue(Context &context, GPUTexture *texture);
* coefficients to compute the luminance. */
float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients);
+/* Computes the sum of the logarithm of the luminance of all pixels in the given texture, using the
+ * given luminance coefficients to compute the luminance. */
+float sum_log_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients);
+
+/* Computes the sum of the colors of all pixels in the given texture. */
+float4 sum_color(Context &context, GPUTexture *texture);
+
/* --------------------------------------------------------------------
* Sum Of Squared Difference Reductions.
*/
@@ -55,4 +62,42 @@ float sum_luminance_squared_difference(Context &context,
float3 luminance_coefficients,
float subtrahend);
+/* --------------------------------------------------------------------
+ * Maximum Reductions.
+ */
+
+/* Computes the maximum luminance of all pixels in the given texture, using the given luminance
+ * coefficients to compute the luminance. */
+float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients);
+
+/* Computes the maximum float of all pixels in the given float texture, limited to the given range.
+ * Values outside of the given range are ignored. If non of the pixel values are in the range, the
+ * lower bound of the range is returned. For instance, if the given range is [-10, 10] and the
+ * image contains the values {2, 5, 11}, the maximum will be 5, since 11 is outside of the range.
+ * This is particularly useful for Z Depth normalization, since Z Depth can contain near infinite
+ * values, so enforcing an upper bound is beneficial. */
+float maximum_float_in_range(Context &context,
+ GPUTexture *texture,
+ float lower_bound,
+ float upper_bound);
+
+/* --------------------------------------------------------------------
+ * Minimum Reductions.
+ */
+
+/* Computes the minimum luminance of all pixels in the given texture, using the given luminance
+ * coefficients to compute the luminance. */
+float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients);
+
+/* Computes the minimum float of all pixels in the given float texture, limited to the given range.
+ * Values outside of the given range are ignored. If non of the pixel values are in the range, the
+ * upper bound of the range is returned. For instance, if the given range is [-10, 10] and the
+ * image contains the values {-11, 2, 5}, the minimum will be 2, since -11 is outside of the range.
+ * This is particularly useful for Z Depth normalization, since Z Depth can contain near infinite
+ * values, so enforcing a lower bound is beneficial. */
+float minimum_float_in_range(Context &context,
+ GPUTexture *texture,
+ float lower_bound,
+ float upper_bound);
+
} // namespace blender::realtime_compositor
diff --git a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc
index 3266ccd14eb..9672431992d 100644
--- a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc
+++ b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc
@@ -134,6 +134,34 @@ float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coef
return sum;
}
+float sum_log_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_sum_log_luminance");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+ const float sum = *reduced_value;
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return sum;
+}
+
+float4 sum_color(Context &context, GPUTexture *texture)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_sum_color");
+ GPU_shader_bind(shader);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_RGBA32F);
+ const float4 sum = float4(reduced_value);
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return sum;
+}
+
/* --------------------------------------------------------------------
* Sum Of Squared Difference Reductions.
*/
@@ -202,4 +230,80 @@ float sum_luminance_squared_difference(Context &context,
return sum;
}
+/* --------------------------------------------------------------------
+ * Maximum Reductions.
+ */
+
+float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_maximum_luminance");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+ const float maximum = *reduced_value;
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return maximum;
+}
+
+float maximum_float_in_range(Context &context,
+ GPUTexture *texture,
+ float lower_bound,
+ float upper_bound)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_maximum_float_in_range");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_1f(shader, "lower_bound", lower_bound);
+ GPU_shader_uniform_1f(shader, "upper_bound", upper_bound);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+ const float maximum = *reduced_value;
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return maximum;
+}
+
+/* --------------------------------------------------------------------
+ * Minimum Reductions.
+ */
+
+float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_minimum_luminance");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+ const float minimum = *reduced_value;
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return minimum;
+}
+
+float minimum_float_in_range(Context &context,
+ GPUTexture *texture,
+ float lower_bound,
+ float upper_bound)
+{
+ GPUShader *shader = context.shader_manager().get("compositor_minimum_float_in_range");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_1f(shader, "lower_bound", lower_bound);
+ GPU_shader_uniform_1f(shader, "upper_bound", upper_bound);
+
+ float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
+ const float minimum = *reduced_value;
+ MEM_freeN(reduced_value);
+ GPU_shader_unbind();
+
+ return minimum;
+}
+
} // namespace blender::realtime_compositor
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 6cb0b985d3d..c84852788fd 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -454,8 +454,8 @@ static int foreach_id_cow_detect_need_for_update_callback(LibraryIDLinkCallbackD
return IDWALK_RET_NOP;
}
if (!ID_TYPE_IS_COW(GS(id->name))) {
- /* No need to go further if thte id never had a cow copy in the depsgraph. This function is
- * only concerned with keeping the mapping between original and cow ids intact. */
+ /* No need to go further if the id never had a cow copy in the depsgraph. This function is
+ * only concerned with keeping the mapping between original and COW ids intact. */
return IDWALK_RET_NOP;
}
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index b5f81f3a307..068b18f1117 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -924,17 +924,14 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata,
if (matcache.depth_grp) {
*matcache.depth_grp_p = DRW_shgroup_hair_create_sub(
ob, psys, md, matcache.depth_grp, NULL);
- DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat);
}
if (matcache.shading_grp) {
*matcache.shading_grp_p = DRW_shgroup_hair_create_sub(
ob, psys, md, matcache.shading_grp, matcache.shading_gpumat);
- DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat);
}
if (matcache.shadow_grp) {
*matcache.shadow_grp_p = DRW_shgroup_hair_create_sub(
ob, psys, md, matcache.shadow_grp, NULL);
- DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat);
*cast_shadow = true;
}
@@ -954,16 +951,13 @@ void EEVEE_object_curves_cache_populate(EEVEE_Data *vedata,
if (matcache.depth_grp) {
*matcache.depth_grp_p = DRW_shgroup_curves_create_sub(ob, matcache.depth_grp, NULL);
- DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat);
}
if (matcache.shading_grp) {
*matcache.shading_grp_p = DRW_shgroup_curves_create_sub(
ob, matcache.shading_grp, matcache.shading_gpumat);
- DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat);
}
if (matcache.shadow_grp) {
*matcache.shadow_grp_p = DRW_shgroup_curves_create_sub(ob, matcache.shadow_grp, NULL);
- DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat);
*cast_shadow = true;
}
diff --git a/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl b/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl
index 90272400915..5af317b7398 100644
--- a/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl
@@ -96,7 +96,7 @@ vec4 cubemap_seamless(sampler2DArray tex, vec4 cubevec, float lod)
/* Mix all colors to get the corner color. */
vec4 col3 = (col + col1 + col2) / 3.0;
- vec2 mix_fac = uv_border * 0.5;
+ vec2 mix_fac = saturate(uv_border * 0.5);
return mix(mix(col, col2, mix_fac.x), mix(col1, col3, mix_fac.x), mix_fac.y);
}
else if (any(border)) {
@@ -108,7 +108,7 @@ vec4 cubemap_seamless(sampler2DArray tex, vec4 cubevec, float lod)
uv = cubemap_face_coord(cubevec.xyz, face);
coord = vec3(uv, cubevec.w * 6.0 + face);
- float mix_fac = max(uv_border.x, uv_border.y) * 0.5;
+ float mix_fac = saturate(max(uv_border.x, uv_border.y) * 0.5);
return mix(col, textureLod(tex, coord, lod), mix_fac);
}
else {
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
index 51a351babd3..5f04cdcebfa 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl
@@ -95,7 +95,11 @@ void main()
weights = dof_layer_weight(cocs) * dof_sample_weight(cocs);
/* Filter NaNs. */
- weights = select(weights, vec4(0.0), equal(cocs, vec4(0.0)));
+ for (int i = 0; i < 4; i++) {
+ if (isnan(weights[i]) || isinf(weights[i])) {
+ weights[i] = 0.0;
+ }
+ }
color1 = colors[0] * weights[0];
color2 = colors[1] * weights[1];
diff --git a/source/blender/draw/intern/draw_curves.cc b/source/blender/draw/intern/draw_curves.cc
index a61769e7a63..8847e3f6016 100644
--- a/source/blender/draw/intern/draw_curves.cc
+++ b/source/blender/draw/intern/draw_curves.cc
@@ -394,6 +394,11 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object,
DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip);
DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip);
+ if (gpu_material) {
+ /* \note: This needs to happen before the drawcall to allow correct attribute extraction.
+ * (see T101896) */
+ DRW_shgroup_add_material_resources(shgrp, gpu_material);
+ }
/* TODO(fclem): Until we have a better way to cull the curves and render with orco, bypass
* culling test. */
GPUBatch *geom = curves_cache->final[subdiv].proc_hairs[thickness_res - 1];
diff --git a/source/blender/draw/intern/draw_hair.cc b/source/blender/draw/intern/draw_hair.cc
index 4e44967e5e9..281e58ea230 100644
--- a/source/blender/draw/intern/draw_hair.cc
+++ b/source/blender/draw/intern/draw_hair.cc
@@ -293,6 +293,11 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root);
DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip);
DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip);
+ if (gpu_material) {
+ /* \note: This needs to happen before the drawcall to allow correct attribute extraction.
+ * (see T101896) */
+ DRW_shgroup_add_material_resources(shgrp, gpu_material);
+ }
/* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass
* culling test. */
GPUBatch *geom = hair_cache->final[subdiv].proc_hairs[thickness_res - 1];
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index da77845feb4..b9a9780e651 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1959,20 +1959,6 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph
DST.buffer_finish_called = false;
}
-/* Callback function for RE_engine_update_render_passes to ensure all
- * render passes are registered. */
-static void draw_render_result_ensure_pass_cb(void *user_data,
- struct Scene *UNUSED(scene),
- struct ViewLayer *view_layer,
- const char *name,
- int channels,
- const char *chanid,
- eNodeSocketDatatype UNUSED(type))
-{
- RenderEngine *engine = user_data;
- RE_engine_add_pass(engine, name, channels, chanid, view_layer->name);
-}
-
void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
@@ -2023,10 +2009,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
/* set default viewport */
GPU_viewport(0, 0, size[0], size[1]);
- /* Update the render passes. This needs to be done before acquiring the render result. */
- RE_engine_update_render_passes(
- engine, scene, view_layer, draw_render_result_ensure_pass_cb, engine);
-
/* Init render result. */
RenderResult *render_result = RE_engine_begin_result(engine,
0,
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index 677bf1bb392..2fd58a9cee0 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -13,9 +13,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_math_geom.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index c8ffbb9acb1..b97cd6a9099 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -345,12 +345,14 @@ typedef enum {
ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */
} eUVPackIsland_MarginMethod;
+/** See also #UnwrapOptions. */
struct UVPackIsland_Params {
uint rotate : 1;
uint only_selected_uvs : 1;
uint only_selected_faces : 1;
uint use_seams : 1;
uint correct_aspect : 1;
+ bool ignore_pinned; /* Ignore islands which have any pinned UVs. */
eUVPackIsland_MarginMethod margin_method; /* Which formula to use when scaling island margin. */
float margin; /* Additional space to add around each island. */
};
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 2a1941f0d9e..7e9422ff867 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1683,6 +1683,7 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name);
* Adds a hint to the button which draws right aligned, grayed out and never clipped.
*/
void UI_but_hint_drawstr_set(uiBut *but, const char *string);
+void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number);
void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]);
@@ -2788,7 +2789,8 @@ typedef struct uiPropertySplitWrapper {
uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout);
void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
-void uiItemL_ex(uiLayout *layout, const char *name, int icon, bool highlight, bool redalert);
+struct uiBut *uiItemL_ex(
+ uiLayout *layout, const char *name, int icon, bool highlight, bool redalert);
/**
* Helper to add a label and creates a property split layout if needed.
*/
diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh
index 6c756984203..fc03b0218c0 100644
--- a/source/blender/editors/include/UI_interface.hh
+++ b/source/blender/editors/include/UI_interface.hh
@@ -35,6 +35,7 @@ struct ContextPathItem {
std::string name;
/* #BIFIconID */
int icon;
+ int icon_indicator_number;
};
void context_path_add_generic(Vector<ContextPathItem> &path,
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index a1a98a4b08c..9669e242dac 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -27,6 +27,12 @@ typedef struct IconFile {
int index;
} IconFile;
+typedef struct IconTextOverlay {
+ char text[5];
+} IconTextOverlay;
+
+#define UI_NO_ICON_OVERLAY_TEXT NULL
+
#define ICON_DEFAULT_HEIGHT 16
#define ICON_DEFAULT_WIDTH 16
@@ -105,7 +111,8 @@ void UI_icon_draw_ex(float x,
float alpha,
float desaturate,
const uchar mono_color[4],
- bool mono_border);
+ bool mono_border,
+ const struct IconTextOverlay *text_overlay);
void UI_icons_free(void);
void UI_icons_free_drawinfo(void *drawinfo);
@@ -124,6 +131,9 @@ int UI_icon_from_library(const struct ID *id);
int UI_icon_from_object_mode(int mode);
int UI_icon_color_from_collection(const struct Collection *collection);
+void UI_icon_text_overlay_init_from_count(struct IconTextOverlay *text_overlay,
+ const int icon_indicator_number);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc
index 422fc34aa50..1f88d25af2b 100644
--- a/source/blender/editors/interface/interface.cc
+++ b/source/blender/editors/interface/interface.cc
@@ -6452,6 +6452,11 @@ void UI_but_hint_drawstr_set(uiBut *but, const char *string)
ui_but_add_shortcut(but, string, false);
}
+void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number)
+{
+ UI_icon_text_overlay_init_from_count(&but->icon_overlay_text, indicator_number);
+}
+
void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4])
{
but->flag |= UI_BUT_NODE_LINK;
diff --git a/source/blender/editors/interface/interface_context_path.cc b/source/blender/editors/interface/interface_context_path.cc
index e8f552e26a3..91b2f9613de 100644
--- a/source/blender/editors/interface/interface_context_path.cc
+++ b/source/blender/editors/interface/interface_context_path.cc
@@ -17,6 +17,8 @@
#include "UI_interface.hh"
#include "UI_resources.h"
+#include "RNA_prototypes.h"
+
#include "WM_api.h"
namespace blender::ui {
@@ -41,7 +43,13 @@ void context_path_add_generic(Vector<ContextPathItem> &path,
static_cast<BIFIconID>(RNA_struct_ui_icon(rna_ptr.type)) :
icon_override;
- path.append({name, int(icon)});
+ if (&rna_type == &RNA_NodeTree) {
+ ID *id = (ID *)ptr;
+ path.append({name, int(icon), id->us});
+ }
+ else {
+ path.append({name, int(icon), 1});
+ }
}
/* -------------------------------------------------------------------- */
@@ -60,7 +68,9 @@ void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path)
if (i > 0) {
uiItemL(sub_row, "", ICON_RIGHTARROW_THIN);
}
- uiItemL(sub_row, context_path[i].name.c_str(), context_path[i].icon);
+ uiBut *but = uiItemL_ex(
+ sub_row, context_path[i].name.c_str(), context_path[i].icon, false, false);
+ UI_but_icon_indicator_number_set(but, context_path[i].icon_indicator_number);
}
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index deb3d84ae66..9a4f98ebcd6 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -415,8 +415,15 @@ static void vicon_collection_color_draw(
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
- UI_icon_draw_ex(
- x, y, ICON_OUTLINER_COLLECTION, aspect, 1.0f, 0.0f, collection_color->color, true);
+ UI_icon_draw_ex(x,
+ y,
+ ICON_OUTLINER_COLLECTION,
+ aspect,
+ 1.0f,
+ 0.0f,
+ collection_color->color,
+ true,
+ UI_NO_ICON_OVERLAY_TEXT);
}
# define DEF_ICON_COLLECTION_COLOR_DRAW(index, color) \
@@ -444,7 +451,8 @@ static void vicon_strip_color_draw(
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
- UI_icon_draw_ex(x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true);
+ UI_icon_draw_ex(
+ x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true, UI_NO_ICON_OVERLAY_TEXT);
}
# define DEF_ICON_STRIP_COLOR_DRAW(index, color) \
@@ -472,8 +480,15 @@ static void vicon_strip_color_draw_library_data_indirect(
{
const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w;
- UI_icon_draw_ex(
- x, y, ICON_LIBRARY_DATA_DIRECT, aspect, ICON_INDIRECT_DATA_ALPHA * alpha, 0.0f, NULL, false);
+ UI_icon_draw_ex(x,
+ y,
+ ICON_LIBRARY_DATA_DIRECT,
+ aspect,
+ ICON_INDIRECT_DATA_ALPHA * alpha,
+ 0.0f,
+ NULL,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
static void vicon_strip_color_draw_library_data_override_noneditable(
@@ -488,7 +503,8 @@ static void vicon_strip_color_draw_library_data_override_noneditable(
ICON_INDIRECT_DATA_ALPHA * alpha * 0.75f,
0.0f,
NULL,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
/* Dynamically render icon instead of rendering a plain color to a texture/buffer
@@ -1716,9 +1732,47 @@ static void icon_draw_texture(float x,
int ih,
float alpha,
const float rgb[3],
- bool with_border)
-{
- if (g_icon_draw_cache.enabled) {
+ bool with_border,
+ const IconTextOverlay *text_overlay)
+{
+ const float zoom_factor = w / UI_DPI_ICON_SIZE;
+ float text_width = 0.0f;
+
+ /* No need to show if too zoomed out, otherwise it just adds noise. */
+ const bool show_indicator = (text_overlay && text_overlay->text[0] != '\0') &&
+ (zoom_factor > 0.7f);
+
+ if (show_indicator) {
+ /* Handle the little numbers on top of the icon. */
+ uchar text_color[4];
+ UI_GetThemeColor3ubv(TH_TEXT, text_color);
+ text_color[3] = 255;
+
+ uiFontStyle fstyle_small = *UI_FSTYLE_WIDGET;
+ fstyle_small.points *= zoom_factor;
+ fstyle_small.points *= 0.8f;
+
+ rcti text_rect = {
+ .xmax = x + UI_UNIT_X * zoom_factor,
+ .xmin = x,
+ .ymax = y,
+ .ymin = y,
+ };
+
+ UI_fontstyle_draw(&fstyle_small,
+ &text_rect,
+ text_overlay->text,
+ sizeof(text_overlay->text),
+ text_color,
+ &(struct uiFontStyleDraw_Params){
+ .align = UI_STYLE_TEXT_RIGHT,
+ });
+ text_width = (float)UI_fontstyle_string_width(&fstyle_small, text_overlay->text) / UI_UNIT_X /
+ zoom_factor;
+ }
+
+ /* Draw the actual icon. */
+ if (!show_indicator && g_icon_draw_cache.enabled) {
icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb, with_border);
return;
}
@@ -1735,7 +1789,7 @@ static void icon_draw_texture(float x,
GPUTexture *texture = with_border ? icongltex.tex[1] : icongltex.tex[0];
- GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_ICON);
GPU_shader_bind(shader);
const int img_binding = GPU_shader_get_texture_binding(shader, "image");
@@ -1752,6 +1806,7 @@ static void icon_draw_texture(float x,
GPU_shader_uniform_vector(shader, rect_tex_loc, 4, 1, (float[4]){x1, y1, x2, y2});
GPU_shader_uniform_vector(shader, rect_geom_loc, 4, 1, (float[4]){x, y, x + w, y + h});
+ GPU_shader_uniform_1f(shader, "text_width", text_width);
GPU_texture_bind_ex(texture, GPU_SAMPLER_ICON, img_binding, false);
@@ -1786,7 +1841,8 @@ static void icon_draw_size(float x,
int draw_size,
const float desaturate,
const uchar mono_rgba[4],
- const bool mono_border)
+ const bool mono_border,
+ const IconTextOverlay *text_overlay)
{
bTheme *btheme = UI_GetTheme();
const float fdraw_size = (float)draw_size;
@@ -1874,7 +1930,8 @@ static void icon_draw_size(float x,
di->data.texture.h,
alpha,
NULL,
- false);
+ false,
+ text_overlay);
}
else if (di->type == ICON_TYPE_MONO_TEXTURE) {
/* Monochrome icon that uses text or theme color. */
@@ -1908,7 +1965,8 @@ static void icon_draw_size(float x,
di->data.texture.h + 2 * border_texel,
color[3],
color,
- with_border);
+ with_border,
+ text_overlay);
}
else if (di->type == ICON_TYPE_BUFFER) {
@@ -2425,17 +2483,27 @@ int UI_icon_color_from_collection(const Collection *collection)
void UI_icon_draw(float x, float y, int icon_id)
{
- UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false);
+ UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false, UI_NO_ICON_OVERLAY_TEXT);
}
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
{
- UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
+ UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false, UI_NO_ICON_OVERLAY_TEXT);
}
void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size)
{
- icon_draw_size(x, y, icon_id, aspect, alpha, ICON_SIZE_PREVIEW, size, false, NULL, false);
+ icon_draw_size(x,
+ y,
+ icon_id,
+ aspect,
+ alpha,
+ ICON_SIZE_PREVIEW,
+ size,
+ false,
+ NULL,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
void UI_icon_draw_ex(float x,
@@ -2445,7 +2513,8 @@ void UI_icon_draw_ex(float x,
float alpha,
float desaturate,
const uchar mono_color[4],
- const bool mono_border)
+ const bool mono_border,
+ const IconTextOverlay *text_overlay)
{
const int draw_size = get_draw_size(ICON_SIZE_ICON);
icon_draw_size(x,
@@ -2457,7 +2526,19 @@ void UI_icon_draw_ex(float x,
draw_size,
desaturate,
mono_color,
- mono_border);
+ mono_border,
+ text_overlay);
+}
+
+void UI_icon_text_overlay_init_from_count(IconTextOverlay *text_overlay,
+ const int icon_indicator_number)
+{
+ /* The icon indicator is used as an aggregator, no need to show if it is 1. */
+ if (icon_indicator_number < 2) {
+ text_overlay->text[0] = '\0';
+ return;
+ }
+ BLI_str_format_integer_unit(text_overlay->text, icon_indicator_number);
}
/* ********** Alert Icons ********** */
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 6ef7d346418..6ef81ad897e 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -23,6 +23,7 @@ struct ARegion;
struct AnimationEvalContext;
struct CurveMapping;
struct CurveProfile;
+struct IconTextOverlay;
struct ID;
struct ImBuf;
struct Main;
@@ -275,6 +276,9 @@ struct uiBut {
uiButPushedStateFunc pushed_state_func;
const void *pushed_state_arg;
+ /** Little indicator (e.g., counter) displayed on top of some icons. */
+ struct IconTextOverlay icon_overlay_text;
+
/* pointer back */
uiBlock *block;
};
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index c906a5b36f1..496f72c089a 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -3235,7 +3235,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
return but;
}
-void uiItemL_ex(
+uiBut *uiItemL_ex(
uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert)
{
uiBut *but = uiItemL_(layout, name, icon);
@@ -3248,6 +3248,8 @@ void uiItemL_ex(
if (redalert) {
UI_but_flag_enable(but, UI_BUT_REDALERT);
}
+
+ return but;
}
void uiItemL(uiLayout *layout, const char *name, int icon)
diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc
index 7a69e2f9b2f..24d8281aad8 100644
--- a/source/blender/editors/interface/interface_panel.cc
+++ b/source/blender/editors/interface/interface_panel.cc
@@ -1112,7 +1112,8 @@ static void panel_draw_aligned_widgets(const uiStyle *style,
0.7f,
0.0f,
title_color,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
@@ -1140,7 +1141,8 @@ static void panel_draw_aligned_widgets(const uiStyle *style,
1.0f,
0.0f,
title_color,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 6ba80e2e0d9..1bad9b34a72 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1420,21 +1420,25 @@ static void widget_draw_icon(
/* to indicate draggable */
if (ui_but_drag_is_draggable(but) && (but->flag & UI_ACTIVE)) {
- UI_icon_draw_ex(xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme, &but->icon_overlay_text);
}
else if (but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) {
- UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, alpha, 0.0f, color, has_theme, &but->icon_overlay_text);
}
else if (!((but->icon != ICON_NONE) && UI_but_is_tool(but))) {
if (has_theme) {
alpha *= 0.8f;
}
- UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, alpha, 0.0f, color, has_theme, &but->icon_overlay_text);
}
else {
const bTheme *btheme = UI_GetTheme();
const float desaturate = 1.0 - btheme->tui.icon_saturation;
- UI_icon_draw_ex(xs, ys, icon, aspect, alpha, desaturate, color, has_theme);
+ UI_icon_draw_ex(
+ xs, ys, icon, aspect, alpha, desaturate, color, has_theme, &but->icon_overlay_text);
}
}
@@ -5426,7 +5430,8 @@ void ui_draw_menu_item(const uiFontStyle *fstyle,
GPU_blend(GPU_BLEND_ALPHA);
/* XXX scale weak get from fstyle? */
- UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false);
+ UI_icon_draw_ex(
+ xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false, UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc
index 3ce39b695e0..f6eee7c0c9e 100644
--- a/source/blender/editors/object/object_add.cc
+++ b/source/blender/editors/object/object_add.cc
@@ -3556,11 +3556,62 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/** \name Duplicate Object Operator
* \{ */
+static void object_add_sync_base_collection(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_src, Object *object_new)
+{
+ if ((base_src != nullptr) && (base_src->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) {
+ BKE_collection_object_add_from(bmain, scene, base_src->object, object_new);
+ }
+ else {
+ LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(bmain, layer_collection->collection, object_new);
+ }
+}
+
+static void object_add_sync_local_view(Base *base_src, Base *base_new)
+{
+ base_new->local_view_bits = base_src->local_view_bits;
+}
+
+static void object_add_sync_rigid_body(Main *bmain, Object *object_src, Object *object_new)
+{
+ /* 1) duplis should end up in same collection as the original
+ * 2) Rigid Body sim participants MUST always be part of a collection...
+ */
+ /* XXX: is 2) really a good measure here? */
+ if (object_src->rigidbody_object || object_src->rigidbody_constraint) {
+ LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
+ if (BKE_collection_has_object(collection, object_src)) {
+ BKE_collection_object_add(bmain, collection, object_new);
+ }
+ }
+ }
+}
+
/**
* - Assumes `id.new` is correct.
* - Leaves selection of base/object unaltered.
* - Sets #ID.newid pointers.
*/
+static void object_add_duplicate_internal(Main *bmain,
+ Object *ob,
+ const eDupli_ID_Flags dupflag,
+ const eLibIDDuplicateFlags duplicate_options,
+ Object **r_ob_new)
+{
+ if (ob->mode & OB_MODE_POSE) {
+ return;
+ }
+
+ Object *obn = static_cast<Object *>(
+ ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options)));
+ if (r_ob_new) {
+ *r_ob_new = obn;
+ }
+ DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ return;
+}
+
static Base *object_add_duplicate_internal(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
@@ -3569,49 +3620,25 @@ static Base *object_add_duplicate_internal(Main *bmain,
const eLibIDDuplicateFlags duplicate_options,
Object **r_ob_new)
{
- Base *base, *basen = nullptr;
- Object *obn;
-
- if (ob->mode & OB_MODE_POSE) {
- /* nothing? */
+ Object *object_new = nullptr;
+ object_add_duplicate_internal(bmain, ob, dupflag, duplicate_options, &object_new);
+ if (r_ob_new) {
+ *r_ob_new = object_new;
+ }
+ if (object_new == nullptr) {
+ return nullptr;
}
- else {
- obn = static_cast<Object *>(
- ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options)));
- if (r_ob_new) {
- *r_ob_new = obn;
- }
- DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- BKE_view_layer_synced_ensure(scene, view_layer);
- base = BKE_view_layer_base_find(view_layer, ob);
- if ((base != nullptr) && (base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) {
- BKE_collection_object_add_from(bmain, scene, ob, obn);
- }
- else {
- LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
- BKE_collection_object_add(bmain, layer_collection->collection, obn);
- }
-
- BKE_view_layer_synced_ensure(scene, view_layer);
- basen = BKE_view_layer_base_find(view_layer, obn);
- if (base != nullptr && basen != nullptr) {
- basen->local_view_bits = base->local_view_bits;
- }
- /* 1) duplis should end up in same collection as the original
- * 2) Rigid Body sim participants MUST always be part of a collection...
- */
- /* XXX: is 2) really a good measure here? */
- if (ob->rigidbody_object || ob->rigidbody_constraint) {
- LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
- if (BKE_collection_has_object(collection, ob)) {
- BKE_collection_object_add(bmain, collection, obn);
- }
- }
- }
+ BKE_view_layer_synced_ensure(scene, view_layer);
+ Base *base_src = BKE_view_layer_base_find(view_layer, ob);
+ object_add_sync_base_collection(bmain, scene, view_layer, base_src, object_new);
+ BKE_view_layer_synced_ensure(scene, view_layer);
+ Base *base_new = BKE_view_layer_base_find(view_layer, object_new);
+ if (base_src && base_new) {
+ object_add_sync_local_view(base_src, base_new);
}
- return basen;
+ object_add_sync_rigid_body(bmain, ob, object_new);
+ return base_new;
}
Base *ED_object_add_duplicate(
@@ -3665,70 +3692,70 @@ static int duplicate_exec(bContext *C, wmOperator *op)
* we also want to remap pointers between those... */
BKE_main_id_newptr_and_tag_clear(bmain);
- /* Do not do collection re-syncs for each object; will do it once afterwards.
- * However this means we can't get to new duplicated Base's immediately, will
- * have to process them after the sync. */
- BKE_layer_collection_resync_forbid();
-
/* Duplicate the selected objects, remember data needed to process
- * after the sync (the base of the original object, and the copy of the
- * original object). */
- blender::Vector<std::pair<Base *, Object *>> source_bases_new_objects;
- Object *ob_new_active = nullptr;
+ * after the sync. */
+ struct DuplicateObjectLink {
+ Base *base_src = nullptr;
+ Object *object_new = nullptr;
+
+ DuplicateObjectLink(Base *base_src) : base_src(base_src)
+ {
+ }
+ };
+ blender::Vector<DuplicateObjectLink> object_base_links;
CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
- Object *ob_new = nullptr;
+ object_base_links.append(DuplicateObjectLink(base));
+ }
+ CTX_DATA_END;
+
+ bool new_objects_created = false;
+ for (DuplicateObjectLink &link : object_base_links) {
object_add_duplicate_internal(bmain,
- scene,
- view_layer,
- base->object,
+ link.base_src->object,
dupflag,
LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID,
- &ob_new);
- if (ob_new == nullptr) {
- continue;
- }
- source_bases_new_objects.append({base, ob_new});
-
- /* note that this is safe to do with this context iterator,
- * the list is made in advance */
- ED_object_base_select(base, BA_DESELECT);
-
- /* new object will become active */
- BKE_view_layer_synced_ensure(scene, view_layer);
- if (BKE_view_layer_active_base_get(view_layer) == base) {
- ob_new_active = ob_new;
+ &link.object_new);
+ if (link.object_new) {
+ new_objects_created = true;
}
}
- CTX_DATA_END;
- BKE_layer_collection_resync_allow();
- if (source_bases_new_objects.is_empty()) {
+ if (!new_objects_created) {
return OPERATOR_CANCELLED;
}
- /* Sync the collection now, after everything is duplicated. */
- BKE_main_collection_sync(bmain);
+ /* Sync that could tag the view_layer out of sync. */
+ for (DuplicateObjectLink &link : object_base_links) {
+ /* note that this is safe to do with this context iterator,
+ * the list is made in advance */
+ ED_object_base_select(link.base_src, BA_DESELECT);
+ if (link.object_new) {
+ object_add_sync_base_collection(bmain, scene, view_layer, link.base_src, link.object_new);
+ object_add_sync_rigid_body(bmain, link.base_src->object, link.object_new);
+ }
+ }
- /* After sync we can get to the new Base data, process it here. */
- for (const auto &item : source_bases_new_objects) {
- Object *ob_new = item.second;
- Base *base_source = item.first;
- BKE_view_layer_synced_ensure(scene, view_layer);
- Base *base_new = BKE_view_layer_base_find(view_layer, ob_new);
- if (base_new == nullptr) {
+ /* Sync the view layer. Everything else should not tag the view_layer out of sync. */
+ BKE_view_layer_synced_ensure(scene, view_layer);
+ const Base *active_base = BKE_view_layer_active_base_get(view_layer);
+ for (DuplicateObjectLink &link : object_base_links) {
+ if (!link.object_new) {
continue;
}
+
+ Base *base_new = BKE_view_layer_base_find(view_layer, link.object_new);
+ BLI_assert(base_new);
ED_object_base_select(base_new, BA_SELECT);
- if (ob_new == ob_new_active) {
+ if (active_base == link.base_src) {
ED_object_base_activate(C, base_new);
}
- if (base_new->object->data) {
- DEG_id_tag_update(static_cast<ID *>(base_new->object->data), 0);
+
+ if (link.object_new->data) {
+ DEG_id_tag_update(static_cast<ID *>(link.object_new->data), 0);
}
- /* #object_add_duplicate_internal will not have done this, since
- * before the collection sync it would not have found the new base yet. */
- base_new->local_view_bits = base_source->local_view_bits;
+
+ object_add_sync_local_view(link.base_src, base_new);
}
/* Note that this will also clear newid pointers and tags. */
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 39e3c7a2f0a..8db968cbb8a 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -187,7 +187,8 @@ static void area_draw_azone_fullscreen(
min_ff(alpha, 0.75f),
0.0f,
NULL,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
/**
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc
index ee1238e0f24..8fb4dea668e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc
@@ -18,6 +18,7 @@
#include "BLI_math_vector.hh"
#include "BLI_span.hh"
#include "BLI_task.h"
+#include "BLI_task.hh"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
@@ -313,6 +314,7 @@ static EnumPropertyItem prop_sculpt_face_set_create_types[] = {
static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
{
+ using namespace blender;
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
@@ -396,25 +398,16 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
}
if (mode == SCULPT_FACE_SET_SELECTION) {
- BMesh *bm;
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
- BMeshCreateParams create_params{};
- create_params.use_toolflags = true;
- bm = BM_mesh_create(&allocsize, &create_params);
-
- BMeshFromMeshParams convert_params{};
- convert_params.calc_vert_normal = true;
- convert_params.calc_face_normal = true;
- BM_mesh_bm_from_me(bm, mesh, &convert_params);
-
- BMIter iter;
- BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- ss->face_sets[BM_elem_index_get(f)] = next_face_set;
+ const bke::AttributeAccessor attributes = mesh->attributes();
+ const VArraySpan<bool> select_poly = attributes.lookup_or_default<bool>(
+ ".select_poly", ATTR_DOMAIN_FACE, false);
+ threading::parallel_for(IndexRange(mesh->totvert), 4096, [&](const IndexRange range) {
+ for (const int i : range) {
+ if (select_poly[i]) {
+ ss->face_sets[i] = next_face_set;
+ }
}
- }
- BM_mesh_free(bm);
+ });
}
for (int i = 0; i < totnode; i++) {
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index e4085bbe9cc..240901318b5 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -410,8 +410,15 @@ static void file_draw_preview(const SpaceFile *sfile,
}
icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
icon_y = yco + (ey / 2.0f) - (icon_size * ((file->typeflag & FILE_TYPE_DIR) ? 0.78f : 0.75f));
- UI_icon_draw_ex(
- icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ icon,
+ icon_aspect / U.dpi_fac,
+ icon_opacity,
+ 0.0f,
+ icon_color,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
if (is_link || is_offline) {
@@ -424,8 +431,24 @@ static void file_draw_preview(const SpaceFile *sfile,
/* At very bottom-left if preview style. */
const uchar dark[4] = {0, 0, 0, 255};
const uchar light[4] = {255, 255, 255, 255};
- UI_icon_draw_ex(icon_x + 1, icon_y - 1, arrow, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
- UI_icon_draw_ex(icon_x, icon_y, arrow, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ UI_icon_draw_ex(icon_x + 1,
+ icon_y - 1,
+ arrow,
+ 1.0f / U.dpi_fac,
+ 0.2f,
+ 0.0f,
+ dark,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ arrow,
+ 1.0f / U.dpi_fac,
+ 0.6f,
+ 0.0f,
+ light,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
else {
/* Link to folder or non-previewed file. */
@@ -433,8 +456,15 @@ static void file_draw_preview(const SpaceFile *sfile,
UI_GetThemeColor4ubv(TH_BACK, icon_color);
icon_x = xco + ((file->typeflag & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx;
icon_y = yco + ((file->typeflag & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy;
- UI_icon_draw_ex(
- icon_x, icon_y, arrow, icon_aspect / U.dpi_fac * 1.8, 0.3f, 0.0f, icon_color, false);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ arrow,
+ icon_aspect / U.dpi_fac * 1.8,
+ 0.3f,
+ 0.0f,
+ icon_color,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
}
else if (icon && !is_icon && !(file->typeflag & FILE_TYPE_FTFONT)) {
@@ -444,8 +474,17 @@ static void file_draw_preview(const SpaceFile *sfile,
const uchar light[4] = {255, 255, 255, 255};
icon_x = xco + (2.0f * UI_DPI_FAC);
icon_y = yco + (2.0f * UI_DPI_FAC);
- UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
- UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ UI_icon_draw_ex(icon_x + 1,
+ icon_y - 1,
+ icon,
+ 1.0f / U.dpi_fac,
+ 0.2f,
+ 0.0f,
+ dark,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
+ UI_icon_draw_ex(
+ icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false, UI_NO_ICON_OVERLAY_TEXT);
}
const bool is_current_main_data = filelist_file_get_id(file) != NULL;
@@ -456,7 +495,15 @@ static void file_draw_preview(const SpaceFile *sfile,
const uchar light[4] = {255, 255, 255, 255};
icon_x = xco + ex - UI_UNIT_X;
icon_y = yco + ey - UI_UNIT_Y;
- UI_icon_draw_ex(icon_x, icon_y, ICON_CURRENT_FILE, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ UI_icon_draw_ex(icon_x,
+ icon_y,
+ ICON_CURRENT_FILE,
+ 1.0f / U.dpi_fac,
+ 0.6f,
+ 0.0f,
+ light,
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
}
/* Contrasting outline around some preview types. */
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index aee72860a0a..12ee6f45991 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -235,7 +235,8 @@ static bool textview_draw_string(TextViewDrawState *tds,
1.0f,
0.0f,
icon_fg,
- false);
+ false,
+ UI_NO_ICON_OVERLAY_TEXT);
GPU_blend(GPU_BLEND_NONE);
}
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index ee9ebd541a0..98b2cacd162 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -2145,6 +2145,9 @@ static void node_draw_basis(const bContext &C,
0,
"");
UI_but_func_set(but, node_toggle_button_cb, &node, (void *)"NODE_OT_group_edit");
+ if (node.id) {
+ UI_but_icon_indicator_number_set(but, node.id->us);
+ }
UI_block_emboss_set(&block, UI_EMBOSS);
}
if (node.type == NODE_CUSTOM && node.typeinfo->ui_icon != ICON_NONE) {
diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc
index b12afcb1faa..637c795d4d7 100644
--- a/source/blender/editors/space_node/node_relationships.cc
+++ b/source/blender/editors/space_node/node_relationships.cc
@@ -815,7 +815,8 @@ static void draw_draglink_tooltip(const bContext * /*C*/, ARegion * /*region*/,
nldrag->cursor[0];
const float y = nldrag->cursor[1] - 2.0f * UI_DPI_FAC;
- UI_icon_draw_ex(x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false);
+ UI_icon_draw_ex(
+ x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT);
}
static void draw_draglink_tooltip_activate(const ARegion &region, bNodeLinkDrag &nldrag)
diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc
index e366c58349f..f76c0980c4f 100644
--- a/source/blender/editors/space_outliner/outliner_draw.cc
+++ b/source/blender/editors/space_outliner/outliner_draw.cc
@@ -2877,7 +2877,8 @@ static bool tselem_draw_icon(uiBlock *block,
TreeStoreElem *tselem,
TreeElement *te,
float alpha,
- const bool is_clickable)
+ const bool is_clickable,
+ const int num_elements)
{
TreeElementIcon data = tree_element_get_icon(tselem, te);
if (data.icon == 0) {
@@ -2885,6 +2886,8 @@ static bool tselem_draw_icon(uiBlock *block,
}
const bool is_collection = outliner_is_collection_tree_element(te);
+ IconTextOverlay text_overlay;
+ UI_icon_text_overlay_init_from_count(&text_overlay, num_elements);
/* Collection colors and icons covered by restrict buttons. */
if (!is_clickable || x >= xmax || is_collection) {
@@ -2904,7 +2907,8 @@ static bool tselem_draw_icon(uiBlock *block,
alpha,
0.0f,
btheme->collection_color[collection->color_tag].color,
- true);
+ true,
+ &text_overlay);
return true;
}
}
@@ -2915,10 +2919,10 @@ static bool tselem_draw_icon(uiBlock *block,
/* Restrict column clip. it has been coded by simply overdrawing, doesn't work for buttons. */
uchar color[4];
if (UI_icon_get_theme_color(data.icon, color)) {
- UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true);
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true, &text_overlay);
}
else {
- UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false);
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false, &text_overlay);
}
}
else {
@@ -2941,104 +2945,6 @@ static bool tselem_draw_icon(uiBlock *block,
return true;
}
-static bool outliner_is_main_row(const ARegion *region, const int ys)
-{
- int ystart;
-
- ystart = int(region->v2d.tot.ymax);
- ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
-
- return ((ys - ystart) / UI_UNIT_Y) % 2;
-}
-
-/**
- * Get the expected row background color to use for the data-block counter
- *
- * This reproduces some of the logic of outliner_draw_highlights.
- * At the moment it doesn't implement the search match color since
- * we don't draw the data-block counter in those cases.
- */
-static void outliner_get_row_color(const ARegion *region,
- const TreeElement *te,
- int ys,
- float r_color[4])
-{
- const TreeStoreElem *tselem = TREESTORE(te);
-
- if ((tselem->flag & TSE_ACTIVE) && (tselem->flag & TSE_SELECTED)) {
- UI_GetThemeColor3fv(TH_ACTIVE, r_color);
- }
- else if (tselem->flag & TSE_SELECTED) {
- UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, r_color);
- }
- else if (outliner_is_main_row(region, ys)) {
- UI_GetThemeColor3fv(TH_BACK, r_color);
- }
- else {
- float color_alternating[4];
- UI_GetThemeColor4fv(TH_ROW_ALTERNATE, color_alternating);
- UI_GetThemeColorBlend3f(TH_BACK, TH_ROW_ALTERNATE, color_alternating[3], r_color);
- }
-
- if (tselem->flag & TSE_HIGHLIGHTED) {
- const float color_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
- interp_v3_v3v3(r_color, r_color, color_highlight, color_highlight[3]);
- }
- r_color[3] = 1.0f;
-}
-
-/**
- * For icon-only children of a collapsed tree,
- * Draw small number over the icon to show how many items of this type are displayed.
- */
-static void outliner_draw_iconrow_number(const ARegion *region,
- const uiFontStyle *fstyle,
- int offsx,
- int ys,
- const TreeElement *te_visible,
- const int num_elements)
-{
- float color[4];
- outliner_get_row_color(region, te_visible, ys, color);
-
- float ufac = 0.25f * UI_UNIT_X;
- float offset_x = float(offsx) + UI_UNIT_X * 0.35f;
- rctf rect{};
- BLI_rctf_init(&rect,
- offset_x + ufac,
- offset_x + UI_UNIT_X - ufac,
- float(ys) - UI_UNIT_Y * 0.2f + ufac,
- float(ys) - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac);
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_4fv_ex(
- &rect, color, NULL, 1.0f, color, U.pixelsize, float(UI_UNIT_Y) / 2.0f - ufac);
-
- /* Now the numbers. */
- uchar text_col[4];
-
- UI_GetThemeColor3ubv(TH_TEXT, text_col);
- text_col[3] = 255;
-
- uiFontStyle fstyle_small = *fstyle;
- fstyle_small.points *= 0.8f;
-
- /* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */
- int num_digits = 4;
- char number_text[4] = "+99";
- if (num_elements < 100) {
- BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements);
- num_digits = num_elements < 10 ? 1 : 2;
- }
- UI_fontstyle_draw_simple(&fstyle_small,
- (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f),
- float(ys) - UI_UNIT_Y * 0.095f + ufac,
- number_text,
- text_col);
- UI_fontstyle_set(fstyle);
- GPU_blend(GPU_BLEND_ALPHA); /* Round-box and text drawing disables. */
-}
-
static void outliner_icon_background_colors(float icon_color[4], float icon_border[4])
{
float text[4];
@@ -3069,11 +2975,8 @@ static void outliner_draw_active_indicator(const float minx,
GPU_blend(GPU_BLEND_ALPHA); /* Round-box disables. */
}
-static void outliner_draw_iconrow_doit(const ARegion *region,
- uiBlock *block,
- TreeElement *te_visible,
+static void outliner_draw_iconrow_doit(uiBlock *block,
TreeElement *te,
- const uiFontStyle *fstyle,
int xmax,
int *offsx,
int ys,
@@ -3102,13 +3005,13 @@ static void outliner_draw_iconrow_doit(const ARegion *region,
if (tselem->flag & TSE_HIGHLIGHTED_ICON) {
alpha_fac += 0.5;
}
- tselem_draw_icon(block, xmax, float(*offsx), float(ys), tselem, te, alpha_fac, false);
+ tselem_draw_icon(
+ block, xmax, float(*offsx), float(ys), tselem, te, alpha_fac, false, num_elements);
te->xs = *offsx;
te->ys = ys;
te->xend = short(*offsx) + UI_UNIT_X;
if (num_elements > 1) {
- outliner_draw_iconrow_number(region, fstyle, *offsx, ys, te_visible, num_elements);
te->flag |= TE_ICONROW_MERGED;
}
else {
@@ -3145,7 +3048,6 @@ static void outliner_draw_iconrow(bContext *C,
const uiFontStyle *fstyle,
const TreeViewContext *tvc,
SpaceOutliner *space_outliner,
- TreeElement *te_visible,
ListBase *lb,
int level,
int xmax,
@@ -3154,7 +3056,6 @@ static void outliner_draw_iconrow(bContext *C,
float alpha_fac,
MergedIconRow *merged)
{
- const ARegion *region = CTX_wm_region(C);
eOLDrawState active = OL_DRAWSEL_NONE;
LISTBASE_FOREACH (TreeElement *, te, lb) {
@@ -3194,8 +3095,7 @@ static void outliner_draw_iconrow(bContext *C,
TSE_POSE_CHANNEL,
TSE_POSEGRP,
TSE_DEFGROUP)) {
- outliner_draw_iconrow_doit(
- region, block, te_visible, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1);
+ outliner_draw_iconrow_doit(block, te, xmax, offsx, ys, alpha_fac, active, 1);
}
else {
const int index = tree_element_id_type_to_index(te);
@@ -3214,7 +3114,6 @@ static void outliner_draw_iconrow(bContext *C,
fstyle,
tvc,
space_outliner,
- te,
&te->subtree,
level + 1,
xmax,
@@ -3236,11 +3135,8 @@ static void outliner_draw_iconrow(bContext *C,
for (int j = 0; j < num_subtypes; j++) {
const int index = index_base + j;
if (merged->num_elements[index] != 0) {
- outliner_draw_iconrow_doit(region,
- block,
- te_visible,
+ outliner_draw_iconrow_doit(block,
merged->tree_element[index],
- fstyle,
xmax,
offsx,
ys,
@@ -3429,7 +3325,8 @@ static void outliner_draw_tree_element(bContext *C,
tselem,
te,
(tselem->flag & TSE_HIGHLIGHTED_ICON) ? alpha_fac + 0.5f : alpha_fac,
- true)) {
+ true,
+ 1)) {
offsx += UI_UNIT_X + 4 * ufac;
}
else {
@@ -3478,7 +3375,6 @@ static void outliner_draw_tree_element(bContext *C,
fstyle,
tvc,
space_outliner,
- te,
&te->subtree,
0,
xmax,
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 8b6d37caa41..1d20926d16c 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -129,7 +129,6 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce
region->regiontype = RGN_TYPE_TOOLS;
region->alignment = RGN_ALIGN_LEFT;
region->flag = RGN_FLAG_HIDDEN;
- region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
/* Channels. */
region = MEM_callocN(sizeof(ARegion), "channels for sequencer");
@@ -137,6 +136,7 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce
BLI_addtail(&sseq->regionbase, region);
region->regiontype = RGN_TYPE_CHANNELS;
region->alignment = RGN_ALIGN_LEFT;
+ region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
/* Preview region. */
/* NOTE: if you change values here, also change them in sequencer_init_preview_region. */
diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c
index 3e0ce892b5a..fcb4f549353 100644
--- a/source/blender/editors/space_view3d/view3d_navigate_walk.c
+++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c
@@ -849,11 +849,15 @@ static void walkEvent(WalkInfo *walk, const wmEvent *event)
if (ret) {
WalkTeleport *teleport = &walk->teleport;
+
+ /* Store the current navigation mode if we are not already teleporting. */
+ if (teleport->state == WALK_TELEPORT_STATE_OFF) {
+ teleport->navigation_mode = walk->navigation_mode;
+ }
teleport->state = WALK_TELEPORT_STATE_ON;
teleport->initial_time = PIL_check_seconds_timer();
teleport->duration = U.walk_navigation.teleport_time;
- teleport->navigation_mode = walk->navigation_mode;
walk_navigation_mode_set(walk, WALK_MODE_FREE);
copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]);
@@ -864,9 +868,7 @@ static void walkEvent(WalkInfo *walk, const wmEvent *event)
sub_v3_v3v3(teleport->direction, loc, teleport->origin);
}
- else {
- walk->teleport.state = WALK_TELEPORT_STATE_OFF;
- }
+
break;
}
@@ -1229,11 +1231,11 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm)
/* keep moving if we were moving */
copy_v2_v2(dvec, walk->teleport.direction);
- z_cur = walk->rv3d->viewinv[3][2];
- z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid;
+ z_cur = walk->rv3d->viewinv[3][2] / walk->grid;
+ z_new = (walk->teleport.origin[2] / walk->grid) - getFreeFallDistance(walk->gravity, t);
/* jump */
- z_new += t * walk->speed_jump * walk->grid;
+ z_new += t * walk->speed_jump;
/* duration is the jump duration */
if (t > walk->teleport.duration) {
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 34e5b78c48f..5b194ae7237 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1594,9 +1594,9 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
RNA_enum_set(op->ptr, "snap_target", t->tsnap.source_select);
eSnapTargetSelect target = t->tsnap.target_select;
- RNA_boolean_set(op->ptr, "use_snap_self", (target & SCE_SNAP_TARGET_NOT_ACTIVE) != 0);
- RNA_boolean_set(op->ptr, "use_snap_edit", (target & SCE_SNAP_TARGET_NOT_EDITED) != 0);
- RNA_boolean_set(op->ptr, "use_snap_nonedit", (target & SCE_SNAP_TARGET_NOT_NONEDITED) != 0);
+ RNA_boolean_set(op->ptr, "use_snap_self", (target & SCE_SNAP_TARGET_NOT_ACTIVE) == 0);
+ RNA_boolean_set(op->ptr, "use_snap_edit", (target & SCE_SNAP_TARGET_NOT_EDITED) == 0);
+ RNA_boolean_set(op->ptr, "use_snap_nonedit", (target & SCE_SNAP_TARGET_NOT_NONEDITED) == 0);
RNA_boolean_set(
op->ptr, "use_snap_selectable", (target & SCE_SNAP_TARGET_ONLY_SELECTABLE) != 0);
}
@@ -1721,13 +1721,18 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
-static void initSnapSpatial(TransInfo *t, float r_snap[2], float r_snap_y[2])
+static void initSnapSpatial(TransInfo *t, float r_snap[3], float *r_snap_precision)
{
+ /* Default values. */
+ r_snap[0] = r_snap[1] = 1.0f;
+ r_snap[1] = 0.0f;
+ *r_snap_precision = 0.1f;
+
if (t->spacetype == SPACE_VIEW3D) {
if (t->region->regiondata) {
View3D *v3d = t->area->spacedata.first;
- r_snap[0] = ED_view3d_grid_view_scale(t->scene, v3d, t->region, NULL) * 1.0f;
- r_snap[1] = r_snap[0] * 0.1f;
+ r_snap[0] = r_snap[1] = r_snap[2] = ED_view3d_grid_view_scale(
+ t->scene, v3d, t->region, NULL);
}
}
else if (t->spacetype == SPACE_IMAGE) {
@@ -1741,24 +1746,16 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2], float r_snap_y[2])
ED_space_image_grid_steps(sima, grid_steps_x, grid_steps_y, grid_size);
/* Snapping value based on what type of grid is used (adaptive-subdividing or custom-grid). */
r_snap[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_x, zoom_factor);
- r_snap[1] = r_snap[0] / 2.0f;
- r_snap_y[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor);
- r_snap_y[1] = r_snap_y[0] / 2.0f;
+ r_snap[1] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor);
+ *r_snap_precision = 0.5f;
}
else if (t->spacetype == SPACE_CLIP) {
- r_snap[0] = 0.125f;
- r_snap[1] = 0.0625f;
+ r_snap[0] = r_snap[1] = 0.125f;
+ *r_snap_precision = 0.5f;
}
else if (t->spacetype == SPACE_NODE) {
r_snap[0] = r_snap[1] = ED_node_grid_size();
}
- else if (t->spacetype == SPACE_GRAPH) {
- r_snap[0] = 1.0;
- r_snap[1] = 0.1f;
- }
- else {
- r_snap[0] = r_snap[1] = 1.0f;
- }
}
bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode)
@@ -1898,7 +1895,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
initSnapping(t, op); /* Initialize snapping data AFTER mode flags */
- initSnapSpatial(t, t->snap_spatial_x, t->snap_spatial_y);
+ initSnapSpatial(t, t->snap_spatial, &t->snap_spatial_precision);
/* EVIL! posemode code can switch translation to rotate when 1 bone is selected.
* will be removed (ton) */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 95686f12fe2..90f2795184b 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -555,9 +555,12 @@ typedef struct TransInfo {
/** Snapping Gears. */
float snap[2];
/** Spatial snapping gears(even when rotating, scaling... etc). */
- float snap_spatial_x[2];
- /** Spatial snapping in the Y coordinate, for non-uniform grid in UV Editor. */
- float snap_spatial_y[2];
+ float snap_spatial[3];
+ /**
+ * Precision factor that is multiplied to snap_spatial when precision
+ * modifier is enabled for snap to grid or incremental snap.
+ */
+ float snap_spatial_precision;
/** Mouse side of the current frame, 'L', 'R' or 'B' */
char frame_side;
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index fa56456d8e7..7abf0e5c00c 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -404,9 +404,11 @@ static void applyAxisConstraintVec(const TransInfo *t,
}
}
+ /* Fallback for when axes are aligned. */
+ mul_m3_v3(t->con.pmtx, out);
+
if (is_snap_to_point) {
- /* With snap points, a projection is alright, no adjustments needed. */
- mul_m3_v3(t->con.pmtx, out);
+ /* Pass. With snap points, a projection is alright, no adjustments needed. */
}
else {
const int dims = getConstraintSpaceDimension(t);
@@ -422,14 +424,9 @@ static void applyAxisConstraintVec(const TransInfo *t,
/* Disabled, as it has not proven to be really useful. (See T82386). */
// constraint_snap_plane_to_face(t, plane, out);
}
- else {
+ else if (!isPlaneProjectionViewAligned(t, plane)) {
/* View alignment correction. */
- if (!isPlaneProjectionViewAligned(t, plane)) {
- planeProjection(t, plane, in, out);
- }
- else {
- mul_m3_v3(t->con.pmtx, out);
- }
+ planeProjection(t, plane, in, out);
}
}
}
diff --git a/source/blender/editors/transform/transform_convert_node.cc b/source/blender/editors/transform/transform_convert_node.cc
index eb5eb822d69..6ab0e1fe701 100644
--- a/source/blender/editors/transform/transform_convert_node.cc
+++ b/source/blender/editors/transform/transform_convert_node.cc
@@ -155,9 +155,52 @@ static void createTransNodeData(bContext * /*C*/, TransInfo *t)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Node Transform Creation
+/** \name Flush Transform Nodes
* \{ */
+static void node_snap_grid_apply(TransInfo *t)
+{
+ int i;
+
+ if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) {
+ return;
+ }
+
+ float grid_size[2];
+ copy_v2_v2(grid_size, t->snap_spatial);
+ if (t->modifiers & MOD_PRECISION) {
+ mul_v2_fl(grid_size, t->snap_spatial_precision);
+ }
+
+ /* Early exit on unusable grid size. */
+ if (is_zero_v2(grid_size)) {
+ return;
+ }
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td;
+
+ for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
+ float iloc[2], loc[2], tvec[2];
+ if (td->flag & TD_SKIP) {
+ continue;
+ }
+
+ if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) {
+ continue;
+ }
+
+ copy_v2_v2(iloc, td->loc);
+
+ loc[0] = roundf(iloc[0] / grid_size[0]) * grid_size[0];
+ loc[1] = roundf(iloc[1] / grid_size[1]) * grid_size[1];
+
+ sub_v2_v2v2(tvec, loc, iloc);
+ add_v2_v2(td->loc, tvec);
+ }
+ }
+}
+
static void flushTransNodes(TransInfo *t)
{
using namespace blender::ed;
@@ -191,7 +234,7 @@ static void flushTransNodes(TransInfo *t)
}
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- applyGridAbsolute(t);
+ node_snap_grid_apply(t);
/* flush to 2d vector from internally used 3d vector */
for (int i = 0; i < tc->data_len; i++) {
diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
index f7f9e14b8ac..76ce7b29619 100644
--- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include "BLI_math.h"
+#include "BLI_math_bits.h"
#include "BLI_string.h"
#include "BKE_context.h"
@@ -62,7 +63,14 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
}
if (td->val) {
- *td->val = td->ival * ratio;
+ if (td->ival == 0.0f && ratio > 1.0f) {
+ /* Allow Shrink/Fatten for zero radius. */
+ *td->val = (ratio - 1.0f) * uint_as_float(POINTER_AS_UINT(t->custom.mode.data));
+ }
+ else {
+ *td->val = td->ival * ratio;
+ }
+
/* apply PET */
*td->val = interpf(*td->val, td->ival, td->factor);
CLAMP_MIN(*td->val, 0.0f);
@@ -92,6 +100,13 @@ void initCurveShrinkFatten(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
t->flag |= T_NO_CONSTRAINT;
+
+ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
+ /* Save a factor to multiply the ratio and use in zero radius cases. */
+ RegionView3D *rv3d = t->region->regiondata;
+ float scale_factor = rv3d->pixsize * t->mouse.factor * t->zfac;
+ t->custom.mode.data = POINTER_FROM_UINT(float_as_uint(scale_factor));
+ }
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
index 91388ecd661..c751a68092f 100644
--- a/source/blender/editors/transform/transform_mode_translate.c
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -170,7 +170,7 @@ static void transdata_elem_translate_fn(void *__restrict iter_data_v,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Transform (Translation)
+/** \name Transform (Translation) Header
* \{ */
static void translate_dist_to_str(char *r_str,
@@ -341,6 +341,96 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform (Translation) Snapping
+ * \{ */
+
+static void translate_snap_target_grid_ensure(TransInfo *t)
+{
+ /* Only need to calculate once. */
+ if ((t->tsnap.status & TARGET_GRID_INIT) == 0) {
+ if (t->data_type == &TransConvertType_Cursor3D) {
+ /* Use a fallback when transforming the cursor.
+ * In this case the center is _not_ derived from the cursor which is being transformed. */
+ copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc);
+ }
+ else if (t->around == V3D_AROUND_CURSOR) {
+ /* Use a fallback for cursor selection,
+ * this isn't useful as a global center for absolute grid snapping
+ * since its not based on the position of the selection. */
+ tranform_snap_target_median_calc(t, t->tsnap.snapTargetGrid);
+ }
+ else {
+ copy_v3_v3(t->tsnap.snapTargetGrid, t->center_global);
+ }
+ t->tsnap.status |= TARGET_GRID_INIT;
+ }
+}
+
+static void translate_snap_grid_apply(TransInfo *t,
+ const int max_index,
+ const float grid_dist[3],
+ const float loc[3],
+ float r_out[3])
+{
+ BLI_assert(max_index <= 2);
+ translate_snap_target_grid_ensure(t);
+ const float *center_global = t->tsnap.snapTargetGrid;
+ const float *asp = t->aspect;
+
+ float in[3];
+ if (t->con.mode & CON_APPLY) {
+ BLI_assert(t->tsnap.snapElem == SCE_SNAP_MODE_NONE);
+ t->con.applyVec(t, NULL, NULL, loc, in);
+ }
+ else {
+ copy_v3_v3(in, loc);
+ }
+
+ for (int i = 0; i <= max_index; i++) {
+ const float iter_fac = grid_dist[i] * asp[i];
+ r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i];
+ }
+}
+
+static bool translate_snap_grid(TransInfo *t, float *val)
+{
+ if (!activeSnap(t)) {
+ return false;
+ }
+
+ if (!(t->tsnap.mode & SCE_SNAP_MODE_GRID) || validSnap(t)) {
+ /* Don't do grid snapping if there is a valid snap point. */
+ return false;
+ }
+
+ /* Don't do grid snapping if not in 3D viewport or UV editor */
+ if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
+ return false;
+ }
+
+ if (t->mode != TFM_TRANSLATION) {
+ return false;
+ }
+
+ float grid_dist[3];
+ copy_v3_v3(grid_dist, t->snap_spatial);
+ if (t->modifiers & MOD_PRECISION) {
+ mul_v3_fl(grid_dist, t->snap_spatial_precision);
+ }
+
+ /* Early bailing out if no need to snap */
+ if (is_zero_v3(grid_dist)) {
+ return false;
+ }
+
+ translate_snap_grid_apply(t, t->idx_max, grid_dist, val, val);
+ t->tsnap.snapElem = SCE_SNAP_MODE_GRID;
+ return true;
+}
+
static void ApplySnapTranslation(TransInfo *t, float vec[3])
{
float point[3];
@@ -372,6 +462,12 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3])
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform (Translation)
+ * \{ */
+
static void applyTranslationValue(TransInfo *t, const float vec[3])
{
struct TranslateCustomData *custom_data = t->custom.mode.data;
@@ -514,7 +610,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
t->tsnap.snapElem = SCE_SNAP_MODE_NONE;
applySnappingAsGroup(t, global_dir);
- transform_snap_grid(t, global_dir);
+ translate_snap_grid(t, global_dir);
if (t->con.mode & CON_APPLY) {
float in[3];
@@ -590,7 +686,8 @@ void initTranslation(TransInfo *t)
t->num.flag = 0;
t->num.idx_max = t->idx_max;
- copy_v2_v2(t->snap, t->snap_spatial_x);
+ t->snap[0] = 1.0;
+ t->snap[1] = t->snap_spatial_precision;
copy_v3_fl(t->num.val_inc, t->snap[0]);
t->num.unit_sys = t->scene->unit.system;
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 553202b5798..672d947936d 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -511,56 +511,6 @@ void applySnappingIndividual(TransInfo *t)
}
}
-void applyGridAbsolute(TransInfo *t)
-{
- int i;
-
- if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) {
- return;
- }
-
- float grid_size_x = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_x[1] : t->snap_spatial_x[0];
- float grid_size_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0];
- float grid_size_z = grid_size_x;
-
- /* Early exit on unusable grid size. */
- if (grid_size_x == 0.0f || grid_size_y == 0.0f || grid_size_z == 0.0f) {
- return;
- }
-
- FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *td;
-
- for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
- float iloc[3], loc[3], tvec[3];
- if (td->flag & TD_SKIP) {
- continue;
- }
-
- if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) {
- continue;
- }
-
- copy_v3_v3(iloc, td->loc);
- if (tc->use_local_mat) {
- mul_m4_v3(tc->mat, iloc);
- }
- else if (t->options & CTX_OBJECT) {
- BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
- copy_v3_v3(iloc, td->ob->obmat[3]);
- }
-
- loc[0] = roundf(iloc[0] / grid_size_x) * grid_size_x;
- loc[1] = roundf(iloc[1] / grid_size_y) * grid_size_y;
- loc[2] = roundf(iloc[2] / grid_size_z) * grid_size_z;
-
- sub_v3_v3v3(tvec, loc, iloc);
- mul_m3_v3(td->smtx, tvec);
- add_v3_v3(td->loc, tvec);
- }
- }
-}
-
void applySnappingAsGroup(TransInfo *t, float *vec)
{
if (!activeSnap_SnappingAsGroup(t)) {
@@ -1187,7 +1137,7 @@ static void snap_calc_sequencer_fn(TransInfo *t, float *UNUSED(vec))
/** \name Target
* \{ */
-static void snap_target_median_impl(TransInfo *t, float r_median[3])
+void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3])
{
int i_accum = 0;
@@ -1223,28 +1173,6 @@ static void snap_target_median_impl(TransInfo *t, float r_median[3])
// TargetSnapOffset(t, NULL);
}
-static void snap_target_grid_ensure(TransInfo *t)
-{
- /* Only need to calculate once. */
- if ((t->tsnap.status & TARGET_GRID_INIT) == 0) {
- if (t->data_type == &TransConvertType_Cursor3D) {
- /* Use a fallback when transforming the cursor.
- * In this case the center is _not_ derived from the cursor which is being transformed. */
- copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc);
- }
- else if (t->around == V3D_AROUND_CURSOR) {
- /* Use a fallback for cursor selection,
- * this isn't useful as a global center for absolute grid snapping
- * since its not based on the position of the selection. */
- snap_target_median_impl(t, t->tsnap.snapTargetGrid);
- }
- else {
- copy_v3_v3(t->tsnap.snapTargetGrid, t->center_global);
- }
- t->tsnap.status |= TARGET_GRID_INIT;
- }
-}
-
static void TargetSnapOffset(TransInfo *t, TransData *td)
{
if (t->spacetype == SPACE_NODE && td != NULL) {
@@ -1316,7 +1244,7 @@ static void TargetSnapMedian(TransInfo *t)
{
/* Only need to calculate once. */
if ((t->tsnap.status & TARGET_INIT) == 0) {
- snap_target_median_impl(t, t->tsnap.snapTarget);
+ tranform_snap_target_median_calc(t, t->tsnap.snapTarget);
t->tsnap.status |= TARGET_INIT;
}
}
@@ -1654,66 +1582,6 @@ bool snapNodesTransform(
/** \name snap Grid
* \{ */
-static void snap_grid_apply(TransInfo *t,
- const int max_index,
- const float grid_dist_x,
- const float grid_dist_y,
- const float loc[3],
- float r_out[3])
-{
- BLI_assert(max_index <= 2);
- snap_target_grid_ensure(t);
- const float *center_global = t->tsnap.snapTargetGrid;
- const float *asp = t->aspect;
-
- float in[3];
- if (t->con.mode & CON_APPLY) {
- BLI_assert(t->tsnap.snapElem == SCE_SNAP_MODE_NONE);
- t->con.applyVec(t, NULL, NULL, loc, in);
- }
- else {
- copy_v3_v3(in, loc);
- }
-
- for (int i = 0; i <= max_index; i++) {
- const float iter_fac = ((i == 1) ? grid_dist_y : grid_dist_x) * asp[i];
- r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i];
- }
-}
-
-bool transform_snap_grid(TransInfo *t, float *val)
-{
- if (!activeSnap(t)) {
- return false;
- }
-
- if (!(t->tsnap.mode & SCE_SNAP_MODE_GRID) || validSnap(t)) {
- /* Don't do grid snapping if there is a valid snap point. */
- return false;
- }
-
- /* Don't do grid snapping if not in 3D viewport or UV editor */
- if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) {
- return false;
- }
-
- if (t->mode != TFM_TRANSLATION) {
- return false;
- }
-
- float grid_dist_x = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_x[1] : t->snap_spatial_x[0];
- float grid_dist_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0];
-
- /* Early bailing out if no need to snap */
- if (grid_dist_x == 0.0f || grid_dist_y == 0.0f) {
- return false;
- }
-
- snap_grid_apply(t, t->idx_max, grid_dist_x, grid_dist_y, val, val);
- t->tsnap.snapElem = SCE_SNAP_MODE_GRID;
- return true;
-}
-
static void snap_increment_apply_ex(const TransInfo *UNUSED(t),
const int max_index,
const float increment_val,
diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h
index 2b78c554ad8..16d9062e978 100644
--- a/source/blender/editors/transform/transform_snap.h
+++ b/source/blender/editors/transform/transform_snap.h
@@ -38,10 +38,10 @@ bool snapNodesTransform(struct TransInfo *t,
bool transformModeUseSnap(const TransInfo *t);
+void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3]);
bool transform_snap_increment_ex(const TransInfo *t, bool use_local_space, float *r_val);
bool transform_snap_increment(const TransInfo *t, float *val);
float transform_snap_increment_get(const TransInfo *t);
-bool transform_snap_grid(TransInfo *t, float *val);
bool activeSnap(const TransInfo *t);
bool activeSnap_SnappingIndividual(const TransInfo *t);
@@ -52,7 +52,6 @@ bool validSnap(const TransInfo *t);
void initSnapping(struct TransInfo *t, struct wmOperator *op);
void freeSnapping(struct TransInfo *t);
void applySnappingIndividual(TransInfo *t);
-void applyGridAbsolute(TransInfo *t);
void applySnappingAsGroup(TransInfo *t, float *vec);
void resetSnapping(TransInfo *t);
eRedrawFlag handleSnapping(TransInfo *t, const struct wmEvent *event);
diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc
index 5c03367cba8..4da1559b726 100644
--- a/source/blender/editors/util/ed_viewer_path.cc
+++ b/source/blender/editors/util/ed_viewer_path.cc
@@ -249,6 +249,9 @@ bool is_active_geometry_nodes_viewer(const bContext &C,
if (md->type != eModifierType_Nodes) {
return false;
}
+ if ((md->mode & eModifierMode_Realtime) == 0) {
+ return false;
+ }
modifier = reinterpret_cast<const NodesModifierData *>(md);
break;
}
diff --git a/source/blender/editors/uvedit/uvedit_islands.cc b/source/blender/editors/uvedit/uvedit_islands.cc
index bdd05b06d94..92745667505 100644
--- a/source/blender/editors/uvedit/uvedit_islands.cc
+++ b/source/blender/editors/uvedit/uvedit_islands.cc
@@ -600,6 +600,22 @@ static BoxPack *pack_islands_params(const blender::Vector<FaceIsland *> &island_
return box_array;
}
+static bool island_has_pins(FaceIsland *island)
+{
+ BMLoop *l;
+ BMIter iter;
+ const int cd_loop_uv_offset = island->cd_loop_uv_offset;
+ for (int i = 0; i < island->faces_len; i++) {
+ BM_ITER_ELEM (l, &iter, island->faces[i], BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = static_cast<MLoopUV *>(BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset));
+ if (luv->flag & MLOOPUV_PINNED) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
/* -------------------------------------------------------------------- */
/** \name Public UV Island Packing
*
@@ -651,8 +667,14 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
aspect_y,
cd_loop_uv_offset);
- int index;
- LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list, index) {
+ /* Remove from linked list and append to blender::Vector. */
+ LISTBASE_FOREACH_MUTABLE (struct FaceIsland *, island, &island_list) {
+ BLI_remlink(&island_list, island);
+ if (params->ignore_pinned && island_has_pins(island)) {
+ MEM_freeN(island->faces);
+ MEM_freeN(island);
+ continue;
+ }
island_vector.append(island);
}
}
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 5e2d9097abd..b65f4889347 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -37,6 +37,7 @@
#include "BKE_node.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "ED_image.h"
#include "ED_mesh.h"
@@ -113,7 +114,8 @@ bool ED_object_get_active_image(Object *ob,
bNode **r_node,
bNodeTree **r_ntree)
{
- Material *ma = BKE_object_material_get(ob, mat_nr);
+ Material *ma = DEG_is_evaluated_object(ob) ? BKE_object_material_get_eval(ob, mat_nr) :
+ BKE_object_material_get(ob, mat_nr);
bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL;
bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL;
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 2c977552e72..ecaba3234a7 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -1050,31 +1050,6 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
/** \name Pack UV Islands Operator
* \{ */
-/**
- * \warning Since this uses #ParamHandle it doesn't work with non-manifold meshes (see T82637).
- * Use #ED_uvedit_pack_islands_multi for a more general solution.
- *
- * TODO: remove this function, in favor of #ED_uvedit_pack_islands_multi.
- */
-static void uvedit_pack_islands_multi(const Scene *scene,
- Object **objects,
- const uint objects_len,
- const UnwrapOptions *options,
- bool rotate,
- bool ignore_pinned)
-{
- ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, options);
- GEO_uv_parametrizer_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned);
- GEO_uv_parametrizer_flush(handle);
- GEO_uv_parametrizer_delete(handle);
-
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *obedit = objects[ob_index];
- DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data);
- }
-}
-
/* Packing targets. */
enum {
PACK_UDIM_SRC_CLOSEST = 0,
@@ -1119,16 +1094,22 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
const bool use_udim_params = ED_uvedit_udim_params_from_image_space(
sima, use_active, &udim_params);
- struct UVPackIsland_Params params = {
+ const struct UVPackIsland_Params pack_island_params = {
.rotate = RNA_boolean_get(op->ptr, "rotate"),
- .only_selected_uvs = true,
- .only_selected_faces = true,
- .correct_aspect = true,
+ .only_selected_uvs = options.only_selected_uvs,
+ .only_selected_faces = options.only_selected_faces,
+ .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams,
+ .correct_aspect = options.correct_aspect,
+ .ignore_pinned = false,
.margin_method = RNA_enum_get(op->ptr, "margin_method"),
.margin = RNA_float_get(op->ptr, "margin"),
};
- ED_uvedit_pack_islands_multi(
- scene, objects, objects_len, NULL, use_udim_params ? &udim_params : NULL, &params);
+ ED_uvedit_pack_islands_multi(scene,
+ objects,
+ objects_len,
+ NULL,
+ use_udim_params ? &udim_params : NULL,
+ &pack_island_params);
MEM_freeN(objects);
return OPERATOR_FINISHED;
@@ -1889,12 +1870,19 @@ void ED_uvedit_live_unwrap(const Scene *scene, Object **objects, int objects_len
.fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0,
.correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0,
};
-
- bool rotate = true;
- bool ignore_pinned = true;
-
uvedit_unwrap_multi(scene, objects, objects_len, &options, NULL);
- uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
+
+ const struct UVPackIsland_Params pack_island_params = {
+ .rotate = true,
+ .only_selected_uvs = options.only_selected_uvs,
+ .only_selected_faces = options.only_selected_faces,
+ .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams,
+ .correct_aspect = options.correct_aspect,
+ .ignore_pinned = true,
+ .margin_method = ED_UVPACK_MARGIN_SCALED,
+ .margin = scene->toolsettings->uvcalc_margin,
+ };
+ ED_uvedit_pack_islands_multi(scene, objects, objects_len, NULL, NULL, &pack_island_params);
}
}
@@ -1926,8 +1914,6 @@ static int unwrap_exec(bContext *C, wmOperator *op)
.correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"),
};
- bool rotate = true;
- bool ignore_pinned = true;
if (CTX_wm_space_image(C)) {
/* Inside the UV Editor, only unwrap selected UVs. */
options.only_selected_uvs = true;
@@ -2032,7 +2018,18 @@ static int unwrap_exec(bContext *C, wmOperator *op)
.count_failed = 0,
};
uvedit_unwrap_multi(scene, objects, objects_len, &options, &result_info);
- uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned);
+
+ const struct UVPackIsland_Params pack_island_params = {
+ .rotate = true,
+ .only_selected_uvs = options.only_selected_uvs,
+ .only_selected_faces = options.only_selected_faces,
+ .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams,
+ .correct_aspect = options.correct_aspect,
+ .ignore_pinned = true,
+ .margin_method = RNA_enum_get(op->ptr, "margin_method"),
+ .margin = RNA_float_get(op->ptr, "margin"),
+ };
+ ED_uvedit_pack_islands_multi(scene, objects, objects_len, NULL, NULL, &pack_island_params);
MEM_freeN(objects);
diff --git a/source/blender/geometry/intern/fillet_curves.cc b/source/blender/geometry/intern/fillet_curves.cc
index 1bbbee6edef..2479458f88d 100644
--- a/source/blender/geometry/intern/fillet_curves.cc
+++ b/source/blender/geometry/intern/fillet_curves.cc
@@ -148,12 +148,14 @@ static float limit_radius(const float3 &position_prev,
const float displacement_prev = radius_prev * std::tan(angle_prev / 2.0f);
const float segment_length_prev = math::distance(position, position_prev);
const float total_displacement_prev = displacement_prev + displacement;
- const float factor_prev = std::clamp(segment_length_prev / total_displacement_prev, 0.0f, 1.0f);
+ const float factor_prev = std::clamp(
+ safe_divide(segment_length_prev, total_displacement_prev), 0.0f, 1.0f);
const float displacement_next = radius_next * std::tan(angle_next / 2.0f);
const float segment_length_next = math::distance(position, position_next);
const float total_displacement_next = displacement_next + displacement;
- const float factor_next = std::clamp(segment_length_next / total_displacement_next, 0.0f, 1.0f);
+ const float factor_next = std::clamp(
+ safe_divide(segment_length_next, total_displacement_next), 0.0f, 1.0f);
return radius * std::min(factor_prev, factor_next);
}
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 5a1e0cde1d8..58b1cd0a50b 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -282,6 +282,8 @@ set(GLSL_SRC
shaders/gpu_shader_2D_image_vert.glsl
shaders/gpu_shader_2D_image_rect_vert.glsl
shaders/gpu_shader_2D_image_multi_rect_vert.glsl
+ shaders/gpu_shader_icon_frag.glsl
+ shaders/gpu_shader_icon_vert.glsl
shaders/gpu_shader_image_frag.glsl
shaders/gpu_shader_image_desaturate_frag.glsl
shaders/gpu_shader_image_overlays_merge_frag.glsl
@@ -349,6 +351,7 @@ set(GLSL_SRC
shaders/compositor/compositor_morphological_distance_feather.glsl
shaders/compositor/compositor_morphological_distance_threshold.glsl
shaders/compositor/compositor_morphological_step.glsl
+ shaders/compositor/compositor_normalize.glsl
shaders/compositor/compositor_parallel_reduction.glsl
shaders/compositor/compositor_projector_lens_distortion.glsl
shaders/compositor/compositor_realize_on_domain.glsl
@@ -357,6 +360,8 @@ set(GLSL_SRC
shaders/compositor/compositor_split_viewer.glsl
shaders/compositor/compositor_symmetric_blur.glsl
shaders/compositor/compositor_symmetric_separable_blur.glsl
+ shaders/compositor/compositor_tone_map_photoreceptor.glsl
+ shaders/compositor/compositor_tone_map_simple.glsl
shaders/compositor/library/gpu_shader_compositor_alpha_over.glsl
shaders/compositor/library/gpu_shader_compositor_blur_common.glsl
@@ -606,6 +611,7 @@ set(SRC_SHADER_CREATE_INFOS
shaders/infos/gpu_shader_3D_smooth_color_info.hh
shaders/infos/gpu_shader_3D_uniform_color_info.hh
shaders/infos/gpu_shader_gpencil_stroke_info.hh
+ shaders/infos/gpu_shader_icon_info.hh
shaders/infos/gpu_shader_instance_varying_color_varying_size_info.hh
shaders/infos/gpu_shader_keyframe_shape_info.hh
shaders/infos/gpu_shader_line_dashed_uniform_color_info.hh
@@ -631,6 +637,7 @@ set(SRC_SHADER_CREATE_INFOS
shaders/compositor/infos/compositor_morphological_distance_info.hh
shaders/compositor/infos/compositor_morphological_distance_threshold_info.hh
shaders/compositor/infos/compositor_morphological_step_info.hh
+ shaders/compositor/infos/compositor_normalize_info.hh
shaders/compositor/infos/compositor_parallel_reduction_info.hh
shaders/compositor/infos/compositor_projector_lens_distortion_info.hh
shaders/compositor/infos/compositor_realize_on_domain_info.hh
@@ -639,6 +646,8 @@ set(SRC_SHADER_CREATE_INFOS
shaders/compositor/infos/compositor_split_viewer_info.hh
shaders/compositor/infos/compositor_symmetric_blur_info.hh
shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh
+ shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh
+ shaders/compositor/infos/compositor_tone_map_simple_info.hh
)
set(SRC_SHADER_CREATE_INFOS_MTL
diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h
index b59ea9e55d2..ac82774039a 100644
--- a/source/blender/gpu/GPU_context.h
+++ b/source/blender/gpu/GPU_context.h
@@ -21,6 +21,8 @@ extern "C" {
* automatically initializes the back-end, and #GPU_context_discard frees it when there
* are no more contexts. */
bool GPU_backend_supported(void);
+void GPU_backend_type_selection_set(const eGPUBackendType backend);
+eGPUBackendType GPU_backend_type_selection_get(void);
eGPUBackendType GPU_backend_get_type(void);
/** Opaque type hiding blender::gpu::Context. */
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 3f35db42eb9..1148207fc57 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -209,6 +209,10 @@ typedef enum eGPUBuiltinShader {
GPU_SHADER_KEYFRAME_SHAPE,
GPU_SHADER_SIMPLE_LIGHTING,
/**
+ * Draw an icon, leaving a semi-transparent rectangle on top of the icon.
+ */
+ GPU_SHADER_ICON,
+ /**
* Take a 2D position and color for each vertex with linear interpolation in window space.
*
* \param color: in vec4
diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc
index 48d7b2019c5..f6b88c4231c 100644
--- a/source/blender/gpu/intern/gpu_context.cc
+++ b/source/blender/gpu/intern/gpu_context.cc
@@ -223,9 +223,19 @@ void GPU_render_step()
/* NOTE: To enable Metal API, we need to temporarily change this to `GPU_BACKEND_METAL`.
* Until a global switch is added, Metal also needs to be enabled in GHOST_ContextCGL:
* `m_useMetalForRendering = true`. */
-static const eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL;
+static eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL;
static GPUBackend *g_backend = nullptr;
+void GPU_backend_type_selection_set(const eGPUBackendType backend)
+{
+ g_backend_type = backend;
+}
+
+eGPUBackendType GPU_backend_type_selection_get()
+{
+ return g_backend_type;
+}
+
bool GPU_backend_supported(void)
{
switch (g_backend_type) {
diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh
index 76e816e7f65..5afcc102e44 100644
--- a/source/blender/gpu/intern/gpu_framebuffer_private.hh
+++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh
@@ -95,11 +95,6 @@ class FrameBuffer {
#endif
public:
- /* Reference of a pointer that needs to be cleaned when deallocating the frame-buffer.
- * Points to #BPyGPUFrameBuffer::fb */
- void **ref = nullptr;
-
- public:
FrameBuffer(const char *name);
virtual ~FrameBuffer();
diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc
index 3b4accf9cc5..81c0a65bb7c 100644
--- a/source/blender/gpu/intern/gpu_immediate.cc
+++ b/source/blender/gpu/intern/gpu_immediate.cc
@@ -45,7 +45,7 @@ void immBindShader(GPUShader *shader)
BLI_assert(imm->shader == nullptr);
imm->shader = shader;
- imm->builtin_shader_bound = GPU_SHADER_TEXT; /* Default value. */
+ imm->builtin_shader_bound = std::nullopt;
if (!imm->vertex_format.packed) {
VertexFormat_pack(&imm->vertex_format);
@@ -125,9 +125,12 @@ static void wide_line_workaround_start(GPUPrimType prim_type)
/* No need to change the shader. */
return;
}
+ if (!imm->builtin_shader_bound) {
+ return;
+ }
eGPUBuiltinShader polyline_sh;
- switch (imm->builtin_shader_bound) {
+ switch (*imm->builtin_shader_bound) {
case GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR:
polyline_sh = GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR;
break;
@@ -180,8 +183,8 @@ static void wide_line_workaround_end()
}
immUnbindProgram();
- immBindBuiltinProgram(imm->prev_builtin_shader);
- imm->prev_builtin_shader = GPU_SHADER_TEXT;
+ immBindBuiltinProgram(*imm->prev_builtin_shader);
+ imm->prev_builtin_shader = std::nullopt;
}
}
diff --git a/source/blender/gpu/intern/gpu_immediate_private.hh b/source/blender/gpu/intern/gpu_immediate_private.hh
index 74ebbdc7ae3..c4e11e7082b 100644
--- a/source/blender/gpu/intern/gpu_immediate_private.hh
+++ b/source/blender/gpu/intern/gpu_immediate_private.hh
@@ -9,6 +9,8 @@
#pragma once
+#include <optional>
+
#include "GPU_batch.h"
#include "GPU_primitive.h"
#include "GPU_shader.h"
@@ -42,9 +44,9 @@ class Immediate {
/** Wide Line workaround. */
/** Previously bound shader to restore after drawing. */
- eGPUBuiltinShader prev_builtin_shader = GPU_SHADER_TEXT;
- /** Builtin shader index. Used to test if the workaround can be done. */
- eGPUBuiltinShader builtin_shader_bound = GPU_SHADER_TEXT;
+ std::optional<eGPUBuiltinShader> prev_builtin_shader;
+ /** Builtin shader index. Used to test if the line width workaround can be done. */
+ std::optional<eGPUBuiltinShader> builtin_shader_bound;
/** Uniform color: Kept here to update the wide-line shader just before #immBegin. */
float uniform_color[4];
diff --git a/source/blender/gpu/intern/gpu_shader_builder.cc b/source/blender/gpu/intern/gpu_shader_builder.cc
index 3aa2963ecd0..abb45ca074a 100644
--- a/source/blender/gpu/intern/gpu_shader_builder.cc
+++ b/source/blender/gpu/intern/gpu_shader_builder.cc
@@ -15,6 +15,8 @@
#include "GPU_init_exit.h"
#include "gpu_shader_create_info_private.hh"
+#include "BLI_vector.hh"
+
#include "CLG_log.h"
namespace blender::gpu::shader_builder {
@@ -41,6 +43,22 @@ void ShaderBuilder::init()
CLG_init();
GHOST_GLSettings glSettings = {0};
+ switch (GPU_backend_type_selection_get()) {
+ case GPU_BACKEND_OPENGL:
+ glSettings.context_type = GHOST_kDrawingContextTypeOpenGL;
+ break;
+
+#ifdef WITH_METAL_BACKEND
+ case GPU_BACKEND_METAL:
+ glSettings.context_type = GHOST_kDrawingContextTypeMetal;
+ break;
+#endif
+
+ default:
+ BLI_assert_unreachable();
+ break;
+ }
+
ghost_system_ = GHOST_CreateSystem();
ghost_context_ = GHOST_CreateOpenGLContext(ghost_system_, glSettings);
GHOST_ActivateOpenGLContext(ghost_context_);
@@ -73,13 +91,32 @@ int main(int argc, const char *argv[])
int exit_code = 0;
- blender::gpu::shader_builder::ShaderBuilder builder;
- builder.init();
- if (!builder.bake_create_infos()) {
- exit_code = 1;
+ struct NamedBackend {
+ std::string name;
+ eGPUBackendType backend;
+ };
+
+ blender::Vector<NamedBackend> backends_to_validate;
+ backends_to_validate.append({"OpenGL", GPU_BACKEND_OPENGL});
+#ifdef WITH_METAL_BACKEND
+ backends_to_validate.append({"Metal", GPU_BACKEND_METAL});
+#endif
+ for (NamedBackend &backend : backends_to_validate) {
+ GPU_backend_type_selection_set(backend.backend);
+ if (!GPU_backend_supported()) {
+ printf("%s isn't supported on this platform. Shader compilation is skipped\n",
+ backend.name.c_str());
+ continue;
+ }
+ blender::gpu::shader_builder::ShaderBuilder builder;
+ builder.init();
+ if (!builder.bake_create_infos()) {
+ printf("Shader compilation failed for %s backend\n", backend.name.c_str());
+ exit_code = 1;
+ }
+ builder.exit();
}
- builder.exit();
- exit(exit_code);
+ exit(exit_code);
return exit_code;
}
diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
index 7a06ede5c6d..65bda7ba858 100644
--- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
+++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
@@ -46,6 +46,15 @@ void IMB_freeImBuf(ImBuf * /*ibuf*/)
BLI_assert_unreachable();
}
+struct ImBuf *IMB_allocImBuf(unsigned int /*x*/,
+ unsigned int /*y*/,
+ unsigned char /*planes*/,
+ unsigned int /*flags*/)
+{
+ BLI_assert_unreachable();
+ return nullptr;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c
index 8a6586e06f6..470643ba863 100644
--- a/source/blender/gpu/intern/gpu_shader_builtin.c
+++ b/source/blender/gpu/intern/gpu_shader_builtin.c
@@ -153,6 +153,11 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.create_info = "gpu_shader_2D_diag_stripes",
},
+ [GPU_SHADER_ICON] =
+ {
+ .name = "GPU_SHADER_ICON",
+ .create_info = "gpu_shader_icon",
+ },
[GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] =
{
.name = "GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE",
diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm
index e9804d4be77..988fb9b793b 100644
--- a/source/blender/gpu/metal/mtl_batch.mm
+++ b/source/blender/gpu/metal/mtl_batch.mm
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
@@ -68,7 +69,7 @@ void MTLBatch::MTLVertexDescriptorCache::vertex_descriptor_cache_ensure()
}
}
- /* Initialise cache if not ready. */
+ /* Initialize cache if not ready. */
if (cache_context_ == nullptr) {
this->vertex_descriptor_cache_init(MTLContext::get());
}
@@ -188,7 +189,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
buffer_stride);
}
else {
- /* Ensure stride is correct for de-interlevaed attributes. */
+ /* Ensure stride is correct for de-interleaved attributes. */
desc.vertex_descriptor.buffer_layouts[buffer_index].stride = buffer_stride;
}
@@ -278,7 +279,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
* elements).
*
* Certain conversion cannot be performed however, and in these cases, we need to
- * instruct the shader to generate a specialised version with a conversion routine upon
+ * instruct the shader to generate a specialized version with a conversion routine upon
* attribute read.
* - This handles cases such as conversion between types e.g. Integer to float without
* normalization.
@@ -310,7 +311,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts,
* This then controls how a given attribute is interpreted. The data will be read
* as specified and then converted appropriately to the correct form.
*
- * e.g. if `GPU_FETCH_INT_TO_FLOAT` is specified, the specialised read-routine
+ * e.g. if `GPU_FETCH_INT_TO_FLOAT` is specified, the specialized read-routine
* in the shader will read the data as an int, and cast this to floating point
* representation. (Rather than reading the source data as float).
*
@@ -403,7 +404,7 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_first, uint v_count, uint i_fi
active_shader_ = (shader) ? static_cast<MTLShader *>(unwrap(shader)) : nullptr;
if (active_shader_ == nullptr || !active_shader_->is_valid()) {
- /* Skip drawing if there is no vaid Metal shader.
+ /* Skip drawing if there is no valid Metal shader.
* This will occur if the path through which the shader is prepared
* is invalid (e.g. Python without create-info), or, the source shader uses a geometry pass. */
BLI_assert_msg(false, "No valid Metal shader!");
@@ -455,7 +456,7 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_first, uint v_count, uint i_fi
/* Fetch RenderPassState to enable resource binding for active pass. */
MTLRenderPassState &rps = ctx->main_command_buffer.get_render_pass_state();
- /* Debug Check: Ensure Framebuffer instance is not dirty. */
+ /* Debug Check: Ensure Frame-buffer instance is not dirty. */
BLI_assert(!ctx->main_command_buffer.get_active_framebuffer()->get_dirty());
/* Bind Shader. */
@@ -495,8 +496,8 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_first, uint v_count, uint i_fi
if (mtl_elem != nullptr) {
- /* Fetch index buffer. This function can situationally return an optimised
- * index buffer of a different primtiive type. If this is the case, `final_prim_type`
+ /* Fetch index buffer. This function can situationally return an optimized
+ * index buffer of a different primitive type. If this is the case, `final_prim_type`
* and `v_count` will be updated with the new format.
* NOTE: For indexed rendering, v_count represents the number of indices. */
idx_buffer = mtl_elem->get_index_buffer(final_prim_type, v_count);
@@ -594,8 +595,10 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings(
desc.reset_vertex_descriptor();
/* Fetch Vertex and Instance Buffers. */
- Span<MTLVertBuf *> mtl_verts(reinterpret_cast<MTLVertBuf **>(this->verts), GPU_BATCH_VBO_MAX_LEN);
- Span<MTLVertBuf *> mtl_inst(reinterpret_cast<MTLVertBuf **>(this->inst), GPU_BATCH_INST_VBO_MAX_LEN);
+ Span<MTLVertBuf *> mtl_verts(reinterpret_cast<MTLVertBuf **>(this->verts),
+ GPU_BATCH_VBO_MAX_LEN);
+ Span<MTLVertBuf *> mtl_inst(reinterpret_cast<MTLVertBuf **>(this->inst),
+ GPU_BATCH_INST_VBO_MAX_LEN);
/* SSBO Vertex fetch also passes vertex descriptor information into the shader. */
if (active_shader_->get_uses_ssbo_vertex_fetch()) {
@@ -671,7 +674,7 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings(
}
}
- /* Extract Vertex attribues (First-bound vertex buffer takes priority). */
+ /* Extract Vertex attributes (First-bound vertex buffer takes priority). */
for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) {
if (mtl_verts[v] != NULL) {
MTL_LOG_INFO(" -- [Batch] Checking bindings for bound vertex buffer %p\n", mtl_verts[v]);
@@ -829,7 +832,7 @@ void MTLBatch::draw_advanced(int v_first, int v_count, int i_first, int i_count)
"Index offset is not 2/4-byte aligned as per METAL spec");
/* Fetch index buffer. May return an index buffer of a differing format,
- * if index buffer optimisation is used. In these cases, final_prim_type and
+ * if index buffer optimization is used. In these cases, final_prim_type and
* index_count get updated with the new properties. */
GPUPrimType final_prim_type = this->prim_type;
uint index_count = v_count;
diff --git a/source/blender/gpu/metal/mtl_drawlist.mm b/source/blender/gpu/metal/mtl_drawlist.mm
index 76e2abb4ea6..99194d2b72c 100644
--- a/source/blender/gpu/metal/mtl_drawlist.mm
+++ b/source/blender/gpu/metal/mtl_drawlist.mm
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
/** \file
* \ingroup gpu
*
@@ -151,7 +153,7 @@ void MTLDrawList::submit()
{
/* Metal does not support MDI from the host side, but we still benefit from only executing the
* batch bind a single time, rather than per-draw.
- * NOTE(Metal): Consider using MTLIndirectCommandBuffer to achieve similar behaviour. */
+ * NOTE(Metal): Consider using #MTLIndirectCommandBuffer to achieve similar behavior. */
if (command_len_ == 0) {
return;
}
@@ -192,12 +194,12 @@ void MTLDrawList::submit()
/* Common properties. */
MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(batch_->prim_type);
- /* Execute multidraw indirect. */
+ /* Execute multi-draw indirect. */
if (can_use_MDI && false) {
/* Metal Doesn't support MDI -- Singular Indirect draw calls are supported,
- * but Multidraw is not.
- * TODO(Metal): Consider using IndirectCommandBuffers to provide similar
- * behaviour. */
+ * but Multi-draw is not.
+ * TODO(Metal): Consider using #IndirectCommandBuffers to provide similar
+ * behavior. */
}
else {
@@ -214,7 +216,7 @@ void MTLDrawList::submit()
uint32_t index_count = cmd->indexCount;
/* Fetch index buffer. May return an index buffer of a differing format,
- * if index buffer optimisation is used. In these cases, mtl_prim_type and
+ * if index buffer optimization is used. In these cases, mtl_prim_type and
* index_count get updated with the new properties. */
GPUPrimType final_prim_type = batch_->prim_type;
id<MTLBuffer> index_buffer = mtl_elem->get_index_buffer(final_prim_type, index_count);
diff --git a/source/blender/gpu/metal/mtl_texture.mm b/source/blender/gpu/metal/mtl_texture.mm
index 4931f8a4f52..29dcc8d32ee 100644
--- a/source/blender/gpu/metal/mtl_texture.mm
+++ b/source/blender/gpu/metal/mtl_texture.mm
@@ -1510,7 +1510,7 @@ bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo)
texture_descriptor_.mipmapLevelCount = mtl_max_mips_;
texture_descriptor_.usage =
MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite |
- MTLTextureUsagePixelFormatView; /* TODO(Metal): Optimise usage flags. */
+ MTLTextureUsagePixelFormatView; /* TODO(Metal): Optimize usage flags. */
texture_descriptor_.storageMode = [source_buffer storageMode];
texture_descriptor_.sampleCount = 1;
texture_descriptor_.cpuCacheMode = [source_buffer cpuCacheMode];
diff --git a/source/blender/gpu/opengl/gl_batch.cc b/source/blender/gpu/opengl/gl_batch.cc
index ff8867fe3e6..28105e326ee 100644
--- a/source/blender/gpu/opengl/gl_batch.cc
+++ b/source/blender/gpu/opengl/gl_batch.cc
@@ -272,8 +272,8 @@ void GLBatch::bind(int i_first)
#if GPU_TRACK_INDEX_RANGE
/* Can be removed if GL 4.3 is required. */
- if (!GLContext::fixed_restart_index_support && (elem != nullptr)) {
- glPrimitiveRestartIndex(this->elem_()->restart_index());
+ if (!GLContext::fixed_restart_index_support) {
+ glPrimitiveRestartIndex((elem != nullptr) ? this->elem_()->restart_index() : 0xFFFFFFFFu);
}
#endif
diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc
index c9432fca561..ef97d74bf81 100644
--- a/source/blender/gpu/opengl/gl_shader_interface.cc
+++ b/source/blender/gpu/opengl/gl_shader_interface.cc
@@ -200,6 +200,9 @@ static Type gpu_type_from_gl_type(int gl_type)
GLShaderInterface::GLShaderInterface(GLuint program)
{
+ GLuint last_program;
+ glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&last_program);
+
/* Necessary to make #glUniform works. */
glUseProgram(program);
@@ -385,6 +388,8 @@ GLShaderInterface::GLShaderInterface(GLuint program)
// this->debug_print();
this->sort_inputs();
+
+ glUseProgram(last_program);
}
GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateInfo &info)
@@ -442,6 +447,9 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI
uint32_t name_buffer_offset = 0;
/* Necessary to make #glUniform works. TODO(fclem) Remove. */
+ GLuint last_program;
+ glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&last_program);
+
glUseProgram(program);
/* Attributes */
@@ -552,6 +560,8 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI
this->sort_inputs();
// this->debug_print();
+
+ glUseProgram(last_program);
}
GLShaderInterface::~GLShaderInterface()
diff --git a/source/blender/gpu/shaders/compositor/compositor_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_blur.glsl
index 4f981c84f59..c7ac620f99b 100644
--- a/source/blender/gpu/shaders/compositor/compositor_blur.glsl
+++ b/source/blender/gpu/shaders/compositor/compositor_blur.glsl
@@ -18,13 +18,24 @@ vec4 load_input(ivec2 texel)
}
/* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from
- * the weights texture, where the texel (0, 0) is considered the center of weights texture. */
+ * the weights texture, where the given texel (0, 0) corresponds the center of weights texture.
+ * Note that we load the weights texture inverted along both directions to maintain the shape of
+ * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D
+ * weights texture whose right half is all ones and whose left half is all zeros. Further, consider
+ * that we are blurring a single white pixel on a black background. When computing the value of a
+ * pixel that is to the right of the white pixel, the white pixel will be in the left region of the
+ * search window, and consequently, without inversion, a zero will be sampled from the left side of
+ * the weights texture and result will be zero. However, what we expect is that pixels to the right
+ * of the white pixel will be white, that is, they should sample a weight of 1 from the right side
+ * of the weights texture, hence the need for inversion. */
vec4 load_weight(ivec2 texel)
{
- /* Add the radius to transform the texel into the range [0, radius * 2], then divide by the upper
- * bound plus one to transform the texel into the normalized range [0, 1] needed to sample the
- * weights sampler. Finally, also add 0.5 to sample at the center of the pixels. */
- return texture(weights_tx, (texel + vec2(radius + 0.5)) / (radius * 2 + 1));
+ /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5
+ * to sample at the center of the pixels, then divide by the upper bound plus one to transform
+ * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally,
+ * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as
+ * mentioned in the function description. */
+ return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1)));
}
void main()
diff --git a/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl b/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl
index e7e5aac12a5..9383bbf9825 100644
--- a/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl
+++ b/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl
@@ -2,7 +2,16 @@
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
/* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from
- * the weights texture, where the texel (0, 0) is considered the center of weights texture. */
+ * the weights texture, where the given texel (0, 0) corresponds the center of weights texture.
+ * Note that we load the weights texture inverted along both directions to maintain the shape of
+ * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D
+ * weights texture whose right half is all ones and whose left half is all zeros. Further, consider
+ * that we are blurring a single white pixel on a black background. When computing the value of a
+ * pixel that is to the right of the white pixel, the white pixel will be in the left region of the
+ * search window, and consequently, without inversion, a zero will be sampled from the left side of
+ * the weights texture and result will be zero. However, what we expect is that pixels to the right
+ * of the white pixel will be white, that is, they should sample a weight of 1 from the right side
+ * of the weights texture, hence the need for inversion. */
vec4 load_weight(ivec2 texel, float radius)
{
/* The center zero texel is always assigned a unit weight regardless of the corresponding weight
@@ -12,10 +21,12 @@ vec4 load_weight(ivec2 texel, float radius)
return vec4(1.0);
}
- /* Add the radius to transform the texel into the range [0, radius * 2], then divide by the upper
- * bound plus one to transform the texel into the normalized range [0, 1] needed to sample the
- * weights sampler. Finally, also add 0.5 to sample at the center of the pixels. */
- return texture(weights_tx, (texel + vec2(radius + 0.5)) / (radius * 2 + 1));
+ /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5
+ * to sample at the center of the pixels, then divide by the upper bound plus one to transform
+ * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally,
+ * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as
+ * mentioned in the function description. */
+ return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1)));
}
void main()
diff --git a/source/blender/gpu/shaders/compositor/compositor_normalize.glsl b/source/blender/gpu/shaders/compositor/compositor_normalize.glsl
new file mode 100644
index 00000000000..53dfeb01730
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/compositor_normalize.glsl
@@ -0,0 +1,10 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
+
+void main()
+{
+ ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
+ float value = texture_load(input_tx, texel).x;
+ float normalized_value = (value - minimum) * scale;
+ float clamped_value = clamp(normalized_value, 0.0, 1.0);
+ imageStore(output_img, texel, vec4(clamped_value));
+}
diff --git a/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl b/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl
new file mode 100644
index 00000000000..167006585ca
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl
@@ -0,0 +1,22 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
+
+/* Tone mapping based on equation (1) and the trilinear interpolation between equations (6) and (7)
+ * from Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor
+ * physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. */
+void main()
+{
+ ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
+
+ vec4 input_color = texture_load(input_tx, texel);
+ float input_luminance = dot(input_color.rgb, luminance_coefficients);
+
+ /* Trilinear interpolation between equations (6) and (7) from Reinhard's 2005 paper. */
+ vec4 local_adaptation_level = mix(vec4(input_luminance), input_color, chromatic_adaptation);
+ vec4 adaptation_level = mix(global_adaptation_level, local_adaptation_level, light_adaptation);
+
+ /* Equation (1) from Reinhard's 2005 paper, assuming Vmax is 1. */
+ vec4 semi_saturation = pow(intensity * adaptation_level, vec4(contrast));
+ vec4 tone_mapped_color = input_color / (input_color + semi_saturation);
+
+ imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a));
+}
diff --git a/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl b/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl
new file mode 100644
index 00000000000..ce42d021dd1
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl
@@ -0,0 +1,26 @@
+#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
+#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl)
+
+/* Tone mapping based on equation (3) from Reinhard, Erik, et al. "Photographic tone reproduction
+ * for digital images." Proceedings of the 29th annual conference on Computer graphics and
+ * interactive techniques. 2002. */
+void main()
+{
+ ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
+
+ vec4 input_color = texture_load(input_tx, texel);
+
+ /* Equation (2) from Reinhard's 2002 paper. */
+ vec4 scaled_color = input_color * luminance_scale;
+
+ /* Equation (3) from Reinhard's 2002 paper, but with the 1 replaced with the blend factor for
+ * more flexibility. See ToneMapOperation::compute_luminance_scale_blend_factor. */
+ vec4 denominator = luminance_scale_blend_factor + scaled_color;
+ vec4 tone_mapped_color = safe_divide(scaled_color, denominator);
+
+ if (inverse_gamma != 0.0) {
+ tone_mapped_color = pow(max(tone_mapped_color, vec4(0.0)), vec4(inverse_gamma));
+ }
+
+ imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a));
+}
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh
new file mode 100644
index 00000000000..02fdc424014
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(compositor_normalize)
+ .local_group_size(16, 16)
+ .push_constant(Type::FLOAT, "minimum")
+ .push_constant(Type::FLOAT, "scale")
+ .sampler(0, ImageType::FLOAT_2D, "input_tx")
+ .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .compute_source("compositor_normalize.glsl")
+ .do_static_compilation(true);
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh
index 2e661f280af..e2252b14758 100644
--- a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh
@@ -12,14 +12,17 @@ GPU_SHADER_CREATE_INFO(compositor_parallel_reduction_shared)
* Sum Reductions.
*/
-GPU_SHADER_CREATE_INFO(compositor_sum_float_shared)
+GPU_SHADER_CREATE_INFO(compositor_sum_shared)
.additional_info("compositor_parallel_reduction_shared")
- .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
- .define("TYPE", "float")
.define("IDENTITY", "vec4(0.0)")
- .define("LOAD(value)", "value.x")
.define("REDUCE(lhs, rhs)", "lhs + rhs");
+GPU_SHADER_CREATE_INFO(compositor_sum_float_shared)
+ .additional_info("compositor_sum_shared")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .define("TYPE", "float")
+ .define("LOAD(value)", "value.x");
+
GPU_SHADER_CREATE_INFO(compositor_sum_red)
.additional_info("compositor_sum_float_shared")
.define("INITIALIZE(value)", "value.r")
@@ -41,6 +44,20 @@ GPU_SHADER_CREATE_INFO(compositor_sum_luminance)
.define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)")
.do_static_compilation(true);
+GPU_SHADER_CREATE_INFO(compositor_sum_log_luminance)
+ .additional_info("compositor_sum_float_shared")
+ .push_constant(Type::VEC3, "luminance_coefficients")
+ .define("INITIALIZE(value)", "log(max(dot(value.rgb, luminance_coefficients), 1e-5))")
+ .do_static_compilation(true);
+
+GPU_SHADER_CREATE_INFO(compositor_sum_color)
+ .additional_info("compositor_sum_shared")
+ .image(0, GPU_RGBA32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .define("TYPE", "vec4")
+ .define("INITIALIZE(value)", "value")
+ .define("LOAD(value)", "value")
+ .do_static_compilation(true);
+
/* --------------------------------------------------------------------
* Sum Of Squared Difference Reductions.
*/
@@ -74,3 +91,59 @@ GPU_SHADER_CREATE_INFO(compositor_sum_luminance_squared_difference)
.push_constant(Type::VEC3, "luminance_coefficients")
.define("INITIALIZE(value)", "pow(dot(value.rgb, luminance_coefficients) - subtrahend, 2.0)")
.do_static_compilation(true);
+
+/* --------------------------------------------------------------------
+ * Maximum Reductions.
+ */
+
+GPU_SHADER_CREATE_INFO(compositor_maximum_luminance)
+ .additional_info("compositor_parallel_reduction_shared")
+ .typedef_source("common_math_lib.glsl")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .push_constant(Type::VEC3, "luminance_coefficients")
+ .define("TYPE", "float")
+ .define("IDENTITY", "vec4(FLT_MIN)")
+ .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)")
+ .define("LOAD(value)", "value.x")
+ .define("REDUCE(lhs, rhs)", "max(lhs, rhs)")
+ .do_static_compilation(true);
+
+GPU_SHADER_CREATE_INFO(compositor_maximum_float_in_range)
+ .additional_info("compositor_parallel_reduction_shared")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .push_constant(Type::FLOAT, "lower_bound")
+ .push_constant(Type::FLOAT, "upper_bound")
+ .define("TYPE", "float")
+ .define("IDENTITY", "vec4(lower_bound)")
+ .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : lower_bound")
+ .define("LOAD(value)", "value.x")
+ .define("REDUCE(lhs, rhs)", "((rhs > lhs) && (rhs <= upper_bound)) ? rhs : lhs")
+ .do_static_compilation(true);
+
+/* --------------------------------------------------------------------
+ * Minimum Reductions.
+ */
+
+GPU_SHADER_CREATE_INFO(compositor_minimum_luminance)
+ .additional_info("compositor_parallel_reduction_shared")
+ .typedef_source("common_math_lib.glsl")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .push_constant(Type::VEC3, "luminance_coefficients")
+ .define("TYPE", "float")
+ .define("IDENTITY", "vec4(FLT_MAX)")
+ .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)")
+ .define("LOAD(value)", "value.x")
+ .define("REDUCE(lhs, rhs)", "min(lhs, rhs)")
+ .do_static_compilation(true);
+
+GPU_SHADER_CREATE_INFO(compositor_minimum_float_in_range)
+ .additional_info("compositor_parallel_reduction_shared")
+ .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .push_constant(Type::FLOAT, "lower_bound")
+ .push_constant(Type::FLOAT, "upper_bound")
+ .define("TYPE", "float")
+ .define("IDENTITY", "vec4(upper_bound)")
+ .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : upper_bound")
+ .define("LOAD(value)", "value.x")
+ .define("REDUCE(lhs, rhs)", "((rhs < lhs) && (rhs >= lower_bound)) ? rhs : lhs")
+ .do_static_compilation(true);
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh
new file mode 100644
index 00000000000..a460c9d58a6
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(compositor_tone_map_photoreceptor)
+ .local_group_size(16, 16)
+ .push_constant(Type::VEC4, "global_adaptation_level")
+ .push_constant(Type::FLOAT, "contrast")
+ .push_constant(Type::FLOAT, "intensity")
+ .push_constant(Type::FLOAT, "chromatic_adaptation")
+ .push_constant(Type::FLOAT, "light_adaptation")
+ .push_constant(Type::VEC3, "luminance_coefficients")
+ .sampler(0, ImageType::FLOAT_2D, "input_tx")
+ .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .compute_source("compositor_tone_map_photoreceptor.glsl")
+ .do_static_compilation(true);
diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh
new file mode 100644
index 00000000000..2b220af9460
--- /dev/null
+++ b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(compositor_tone_map_simple)
+ .local_group_size(16, 16)
+ .push_constant(Type::FLOAT, "luminance_scale")
+ .push_constant(Type::FLOAT, "luminance_scale_blend_factor")
+ .push_constant(Type::FLOAT, "inverse_gamma")
+ .sampler(0, ImageType::FLOAT_2D, "input_tx")
+ .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
+ .compute_source("compositor_tone_map_simple.glsl")
+ .do_static_compilation(true);
diff --git a/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl
new file mode 100644
index 00000000000..4452349f23c
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl
@@ -0,0 +1,42 @@
+/**
+ * Draw the icons, leaving a semi-transparent rectangle on top of the icon.
+ *
+ * The top-left corner of the rectangle is rounded and drawned with anti-alias.
+ * The anti-alias is done by transitioning from the outer to the inner radius of
+ * the rounded corner, and the rectangle sides.
+ */
+
+void main()
+{
+ /* Top-left rounded corner parameters. */
+ const float circle_radius_outer = 0.1;
+ const float circle_radius_inner = 0.075;
+
+ /**
+ * Add a bit transparency to see a bit of the icon, without
+ * getting on the way of readability. */
+ const float mask_transparency = 0.25;
+
+ vec2 circle_center = vec2(circle_radius_outer - text_width, 0.5);
+ fragColor = texture(image, texCoord_interp) * color;
+
+ /* radius in icon space (1 is the icon width). */
+ float radius = length(mask_coord_interp - circle_center);
+ float mask = smoothstep(circle_radius_inner, circle_radius_outer, radius);
+
+ bool lower_half = mask_coord_interp.y < circle_center.y;
+ bool right_half = mask_coord_interp.x > circle_center.x;
+
+ if (right_half && mask_coord_interp.y < circle_center.y + circle_radius_outer) {
+ mask = smoothstep(circle_center.y + circle_radius_inner,
+ circle_center.y + circle_radius_outer,
+ mask_coord_interp.y);
+ }
+ if (lower_half && mask_coord_interp.x > circle_center.x - circle_radius_outer) {
+ mask = smoothstep(circle_center.x - circle_radius_inner,
+ circle_center.x - circle_radius_outer,
+ mask_coord_interp.x);
+ }
+
+ fragColor = mix(vec4(0.0), fragColor, max(mask_transparency, mask));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl b/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl
new file mode 100644
index 00000000000..25f64bfe0b6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl
@@ -0,0 +1,37 @@
+/**
+ * Simple shader that just draw one icon at the specified location
+ * does not need any vertex input (producing less call to immBegin/End)
+ */
+
+void main()
+{
+ vec2 uv;
+ vec2 co;
+
+ if (gl_VertexID == 0) {
+ co = rect_geom.xw;
+ uv = rect_icon.xw;
+ mask_coord_interp = vec2(0, 1);
+ }
+ else if (gl_VertexID == 1) {
+ co = rect_geom.xy;
+ uv = rect_icon.xy;
+ mask_coord_interp = vec2(0, 0);
+ }
+ else if (gl_VertexID == 2) {
+ co = rect_geom.zw;
+ uv = rect_icon.zw;
+ mask_coord_interp = vec2(1, 1);
+ }
+ else {
+ co = rect_geom.zy;
+ uv = rect_icon.zy;
+ mask_coord_interp = vec2(1, 0);
+ }
+
+ /* Put origin in lower right corner. */
+ mask_coord_interp.x -= 1;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f);
+ texCoord_interp = uv;
+}
diff --git a/source/blender/gpu/shaders/infos/gpu_interface_info.hh b/source/blender/gpu/shaders/infos/gpu_interface_info.hh
index d77c65e48a7..060def16f81 100644
--- a/source/blender/gpu/shaders/infos/gpu_interface_info.hh
+++ b/source/blender/gpu/shaders/infos/gpu_interface_info.hh
@@ -18,3 +18,6 @@ GPU_SHADER_INTERFACE_INFO(smooth_radii_outline_iface, "").smooth(Type::VEC4, "ra
GPU_SHADER_INTERFACE_INFO(flat_color_smooth_tex_coord_interp_iface, "")
.flat(Type::VEC4, "finalColor")
.smooth(Type::VEC2, "texCoord_interp");
+GPU_SHADER_INTERFACE_INFO(smooth_icon_interp_iface, "")
+ .smooth(Type::VEC2, "texCoord_interp")
+ .smooth(Type::VEC2, "mask_coord_interp");
diff --git a/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh
new file mode 100644
index 00000000000..3d4077bdb09
--- /dev/null
+++ b/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "gpu_interface_info.hh"
+#include "gpu_shader_create_info.hh"
+
+GPU_SHADER_CREATE_INFO(gpu_shader_icon)
+ .vertex_out(smooth_icon_interp_iface)
+ .fragment_out(0, Type::VEC4, "fragColor")
+ .push_constant(Type::MAT4, "ModelViewProjectionMatrix")
+ .push_constant(Type::VEC4, "color")
+ .push_constant(Type::VEC4, "rect_icon")
+ .push_constant(Type::VEC4, "rect_geom")
+ .push_constant(Type::FLOAT, "text_width")
+ .sampler(0, ImageType::FLOAT_2D, "image")
+ .vertex_source("gpu_shader_icon_vert.glsl")
+ .fragment_source("gpu_shader_icon_frag.glsl")
+ .do_static_compilation(true);
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 8965700c08a..eaa72441fb6 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -498,7 +498,9 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
rv->anim = anim;
get_proxy_filepath(rv->anim, rv->proxy_size, filepath, true);
- BLI_make_existing_file(filepath);
+ if (!BLI_make_existing_file(filepath)) {
+ return NULL;
+ }
rv->of = avformat_alloc_context();
rv->of->oformat = av_guess_format("avi", NULL, NULL);
@@ -905,6 +907,14 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
}
}
+ if (context->proxy_ctx[0] == NULL && context->proxy_ctx[1] == NULL &&
+ context->proxy_ctx[2] == NULL && context->proxy_ctx[3] == NULL) {
+ avformat_close_input(&context->iFormatCtx);
+ avcodec_free_context(&context->iCodecCtx);
+ MEM_freeN(context);
+ return NULL; /* Nothing to transcode. */
+ }
+
for (i = 0; i < num_indexers; i++) {
if (tcs_in_use & tc_types[i]) {
char filepath[FILE_MAX];
diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c
index dd509677d8d..5ed6b2b9843 100644
--- a/source/blender/imbuf/intern/util_gpu.c
+++ b/source/blender/imbuf/intern/util_gpu.c
@@ -174,6 +174,7 @@ static void *imb_gpu_get_data(const ImBuf *ibuf,
/* Other colorspace, store as float texture to avoid precision loss. */
data_rect = MEM_mallocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__);
*r_freedata = freedata = true;
+ is_float_rect = true;
if (data_rect == NULL) {
return NULL;
diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc
index f08514dc45c..2531bd62609 100644
--- a/source/blender/io/alembic/intern/abc_reader_mesh.cc
+++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc
@@ -763,7 +763,7 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh,
std::map<std::string, int> mat_map;
bke::MutableAttributeAccessor attributes = new_mesh->attributes_for_write();
bke::SpanAttributeWriter<int> material_indices =
- attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE);
+ attributes.lookup_or_add_for_write_span<int>("material_index", ATTR_DOMAIN_FACE);
assign_facesets_to_material_indices(sample_sel, material_indices.span, mat_map);
material_indices.finish();
}
@@ -823,8 +823,8 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const ISampleSel
{
std::map<std::string, int> mat_map;
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
- bke::SpanAttributeWriter<int> material_indices =
- attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE);
+ bke::SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
+ "material_index", ATTR_DOMAIN_FACE);
assign_facesets_to_material_indices(sample_sel, material_indices.span, mat_map);
material_indices.finish();
utils::assign_materials(bmain, m_object, mat_map);
diff --git a/source/blender/io/stl/CMakeLists.txt b/source/blender/io/stl/CMakeLists.txt
index 3a21da5c579..f7eb933d198 100644
--- a/source/blender/io/stl/CMakeLists.txt
+++ b/source/blender/io/stl/CMakeLists.txt
@@ -2,7 +2,7 @@
set(INC
.
- ./importer
+ importer
../common
../../blenkernel
../../blenlib
diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc
index 77c79852141..01db6baeb5c 100644
--- a/source/blender/io/usd/intern/usd_reader_mesh.cc
+++ b/source/blender/io/usd/intern/usd_reader_mesh.cc
@@ -804,8 +804,8 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot
std::map<pxr::SdfPath, int> mat_map;
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
- bke::SpanAttributeWriter<int> material_indices =
- attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE);
+ bke::SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_span<int>(
+ "material_index", ATTR_DOMAIN_FACE);
this->assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map);
material_indices.finish();
/* Build material name map if it's not built yet. */
@@ -914,7 +914,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
std::map<pxr::SdfPath, int> mat_map;
bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write();
bke::SpanAttributeWriter<int> material_indices =
- attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE);
+ attributes.lookup_or_add_for_write_span<int>("material_index", ATTR_DOMAIN_FACE);
assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map);
material_indices.finish();
}
diff --git a/source/blender/io/wavefront_obj/CMakeLists.txt b/source/blender/io/wavefront_obj/CMakeLists.txt
index f7958ef4ec6..bfbc715a45f 100644
--- a/source/blender/io/wavefront_obj/CMakeLists.txt
+++ b/source/blender/io/wavefront_obj/CMakeLists.txt
@@ -2,8 +2,8 @@
set(INC
.
- ./exporter
- ./importer
+ exporter
+ importer
../common
../../blenkernel
../../blenlib
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 315bcbd971c..c7962db8198 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -2083,6 +2083,12 @@ typedef enum CMPNodeLevelsChannel {
CMP_NODE_LEVLES_LUMINANCE_BT709 = 5,
} CMPNodeLevelsChannel;
+/* Tone Map Node. Stored in NodeTonemap.type. */
+typedef enum CMPNodeToneMapType {
+ CMP_NODE_TONE_MAP_SIMPLE = 0,
+ CMP_NODE_TONE_MAP_PHOTORECEPTOR = 1,
+} CMPNodeToneMapType;
+
/* Plane track deform node. */
enum {
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 16c101c15d3..1776376b8ce 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -473,6 +473,7 @@ typedef struct ImageFormatData {
#define R_IMF_IMTYPE_THEORA 33
#define R_IMF_IMTYPE_PSD 34
#define R_IMF_IMTYPE_WEBP 35
+#define R_IMF_IMTYPE_AV1 36
#define R_IMF_IMTYPE_INVALID 255
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index 0d04d7df067..50fd51e88a1 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -116,8 +116,8 @@ blender_add_lib(bf_dna "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# -----------------------------------------------------------------------------
# Build bf_dna_blenlib library
set(INC
+ ..
../../blenlib
- ../../makesdna
../../../../intern/atomic
../../../../intern/guardedalloc
)
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index a5a7fd84203..a4830dfed36 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -201,7 +201,7 @@ set(INC
../../imbuf
../../makesdna
../../modifiers
- ../../nodes/
+ ../../nodes
../../sequencer
../../simulation
../../windowmanager
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index b986b720447..e4bc3b3ffd3 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -3630,6 +3630,10 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Use Vertex", "Use this brush in grease pencil vertex color mode");
+ prop = RNA_def_property(srna, "use_paint_sculpt_curves", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "ob_mode", OB_MODE_SCULPT_CURVES);
+ RNA_def_property_ui_text(prop, "Use Sculpt", "Use this brush in sculpt curves mode");
+
/* texture */
prop = RNA_def_property(srna, "texture_slot", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "BrushTextureSlot");
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 4a36443ca42..320ef169ae5 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -9,11 +9,8 @@
#include <stdlib.h>
#include "DNA_armature_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_cachefile_types.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
@@ -21,20 +18,13 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
-#include "BLI_rand.h"
+#include "BLI_math_base.h"
+#include "BLI_math_rotation.h"
#include "BLI_string_utils.h"
#include "BLT_translation.h"
#include "BKE_animsys.h"
-#include "BKE_data_transfer.h"
-#include "BKE_dynamicpaint.h"
-#include "BKE_effect.h"
-#include "BKE_fluid.h" /* For BKE_fluid_modifier_free & BKE_fluid_modifier_create_type_data */
-#include "BKE_mesh_mapping.h"
-#include "BKE_mesh_remap.h"
-#include "BKE_multires.h"
#include "RNA_access.h"
#include "RNA_define.h"
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index a22ed5d1d5c..f437f3b698f 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -328,7 +328,9 @@ void rna_object_vcollayer_name_set(struct PointerRNA *ptr,
PointerRNA rna_object_shapekey_index_get(struct ID *id, int value);
int rna_object_shapekey_index_set(struct ID *id, PointerRNA value, int current);
-void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag);
+void rna_def_object_type_visibility_flags_common(StructRNA *srna,
+ int noteflag,
+ const char *update_func);
int rna_object_type_visibility_icon_get_common(int object_type_exclude_viewport,
const int *object_type_exclude_select);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 9252d790261..b1a2c1243b8 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -6020,6 +6020,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
{FFMPEG_MKV, "MKV", 0, "Matroska", ""},
{FFMPEG_FLV, "FLASH", 0, "Flash", ""},
{FFMPEG_WEBM, "WEBM", 0, "WebM", ""},
+ {AV_CODEC_ID_AV1, "AV1", 0, "AV1", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -6037,7 +6038,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
{AV_CODEC_ID_PNG, "PNG", 0, "PNG", ""},
{AV_CODEC_ID_QTRLE, "QTRLE", 0, "QT rle / QT Animation", ""},
{AV_CODEC_ID_THEORA, "THEORA", 0, "Theora", ""},
- {AV_CODEC_ID_VP9, "WEBM", 0, "WEBM / VP9", ""},
+ {AV_CODEC_ID_VP9, "WEBM", 0, "WebM / VP9", ""},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 5c192b80dc1..b2663b89333 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -990,6 +990,13 @@ static PointerRNA rna_SpaceView3D_region_3d_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_RegionView3D, regiondata);
}
+static void rna_SpaceView3D_object_type_visibility_update(Main *UNUSED(bmain),
+ Scene *scene,
+ PointerRNA *UNUSED(ptr))
+{
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+}
+
static void rna_SpaceView3D_region_quadviews_begin(CollectionPropertyIterator *iter,
PointerRNA *ptr)
{
@@ -5086,7 +5093,8 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_mirror_xr_session_update");
rna_def_object_type_visibility_flags_common(srna,
- NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING);
+ NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING,
+ "rna_SpaceView3D_object_type_visibility_update");
/* Helper for drawing the icon. */
prop = RNA_def_property(srna, "icon_from_show_object_viewport", PROP_INT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c
index b3896919275..9790a85e1c8 100644
--- a/source/blender/makesrna/intern/rna_space_api.c
+++ b/source/blender/makesrna/intern/rna_space_api.c
@@ -119,7 +119,9 @@ void RNA_api_space_text(StructRNA *srna)
RNA_def_function_output(func, parm);
}
-void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag)
+void rna_def_object_type_visibility_flags_common(StructRNA *srna,
+ int noteflag,
+ const char *update_func)
{
PropertyRNA *prop;
@@ -173,7 +175,7 @@ void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag)
RNA_def_property_boolean_negative_sdna(
prop, NULL, view_mask_member[mask_index], info[type_index].type_mask);
RNA_def_property_ui_text(prop, info[type_index].name, "");
- RNA_def_property_update(prop, noteflag, NULL);
+ RNA_def_property_update(prop, noteflag, update_func);
}
}
}
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 5b5544120a1..eebe595820e 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -99,13 +99,6 @@ static const EnumPropertyItem event_ndof_type_items[] = {
{NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""},
{NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""},
{NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""},
-# if 0 /* Never used (converted to keyboard events by GHOST). */
- /* keyboard emulation */
- {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"},
- {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "Alt"},
- {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "Shift"},
- {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "Ctrl"},
-# endif
/* general-purpose buttons */
{NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""},
{NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""},
@@ -120,6 +113,21 @@ static const EnumPropertyItem event_ndof_type_items[] = {
{NDOF_BUTTON_A, "NDOF_BUTTON_A", 0, "Button A", ""},
{NDOF_BUTTON_B, "NDOF_BUTTON_B", 0, "Button B", ""},
{NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "Button C", ""},
+ /* View buttons. */
+ {NDOF_BUTTON_V1, "NDOF_BUTTON_V1", 0, "View 1", ""},
+ {NDOF_BUTTON_V2, "NDOF_BUTTON_V2", 0, "View 2", ""},
+ {NDOF_BUTTON_V3, "NDOF_BUTTON_V3", 0, "View 3", ""},
+# if 0 /* Never used (converted to keyboard events by GHOST). */
+ /* keyboard emulation */
+ {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"},
+ {NDOF_BUTTON_ENTER, "NDOF_BUTTON_ENTER", 0, "Enter"},
+ {NDOF_BUTTON_DELETE, "NDOF_BUTTON_DELETE", 0, "Delete"},
+ {NDOF_BUTTON_TAB, "NDOF_BUTTON_TAB", 0, "Tab"},
+ {NDOF_BUTTON_SPACE, "NDOF_BUTTON_SPACE", 0, "Space"},
+ {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "Alt"},
+ {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "Shift"},
+ {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "Ctrl"},
+# endif
{0, NULL, 0, NULL, NULL},
};
#endif /* RNA_RUNTIME */
diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c
index dcfa1bbca51..c803e5dc9a8 100644
--- a/source/blender/makesrna/intern/rna_xr.c
+++ b/source/blender/makesrna/intern/rna_xr.c
@@ -2052,7 +2052,7 @@ static void rna_def_xr_session_settings(BlenderRNA *brna)
"Allow the VR tracking origin to be defined independently of the headset location");
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
- rna_def_object_type_visibility_flags_common(srna, NC_WM | ND_XR_DATA_CHANGED);
+ rna_def_object_type_visibility_flags_common(srna, NC_WM | ND_XR_DATA_CHANGED, NULL);
/* Helper for drawing the icon. */
prop = RNA_def_property(srna, "icon_from_show_object_viewport", PROP_INT, PROP_NONE);
diff --git a/source/blender/nodes/composite/nodes/node_composite_normalize.cc b/source/blender/nodes/composite/nodes/node_composite_normalize.cc
index 21765825468..34fd63e5805 100644
--- a/source/blender/nodes/composite/nodes/node_composite_normalize.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_normalize.cc
@@ -5,7 +5,9 @@
* \ingroup cmpnodes
*/
+#include "COM_algorithm_parallel_reduction.hh"
#include "COM_node_operation.hh"
+#include "COM_utilities.hh"
#include "node_composite_util.hh"
@@ -15,19 +17,60 @@ namespace blender::nodes::node_composite_normalize_cc {
static void cmp_node_normalize_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Float>(N_("Value")).default_value(1.0f).min(0.0f).max(1.0f);
+ b.add_input<decl::Float>(N_("Value"))
+ .default_value(1.0f)
+ .min(0.0f)
+ .max(1.0f)
+ .compositor_domain_priority(0);
b.add_output<decl::Float>(N_("Value"));
}
using namespace blender::realtime_compositor;
class NormalizeOperation : public NodeOperation {
+ private:
+ /* The normalize operation is specifically designed to normalize Z Depth information. But since Z
+ * Depth can contain near infinite values, normalization is limited to [-range_, range], meaning
+ * that values outside of that range will be ignored when computing the maximum and minimum for
+ * normalization and will eventually be 0 or 1 if they are less than or larger than the range
+ * respectively. */
+ constexpr static float range_ = 10000.0f;
+
public:
using NodeOperation::NodeOperation;
void execute() override
{
- get_input("Value").pass_through(get_result("Value"));
+ Result &input_image = get_input("Value");
+ Result &output_image = get_result("Value");
+ if (input_image.is_single_value()) {
+ input_image.pass_through(output_image);
+ return;
+ }
+
+ const float maximum = maximum_float_in_range(
+ context(), input_image.texture(), -range_, range_);
+ const float minimum = minimum_float_in_range(
+ context(), input_image.texture(), -range_, range_);
+ const float scale = (maximum != minimum) ? (1.0f / (maximum - minimum)) : 0.0f;
+
+ GPUShader *shader = shader_manager().get("compositor_normalize");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_1f(shader, "minimum", minimum);
+ GPU_shader_uniform_1f(shader, "scale", scale);
+
+ input_image.bind_as_texture(shader, "input_tx");
+
+ const Domain domain = compute_domain();
+ output_image.allocate_texture(domain);
+ output_image.bind_as_image(shader, "output_img");
+
+ compute_dispatch_threads_at_least(shader, domain.size);
+
+ GPU_shader_unbind();
+ output_image.unbind_as_image();
+ input_image.unbind_as_texture();
}
};
diff --git a/source/blender/nodes/composite/nodes/node_composite_tonemap.cc b/source/blender/nodes/composite/nodes/node_composite_tonemap.cc
index 2e06ad99df1..d26a01bb3c9 100644
--- a/source/blender/nodes/composite/nodes/node_composite_tonemap.cc
+++ b/source/blender/nodes/composite/nodes/node_composite_tonemap.cc
@@ -5,20 +5,35 @@
* \ingroup cmpnodes
*/
+#include <cmath>
+
+#include "BLI_assert.h"
+#include "BLI_math_base.hh"
+#include "BLI_math_vec_types.hh"
+#include "BLI_math_vector.hh"
+
#include "RNA_access.h"
#include "UI_interface.h"
#include "UI_resources.h"
+#include "IMB_colormanagement.h"
+
+#include "COM_algorithm_parallel_reduction.hh"
#include "COM_node_operation.hh"
+#include "COM_utilities.hh"
#include "node_composite_util.hh"
namespace blender::nodes::node_composite_tonemap_cc {
+NODE_STORAGE_FUNCS(NodeTonemap)
+
static void cmp_node_tonemap_declare(NodeDeclarationBuilder &b)
{
- b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
+ b.add_input<decl::Color>(N_("Image"))
+ .default_value({1.0f, 1.0f, 1.0f, 1.0f})
+ .compositor_domain_priority(0);
b.add_output<decl::Color>(N_("Image"));
}
@@ -68,7 +83,236 @@ class ToneMapOperation : public NodeOperation {
void execute() override
{
- get_input("Image").pass_through(get_result("Image"));
+ Result &input_image = get_input("Image");
+ Result &output_image = get_result("Image");
+ if (input_image.is_single_value()) {
+ input_image.pass_through(output_image);
+ return;
+ }
+
+ switch (get_type()) {
+ case CMP_NODE_TONE_MAP_SIMPLE:
+ execute_simple();
+ return;
+ case CMP_NODE_TONE_MAP_PHOTORECEPTOR:
+ execute_photoreceptor();
+ return;
+ default:
+ BLI_assert_unreachable();
+ return;
+ }
+ }
+
+ /* Tone mapping based on equation (3) from Reinhard, Erik, et al. "Photographic tone reproduction
+ * for digital images." Proceedings of the 29th annual conference on Computer graphics and
+ * interactive techniques. 2002. */
+ void execute_simple()
+ {
+ const float luminance_scale = compute_luminance_scale();
+ const float luminance_scale_blend_factor = compute_luminance_scale_blend_factor();
+ const float gamma = node_storage(bnode()).gamma;
+ const float inverse_gamma = gamma != 0.0f ? 1.0f / gamma : 0.0f;
+
+ GPUShader *shader = shader_manager().get("compositor_tone_map_simple");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_1f(shader, "luminance_scale", luminance_scale);
+ GPU_shader_uniform_1f(shader, "luminance_scale_blend_factor", luminance_scale_blend_factor);
+ GPU_shader_uniform_1f(shader, "inverse_gamma", inverse_gamma);
+
+ const Result &input_image = get_input("Image");
+ input_image.bind_as_texture(shader, "input_tx");
+
+ const Domain domain = compute_domain();
+ Result &output_image = get_result("Image");
+ output_image.allocate_texture(domain);
+ output_image.bind_as_image(shader, "output_img");
+
+ compute_dispatch_threads_at_least(shader, domain.size);
+
+ GPU_shader_unbind();
+ output_image.unbind_as_image();
+ input_image.unbind_as_texture();
+ }
+
+ /* Computes the scaling factor in equation (2) from Reinhard's 2002 paper. */
+ float compute_luminance_scale()
+ {
+ const float geometric_mean = compute_geometric_mean_of_luminance();
+ return geometric_mean != 0.0 ? node_storage(bnode()).key / geometric_mean : 0.0f;
+ }
+
+ /* Computes equation (1) from Reinhard's 2002 paper. However, note that the equation in the paper
+ * is most likely wrong, and the intention is actually to compute the geometric mean through a
+ * logscale arithmetic mean, that is, the division should happen inside the exponential function,
+ * not outside of it. That's because the sum of the log luminance will be a very large negative
+ * number, whose exponential will almost always be zero, which is unexpected and useless. */
+ float compute_geometric_mean_of_luminance()
+ {
+ return std::exp(compute_average_log_luminance());
+ }
+
+ /* Equation (3) from Reinhard's 2002 paper blends between high luminance scaling for high
+ * luminance values and low luminance scaling for low luminance values. This is done by adding 1
+ * to the denominator, since for low luminance values, the denominator will be close to 1 and for
+ * high luminance values, the 1 in the denominator will be relatively insignificant. But the
+ * response of such function is not always ideal, so in this implementation, the 1 was exposed as
+ * a parameter to the user for more flexibility. */
+ float compute_luminance_scale_blend_factor()
+ {
+ return node_storage(bnode()).offset;
+ }
+
+ /* Tone mapping based on equation (1) and the trilinear interpolation between equations (6) and
+ * (7) from Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor
+ * physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. */
+ void execute_photoreceptor()
+ {
+ const float4 global_adaptation_level = compute_global_adaptation_level();
+ const float contrast = compute_contrast();
+ const float intensity = compute_intensity();
+ const float chromatic_adaptation = get_chromatic_adaptation();
+ const float light_adaptation = get_light_adaptation();
+
+ GPUShader *shader = shader_manager().get("compositor_tone_map_photoreceptor");
+ GPU_shader_bind(shader);
+
+ GPU_shader_uniform_4fv(shader, "global_adaptation_level", global_adaptation_level);
+ GPU_shader_uniform_1f(shader, "contrast", contrast);
+ GPU_shader_uniform_1f(shader, "intensity", intensity);
+ GPU_shader_uniform_1f(shader, "chromatic_adaptation", chromatic_adaptation);
+ GPU_shader_uniform_1f(shader, "light_adaptation", light_adaptation);
+
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+ GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
+
+ const Result &input_image = get_input("Image");
+ input_image.bind_as_texture(shader, "input_tx");
+
+ const Domain domain = compute_domain();
+ Result &output_image = get_result("Image");
+ output_image.allocate_texture(domain);
+ output_image.bind_as_image(shader, "output_img");
+
+ compute_dispatch_threads_at_least(shader, domain.size);
+
+ GPU_shader_unbind();
+ output_image.unbind_as_image();
+ input_image.unbind_as_texture();
+ }
+
+ /* Computes the global adaptation level from the trilinear interpolation equations constructed
+ * from equations (6) and (7) in Reinhard's 2005 paper. */
+ float4 compute_global_adaptation_level()
+ {
+ const float4 average_color = compute_average_color();
+ const float average_luminance = compute_average_luminance();
+ const float chromatic_adaptation = get_chromatic_adaptation();
+ return math::interpolate(float4(average_luminance), average_color, chromatic_adaptation);
+ }
+
+ float4 compute_average_color()
+ {
+ /* The average color will reduce to zero if chromatic adaptation is zero, so just return zero
+ * in this case to avoid needlessly computing the average. See the trilinear interpolation
+ * equations constructed from equations (6) and (7) in Reinhard's 2005 paper. */
+ if (get_chromatic_adaptation() == 0.0f) {
+ return float4(0.0f);
+ }
+
+ const Result &input = get_input("Image");
+ return sum_color(context(), input.texture()) / (input.domain().size.x * input.domain().size.y);
+ }
+
+ float compute_average_luminance()
+ {
+ /* The average luminance will reduce to zero if chromatic adaptation is one, so just return
+ * zero in this case to avoid needlessly computing the average. See the trilinear interpolation
+ * equations constructed from equations (6) and (7) in Reinhard's 2005 paper. */
+ if (get_chromatic_adaptation() == 1.0f) {
+ return 0.0f;
+ }
+
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+ const Result &input = get_input("Image");
+ float sum = sum_luminance(context(), input.texture(), luminance_coefficients);
+ return sum / (input.domain().size.x * input.domain().size.y);
+ }
+
+ /* Computes equation (5) from Reinhard's 2005 paper. */
+ float compute_intensity()
+ {
+ return std::exp(-node_storage(bnode()).f);
+ }
+
+ /* If the contrast is not zero, return it, otherwise, a zero contrast denote automatic derivation
+ * of the contrast value based on equations (2) and (4) from Reinhard's 2005 paper. */
+ float compute_contrast()
+ {
+ if (node_storage(bnode()).m != 0.0f) {
+ return node_storage(bnode()).m;
+ }
+
+ const float log_maximum_luminance = compute_log_maximum_luminance();
+ const float log_minimum_luminance = compute_log_minimum_luminance();
+
+ /* This is merely to guard against zero division later. */
+ if (log_maximum_luminance == log_minimum_luminance) {
+ return 1.0f;
+ }
+
+ const float average_log_luminance = compute_average_log_luminance();
+ const float dynamic_range = log_maximum_luminance - log_minimum_luminance;
+ const float luminance_key = (log_maximum_luminance - average_log_luminance) / (dynamic_range);
+
+ return 0.3f + 0.7f * std::pow(luminance_key, 1.4f);
+ }
+
+ float compute_average_log_luminance()
+ {
+ const Result &input_image = get_input("Image");
+
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+ const float sum_of_log_luminance = sum_log_luminance(
+ context(), input_image.texture(), luminance_coefficients);
+
+ return sum_of_log_luminance / (input_image.domain().size.x * input_image.domain().size.y);
+ }
+
+ float compute_log_maximum_luminance()
+ {
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+ const float maximum = maximum_luminance(
+ context(), get_input("Image").texture(), luminance_coefficients);
+ return std::log(math::max(maximum, 1e-5f));
+ }
+
+ float compute_log_minimum_luminance()
+ {
+ float luminance_coefficients[3];
+ IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
+ const float minimum = minimum_luminance(
+ context(), get_input("Image").texture(), luminance_coefficients);
+ return std::log(math::max(minimum, 1e-5f));
+ }
+
+ float get_chromatic_adaptation()
+ {
+ return node_storage(bnode()).c;
+ }
+
+ float get_light_adaptation()
+ {
+ return node_storage(bnode()).a;
+ }
+
+ CMPNodeToneMapType get_type()
+ {
+ return static_cast<CMPNodeToneMapType>(node_storage(bnode()).type);
}
};
diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
index a433a0df9b0..3e48a9fd923 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -4,6 +4,7 @@
#include "UI_resources.h"
#include "BLI_array.hh"
+#include "BLI_array_utils.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -23,15 +24,9 @@ namespace blender::nodes::node_geo_delete_geometry_cc {
using blender::bke::CustomDataAttributes;
template<typename T>
-static void copy_data_based_on_mask(Span<T> data, MutableSpan<T> r_data, IndexMask mask)
-{
- for (const int i_out : mask.index_range()) {
- r_data[i_out] = data[mask[i_out]];
- }
-}
-
-template<typename T>
-static void copy_data_based_on_map(Span<T> src, MutableSpan<T> dst, Span<int> index_map)
+static void copy_data_based_on_map(const Span<T> src,
+ const Span<int> index_map,
+ MutableSpan<T> dst)
{
for (const int i_src : index_map.index_range()) {
const int i_dst = index_map[i_src];
@@ -55,26 +50,17 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes
if (!attribute) {
continue;
}
-
/* Only copy if it is on a domain we want. */
if (!domains.contains(attribute.domain)) {
continue;
}
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
-
GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, attribute.domain, data_type);
-
if (!result_attribute) {
continue;
}
-
- attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
- using T = decltype(dummy);
- VArraySpan<T> span{attribute.varray.typed<T>()};
- MutableSpan<T> out_span = result_attribute.span.typed<T>();
- out_span.copy_from(span);
- });
+ attribute.varray.materialize(result_attribute.span.data());
result_attribute.finish();
}
}
@@ -95,26 +81,19 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
if (!attribute) {
continue;
}
-
/* Only copy if it is on a domain we want. */
if (domain != attribute.domain) {
continue;
}
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
-
GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, attribute.domain, data_type);
-
if (!result_attribute) {
continue;
}
- attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
- using T = decltype(dummy);
- VArraySpan<T> span{attribute.varray.typed<T>()};
- MutableSpan<T> out_span = result_attribute.span.typed<T>();
- copy_data_based_on_mask(span, out_span, mask);
- });
+ array_utils::gather(attribute.varray, mask, result_attribute.span);
+
result_attribute.finish();
}
}
@@ -131,16 +110,13 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind
if (!attribute) {
continue;
}
-
/* Only copy if it is on a domain we want. */
if (domain != attribute.domain) {
continue;
}
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
-
GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, attribute.domain, data_type);
-
if (!result_attribute) {
continue;
}
@@ -149,7 +125,7 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind
using T = decltype(dummy);
VArraySpan<T> span{attribute.varray.typed<T>()};
MutableSpan<T> out_span = result_attribute.span.typed<T>();
- copy_data_based_on_map(span, out_span, index_map);
+ copy_data_based_on_map(span, index_map, out_span);
});
result_attribute.finish();
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc
index 091337c28cf..95173bd23a5 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc
@@ -15,6 +15,8 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "DEG_depsgraph_query.h"
+
#include "node_geometry_util.hh"
namespace blender::nodes {
@@ -208,6 +210,7 @@ static void geo_node_distribute_points_in_volume_exec(GeoNodeExecParams params)
}
const VolumeComponent *component = geometry_set.get_component_for_read<VolumeComponent>();
const Volume *volume = component->get_for_read();
+ BKE_volume_load(volume, DEG_get_bmain(params.depsgraph()));
Vector<float3> positions;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc
index 84e63845b84..9b1c13bf563 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "BLI_array_utils.hh"
#include "BLI_task.hh"
#include "DNA_mesh_types.h"
@@ -105,18 +106,6 @@ static void copy_data_based_on_pairs(Span<T> data,
}
}
-/* Copy using the map. */
-template<typename T>
-static void copy_data_based_on_new_to_old_map(Span<T> data,
- MutableSpan<T> r_data,
- const Span<int> new_to_old_map)
-{
- for (const int i : r_data.index_range()) {
- const int old_i = new_to_old_map[i];
- r_data[i] = data[old_i];
- }
-}
-
/**
* Transfers the attributes from the original mesh to the new mesh using the following logic:
* - If the attribute was on the face domain it is now on the point domain, and this is true
@@ -168,7 +157,6 @@ static void transfer_attributes(
src_attribute.varray.type());
GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, out_domain, data_type);
-
if (!dst_attribute) {
continue;
}
@@ -177,20 +165,24 @@ static void transfer_attributes(
using T = decltype(dummy);
VArraySpan<T> span{src_attribute.varray.typed<T>()};
MutableSpan<T> dst_span = dst_attribute.span.typed<T>();
- if (src_attribute.domain == ATTR_DOMAIN_FACE) {
- dst_span.take_front(span.size()).copy_from(span);
- if (keep_boundaries) {
- copy_data_based_on_pairs(span, dst_span, boundary_vertex_to_relevant_face_map);
- }
- }
- else if (src_attribute.domain == ATTR_DOMAIN_POINT) {
- copy_data_based_on_vertex_types(span, dst_span, vertex_types, keep_boundaries);
- }
- else if (src_attribute.domain == ATTR_DOMAIN_EDGE) {
- copy_data_based_on_new_to_old_map(span, dst_span, new_to_old_edges_map);
- }
- else {
- copy_data_based_on_new_to_old_map(span, dst_span, new_to_old_face_corners_map);
+ switch (src_attribute.domain) {
+ case ATTR_DOMAIN_POINT:
+ copy_data_based_on_vertex_types(span, dst_span, vertex_types, keep_boundaries);
+ break;
+ case ATTR_DOMAIN_EDGE:
+ array_utils::gather(span, new_to_old_edges_map, dst_span);
+ break;
+ case ATTR_DOMAIN_FACE:
+ dst_span.take_front(span.size()).copy_from(span);
+ if (keep_boundaries) {
+ copy_data_based_on_pairs(span, dst_span, boundary_vertex_to_relevant_face_map);
+ }
+ break;
+ case ATTR_DOMAIN_CORNER:
+ array_utils::gather(span, new_to_old_face_corners_map, dst_span);
+ break;
+ default:
+ BLI_assert_unreachable();
}
});
dst_attribute.finish();
diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
index 70583625a7a..486f900aca5 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "BLI_array_utils.hh"
#include "BLI_map.hh"
#include "BLI_noise.hh"
#include "BLI_span.hh"
@@ -105,16 +106,6 @@ static void threaded_slice_fill(Span<int> offsets,
});
}
-template<typename T>
-static void threaded_mapped_copy(const Span<int> mapping, const Span<T> src, MutableSpan<T> dst)
-{
- threading::parallel_for(mapping.index_range(), 512, [&](IndexRange range) {
- for (const int i : range) {
- dst[i] = src[mapping[i]];
- }
- });
-}
-
static void copy_hashed_ids(const Span<int> src, const int hash, MutableSpan<int> dst)
{
for (const int i : src.index_range()) {
@@ -440,17 +431,17 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set,
MutableSpan<T> dst = dst_attribute.span.typed<T>();
switch (out_domain) {
- case ATTR_DOMAIN_FACE:
- threaded_slice_fill<T>(offsets, selection, src, dst);
+ case ATTR_DOMAIN_POINT:
+ array_utils::gather(src, vert_mapping, dst);
break;
case ATTR_DOMAIN_EDGE:
- threaded_mapped_copy<T>(edge_mapping, src, dst);
+ array_utils::gather(src, edge_mapping, dst);
break;
- case ATTR_DOMAIN_POINT:
- threaded_mapped_copy<T>(vert_mapping, src, dst);
+ case ATTR_DOMAIN_FACE:
+ threaded_slice_fill<T>(offsets, selection, src, dst);
break;
case ATTR_DOMAIN_CORNER:
- threaded_mapped_copy<T>(loop_mapping, src, dst);
+ array_utils::gather(src, loop_mapping, dst);
break;
default:
break;
@@ -653,7 +644,7 @@ static void copy_edge_attributes_without_id(GeometrySet &geometry_set,
threaded_slice_fill<T>(offsets, selection, src, dst);
break;
case ATTR_DOMAIN_POINT:
- threaded_mapped_copy<T>(point_mapping, src, dst);
+ array_utils::gather(src, point_mapping, dst);
break;
default:
break;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
index d348d886ad6..151ba3e59cc 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include "BLI_array_utils.hh"
#include "BLI_disjoint_set.hh"
#include "BLI_task.hh"
#include "BLI_vector_set.hh"
@@ -175,24 +176,6 @@ static MPoly new_poly(const int loopstart, const int totloop)
return poly;
}
-template<typename T> void copy_with_indices(MutableSpan<T> dst, Span<T> src, Span<int> indices)
-{
- BLI_assert(dst.size() == indices.size());
- for (const int i : dst.index_range()) {
- dst[i] = src[indices[i]];
- }
-}
-
-template<typename T> void copy_with_mask(MutableSpan<T> dst, Span<T> src, IndexMask mask)
-{
- BLI_assert(dst.size() == mask.size());
- threading::parallel_for(mask.index_range(), 512, [&](const IndexRange range) {
- for (const int i : range) {
- dst[i] = src[mask[i]];
- }
- });
-}
-
/**
* \param get_mix_indices_fn: Returns a Span of indices of the source points to mix for every
* result point.
@@ -265,26 +248,24 @@ static void extrude_mesh_vertices(Mesh &mesh,
}
GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span(
id, meta_data.domain, meta_data.data_type);
- attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
- using T = decltype(dummy);
- MutableSpan<T> data = attribute.span.typed<T>();
- switch (attribute.domain) {
- case ATTR_DOMAIN_POINT: {
- /* New vertices copy the attribute values from their source vertex. */
- copy_with_mask(data.slice(new_vert_range), data.as_span(), selection);
- break;
- }
- case ATTR_DOMAIN_EDGE: {
+ switch (attribute.domain) {
+ case ATTR_DOMAIN_POINT:
+ /* New vertices copy the attribute values from their source vertex. */
+ array_utils::gather(attribute.span, selection, attribute.span.slice(new_vert_range));
+ break;
+ case ATTR_DOMAIN_EDGE:
+ attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
+ using T = decltype(dummy);
+ MutableSpan<T> data = attribute.span.typed<T>();
/* New edge values are mixed from of all the edges connected to the source vertex. */
copy_with_mixing(data.slice(new_edge_range), data.as_span(), [&](const int i) {
return vert_to_edge_map[selection[i]].as_span();
});
- break;
- }
- default:
- BLI_assert_unreachable();
- }
- });
+ });
+ break;
+ default:
+ BLI_assert_unreachable();
+ }
attribute.finish();
return true;
@@ -524,13 +505,14 @@ static void extrude_mesh_edges(Mesh &mesh,
switch (attribute.domain) {
case ATTR_DOMAIN_POINT: {
/* New vertices copy the attribute values from their source vertex. */
- copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_indices);
+ array_utils::gather(
+ data.as_span(), new_vert_indices.as_span(), data.slice(new_vert_range));
break;
}
case ATTR_DOMAIN_EDGE: {
/* Edges parallel to original edges copy the edge attributes from the original edges. */
MutableSpan<T> duplicate_data = data.slice(duplicate_edge_range);
- copy_with_mask(duplicate_data, data.as_span(), edge_selection);
+ array_utils::gather(data.as_span(), edge_selection, duplicate_data);
/* Edges connected to original vertices mix values of selected connected edges. */
MutableSpan<T> connect_data = data.slice(connect_edge_range);
@@ -910,17 +892,18 @@ static void extrude_mesh_face_regions(Mesh &mesh,
switch (attribute.domain) {
case ATTR_DOMAIN_POINT: {
/* New vertices copy the attributes from their original vertices. */
- copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_indices);
+ array_utils::gather(
+ data.as_span(), new_vert_indices.as_span(), data.slice(new_vert_range));
break;
}
case ATTR_DOMAIN_EDGE: {
/* Edges parallel to original edges copy the edge attributes from the original edges. */
MutableSpan<T> boundary_data = data.slice(boundary_edge_range);
- copy_with_indices(boundary_data, data.as_span(), boundary_edge_indices);
+ array_utils::gather(data.as_span(), boundary_edge_indices.as_span(), boundary_data);
/* Edges inside of face regions also just duplicate their source data. */
MutableSpan<T> new_inner_data = data.slice(new_inner_edge_range);
- copy_with_indices(new_inner_data, data.as_span(), new_inner_edge_indices);
+ array_utils::gather(data.as_span(), new_inner_edge_indices.as_span(), new_inner_data);
/* Edges connected to original vertices mix values of selected connected edges. */
MutableSpan<T> connect_data = data.slice(connect_edge_range);
@@ -932,8 +915,8 @@ static void extrude_mesh_face_regions(Mesh &mesh,
case ATTR_DOMAIN_FACE: {
/* New faces on the side of extrusions get the values from the corresponding selected
* face. */
- copy_with_indices(
- data.slice(side_poly_range), data.as_span(), edge_extruded_face_indices);
+ array_utils::gather(
+ data.as_span(), edge_extruded_face_indices.as_span(), data.slice(side_poly_range));
break;
}
case ATTR_DOMAIN_CORNER: {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
index affeb43e33b..64546684186 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
@@ -2,6 +2,7 @@
#include "DNA_collection_types.h"
+#include "BLI_array_utils.hh"
#include "BLI_hash.h"
#include "BLI_task.hh"
@@ -172,18 +173,7 @@ static void add_instances_from_component(
dst_attribute_opt = instance_attributes.get_for_write(attribute_id);
}
BLI_assert(dst_attribute_opt);
- const GMutableSpan dst_attribute = dst_attribute_opt->slice(start_len, select_len);
- threading::parallel_for(selection.index_range(), 1024, [&](IndexRange selection_range) {
- attribute_math::convert_to_static_type(attribute_kind.data_type, [&](auto dummy) {
- using T = decltype(dummy);
- VArray<T> src = src_attribute.typed<T>();
- MutableSpan<T> dst = dst_attribute.typed<T>();
- for (const int range_i : selection_range) {
- const int i = selection[range_i];
- dst[range_i] = src[i];
- }
- });
- });
+ array_utils::gather(src_attribute, selection, dst_attribute_opt->slice(start_len, select_len));
}
}
diff --git a/source/blender/nodes/texture/CMakeLists.txt b/source/blender/nodes/texture/CMakeLists.txt
index 77db71d4b1a..2d704ac2228 100644
--- a/source/blender/nodes/texture/CMakeLists.txt
+++ b/source/blender/nodes/texture/CMakeLists.txt
@@ -2,7 +2,7 @@
set(INC
.
- ../
+ ..
../intern
../../editors/include
../../blenkernel
diff --git a/source/blender/python/gpu/gpu_py_platform.c b/source/blender/python/gpu/gpu_py_platform.c
index b877e3ceb98..51366d199b0 100644
--- a/source/blender/python/gpu/gpu_py_platform.c
+++ b/source/blender/python/gpu/gpu_py_platform.c
@@ -11,6 +11,7 @@
#include "BLI_utildefines.h"
+#include "GPU_context.h"
#include "GPU_platform.h"
#include "gpu_py_platform.h" /* Own include. */
@@ -83,6 +84,28 @@ static PyObject *pygpu_platform_device_type_get(PyObject *UNUSED(self))
return PyUnicode_FromString("UNKNOWN");
}
+PyDoc_STRVAR(pygpu_platform_backend_type_get_doc,
+ ".. function:: backend_type_get()\n"
+ "\n"
+ " Get actuve GPU backend.\n"
+ "\n"
+ " :return: Backend type ('OPENGL', 'METAL', 'NONE', 'UNKNOWN').\n"
+ " :rtype: str\n");
+static PyObject *pygpu_platform_backend_type_get(PyObject *UNUSED(self))
+{
+ switch (GPU_backend_get_type()) {
+ case GPU_BACKEND_METAL:
+ return PyUnicode_FromString("METAL");
+ case GPU_BACKEND_NONE:
+ return PyUnicode_FromString("NONE");
+ case GPU_BACKEND_OPENGL:
+ return PyUnicode_FromString("OPENGL");
+ case GPU_BACKEND_ANY:
+ break;
+ }
+ return PyUnicode_FromString("UNKNOWN");
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -106,6 +129,10 @@ static struct PyMethodDef pygpu_platform__tp_methods[] = {
(PyCFunction)pygpu_platform_device_type_get,
METH_NOARGS,
pygpu_platform_device_type_get_doc},
+ {"backend_type_get",
+ (PyCFunction)pygpu_platform_backend_type_get,
+ METH_NOARGS,
+ pygpu_platform_backend_type_get_doc},
{NULL, NULL, 0, NULL},
};
diff --git a/source/blender/render/intern/engine.cc b/source/blender/render/intern/engine.cc
index 5eb4db6faa4..b8757d33580 100644
--- a/source/blender/render/intern/engine.cc
+++ b/source/blender/render/intern/engine.cc
@@ -969,6 +969,40 @@ static void engine_render_view_layer(Render *re,
engine_depsgraph_exit(engine);
}
+/* Callback function for engine_render_create_result to add all render passes to the result. */
+static void engine_render_add_result_pass_cb(void *user_data,
+ struct Scene *UNUSED(scene),
+ struct ViewLayer *view_layer,
+ const char *name,
+ int channels,
+ const char *chanid,
+ eNodeSocketDatatype UNUSED(type))
+{
+ RenderResult *rr = (RenderResult *)user_data;
+ RE_create_render_pass(rr, name, channels, chanid, view_layer->name, RR_ALL_VIEWS, false);
+}
+
+static RenderResult *engine_render_create_result(Render *re)
+{
+ RenderResult *rr = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS);
+ if (rr == nullptr) {
+ return nullptr;
+ }
+
+ FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) {
+ RE_engine_update_render_passes(
+ re->engine, re->scene, view_layer, engine_render_add_result_pass_cb, rr);
+ }
+ FOREACH_VIEW_LAYER_TO_RENDER_END;
+
+ /* Preview does not support deferred render result allocation. */
+ if (re->r.scemode & R_BUTS_PREVIEW) {
+ render_result_passes_allocated_ensure(rr);
+ }
+
+ return rr;
+}
+
bool RE_engine_render(Render *re, bool do_all)
{
RenderEngineType *type = RE_engines_find(re->r.engine);
@@ -1008,6 +1042,14 @@ bool RE_engine_render(Render *re, bool do_all)
render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers);
}
+ /* Create engine. */
+ RenderEngine *engine = re->engine;
+
+ if (!engine) {
+ engine = RE_engine_create(type);
+ re->engine = engine;
+ }
+
/* create render result */
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
if (re->result == nullptr || !(re->r.scemode & R_BUTS_PREVIEW)) {
@@ -1015,7 +1057,7 @@ bool RE_engine_render(Render *re, bool do_all)
render_result_free(re->result);
}
- re->result = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS);
+ re->result = engine_render_create_result(re);
}
BLI_rw_mutex_unlock(&re->resultmutex);
@@ -1024,6 +1066,9 @@ bool RE_engine_render(Render *re, bool do_all)
if (re->draw_lock) {
re->draw_lock(re->dlh, false);
}
+ /* Free engine. */
+ RE_engine_free(engine);
+ re->engine = nullptr;
/* Too small image is handled earlier, here it could only happen if
* there was no sufficient memory to allocate all passes.
*/
@@ -1036,14 +1081,6 @@ bool RE_engine_render(Render *re, bool do_all)
re->i.cfra = re->scene->r.cfra;
BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name));
- /* render */
- RenderEngine *engine = re->engine;
-
- if (!engine) {
- engine = RE_engine_create(type);
- re->engine = engine;
- }
-
engine->flag |= RE_ENGINE_RENDERING;
/* TODO: actually link to a parent which shouldn't happen */
diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc
index bd5c6a0f5c4..f9524fdbf05 100644
--- a/source/blender/render/intern/render_result.cc
+++ b/source/blender/render/intern/render_result.cc
@@ -290,90 +290,8 @@ RenderResult *render_result_new(Render *re,
}
}
-#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \
- do { \
- if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id, false) == nullptr) { \
- render_result_free(rr); \
- return nullptr; \
- } \
- } while (false)
-
/* A render-layer should always have a "Combined" pass. */
render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA", false);
-
- if (view_layer->passflag & SCE_PASS_Z) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z");
- }
- if (view_layer->passflag & SCE_PASS_VECTOR) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW");
- }
- if (view_layer->passflag & SCE_PASS_NORMAL) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ");
- }
- if (view_layer->passflag & SCE_PASS_POSITION) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_POSITION, view, "XYZ");
- }
- if (view_layer->passflag & SCE_PASS_UV) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA");
- }
- if (view_layer->passflag & SCE_PASS_EMIT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_AO) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_ENVIRONMENT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_SHADOW) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_INDEXOB) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X");
- }
- if (view_layer->passflag & SCE_PASS_INDEXMA) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X");
- }
- if (view_layer->passflag & SCE_PASS_MIST) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z");
- }
- if (view_layer->passflag & SCE_PASS_DIFFUSE_DIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_DIFFUSE_INDIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_DIFFUSE_COLOR) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_GLOSSY_DIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_GLOSSY_INDIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_GLOSSY_COLOR) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_TRANSM_DIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_TRANSM_INDIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_TRANSM_COLOR) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB");
- }
- if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) {
- RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB");
- }
-#undef RENDER_LAYER_ADD_PASS_SAFE
}
}
FOREACH_VIEW_LAYER_TO_RENDER_END;
@@ -411,11 +329,6 @@ RenderResult *render_result_new(Render *re,
rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2);
- /* Preview does not support deferred render result allocation. */
- if (re->r.scemode & R_BUTS_PREVIEW) {
- render_result_passes_allocated_ensure(rr);
- }
-
return rr;
}
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.cc b/source/blender/windowmanager/intern/wm_dragdrop.cc
index 0896daec561..fb63abed9e9 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.cc
+++ b/source/blender/windowmanager/intern/wm_dragdrop.cc
@@ -853,7 +853,8 @@ static void wm_drag_draw_icon(bContext * /*C*/, wmWindow * /*win*/, wmDrag *drag
y = xy[1] - 2 * UI_DPI_FAC;
const uchar text_col[] = {255, 255, 255, 255};
- UI_icon_draw_ex(x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false);
+ UI_icon_draw_ex(
+ x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT);
}
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc
index affe0bcf45a..181ec89cabd 100644
--- a/source/blender/windowmanager/intern/wm_event_system.cc
+++ b/source/blender/windowmanager/intern/wm_event_system.cc
@@ -5620,7 +5620,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
case GHOST_kEventNDOFButton: {
GHOST_TEventNDOFButtonData *e = static_cast<GHOST_TEventNDOFButtonData *>(customdata);
- event.type = NDOF_BUTTON_NONE + e->button;
+ event.type = NDOF_BUTTON_INDEX_AS_EVENT(e->button);
switch (e->action) {
case GHOST_kPress:
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index bf793ee41a0..3e5399a6f56 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -59,6 +59,8 @@
#include "DEG_depsgraph.h"
+#include "wm_window_private.h"
+
#include "WM_api.h" /* only for WM_main_playanim */
#ifdef WITH_AUDASPACE
@@ -1340,6 +1342,8 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey)
{
GHOST_GLSettings glsettings = {0};
+ const eGPUBackendType gpu_backend = GPU_backend_type_selection_get();
+ glsettings.context_type = wm_ghost_drawing_context_type(gpu_backend);
uint32_t scr_w, scr_h;
GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h);
@@ -1356,7 +1360,6 @@ static void playanim_window_open(const char *title, int posx, int posy, int size
/* Could optionally start full-screen. */
GHOST_kWindowStateNormal,
false,
- GHOST_kDrawingContextTypeOpenGL,
glsettings);
}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index b1b13390932..2ca7b5f470d 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -556,6 +556,9 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm,
glSettings.flags |= GHOST_glDebugContext;
}
+ eGPUBackendType gpu_backend = GPU_backend_type_selection_get();
+ glSettings.context_type = wm_ghost_drawing_context_type(gpu_backend);
+
int scr_w, scr_h;
wm_get_desktopsize(&scr_w, &scr_h);
int posy = (scr_h - win->posy - win->sizey);
@@ -573,7 +576,6 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm,
win->sizey,
(GHOST_TWindowState)win->windowstate,
is_dialog,
- GHOST_kDrawingContextTypeOpenGL,
glSettings);
if (ghostwin) {
@@ -1615,6 +1617,29 @@ const char *WM_ghost_backend(void)
#endif
}
+GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gpu_backend)
+{
+ switch (gpu_backend) {
+ case GPU_BACKEND_NONE:
+ return GHOST_kDrawingContextTypeNone;
+ case GPU_BACKEND_ANY:
+ case GPU_BACKEND_OPENGL:
+ return GHOST_kDrawingContextTypeOpenGL;
+ case GPU_BACKEND_METAL:
+#ifdef WITH_METAL_BACKEND
+ return GHOST_kDrawingContextTypeMetal;
+#else
+ BLI_assert_unreachable();
+ return GHOST_kDrawingContextTypeNone;
+#endif
+ }
+
+ /* Avoid control reaches end of non-void function compilation warning, which could be promoted
+ * to error. */
+ BLI_assert_unreachable();
+ return GHOST_kDrawingContextTypeNone;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/windowmanager/intern/wm_window_private.h b/source/blender/windowmanager/intern/wm_window_private.h
index f68d4e3e693..dad3e749817 100644
--- a/source/blender/windowmanager/intern/wm_window_private.h
+++ b/source/blender/windowmanager/intern/wm_window_private.h
@@ -7,8 +7,11 @@
#pragma once
#include "BLI_sys_types.h"
+
#include "GHOST_Types.h"
+#include "GPU_context.h"
+
/* *************** Message box *************** */
/* `WM_ghost_show_message_box` is implemented in `wm_windows.c` it is
* defined here as it was implemented to be used for showing
@@ -21,3 +24,5 @@ void WM_ghost_show_message_box(const char *title,
const char *continue_label,
const char *link,
GHOST_DialogOptions dialog_options);
+
+GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gpu_backend);
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 405b7225bd5..c36c57a12ae 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -252,8 +252,6 @@ enum {
#define _NDOF_MIN NDOF_MOTION
#define _NDOF_BUTTON_MIN NDOF_BUTTON_MENU
- /* used internally, never sent */
- NDOF_BUTTON_NONE = NDOF_MOTION,
/* these two are available from any 3Dconnexion device */
NDOF_BUTTON_MENU = 0x0191, /* 401 */
@@ -281,35 +279,42 @@ enum {
NDOF_BUTTON_DOMINANT = 0x01a3, /* 419 */
NDOF_BUTTON_PLUS = 0x01a4, /* 420 */
NDOF_BUTTON_MINUS = 0x01a5, /* 421 */
+ /* General-purpose buttons. */
+ NDOF_BUTTON_1 = 0x01a6, /* 422 */
+ NDOF_BUTTON_2 = 0x01a7, /* 423 */
+ NDOF_BUTTON_3 = 0x01a8, /* 424 */
+ NDOF_BUTTON_4 = 0x01a9, /* 425 */
+ NDOF_BUTTON_5 = 0x01aa, /* 426 */
+ NDOF_BUTTON_6 = 0x01ab, /* 427 */
+ NDOF_BUTTON_7 = 0x01ac, /* 428 */
+ NDOF_BUTTON_8 = 0x01ad, /* 429 */
+ NDOF_BUTTON_9 = 0x01ae, /* 430 */
+ NDOF_BUTTON_10 = 0x01af, /* 431 */
+ /* more general-purpose buttons */
+ NDOF_BUTTON_A = 0x01b0, /* 432 */
+ NDOF_BUTTON_B = 0x01b1, /* 433 */
+ NDOF_BUTTON_C = 0x01b2, /* 434 */
+ /* Store/restore views. */
+ NDOF_BUTTON_V1 = 0x01b3, /* 435 */
+ NDOF_BUTTON_V2 = 0x01b4, /* 436 */
+ NDOF_BUTTON_V3 = 0x01b5, /* 437 */
/* Disabled as GHOST converts these to keyboard events
* which use regular keyboard event handling logic. */
#if 0
/* keyboard emulation */
- NDOF_BUTTON_ESC = 0x01a6, /* 422 */
- NDOF_BUTTON_ALT = 0x01a7, /* 423 */
- NDOF_BUTTON_SHIFT = 0x01a8, /* 424 */
- NDOF_BUTTON_CTRL = 0x01a9, /* 425 */
+ NDOF_BUTTON_ESC = 0x01b6, /* 438 */
+ NDOF_BUTTON_ENTER = 0x01b7, /* 439 */
+ NDOF_BUTTON_DELETE = 0x01b8, /* 440 */
+ NDOF_BUTTON_TAB = 0x01b9, /* 441 */
+ NDOF_BUTTON_SPACE = 0x01ba, /* 442 */
+ NDOF_BUTTON_ALT = 0x01bb, /* 443 */
+ NDOF_BUTTON_SHIFT = 0x01bc, /* 444 */
+ NDOF_BUTTON_CTRL = 0x01bd, /* 445 */
#endif
- /* general-purpose buttons */
- NDOF_BUTTON_1 = 0x01aa, /* 426 */
- NDOF_BUTTON_2 = 0x01ab, /* 427 */
- NDOF_BUTTON_3 = 0x01ac, /* 428 */
- NDOF_BUTTON_4 = 0x01ad, /* 429 */
- NDOF_BUTTON_5 = 0x01ae, /* 430 */
- NDOF_BUTTON_6 = 0x01af, /* 431 */
- NDOF_BUTTON_7 = 0x01b0, /* 432 */
- NDOF_BUTTON_8 = 0x01b1, /* 433 */
- NDOF_BUTTON_9 = 0x01b2, /* 434 */
- NDOF_BUTTON_10 = 0x01b3, /* 435 */
- /* more general-purpose buttons */
- NDOF_BUTTON_A = 0x01b4, /* 436 */
- NDOF_BUTTON_B = 0x01b5, /* 437 */
- NDOF_BUTTON_C = 0x01b6, /* 438 */
-
-#define _NDOF_MAX NDOF_BUTTON_C
-#define _NDOF_BUTTON_MAX NDOF_BUTTON_C
+#define _NDOF_MAX NDOF_BUTTON_V3
+#define _NDOF_BUTTON_MAX NDOF_BUTTON_V3
/* ********** End of Input devices. ********** */
@@ -449,6 +454,8 @@ enum eEventType_Mask {
(EVT_TYPE_MASK_KEYBOARD | EVT_TYPE_MASK_MOUSE | EVT_TYPE_MASK_NDOF)
#define EVT_TYPE_MASK_HOTKEY_EXCLUDE EVT_TYPE_MASK_KEYBOARD_MODIFIER
+#define NDOF_BUTTON_INDEX_AS_EVENT(i) (_NDOF_BUTTON_MIN + (i))
+
bool WM_event_type_mask_test(int event_type, enum eEventType_Mask mask);
/** \} */
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 06b898587bf..4144603555b 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -42,6 +42,8 @@
# include "BKE_scene.h"
# include "BKE_sound.h"
+# include "GPU_context.h"
+
# ifdef WITH_FFMPEG
# include "IMB_imbuf.h"
# endif
@@ -1111,6 +1113,44 @@ static int arg_handle_debug_gpu_set(int UNUSED(argc),
return 0;
}
+static const char arg_handle_gpu_backend_set_doc[] =
+ "\n"
+ "\tForce to use a specific GPU backend. Valid options: "
+# ifdef WITH_METAL_BACKEND
+ "'metal', "
+# endif
+ "'opengl').";
+static int arg_handle_gpu_backend_set(int argc, const char **argv, void *UNUSED(data))
+{
+ if (argc == 0) {
+ printf("\nError: GPU backend must follow '--gpu-backend'.\n");
+ return 0;
+ }
+
+ eGPUBackendType gpu_backend = GPU_BACKEND_NONE;
+
+ if (STREQ(argv[1], "opengl")) {
+ gpu_backend = GPU_BACKEND_OPENGL;
+ }
+# ifdef WITH_METAL_BACKEND
+ else if (STREQ(argv[1], "metal")) {
+ gpu_backend = GPU_BACKEND_METAL;
+ }
+# endif
+ else {
+ printf("\nError: Unrecognized GPU backend for '--gpu-backend'.\n");
+ return 0;
+ }
+
+ GPU_backend_type_selection_set(gpu_backend);
+ if (!GPU_backend_supported()) {
+ printf("\nError: GPU backend not supported.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
static const char arg_handle_debug_fpe_set_doc[] =
"\n\t"
"Enable floating-point exceptions.";
@@ -2074,6 +2114,10 @@ void main_args_setup(bContext *C, bArgs *ba)
BLI_args_add(ba, NULL, "--log-show-timestamp", CB(arg_handle_log_show_timestamp_set), ba);
BLI_args_add(ba, NULL, "--log-file", CB(arg_handle_log_file_set), ba);
+ /* GPU backend selection should be part of ARG_PASS_ENVIRONMENT for correct GPU context selection
+ * for anim player. */
+ BLI_args_add(ba, NULL, "--gpu-backend", CB(arg_handle_gpu_backend_set), NULL);
+
/* Pass: Background Mode & Settings
*
* Also and commands that exit after usage. */