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:
authorClément Foucault <foucault.clem@gmail.com>2022-01-26 12:21:47 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-01-26 12:21:47 +0300
commit3ffd662586e017668f6c0a1c2f1c754f4db0bf4e (patch)
tree35cb9af1c2656d39be3a3b5db16edcf2bf37df02
parentbe4f593758c5913705b43fa092ee0294b4e1bb0a (diff)
parent0cb5eae9d0617abedf745753c23061ddfcfd1416 (diff)
Merge branch 'master' into tmp-workbench-shader-create-infostmp-workbench-shader-create-infos
-rw-r--r--CMakeLists.txt4
-rw-r--r--build_files/build_environment/cmake/boost.cmake9
-rw-r--r--build_files/build_environment/windows/build_deps.cmd53
-rw-r--r--build_files/cmake/Modules/FindBrotli.cmake2
-rw-r--r--build_files/cmake/platform/platform_unix.cmake31
-rw-r--r--intern/cycles/scene/shader_nodes.cpp20
-rw-r--r--intern/cycles/util/math.h2
-rw-r--r--intern/ghost/test/CMakeLists.txt2
-rw-r--r--source/blender/blenfont/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/BKE_crazyspace.h2
-rw-r--r--source/blender/blenkernel/BKE_layer.h3
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/lib_id.c2
-rw-r--r--source/blender/blenkernel/intern/object.cc2
-rw-r--r--source/blender/editors/space_clip/clip_ops.c3
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c48
-rw-r--r--source/blender/editors/space_sequencer/sequencer_proxy.c4
-rw-r--r--source/blender/geometry/GEO_mesh_merge_by_distance.hh8
-rw-r--r--source/blender/geometry/intern/mesh_merge_by_distance.cc14
-rw-r--r--source/blender/gpu/intern/gpu_select.c44
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c2
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.cc2
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.hh5
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc2
-rw-r--r--source/blender/gpu/opengl/gl_shader.cc5
-rw-r--r--source/blender/imbuf/IMB_imbuf.h6
-rw-r--r--source/blender/imbuf/intern/indexer.c133
-rw-r--r--source/blender/makesdna/DNA_brush_enums.h4
-rw-r--r--source/blender/makesdna/DNA_node_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_space.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hair_info.cc1
-rw-r--r--source/blender/sequencer/SEQ_proxy.h3
-rw-r--r--source/blender/sequencer/intern/proxy.c6
-rw-r--r--source/blender/sequencer/intern/sound.c9
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c176
35 files changed, 448 insertions, 172 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 25cdd122a7f..0a73a2fae1a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -273,11 +273,13 @@ endif()
if(UNIX AND NOT APPLE)
option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
- option(WITH_SYSTEM_GLES "Use OpenGL ES library provided by the operating system" ON)
+ option(WITH_SYSTEM_GLEW "Use GLEW OpenGL wrapper library provided by the operating system" OFF)
+ option(WITH_SYSTEM_FREETYPE "Use the freetype library provided by the operating system" OFF)
else()
# not an option for other OS's
set(WITH_SYSTEM_GLEW OFF)
set(WITH_SYSTEM_GLES OFF)
+ set(WITH_SYSTEM_FREETYPE OFF)
endif()
diff --git a/build_files/build_environment/cmake/boost.cmake b/build_files/build_environment/cmake/boost.cmake
index 5170a3a123e..f2944a41af8 100644
--- a/build_files/build_environment/cmake/boost.cmake
+++ b/build_files/build_environment/cmake/boost.cmake
@@ -25,8 +25,13 @@ else()
endif()
if(WIN32)
- set(BOOST_TOOLSET toolset=msvc-14.1)
- set(BOOST_COMPILER_STRING -vc141)
+ if(MSVC_VERSION GREATER_EQUAL 1920) # 2019
+ set(BOOST_TOOLSET toolset=msvc-14.2)
+ set(BOOST_COMPILER_STRING -vc142)
+ else() # 2017
+ set(BOOST_TOOLSET toolset=msvc-14.1)
+ set(BOOST_COMPILER_STRING -vc141)
+ endif()
set(BOOST_CONFIGURE_COMMAND bootstrap.bat)
set(BOOST_BUILD_COMMAND b2)
diff --git a/build_files/build_environment/windows/build_deps.cmd b/build_files/build_environment/windows/build_deps.cmd
index 5174af8e20d..c0e13ac3a55 100644
--- a/build_files/build_environment/windows/build_deps.cmd
+++ b/build_files/build_environment/windows/build_deps.cmd
@@ -1,19 +1,5 @@
@echo off
if NOT "%1" == "" (
- if "%1" == "2013" (
- echo "Building for VS2013"
- set VSVER=12.0
- set VSVER_SHORT=12
- set BuildDir=VS12
- goto par2
- )
- if "%1" == "2015" (
- echo "Building for VS2015"
- set VSVER=14.0
- set VSVER_SHORT=14
- set BuildDir=VS14
- goto par2
- )
if "%1" == "2017" (
echo "Building for VS2017"
set VSVER=15.0
@@ -21,44 +7,33 @@ if NOT "%1" == "" (
set BuildDir=VS15
goto par2
)
+ if "%1" == "2019" (
+ echo "Building for VS2019"
+ set VSVER=15.0
+ set VSVER_SHORT=15
+ set BuildDir=VS15
+ goto par2
+ )
)
:usage
-Echo Usage build_deps 2013/2015/2017 x64/x86
+Echo Usage build_deps 2017/2019 x64
goto exit
:par2
if NOT "%2" == "" (
- if "%2" == "x86" (
- echo "Building for x86"
- set HARVESTROOT=Windows_vc
- set ARCH=86
- if "%1" == "2013" (
- set CMAKE_BUILDER=Visual Studio 12 2013
- )
- if "%1" == "2015" (
- set CMAKE_BUILDER=Visual Studio 14 2015
- )
- if "%1" == "2017" (
- set CMAKE_BUILDER=Visual Studio 15 2017
- )
-
- goto start
- )
if "%2" == "x64" (
echo "Building for x64"
set HARVESTROOT=Win64_vc
set ARCH=64
- if "%1" == "2013" (
- set CMAKE_BUILDER=Visual Studio 12 2013 Win64
- )
- if "%1" == "2015" (
- set CMAKE_BUILDER=Visual Studio 14 2015 Win64
+ if "%1" == "2019" (
+ set CMAKE_BUILDER=Visual Studio 16 2019
+ set CMAKE_BUILD_ARCH=-A x64
)
if "%1" == "2017" (
set CMAKE_BUILDER=Visual Studio 15 2017 Win64
+ set CMAKE_BUILD_ARCH=
)
-
goto start
)
)
@@ -120,7 +95,7 @@ set path=%BUILD_DIR%\downloads\mingw\mingw64\msys\1.0\bin\;%BUILD_DIR%\downloads
mkdir %STAGING%\%BuildDir%%ARCH%R
cd %Staging%\%BuildDir%%ARCH%R
echo %DATE% %TIME% : Start > %StatusFile%
-cmake -G "%CMAKE_BUILDER%" -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DBUILD_MODE=Release -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/
+cmake -G "%CMAKE_BUILDER%" %CMAKE_BUILD_ARCH% -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DBUILD_MODE=Release -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/
echo %DATE% %TIME% : Release Configuration done >> %StatusFile%
if "%dobuild%" == "1" (
msbuild /m "ll.vcxproj" /p:Configuration=Release /fl /flp:logfile=BlenderDeps_llvm.log;Verbosity=normal
@@ -133,7 +108,7 @@ if "%NODEBUG%" == "1" goto exit
cd %BUILD_DIR%
mkdir %STAGING%\%BuildDir%%ARCH%D
cd %Staging%\%BuildDir%%ARCH%D
-cmake -G "%CMAKE_BUILDER%" -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DCMAKE_BUILD_TYPE=Debug -DBUILD_MODE=Debug -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/ %CMAKE_DEBUG_OPTIONS%
+cmake -G "%CMAKE_BUILDER%" %CMAKE_BUILD_ARCH% -Thost=x64 %SOURCE_DIR% -DPACKAGE_DIR=%BUILD_DIR%/packages -DDOWNLOAD_DIR=%BUILD_DIR%/downloads -DCMAKE_BUILD_TYPE=Debug -DBUILD_MODE=Debug -DHARVEST_TARGET=%HARVEST_DIR%/%HARVESTROOT%%VSVER_SHORT%/ %CMAKE_DEBUG_OPTIONS%
echo %DATE% %TIME% : Debug Configuration done >> %StatusFile%
if "%dobuild%" == "1" (
msbuild /m "ll.vcxproj" /p:Configuration=Debug /fl /flp:logfile=BlenderDeps_llvm.log;;Verbosity=normal
diff --git a/build_files/cmake/Modules/FindBrotli.cmake b/build_files/cmake/Modules/FindBrotli.cmake
index 7460a87b14a..d1e40b1966a 100644
--- a/build_files/cmake/Modules/FindBrotli.cmake
+++ b/build_files/cmake/Modules/FindBrotli.cmake
@@ -75,6 +75,8 @@ ENDIF()
MARK_AS_ADVANCED(
BROTLI_INCLUDE_DIR
+ BROTLI_LIBRARY_COMMON
+ BROTLI_LIBRARY_DEC
BROTLI_LIBRARY_DIR
)
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake
index 5778699ee49..261a794b5c8 100644
--- a/build_files/cmake/platform/platform_unix.cmake
+++ b/build_files/cmake/platform/platform_unix.cmake
@@ -48,6 +48,9 @@ if(NOT DEFINED LIBDIR)
unset(LIBDIR_CENTOS7_ABI)
endif()
+# Support restoring this value once pre-compiled libraries have been handled.
+set(WITH_STATIC_LIBS_INIT ${WITH_STATIC_LIBS})
+
if(EXISTS ${LIBDIR})
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
@@ -101,10 +104,15 @@ find_package_wrapper(PNG REQUIRED)
find_package_wrapper(ZLIB REQUIRED)
find_package_wrapper(Zstd REQUIRED)
-# FreeType compiled with Brotli compression for woff2.
-find_package_wrapper(Freetype REQUIRED)
-if(EXISTS ${LIBDIR})
- find_package_wrapper(Brotli REQUIRED)
+if(NOT WITH_SYSTEM_FREETYPE)
+ # FreeType compiled with Brotli compression for woff2.
+ find_package_wrapper(Freetype REQUIRED)
+ if(EXISTS ${LIBDIR})
+ find_package_wrapper(Brotli REQUIRED)
+ list(APPEND FREETYPE_LIBRARIES
+ ${BROTLI_LIBRARIES}
+ )
+ endif()
endif()
if(WITH_PYTHON)
@@ -541,6 +549,21 @@ add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
#
# Keep last, so indirectly linked libraries don't override our own pre-compiled libs.
+if(EXISTS ${LIBDIR})
+ # Clear the prefix path as it causes the `LIBDIR` to override system locations.
+ unset(CMAKE_PREFIX_PATH)
+
+ # Since the pre-compiled `LIBDIR` directories have been handled, don't prefer static libraries.
+ set(WITH_STATIC_LIBS ${WITH_STATIC_LIBS_INIT})
+endif()
+
+if(WITH_SYSTEM_FREETYPE)
+ find_package_wrapper(Freetype)
+ if(NOT FREETYPE_FOUND)
+ message(FATAL_ERROR "Failed finding system FreeType version!")
+ endif()
+endif()
+
if(WITH_LZO AND WITH_SYSTEM_LZO)
find_package_wrapper(LZO)
if(NOT LZO_FOUND)
diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp
index 40d2e0ba814..34675be8e80 100644
--- a/intern/cycles/scene/shader_nodes.cpp
+++ b/intern/cycles/scene/shader_nodes.cpp
@@ -32,6 +32,7 @@
#include "util/color.h"
#include "util/foreach.h"
#include "util/log.h"
+#include "util/string.h"
#include "util/transform.h"
#include "kernel/tables.h"
@@ -462,8 +463,12 @@ void ImageTextureNode::compile(OSLCompiler &compiler)
const ustring known_colorspace = metadata.colorspace;
if (handle.svm_slot() == -1) {
+ /* OIIO currently does not support <UVTILE> substitutions natively. Replace with a format they
+ * understand. */
+ std::string osl_filename = filename.string();
+ string_replace(osl_filename, "<UVTILE>", "<U>_<V>");
compiler.parameter_texture(
- "filename", filename, compress_as_srgb ? u_colorspace_raw : known_colorspace);
+ "filename", ustring(osl_filename), compress_as_srgb ? u_colorspace_raw : known_colorspace);
}
else {
compiler.parameter_texture("filename", handle.svm_slot());
@@ -472,7 +477,8 @@ void ImageTextureNode::compile(OSLCompiler &compiler)
const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) ||
alpha_type == IMAGE_ALPHA_CHANNEL_PACKED ||
alpha_type == IMAGE_ALPHA_IGNORE);
- const bool is_tiled = (filename.find("<UDIM>") != string::npos);
+ const bool is_tiled = (filename.find("<UDIM>") != string::npos ||
+ filename.find("<UVTILE>") != string::npos);
compiler.parameter(this, "projection");
compiler.parameter(this, "projection_blend");
@@ -4388,9 +4394,6 @@ NODE_DEFINE(HairInfoNode)
SOCKET_OUT_FLOAT(size, "Length");
SOCKET_OUT_FLOAT(thickness, "Thickness");
SOCKET_OUT_NORMAL(tangent_normal, "Tangent Normal");
-#if 0 /* Output for minimum hair width transparency - deactivated. */
- SOCKET_OUT_FLOAT(fade, "Fade");
-#endif
SOCKET_OUT_FLOAT(index, "Random");
return type;
@@ -4448,12 +4451,7 @@ void HairInfoNode::compile(SVMCompiler &compiler)
if (!out->links.empty()) {
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out));
}
-#if 0
- out = output("Fade");
- if(!out->links.empty()) {
- compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out));
- }
-#endif
+
out = output("Random");
if (!out->links.empty()) {
int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
diff --git a/intern/cycles/util/math.h b/intern/cycles/util/math.h
index 18b60b70a4b..605a19aaef0 100644
--- a/intern/cycles/util/math.h
+++ b/intern/cycles/util/math.h
@@ -401,7 +401,7 @@ ccl_device_inline float fractf(float x)
return x - floorf(x);
}
-/* Adapted from godot-engine math_funcs.h. */
+/* Adapted from `godot-engine` math_funcs.h. */
ccl_device_inline float wrapf(float value, float max, float min)
{
float range = max - min;
diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt
index c564085c774..acd0da8785e 100644
--- a/intern/ghost/test/CMakeLists.txt
+++ b/intern/ghost/test/CMakeLists.txt
@@ -292,7 +292,7 @@ target_link_libraries(multitest_c
guardedalloc_lib
wcwidth_lib
${OPENGL_gl_LIBRARY}
- ${FREETYPE_LIBRARIES} ${BROTLI_LIBRARIES}
+ ${FREETYPE_LIBRARIES}
${ZLIB_LIBRARIES}
${CMAKE_DL_LIBS}
${PLATFORM_LINKLIBS}
diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt
index dd22bc2e7e0..b1453b243c0 100644
--- a/source/blender/blenfont/CMakeLists.txt
+++ b/source/blender/blenfont/CMakeLists.txt
@@ -54,7 +54,7 @@ set(LIB
bf_gpu
bf_intern_guardedalloc
- ${FREETYPE_LIBRARIES} ${BROTLI_LIBRARIES}
+ ${FREETYPE_LIBRARIES}
)
if(WIN32)
diff --git a/source/blender/blenkernel/BKE_crazyspace.h b/source/blender/blenkernel/BKE_crazyspace.h
index 61c5b2ae29e..42d85c70bc1 100644
--- a/source/blender/blenkernel/BKE_crazyspace.h
+++ b/source/blender/blenkernel/BKE_crazyspace.h
@@ -72,7 +72,7 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
float (**deformcos)[3]);
/* -------------------------------------------------------------------- */
-/** \name Crazyspace API
+/** \name Crazy-Space API
* \{ */
void BKE_crazyspace_api_eval(struct Depsgraph *depsgraph,
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 6460dedb736..accdfe1ca25 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -157,7 +157,8 @@ int BKE_layer_collection_findindex(struct ViewLayer *view_layer, const struct La
void BKE_layer_collection_resync_forbid(void);
void BKE_layer_collection_resync_allow(void);
-/** Helper to fix older pre-2.80 blendfiles.
+/**
+ * Helper to fix older pre-2.80 blend-files.
*
* Ensures the given `view_layer` as a valid first-level layer collection, i.e. a single one
* matching the scene's master collection. This is a requirement for `BKE_layer_collection_sync`.
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 41ca8084849..358ae934088 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -522,7 +522,7 @@ set(LIB
bf_simulation
# For `vfontdata_freetype.c`.
- ${FREETYPE_LIBRARIES} ${BROTLI_LIBRARIES}
+ ${FREETYPE_LIBRARIES}
)
if(WITH_BINRELOC)
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 26b0b72cd63..49a518607f1 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -462,7 +462,7 @@ void BKE_lib_id_make_local_generic_action_define(
BLI_assert(force_copy == false || force_copy != force_local);
if (force_local || force_copy) {
- /* Already set by caller code, nothig to do here. */
+ /* Already set by caller code, nothing to do here. */
*r_force_local = force_local;
*r_force_copy = force_copy;
return;
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index ed0174bd592..e177b1ce29e 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -4572,7 +4572,7 @@ Mesh *BKE_object_get_editmesh_eval_final(const Object *object)
const Mesh *mesh = static_cast<const Mesh *>(object->data);
if (mesh->edit_mesh == nullptr) {
- /* Heppens when requesting material of evaluated 3d font obejct: the evaluated object get
+ /* Happens when requesting material of evaluated 3d font object: the evaluated object get
* converted to mesh, and it does not have edit mesh. */
return nullptr;
}
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index ef522e57d02..03b6d8c7381 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -1560,7 +1560,8 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
clip->proxy.build_size_flag,
clip->proxy.quality,
true,
- NULL);
+ NULL,
+ false);
}
WM_jobs_customdata_set(wm_job, pj, proxy_freejob);
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 9f31e55439d..72c39839739 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -59,6 +59,7 @@
#include "SEQ_add.h"
#include "SEQ_effects.h"
+#include "SEQ_iterator.h"
#include "SEQ_proxy.h"
#include "SEQ_relations.h"
#include "SEQ_render.h"
@@ -601,29 +602,28 @@ static IMB_Proxy_Size seq_get_proxy_size_flags(bContext *C)
return proxy_sizes;
}
-static void seq_build_proxy(bContext *C, Sequence *seq)
+static void seq_build_proxy(bContext *C, SeqCollection *movie_strips)
{
if (U.sequencer_proxy_setup != USER_SEQ_PROXY_SETUP_AUTOMATIC) {
return;
}
- /* Enable and set proxy size. */
- SEQ_proxy_set(seq, true);
- seq->strip->proxy->build_size_flags = seq_get_proxy_size_flags(C);
- seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
-
- /* Build proxy. */
- GSet *file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
wmJob *wm_job = ED_seq_proxy_wm_job_get(C);
ProxyJob *pj = ED_seq_proxy_job_get(C, wm_job);
- SEQ_proxy_rebuild_context(pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
- BLI_gset_free(file_list, MEM_freeN);
+
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, movie_strips) {
+ /* Enable and set proxy size. */
+ SEQ_proxy_set(seq, true);
+ seq->strip->proxy->build_size_flags = seq_get_proxy_size_flags(C);
+ seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING;
+ SEQ_proxy_rebuild_context(pj->main, pj->depsgraph, pj->scene, seq, NULL, &pj->queue, true);
+ }
if (!WM_jobs_is_running(wm_job)) {
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-
ED_area_tag_redraw(CTX_wm_area(C));
}
@@ -642,7 +642,8 @@ static void sequencer_add_movie_clamp_sound_strip_length(Scene *scene,
static void sequencer_add_movie_multiple_strips(bContext *C,
wmOperator *op,
- SeqLoadData *load_data)
+ SeqLoadData *load_data,
+ SeqCollection *r_movie_strips)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -705,13 +706,16 @@ static void sequencer_add_movie_multiple_strips(bContext *C,
sequencer_add_movie_clamp_sound_strip_length(scene, ed->seqbasep, seq_movie, seq_sound);
seq_load_apply_generic_options(C, op, seq_sound);
seq_load_apply_generic_options(C, op, seq_movie);
- seq_build_proxy(C, seq_movie);
+ SEQ_collection_append_strip(seq_movie, r_movie_strips);
}
}
RNA_END;
}
-static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, SeqLoadData *load_data)
+static bool sequencer_add_movie_single_strip(bContext *C,
+ wmOperator *op,
+ SeqLoadData *load_data,
+ SeqCollection *r_movie_strips)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -757,7 +761,7 @@ static bool sequencer_add_movie_single_strip(bContext *C, wmOperator *op, SeqLoa
sequencer_add_movie_clamp_sound_strip_length(scene, ed->seqbasep, seq_movie, seq_sound);
seq_load_apply_generic_options(C, op, seq_sound);
seq_load_apply_generic_options(C, op, seq_movie);
- seq_build_proxy(C, seq_movie);
+ SEQ_collection_append_strip(seq_movie, r_movie_strips);
return true;
}
@@ -774,21 +778,25 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op)
ED_sequencer_deselect_all(scene);
}
+ SeqCollection *movie_strips = SEQ_collection_create(__func__);
const int tot_files = RNA_property_collection_length(op->ptr,
RNA_struct_find_property(op->ptr, "files"));
if (tot_files > 1) {
- sequencer_add_movie_multiple_strips(C, op, &load_data);
+ sequencer_add_movie_multiple_strips(C, op, &load_data, movie_strips);
}
else {
- if (!sequencer_add_movie_single_strip(C, op, &load_data)) {
- sequencer_add_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
+ sequencer_add_movie_single_strip(C, op, &load_data, movie_strips);
+ }
+
+ if (SEQ_collection_len(movie_strips) == 0) {
+ SEQ_collection_free(movie_strips);
+ return OPERATOR_CANCELLED;
}
/* Free custom data. */
sequencer_add_cancel(C, op);
+ seq_build_proxy(C, movie_strips);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c
index 0a8eb7cb88f..fb561025da2 100644
--- a/source/blender/editors/space_sequencer/sequencer_proxy.c
+++ b/source/blender/editors/space_sequencer/sequencer_proxy.c
@@ -85,7 +85,7 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports)
}
bool success = SEQ_proxy_rebuild_context(
- pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
+ pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue, false);
if (!success && (seq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) != 0) {
BKE_reportf(reports, RPT_WARNING, "Overwrite is not checked for %s, skipping", seq->name);
@@ -137,7 +137,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op))
short stop = 0, do_update;
float progress;
- SEQ_proxy_rebuild_context(bmain, depsgraph, scene, seq, file_list, &queue);
+ SEQ_proxy_rebuild_context(bmain, depsgraph, scene, seq, file_list, &queue, false);
for (link = queue.first; link; link = link->next) {
struct SeqIndexBuildContext *context = link->data;
diff --git a/source/blender/geometry/GEO_mesh_merge_by_distance.hh b/source/blender/geometry/GEO_mesh_merge_by_distance.hh
index 00ba45f9dd2..1d64680a02b 100644
--- a/source/blender/geometry/GEO_mesh_merge_by_distance.hh
+++ b/source/blender/geometry/GEO_mesh_merge_by_distance.hh
@@ -33,8 +33,8 @@ namespace blender::geometry {
* Merge selected vertices into other selected vertices within the \a merge_distance. The merged
* indices favor speed over accuracy, since the results will depend on the order of the vertices.
*
- * \returns std::nullopt if the mesh should not be changed (no vertices are merged), in order to
- * avoid copying the input. Otherwise returns the new mesh with merged geoemetry.
+ * \returns #std::nullopt if the mesh should not be changed (no vertices are merged), in order to
+ * avoid copying the input. Otherwise returns the new mesh with merged geometry.
*/
std::optional<Mesh *> mesh_merge_by_distance_all(const Mesh &mesh,
IndexMask selection,
@@ -44,8 +44,8 @@ std::optional<Mesh *> mesh_merge_by_distance_all(const Mesh &mesh,
* Merge selected vertices along edges to other selected vertices. Only vertices connected by edges
* are considered for merging.
*
- * \returns std::nullopt if the mesh should not be changed (no vertices are merged), in order to
- * avoid copying the input. Otherwise returns the new mesh with merged geoemetry.
+ * \returns #std::nullopt if the mesh should not be changed (no vertices are merged), in order to
+ * avoid copying the input. Otherwise returns the new mesh with merged geometry.
*/
std::optional<Mesh *> mesh_merge_by_distance_connected(const Mesh &mesh,
Span<bool> selection,
diff --git a/source/blender/geometry/intern/mesh_merge_by_distance.cc b/source/blender/geometry/intern/mesh_merge_by_distance.cc
index e49848a030b..1a07ebf31f6 100644
--- a/source/blender/geometry/intern/mesh_merge_by_distance.cc
+++ b/source/blender/geometry/intern/mesh_merge_by_distance.cc
@@ -563,14 +563,10 @@ static void weld_edge_groups_setup(const int medge_len,
Array<WeldGroupEdge> &r_edge_groups)
{
/* Get weld edge groups. */
-
- struct WeldGroupEdge *wegrp_iter;
-
int wgroups_len = wedge.size() - edge_kill_len;
r_edge_groups.reinitialize(wgroups_len);
r_edge_groups.fill({{0}});
MutableSpan<WeldGroupEdge> wegroups = r_edge_groups;
- wegrp_iter = &r_edge_groups[0];
wgroups_len = 0;
for (const int i : IndexRange(medge_len)) {
@@ -584,11 +580,10 @@ static void weld_edge_groups_setup(const int medge_len,
}
else {
we->edge_dest = we->edge_orig;
- wegrp_iter->v1 = we->vert_a;
- wegrp_iter->v2 = we->vert_b;
+ wegroups[wgroups_len].v1 = we->vert_a;
+ wegroups[wgroups_len].v2 = we->vert_b;
r_edge_groups_map[i] = wgroups_len;
wgroups_len++;
- wegrp_iter++;
}
}
else {
@@ -598,6 +593,11 @@ static void weld_edge_groups_setup(const int medge_len,
BLI_assert(wgroups_len == wedge.size() - edge_kill_len);
+ if (wgroups_len == 0) {
+ /* All edges in the context are collapsed. */
+ return;
+ }
+
for (const WeldEdge &we : wedge) {
if (we.flag == ELEM_COLLAPSED) {
continue;
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index aadb52fb49c..958aab65b57 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -61,6 +61,15 @@ typedef struct GPUSelectState {
char algorithm;
/* allow GPU_select_begin/end without drawing */
bool use_cache;
+ /**
+ * Signifies that #GPU_select_cache_begin has been called,
+ * future calls to #GPU_select_begin should initialize the cache.
+ *
+ * \note #GPU_select_cache_begin could perform initialization but doesn't as it's inconvenient
+ * for callers making the cache begin/end calls outside lower level selection logic
+ * where the `mode` to pass to #GPU_select_begin yet isn't known.
+ */
+ bool use_cache_needs_init;
} GPUSelectState;
static GPUSelectState g_select_state = {0};
@@ -90,9 +99,26 @@ void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode,
g_select_state.algorithm = ALGO_GL_QUERY;
}
+ /* This function is called when cache has already been initialized,
+ * so only manipulate cache values when cache is pending. */
+ if (g_select_state.use_cache_needs_init) {
+ g_select_state.use_cache_needs_init = false;
+
+ switch (g_select_state.algorithm) {
+ case ALGO_GL_QUERY: {
+ g_select_state.use_cache = false;
+ break;
+ }
+ default: {
+ g_select_state.use_cache = true;
+ gpu_select_pick_cache_begin();
+ break;
+ }
+ }
+ }
+
switch (g_select_state.algorithm) {
case ALGO_GL_QUERY: {
- g_select_state.use_cache = false;
gpu_select_query_begin((uint(*)[4])buffer, bufsize / 4, input, mode, oldhits);
break;
}
@@ -154,12 +180,13 @@ uint GPU_select_end(void)
void GPU_select_cache_begin(void)
{
- /* validate on GPU_select_begin, clear if not supported */
- BLI_assert(g_select_state.use_cache == false);
- g_select_state.use_cache = true;
- if (g_select_state.algorithm == ALGO_GL_PICK) {
- gpu_select_pick_cache_begin();
- }
+ BLI_assert(g_select_state.select_is_active == false);
+ /* Ensure #GPU_select_cache_end is always called. */
+ BLI_assert(g_select_state.use_cache_needs_init == false);
+
+ /* Signal that cache should be used, instead of calling the algorithms cache-begin function.
+ * This is more convenient as the exact method of selection may not be known by the caller. */
+ g_select_state.use_cache_needs_init = true;
}
void GPU_select_cache_load_id(void)
@@ -173,9 +200,12 @@ void GPU_select_cache_load_id(void)
void GPU_select_cache_end(void)
{
if (g_select_state.algorithm == ALGO_GL_PICK) {
+ BLI_assert(g_select_state.use_cache == true);
gpu_select_pick_cache_end();
}
g_select_state.use_cache = false;
+ /* Paranoid assignment, should already be false. */
+ g_select_state.use_cache_needs_init = false;
}
bool GPU_select_is_cached(void)
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index 737e4c6e874..ddd3dfc6879 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -673,7 +673,7 @@ uint gpu_select_pick_end(void)
#endif
/* first 3 are dummy values */
g_pick_state.buffer[hits][0] = 1;
- g_pick_state.buffer[hits][1] = 0x0; /* depth_data[i].depth; */ /* unused */
+ g_pick_state.buffer[hits][1] = depth_data[i].depth;
g_pick_state.buffer[hits][2] = 0x0; /* z-far is currently never used. */
g_pick_state.buffer[hits][3] = depth_data[i].id;
hits++;
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc
index e245d9b5269..f7622751726 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.cc
+++ b/source/blender/gpu/intern/gpu_shader_create_info.cc
@@ -112,7 +112,7 @@ void ShaderCreateInfo::finalize()
void ShaderCreateInfo::validate(const ShaderCreateInfo &other_info)
{
{
- /* Check same bindpoints usage in OGL. */
+ /* Check same bind-points usage in OGL. */
Set<int> images, samplers, ubos, ssbos;
auto register_resource = [&](const Resource &res) -> bool {
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh
index 391752a31a8..6236e92a226 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.hh
+++ b/source/blender/gpu/intern/gpu_shader_create_info.hh
@@ -63,7 +63,10 @@ enum class Type {
};
enum class BuiltinBits {
- /** Allow getting barycentic coordinates inside the fragment shader. NOTE: emulated on OpenGL. */
+ /**
+ * Allow getting barycentric coordinates inside the fragment shader.
+ * \note Emulated on OpenGL.
+ */
BARYCENTRIC_COORD = (1 << 0),
FRAG_COORD = (1 << 2),
FRONT_FACING = (1 << 4),
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index c32123bc15e..92d180f1140 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -423,7 +423,7 @@ static void detect_workarounds()
/* Buggy interface query functions cause crashes when handling SSBOs (T93680) */
if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY) &&
- (strstr(renderer, "HD Graphics 4400")|| strstr(renderer, "HD Graphics 4600"))) {
+ (strstr(renderer, "HD Graphics 4400") || strstr(renderer, "HD Graphics 4600"))) {
GCaps.shader_storage_buffer_objects_support = false;
}
} // namespace blender::gpu
diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index 0d4f1d15f39..1e6e2475665 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -601,11 +601,6 @@ static char *glsl_patch_default_get()
STR_CONCAT(patch, slen, "#extension GL_ARB_shading_language_420pack: enable\n");
}
- if (!GLContext::shader_draw_parameters_support) {
- /* Fallback: Emulate base instance using a uniform. */
- STR_CONCAT(patch, slen, "uniform int gpu_BaseInstance;\n");
- }
-
/* Fallbacks. */
if (!GLContext::shader_draw_parameters_support) {
STR_CONCAT(patch, slen, "uniform int gpu_BaseInstance;\n");
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 65d7631445d..a557d7dc6d1 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -378,8 +378,9 @@ struct IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim,
IMB_Timecode_Type tcs_in_use,
IMB_Proxy_Size proxy_sizes_in_use,
int quality,
- bool overwrite,
- struct GSet *file_list);
+ const bool overwrite,
+ struct GSet *file_list,
+ bool build_only_on_bad_performance);
/**
* Will rebuild all used indices and proxies at once.
@@ -431,6 +432,7 @@ bool IMB_anim_can_produce_frames(const struct anim *anim);
int ismovie(const char *filepath);
int IMB_anim_get_image_width(struct anim *anim);
int IMB_anim_get_image_height(struct anim *anim);
+bool IMB_get_gop_decode_time(struct anim *anim);
/**
*
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 7aeee2740c0..a85ba65d014 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -37,6 +37,8 @@
# include "BLI_winstuff.h"
#endif
+#include "PIL_time.h"
+
#include "IMB_anim.h"
#include "IMB_indexer.h"
#include "imbuf.h"
@@ -814,12 +816,16 @@ typedef struct FFmpegIndexBuilderContext {
double pts_time_base;
int frameno, frameno_gapless;
int start_pts_set;
+
+ bool build_only_on_bad_performance;
+ bool building_cancelled;
} FFmpegIndexBuilderContext;
static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
IMB_Timecode_Type tcs_in_use,
IMB_Proxy_Size proxy_sizes_in_use,
- int quality)
+ int quality,
+ bool build_only_on_bad_performance)
{
FFmpegIndexBuilderContext *context = MEM_callocN(sizeof(FFmpegIndexBuilderContext),
"FFmpeg index builder context");
@@ -831,6 +837,7 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
context->proxy_sizes_in_use = proxy_sizes_in_use;
context->num_proxy_sizes = IMB_PROXY_MAX_SLOT;
context->num_indexers = IMB_TC_MAX_SLOT;
+ context->build_only_on_bad_performance = build_only_on_bad_performance;
memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx));
memset(context->indexer, 0, sizeof(context->indexer));
@@ -936,15 +943,17 @@ static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, int
{
int i;
+ const bool do_rollback = stop || context->building_cancelled;
+
for (i = 0; i < context->num_indexers; i++) {
if (context->tcs_in_use & tc_types[i]) {
- IMB_index_builder_finish(context->indexer[i], stop);
+ IMB_index_builder_finish(context->indexer[i], do_rollback);
}
}
for (i = 0; i < context->num_proxy_sizes; i++) {
if (context->proxy_sizes_in_use & proxy_sizes[i]) {
- free_proxy_output_ffmpeg(context->proxy_ctx[i], stop);
+ free_proxy_output_ffmpeg(context->proxy_ctx[i], do_rollback);
}
}
@@ -1095,6 +1104,111 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
return 1;
}
+/* Get number of frames, that can be decoded in specified time period. */
+static int indexer_performance_get_decode_rate(FFmpegIndexBuilderContext *context,
+ const double time_period)
+{
+ AVFrame *in_frame = av_frame_alloc();
+ AVPacket *packet = av_packet_alloc();
+
+ const double start = PIL_check_seconds_timer();
+ int frames_decoded = 0;
+
+ while (av_read_frame(context->iFormatCtx, packet) >= 0) {
+ if (packet->stream_index != context->videoStream) {
+ continue;
+ }
+
+ int ret = avcodec_send_packet(context->iCodecCtx, packet);
+ while (ret >= 0) {
+ ret = avcodec_receive_frame(context->iCodecCtx, in_frame);
+
+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+ break;
+ }
+
+ if (ret < 0) {
+ fprintf(stderr, "Error decoding proxy frame: %s\n", av_err2str(ret));
+ break;
+ }
+ frames_decoded++;
+ }
+
+ const double end = PIL_check_seconds_timer();
+
+ if (end > start + time_period) {
+ break;
+ }
+ }
+
+ avcodec_flush_buffers(context->iCodecCtx);
+ av_seek_frame(context->iFormatCtx, -1, 0, AVSEEK_FLAG_BACKWARD);
+ return frames_decoded;
+}
+
+/* Read up to 10k movie packets and return max GOP size detected.
+ * Number of packets is arbitrary. It should be as large as possible, but processed within
+ * reasonable time period, so detected GOP size is as close to real as possible. */
+static int indexer_performance_get_max_gop_size(FFmpegIndexBuilderContext *context)
+{
+ AVPacket *packet = av_packet_alloc();
+
+ const int packets_max = 10000;
+ int packet_index = 0;
+ int max_gop = 0;
+ int cur_gop = 0;
+
+ while (av_read_frame(context->iFormatCtx, packet) >= 0) {
+ if (packet->stream_index != context->videoStream) {
+ continue;
+ }
+ packet_index++;
+ cur_gop++;
+
+ if (packet->flags & AV_PKT_FLAG_KEY) {
+ max_gop = max_ii(max_gop, cur_gop);
+ cur_gop = 0;
+ }
+
+ if (packet_index > packets_max) {
+ break;
+ }
+ }
+
+ av_seek_frame(context->iFormatCtx, -1, 0, AVSEEK_FLAG_BACKWARD);
+ return max_gop;
+}
+
+/* Assess scrubbing performance of provided file. This function is not meant to be very exact.
+ * It compares number number of frames decoded in reasonable time with largest detected GOP size.
+ * Because seeking happens in single GOP, it means, that maximum seek time can be detected this
+ * way.
+ * Since proxies use GOP size of 10 frames, skip building if detected GOP size is less or
+ * equal.
+ */
+static bool indexer_need_to_build_proxy(FFmpegIndexBuilderContext *context)
+{
+ if (!context->build_only_on_bad_performance) {
+ return true;
+ }
+
+ /* Make sure, that file is not cold read. */
+ indexer_performance_get_decode_rate(context, 0.1);
+ /* Get decode rate per 100ms. This is arbitrary, but seems to be good baseline cadence of
+ * seeking. */
+ const int decode_rate = indexer_performance_get_decode_rate(context, 0.1);
+ const int max_gop_size = indexer_performance_get_max_gop_size(context);
+
+ if (max_gop_size <= 10 || max_gop_size < decode_rate) {
+ printf("Skipping proxy building for %s: Decoding performance is already good.\n",
+ context->iFormatCtx->url);
+ context->building_cancelled = true;
+ return false;
+ }
+
+ return true;
+}
+
#endif
/* ----------------------------------------------------------------------
@@ -1274,7 +1388,8 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim,
IMB_Proxy_Size proxy_sizes_in_use,
int quality,
const bool overwrite,
- GSet *file_list)
+ GSet *file_list,
+ bool build_only_on_bad_performance)
{
IndexBuildContext *context = NULL;
IMB_Proxy_Size proxy_sizes_to_build = proxy_sizes_in_use;
@@ -1328,9 +1443,13 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim,
switch (anim->curtype) {
#ifdef WITH_FFMPEG
case ANIM_FFMPEG:
- context = index_ffmpeg_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality);
+ context = index_ffmpeg_create_context(
+ anim, tcs_in_use, proxy_sizes_to_build, quality, build_only_on_bad_performance);
break;
+#else
+ UNUSED_VARS(build_only_on_bad_performance);
#endif
+
#ifdef WITH_AVI
default:
context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality);
@@ -1358,7 +1477,9 @@ void IMB_anim_index_rebuild(struct IndexBuildContext *context,
switch (context->anim_type) {
#ifdef WITH_FFMPEG
case ANIM_FFMPEG:
- index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress);
+ if (indexer_need_to_build_proxy((FFmpegIndexBuilderContext *)context)) {
+ index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress);
+ }
break;
#endif
#ifdef WITH_AVI
diff --git a/source/blender/makesdna/DNA_brush_enums.h b/source/blender/makesdna/DNA_brush_enums.h
index 68e50c5b29d..2f41389f2c6 100644
--- a/source/blender/makesdna/DNA_brush_enums.h
+++ b/source/blender/makesdna/DNA_brush_enums.h
@@ -522,7 +522,7 @@ typedef enum eBrushUVSculptTool {
SCULPT_TOOL_SLIDE_RELAX, \
SCULPT_TOOL_MASK) == 0)
-/* ImagePaintSettings.tool */
+/** #ImagePaintSettings.tool */
typedef enum eBrushImagePaintTool {
PAINT_TOOL_DRAW = 0,
PAINT_TOOL_SOFTEN = 1,
@@ -534,7 +534,7 @@ typedef enum eBrushImagePaintTool {
/* The enums here should be kept in sync with the weight paint tool.
* This is because #smooth_brush_toggle_on and #smooth_brush_toggle_off
- * assumes that the Blur blursh has the same enum value. */
+ * assumes that the blur brush has the same enum value. */
typedef enum eBrushVertexPaintTool {
VPAINT_TOOL_DRAW = 0,
VPAINT_TOOL_BLUR = 1,
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index b154576df76..099e41d7ff0 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1848,7 +1848,6 @@ enum {
/* math node clamp */
#define SHD_MATH_CLAMP 1
-/** Math node operations. */
typedef enum NodeMathOperation {
NODE_MATH_ADD = 0,
NODE_MATH_SUBTRACT = 1,
@@ -1892,7 +1891,6 @@ typedef enum NodeMathOperation {
NODE_MATH_SMOOTH_MAX = 39,
} NodeMathOperation;
-/** Vector Math node operations. */
typedef enum NodeVectorMathOperation {
NODE_VECTOR_MATH_ADD = 0,
NODE_VECTOR_MATH_SUBTRACT = 1,
@@ -1926,7 +1924,6 @@ typedef enum NodeVectorMathOperation {
NODE_VECTOR_MATH_MULTIPLY_ADD = 26,
} NodeVectorMathOperation;
-/** Boolean math node operations. */
typedef enum NodeBooleanMathOperation {
NODE_BOOLEAN_MATH_AND = 0,
NODE_BOOLEAN_MATH_OR = 1,
@@ -1941,7 +1938,6 @@ typedef enum NodeBooleanMathOperation {
NODE_BOOLEAN_MATH_NIMPLY = 8,
} NodeBooleanMathOperation;
-/** Float compare node operations. */
typedef enum NodeCompareMode {
NODE_COMPARE_MODE_ELEMENT = 0,
NODE_COMPARE_MODE_LENGTH = 1,
@@ -1959,10 +1955,8 @@ typedef enum NodeCompareOperation {
NODE_COMPARE_NOT_EQUAL = 5,
NODE_COMPARE_COLOR_BRIGHTER = 6,
NODE_COMPARE_COLOR_DARKER = 7,
-
} NodeCompareOperation;
-/** Float to Int node operations. */
typedef enum FloatToIntRoundingMode {
FN_NODE_FLOAT_TO_INT_ROUND = 0,
FN_NODE_FLOAT_TO_INT_FLOOR = 1,
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index ec9b67deeac..e2411f5f4ae 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -2340,7 +2340,8 @@ static void seq_build_proxy(bContext *C, PointerRNA *ptr)
seq->strip->proxy->build_size_flags |= SEQ_rendersize_to_proxysize(sseq->render_size);
/* Build proxy. */
- SEQ_proxy_rebuild_context(pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
+ SEQ_proxy_rebuild_context(
+ pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue, true);
}
BLI_gset_free(file_list, MEM_freeN);
diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.cc b/source/blender/nodes/shader/nodes/node_shader_hair_info.cc
index e22a825c066..12c29c40b1d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hair_info.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.cc
@@ -28,7 +28,6 @@ static void node_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Float>(N_("Length"));
b.add_output<decl::Float>(N_("Thickness"));
b.add_output<decl::Vector>(N_("Tangent Normal"));
- // b.add_output<decl::Float>(N_("Fade"));
b.add_output<decl::Float>(N_("Random"));
}
diff --git a/source/blender/sequencer/SEQ_proxy.h b/source/blender/sequencer/SEQ_proxy.h
index 7bfe932ff1c..164b279245c 100644
--- a/source/blender/sequencer/SEQ_proxy.h
+++ b/source/blender/sequencer/SEQ_proxy.h
@@ -42,7 +42,8 @@ bool SEQ_proxy_rebuild_context(struct Main *bmain,
struct Scene *scene,
struct Sequence *seq,
struct GSet *file_list,
- struct ListBase *queue);
+ struct ListBase *queue,
+ bool build_only_on_bad_performance);
void SEQ_proxy_rebuild(struct SeqIndexBuildContext *context,
short *stop,
short *do_update,
diff --git a/source/blender/sequencer/intern/proxy.c b/source/blender/sequencer/intern/proxy.c
index cc0ea0634a3..5982f89a287 100644
--- a/source/blender/sequencer/intern/proxy.c
+++ b/source/blender/sequencer/intern/proxy.c
@@ -415,7 +415,8 @@ bool SEQ_proxy_rebuild_context(Main *bmain,
Scene *scene,
Sequence *seq,
struct GSet *file_list,
- ListBase *queue)
+ ListBase *queue,
+ bool build_only_on_bad_performance)
{
SeqIndexBuildContext *context;
Sequence *nseq;
@@ -476,7 +477,8 @@ bool SEQ_proxy_rebuild_context(Main *bmain,
context->size_flags,
context->quality,
context->overwrite,
- file_list);
+ file_list,
+ build_only_on_bad_performance);
}
if (!context->index_context) {
MEM_freeN(context);
diff --git a/source/blender/sequencer/intern/sound.c b/source/blender/sequencer/intern/sound.c
index 86a37aca4a9..0788003fb12 100644
--- a/source/blender/sequencer/intern/sound.c
+++ b/source/blender/sequencer/intern/sound.c
@@ -31,6 +31,7 @@
#include "DNA_sound_types.h"
#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
#include "BKE_main.h"
#include "BKE_scene.h"
@@ -56,11 +57,15 @@ static bool sequencer_refresh_sound_length_recursive(Main *bmain, Scene *scene,
}
}
else if (seq->type == SEQ_TYPE_SOUND_RAM && seq->sound) {
- const float length = BKE_sound_get_length(bmain, seq->sound);
+ SoundInfo info;
+ if (!BKE_sound_info_get(bmain, seq->sound, &info)) {
+ continue;
+ }
+
int old = seq->len;
float fac;
- seq->len = (int)ceil((double)length * FPS);
+ seq->len = MAX2(1, round((info.length - seq->sound->offset_time) * FPS));
fac = (float)seq->len / (float)old;
old = seq->startofs;
seq->startofs *= fac;
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index d3e682f1490..e61de28d0a4 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -38,9 +38,11 @@
#include "ED_select_utils.h"
#include "ED_view3d.h"
+#include "GPU_framebuffer.h"
#include "GPU_matrix.h"
#include "GPU_select.h"
#include "GPU_state.h"
+#include "GPU_viewport.h"
#include "MEM_guardedalloc.h"
@@ -505,8 +507,7 @@ void WM_gizmomap_draw(wmGizmoMap *gzmap,
static void gizmo_draw_select_3d_loop(const bContext *C,
wmGizmo **visible_gizmos,
- const int visible_gizmos_len,
- bool *r_use_select_bias)
+ const int visible_gizmos_len)
{
/* TODO(campbell): this depends on depth buffer being written to,
@@ -542,10 +543,6 @@ static void gizmo_draw_select_3d_loop(const bContext *C,
is_depth_skip_prev = is_depth_skip;
}
- if (gz->select_bias != 0.0) {
- *r_use_select_bias = true;
- }
-
/* pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id */
gz->type->draw_select(C, gz, select_id << 8);
@@ -563,7 +560,10 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
const int visible_gizmos_len,
const bContext *C,
const int co[2],
- const int hotspot)
+ const int hotspot,
+ const bool use_depth_test,
+ const bool has_3d_select_bias,
+ int *r_hits)
{
const wmWindowManager *wm = CTX_wm_manager(C);
ScrArea *area = CTX_wm_area(C);
@@ -577,30 +577,69 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
BLI_rcti_init_pt_radius(&rect, co, hotspot);
- ED_view3d_draw_setup_view(
- wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, &rect);
-
- bool use_select_bias = false;
+ /* The selection mode is assigned for the following reasons:
+ *
+ * - #GPU_SELECT_ALL: Use it to check if there is anything at the cursor location
+ * (only ever runs once).
+ * - #GPU_SELECT_PICK_NEAREST: Use if there are more than 1 item at the cursor location,
+ * select the best one.
+ * - #GPU_SELECT_PICK_ALL: Use for the same purpose as #GPU_SELECT_PICK_NEAREST
+ * when the selection depths need to re-ordered based on a bias.
+ * */
+ const int gpu_select_mode = (use_depth_test ?
+ (has_3d_select_bias ?
+ /* Using select bias means the depths need to be
+ * re-calculated based on the bias to pick the best. */
+ GPU_SELECT_PICK_ALL :
+ /* No bias, just pick the closest. */
+ GPU_SELECT_PICK_NEAREST) :
+ /* Fast-path (occlusion queries). */
+ GPU_SELECT_ALL);
+
+ if (GPU_select_is_cached()) {
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, gpu_select_mode, 0);
+ GPU_select_cache_load_id();
+ hits = GPU_select_end();
+ }
+ else {
+ /* TODO: waiting for the GPU in the middle of the event loop for every
+ * mouse move is bad for performance, we need to find a solution to not
+ * use the GPU or draw something once. (see T61474) */
+
+ ED_view3d_draw_setup_view(
+ wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, &rect);
+
+ /* There is no need to bind to the depth buffer outside this function
+ * because all future passes the will use the cached depths. */
+ GPUFrameBuffer *depth_read_fb = NULL;
+ if (use_depth_test) {
+ GPUViewport *viewport = WM_draw_region_get_viewport(CTX_wm_region(C));
+ GPUTexture *depth_tx = GPU_viewport_depth_texture(viewport);
+ GPU_framebuffer_ensure_config(&depth_read_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(depth_tx),
+ GPU_ATTACHMENT_NONE,
+ });
+ GPU_framebuffer_bind(depth_read_fb);
+ }
- /* TODO: waiting for the GPU in the middle of the event loop for every
- * mouse move is bad for performance, we need to find a solution to not
- * use the GPU or draw something once. (see T61474) */
- GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
- /* do the drawing */
- gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, gpu_select_mode, 0);
+ gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len);
+ hits = GPU_select_end();
- hits = GPU_select_end();
+ if (use_depth_test) {
+ GPU_framebuffer_restore();
+ GPU_framebuffer_free(depth_read_fb);
+ }
- if (hits > 0) {
- GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
- gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
- GPU_select_end();
+ ED_view3d_draw_setup_view(
+ wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, NULL);
}
- ED_view3d_draw_setup_view(
- wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, NULL);
+ /* When selection bias is needed, this function will run again with `use_depth_test` enabled. */
+ int hit_found = -1;
- if (use_select_bias && (hits > 1)) {
+ if (has_3d_select_bias && use_depth_test && (hits > 1)) {
float co_direction[3];
float co_screen[3] = {co[0], co[1], 0.0f};
ED_view3d_win_to_vector(region, (float[2]){UNPACK2(co)}, co_direction);
@@ -612,7 +651,6 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
uint *buf_iter = buffer;
- int hit_found = -1;
float dot_best = FLT_MAX;
for (int i = 0; i < hits; i++, buf_iter += 4) {
@@ -632,11 +670,16 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
hit_found = buf_iter[3];
}
}
- return hit_found;
+ }
+ else {
+ const uint *hit_near = GPU_select_buffer_near(buffer, hits);
+ if (hit_near) {
+ hit_found = hit_near[3];
+ }
}
- const uint *hit_near = GPU_select_buffer_near(buffer, hits);
- return hit_near ? hit_near[3] : -1;
+ *r_hits = hits;
+ return hit_found;
}
/**
@@ -659,6 +702,7 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
/* Search for 3D gizmo's that use the 2D callback for checking intersections. */
bool has_3d = false;
+ bool has_3d_select_bias = false;
{
for (int select_id = 0; select_id < visible_gizmos_len; select_id++) {
wmGizmo *gz = visible_gizmos[select_id];
@@ -674,6 +718,9 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
}
else if (gz->type->draw_select != NULL) {
has_3d = true;
+ if (gz->select_bias != 0.0f) {
+ has_3d_select_bias = true;
+ }
}
}
}
@@ -681,17 +728,78 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
/* Search for 3D intersections if they're before 2D that have been found (if any).
* This way we always use the first hit. */
if (has_3d) {
+
+ /* NOTE(@campbellbarton): The selection logic here uses a fast-path that exits early
+ * where possible. This is important as this runs on cursor-motion in the 3D view-port.
+ *
+ * - First, don't use the depth buffer at all, use occlusion queries to detect any gizmos.
+ * If there are no gizmos or only one - early exit, otherwise.
+ *
+ * - Bind the depth buffer and and use selection picking logic.
+ * This is much slower than occlusion queries (since it's reading depths while drawing).
+ * When there is a single gizmo under the cursor (quite common), early exit, otherwise.
+ *
+ * - Perform another pass at a reduced size (see: `hotspot_radii`),
+ * since the result depths are cached this pass is practically free.
+ *
+ * Other notes:
+ *
+ * - If any of these passes fail, use the nearest result from the previous pass.
+ *
+ * - Drawing is only ever done twice.
+ */
+
+ /* Order largest to smallest so the first pass can be used as cache for
+ * later passes (when `use_depth_test == true`). */
const int hotspot_radii[] = {
- 3 * U.pixelsize,
- /* This runs on mouse move, careful doing too many tests! */
10 * U.pixelsize,
+ /* This runs on mouse move, careful doing too many tests! */
+ 3 * U.pixelsize,
};
+
+ /* Narrowing may assign zero to `hit`, allow falling back to the previous test. */
+ int hit_prev = -1;
+
+ bool use_depth_test = false;
+ bool use_depth_cache = false;
+
for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) {
- hit = gizmo_find_intersected_3d_intern(
- visible_gizmos, visible_gizmos_len_trim, C, co, hotspot_radii[i]);
- if (hit != -1) {
+
+ if (use_depth_test && (use_depth_cache == false)) {
+ GPU_select_cache_begin();
+ use_depth_cache = true;
+ }
+
+ int hit_count;
+ hit = gizmo_find_intersected_3d_intern(visible_gizmos,
+ visible_gizmos_len_trim,
+ C,
+ co,
+ hotspot_radii[i],
+ use_depth_test,
+ has_3d_select_bias,
+ &hit_count);
+ /* Only continue searching when there are multiple options to narrow down. */
+ if (hit_count < 2) {
break;
}
+
+ /* Fast path for simple case, one item or nothing. */
+ if (use_depth_test == false) {
+ /* Restart, using depth buffer (slower). */
+ use_depth_test = true;
+ i = -1;
+ }
+ hit_prev = hit;
+ }
+ /* Narrowing the search area may yield no hits,
+ * in this case fall back to the previous search. */
+ if (hit == -1) {
+ hit = hit_prev;
+ }
+
+ if (use_depth_cache) {
+ GPU_select_cache_end();
}
if (hit != -1) {