diff options
author | Mai Lavelle <mai.lavelle@gmail.com> | 2017-11-29 00:58:57 +0300 |
---|---|---|
committer | Mai Lavelle <mai.lavelle@gmail.com> | 2017-11-29 00:58:57 +0300 |
commit | 137fd5ffcba7f049e50200114da8e231cc136189 (patch) | |
tree | adeca4ed58480845bf8ef93783ca81eccef32522 | |
parent | 1261f8eaa7d60554d8678ca2256f123951ed509d (diff) | |
parent | 0c7fbc435f4611d6f25a58b17f7f65318bef572d (diff) |
Merge branch 'master' into split-kernel-faster-building
242 files changed, 4191 insertions, 2695 deletions
diff --git a/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake b/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake index d490b7a2ff3..8565ddc73ed 100644 --- a/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake +++ b/build_files/build_environment/patches/cmake/modules/FindBlosc.cmake @@ -32,7 +32,6 @@ SET(_blosc_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/blosc ) diff --git a/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake b/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake index 3dd480356af..781ec0ce6c8 100644 --- a/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake +++ b/build_files/build_environment/patches/cmake/modules/FindCppUnit.cmake @@ -32,7 +32,6 @@ SET(_cppunit_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/cppunit ) diff --git a/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake b/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake index 2002419cc75..6575cd0c763 100644 --- a/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake +++ b/build_files/build_environment/patches/cmake/modules/FindLogC4Plus.cmake @@ -32,7 +32,6 @@ SET(_logc4plus_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/logc4plus ) diff --git a/build_files/build_environment/patches/cmake/modules/FindTBB.cmake b/build_files/build_environment/patches/cmake/modules/FindTBB.cmake index 8a821f8092e..c44e03b207d 100644 --- a/build_files/build_environment/patches/cmake/modules/FindTBB.cmake +++ b/build_files/build_environment/patches/cmake/modules/FindTBB.cmake @@ -32,7 +32,6 @@ SET(_tbb_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/tbb ) diff --git a/build_files/cmake/Modules/FindAlembic.cmake b/build_files/cmake/Modules/FindAlembic.cmake index 1f61b5ef462..9f975c08e1a 100644 --- a/build_files/cmake/Modules/FindAlembic.cmake +++ b/build_files/cmake/Modules/FindAlembic.cmake @@ -30,7 +30,6 @@ SET(_alembic_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/alembic ) diff --git a/build_files/cmake/Modules/FindAudaspace.cmake b/build_files/cmake/Modules/FindAudaspace.cmake index c332ef9a039..cd5116979e2 100644 --- a/build_files/cmake/Modules/FindAudaspace.cmake +++ b/build_files/cmake/Modules/FindAudaspace.cmake @@ -20,7 +20,6 @@ SET(_audaspace_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) # Use pkg-config to get hints about paths diff --git a/build_files/cmake/Modules/FindEigen3.cmake b/build_files/cmake/Modules/FindEigen3.cmake index 400e8eb047d..c1b25d4169c 100644 --- a/build_files/cmake/Modules/FindEigen3.cmake +++ b/build_files/cmake/Modules/FindEigen3.cmake @@ -28,7 +28,6 @@ SET(_eigen3_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) FIND_PATH(EIGEN3_INCLUDE_DIR diff --git a/build_files/cmake/Modules/FindFftw3.cmake b/build_files/cmake/Modules/FindFftw3.cmake index 197d4aab7b6..8917cc1c120 100644 --- a/build_files/cmake/Modules/FindFftw3.cmake +++ b/build_files/cmake/Modules/FindFftw3.cmake @@ -32,7 +32,6 @@ SET(_fftw3_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) FIND_PATH(FFTW3_INCLUDE_DIR diff --git a/build_files/cmake/Modules/FindGflags.cmake b/build_files/cmake/Modules/FindGflags.cmake index 0a138c02465..31d951318c8 100644 --- a/build_files/cmake/Modules/FindGflags.cmake +++ b/build_files/cmake/Modules/FindGflags.cmake @@ -445,7 +445,6 @@ if(NOT GFLAGS_FOUND) /opt/local/include /usr/include /sw/include # Fink - /opt/csw/include # Blastwave /opt/lib/gflags/include) list(APPEND GFLAGS_CHECK_PATH_SUFFIXES @@ -459,7 +458,6 @@ if(NOT GFLAGS_FOUND) /opt/local/lib /usr/lib /sw/lib # Fink - /opt/csw/lib # Blastwave /opt/lib/gflags/lib) list(APPEND GFLAGS_CHECK_LIBRARY_SUFFIXES gflags/lib # Windows (for C:/Program Files prefix). diff --git a/build_files/cmake/Modules/FindGlog.cmake b/build_files/cmake/Modules/FindGlog.cmake index 66c2aab2762..105d42875f6 100644 --- a/build_files/cmake/Modules/FindGlog.cmake +++ b/build_files/cmake/Modules/FindGlog.cmake @@ -129,7 +129,6 @@ list(APPEND GLOG_CHECK_INCLUDE_DIRS /opt/local/include /usr/include /sw/include # Fink - /opt/csw/include # Blastwave /opt/lib/glog/include) # Windows (for C:/Program Files prefix). list(APPEND GLOG_CHECK_PATH_SUFFIXES @@ -145,7 +144,6 @@ list(APPEND GLOG_CHECK_LIBRARY_DIRS /opt/local/lib /usr/lib /sw/lib # Fink - /opt/csw/lib # Blastwave /opt/lib/gflags/lib) # Windows (for C:/Program Files prefix). list(APPEND GLOG_CHECK_LIBRARY_SUFFIXES diff --git a/build_files/cmake/Modules/FindHDF5.cmake b/build_files/cmake/Modules/FindHDF5.cmake index 56ceda8fb5e..ed140614aa2 100644 --- a/build_files/cmake/Modules/FindHDF5.cmake +++ b/build_files/cmake/Modules/FindHDF5.cmake @@ -29,7 +29,6 @@ SET(_hdf5_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/hdf5 ) diff --git a/build_files/cmake/Modules/FindIcuLinux.cmake b/build_files/cmake/Modules/FindIcuLinux.cmake index e0e5873a4eb..5ccd327da16 100644 --- a/build_files/cmake/Modules/FindIcuLinux.cmake +++ b/build_files/cmake/Modules/FindIcuLinux.cmake @@ -35,7 +35,6 @@ SET(_icu_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) # We don't need includes, only libs to link against... diff --git a/build_files/cmake/Modules/FindJack.cmake b/build_files/cmake/Modules/FindJack.cmake index caafa3c34a1..ab4fdc99f25 100644 --- a/build_files/cmake/Modules/FindJack.cmake +++ b/build_files/cmake/Modules/FindJack.cmake @@ -32,7 +32,6 @@ SET(_jack_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) FIND_PATH(JACK_INCLUDE_DIR diff --git a/build_files/cmake/Modules/FindJeMalloc.cmake b/build_files/cmake/Modules/FindJeMalloc.cmake index 466456baf32..707739a3d98 100644 --- a/build_files/cmake/Modules/FindJeMalloc.cmake +++ b/build_files/cmake/Modules/FindJeMalloc.cmake @@ -32,7 +32,6 @@ SET(_jemalloc_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/jemalloc ) diff --git a/build_files/cmake/Modules/FindLZO.cmake b/build_files/cmake/Modules/FindLZO.cmake index a21aa0a03bb..7aa4adca777 100644 --- a/build_files/cmake/Modules/FindLZO.cmake +++ b/build_files/cmake/Modules/FindLZO.cmake @@ -32,7 +32,6 @@ SET(_lzo_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) FIND_PATH(LZO_INCLUDE_DIR lzo/lzo1x.h diff --git a/build_files/cmake/Modules/FindOpenCOLLADA.cmake b/build_files/cmake/Modules/FindOpenCOLLADA.cmake index 63bc520ea15..ed9948b8a6c 100644 --- a/build_files/cmake/Modules/FindOpenCOLLADA.cmake +++ b/build_files/cmake/Modules/FindOpenCOLLADA.cmake @@ -65,7 +65,6 @@ SET(_opencollada_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/opencollada ) diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake index bd1ecac0a39..bcc22f55bcc 100644 --- a/build_files/cmake/Modules/FindOpenColorIO.cmake +++ b/build_files/cmake/Modules/FindOpenColorIO.cmake @@ -38,7 +38,6 @@ SET(_opencolorio_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/ocio ) diff --git a/build_files/cmake/Modules/FindOpenEXR.cmake b/build_files/cmake/Modules/FindOpenEXR.cmake index 41e60a75294..ef8d76ea3a5 100644 --- a/build_files/cmake/Modules/FindOpenEXR.cmake +++ b/build_files/cmake/Modules/FindOpenEXR.cmake @@ -50,7 +50,6 @@ SET(_openexr_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/openexr ) diff --git a/build_files/cmake/Modules/FindOpenImageIO.cmake b/build_files/cmake/Modules/FindOpenImageIO.cmake index d59f9cfcdfc..52b7856c79c 100644 --- a/build_files/cmake/Modules/FindOpenImageIO.cmake +++ b/build_files/cmake/Modules/FindOpenImageIO.cmake @@ -34,7 +34,6 @@ SET(_openimageio_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/oiio ) @@ -76,6 +75,8 @@ IF(OPENIMAGEIO_FOUND) SET(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR}) IF(EXISTS ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO/pugixml.hpp) SET(OPENIMAGEIO_PUGIXML_FOUND TRUE) + ELSE() + SET(OPENIMAGEIO_PUGIXML_FOUND FALSE) ENDIF() ELSE() SET(OPENIMAGEIO_PUGIXML_FOUND FALSE) diff --git a/build_files/cmake/Modules/FindOpenJPEG.cmake b/build_files/cmake/Modules/FindOpenJPEG.cmake index d765103638b..4b021f13634 100644 --- a/build_files/cmake/Modules/FindOpenJPEG.cmake +++ b/build_files/cmake/Modules/FindOpenJPEG.cmake @@ -32,7 +32,6 @@ SET(_openjpeg_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) FIND_PATH(OPENJPEG_INCLUDE_DIR diff --git a/build_files/cmake/Modules/FindOpenShadingLanguage.cmake b/build_files/cmake/Modules/FindOpenShadingLanguage.cmake index 824d0f90597..9d9788b9900 100644 --- a/build_files/cmake/Modules/FindOpenShadingLanguage.cmake +++ b/build_files/cmake/Modules/FindOpenShadingLanguage.cmake @@ -38,7 +38,6 @@ SET(_osl_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/osl ) diff --git a/build_files/cmake/Modules/FindOpenSubdiv.cmake b/build_files/cmake/Modules/FindOpenSubdiv.cmake index 72025506c97..3fca453a7a0 100644 --- a/build_files/cmake/Modules/FindOpenSubdiv.cmake +++ b/build_files/cmake/Modules/FindOpenSubdiv.cmake @@ -37,7 +37,6 @@ SET(_opensubdiv_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/opensubdiv /opt/lib/osd # install_deps.sh ) diff --git a/build_files/cmake/Modules/FindOpenVDB.cmake b/build_files/cmake/Modules/FindOpenVDB.cmake index a13feab8e0e..510a5fab261 100644 --- a/build_files/cmake/Modules/FindOpenVDB.cmake +++ b/build_files/cmake/Modules/FindOpenVDB.cmake @@ -32,7 +32,6 @@ SET(_openvdb_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/openvdb /opt/lib/openvdb ) diff --git a/build_files/cmake/Modules/FindPCRE.cmake b/build_files/cmake/Modules/FindPCRE.cmake index ff4b7261555..1649a6cbb36 100644 --- a/build_files/cmake/Modules/FindPCRE.cmake +++ b/build_files/cmake/Modules/FindPCRE.cmake @@ -32,7 +32,6 @@ SET(_pcre_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) FIND_PATH(PCRE_INCLUDE_DIR pcre.h diff --git a/build_files/cmake/Modules/FindPugiXML.cmake b/build_files/cmake/Modules/FindPugiXML.cmake index f7104c16921..2a0dcf08c7e 100644 --- a/build_files/cmake/Modules/FindPugiXML.cmake +++ b/build_files/cmake/Modules/FindPugiXML.cmake @@ -32,7 +32,6 @@ SET(_pugixml_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/oiio ) diff --git a/build_files/cmake/Modules/FindSDL2.cmake b/build_files/cmake/Modules/FindSDL2.cmake index 2a835cf94fa..7c40a6ef6f3 100644 --- a/build_files/cmake/Modules/FindSDL2.cmake +++ b/build_files/cmake/Modules/FindSDL2.cmake @@ -34,7 +34,6 @@ SET(_sdl2_SEARCH_DIRS /usr /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) FIND_PATH(SDL2_INCLUDE_DIR diff --git a/build_files/cmake/Modules/FindSndFile.cmake b/build_files/cmake/Modules/FindSndFile.cmake index 1b685eacfbd..4094b05adab 100644 --- a/build_files/cmake/Modules/FindSndFile.cmake +++ b/build_files/cmake/Modules/FindSndFile.cmake @@ -32,7 +32,6 @@ SET(_sndfile_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) FIND_PATH(SNDFILE_INCLUDE_DIR sndfile.h diff --git a/build_files/cmake/Modules/FindSpacenav.cmake b/build_files/cmake/Modules/FindSpacenav.cmake index 206f3611ed6..84599643c2d 100644 --- a/build_files/cmake/Modules/FindSpacenav.cmake +++ b/build_files/cmake/Modules/FindSpacenav.cmake @@ -32,7 +32,6 @@ SET(_spacenav_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) FIND_PATH(SPACENAV_INCLUDE_DIR diff --git a/build_files/cmake/Modules/FindTBB.cmake b/build_files/cmake/Modules/FindTBB.cmake index 8a821f8092e..c44e03b207d 100644 --- a/build_files/cmake/Modules/FindTBB.cmake +++ b/build_files/cmake/Modules/FindTBB.cmake @@ -32,7 +32,6 @@ SET(_tbb_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave /opt/lib/tbb ) diff --git a/build_files/cmake/Modules/FindXML2.cmake b/build_files/cmake/Modules/FindXML2.cmake index 40cc332fb88..d2df90fa2ec 100644 --- a/build_files/cmake/Modules/FindXML2.cmake +++ b/build_files/cmake/Modules/FindXML2.cmake @@ -32,7 +32,6 @@ SET(_xml2_SEARCH_DIRS /usr/local /sw # Fink /opt/local # DarwinPorts - /opt/csw # Blastwave ) FIND_PATH(XML2_INCLUDE_DIR libxml2/libxml/xpath.h diff --git a/intern/atomic/atomic_ops.h b/intern/atomic/atomic_ops.h index 38670be56fd..e849bcf6cef 100644 --- a/intern/atomic/atomic_ops.h +++ b/intern/atomic/atomic_ops.h @@ -82,6 +82,12 @@ ATOMIC_INLINE uint64_t atomic_sub_and_fetch_uint64(uint64_t *p, uint64_t x); ATOMIC_INLINE uint64_t atomic_fetch_and_add_uint64(uint64_t *p, uint64_t x); ATOMIC_INLINE uint64_t atomic_fetch_and_sub_uint64(uint64_t *p, uint64_t x); ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new); + +ATOMIC_INLINE int64_t atomic_add_and_fetch_int64(int64_t *p, int64_t x); +ATOMIC_INLINE int64_t atomic_sub_and_fetch_int64(int64_t *p, int64_t x); +ATOMIC_INLINE int64_t atomic_fetch_and_add_int64(int64_t *p, int64_t x); +ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x); +ATOMIC_INLINE int64_t atomic_cas_int64(int64_t *v, int64_t old, int64_t _new); #endif ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x); @@ -92,9 +98,23 @@ ATOMIC_INLINE uint32_t atomic_fetch_and_add_uint32(uint32_t *p, uint32_t x); ATOMIC_INLINE uint32_t atomic_fetch_and_or_uint32(uint32_t *p, uint32_t x); ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x); +ATOMIC_INLINE int32_t atomic_add_and_fetch_int32(int32_t *p, int32_t x); +ATOMIC_INLINE int32_t atomic_sub_and_fetch_int32(int32_t *p, int32_t x); +ATOMIC_INLINE int32_t atomic_cas_int32(int32_t *v, int32_t old, int32_t _new); + +ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x); +ATOMIC_INLINE int32_t atomic_fetch_and_or_int32(int32_t *p, int32_t x); +ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x); + ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b); ATOMIC_INLINE uint8_t atomic_fetch_and_and_uint8(uint8_t *p, uint8_t b); +ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b); +ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b); + +ATOMIC_INLINE char atomic_fetch_and_or_char(char *p, char b); +ATOMIC_INLINE char atomic_fetch_and_and_char(char *p, char b); + ATOMIC_INLINE size_t atomic_add_and_fetch_z(size_t *p, size_t x); ATOMIC_INLINE size_t atomic_sub_and_fetch_z(size_t *p, size_t x); ATOMIC_INLINE size_t atomic_fetch_and_add_z(size_t *p, size_t x); @@ -110,6 +130,9 @@ ATOMIC_INLINE unsigned int atomic_cas_u(unsigned int *v, unsigned int old, unsig ATOMIC_INLINE void *atomic_cas_ptr(void **v, void *old, void *_new); + +ATOMIC_INLINE float atomic_cas_float(float *v, float old, float _new); + /* WARNING! Float 'atomics' are really faked ones, those are actually closer to some kind of spinlock-sync'ed operation, * which means they are only efficient if collisions are highly unlikely (i.e. if probability of two threads * working on the same pointer at the same time is very low). */ diff --git a/intern/atomic/intern/atomic_ops_ext.h b/intern/atomic/intern/atomic_ops_ext.h index 34158a0b45e..1b1fea9642d 100644 --- a/intern/atomic/intern/atomic_ops_ext.h +++ b/intern/atomic/intern/atomic_ops_ext.h @@ -56,10 +56,10 @@ /******************************************************************************/ /* size_t operations. */ +ATOMIC_STATIC_ASSERT(sizeof(size_t) == LG_SIZEOF_PTR, "sizeof(size_t) != LG_SIZEOF_PTR"); + ATOMIC_INLINE size_t atomic_add_and_fetch_z(size_t *p, size_t x) { - assert(sizeof(size_t) == LG_SIZEOF_PTR); - #if (LG_SIZEOF_PTR == 8) return (size_t)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)x); #elif (LG_SIZEOF_PTR == 4) @@ -69,8 +69,6 @@ ATOMIC_INLINE size_t atomic_add_and_fetch_z(size_t *p, size_t x) ATOMIC_INLINE size_t atomic_sub_and_fetch_z(size_t *p, size_t x) { - assert(sizeof(size_t) == LG_SIZEOF_PTR); - #if (LG_SIZEOF_PTR == 8) return (size_t)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)-((int64_t)x)); #elif (LG_SIZEOF_PTR == 4) @@ -80,8 +78,6 @@ ATOMIC_INLINE size_t atomic_sub_and_fetch_z(size_t *p, size_t x) ATOMIC_INLINE size_t atomic_fetch_and_add_z(size_t *p, size_t x) { - assert(sizeof(size_t) == LG_SIZEOF_PTR); - #if (LG_SIZEOF_PTR == 8) return (size_t)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)x); #elif (LG_SIZEOF_PTR == 4) @@ -91,8 +87,6 @@ ATOMIC_INLINE size_t atomic_fetch_and_add_z(size_t *p, size_t x) ATOMIC_INLINE size_t atomic_fetch_and_sub_z(size_t *p, size_t x) { - assert(sizeof(size_t) == LG_SIZEOF_PTR); - #if (LG_SIZEOF_PTR == 8) return (size_t)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)-((int64_t)x)); #elif (LG_SIZEOF_PTR == 4) @@ -102,8 +96,6 @@ ATOMIC_INLINE size_t atomic_fetch_and_sub_z(size_t *p, size_t x) ATOMIC_INLINE size_t atomic_cas_z(size_t *v, size_t old, size_t _new) { - assert(sizeof(size_t) == LG_SIZEOF_PTR); - #if (LG_SIZEOF_PTR == 8) return (size_t)atomic_cas_uint64((uint64_t *)v, (uint64_t)old, (uint64_t)_new); #elif (LG_SIZEOF_PTR == 4) @@ -124,10 +116,10 @@ ATOMIC_INLINE size_t atomic_fetch_and_update_max_z(size_t *p, size_t x) /******************************************************************************/ /* unsigned operations. */ +ATOMIC_STATIC_ASSERT(sizeof(unsigned int) == LG_SIZEOF_INT, "sizeof(unsigned int) != LG_SIZEOF_INT"); + ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int x) { - assert(sizeof(unsigned int) == LG_SIZEOF_INT); - #if (LG_SIZEOF_INT == 8) return (unsigned int)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)x); #elif (LG_SIZEOF_INT == 4) @@ -137,8 +129,6 @@ ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int ATOMIC_INLINE unsigned int atomic_sub_and_fetch_u(unsigned int *p, unsigned int x) { - assert(sizeof(unsigned int) == LG_SIZEOF_INT); - #if (LG_SIZEOF_INT == 8) return (unsigned int)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)-((int64_t)x)); #elif (LG_SIZEOF_INT == 4) @@ -148,8 +138,6 @@ ATOMIC_INLINE unsigned int atomic_sub_and_fetch_u(unsigned int *p, unsigned int ATOMIC_INLINE unsigned int atomic_fetch_and_add_u(unsigned int *p, unsigned int x) { - assert(sizeof(unsigned int) == LG_SIZEOF_INT); - #if (LG_SIZEOF_INT == 8) return (unsigned int)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)x); #elif (LG_SIZEOF_INT == 4) @@ -159,8 +147,6 @@ ATOMIC_INLINE unsigned int atomic_fetch_and_add_u(unsigned int *p, unsigned int ATOMIC_INLINE unsigned int atomic_fetch_and_sub_u(unsigned int *p, unsigned int x) { - assert(sizeof(unsigned int) == LG_SIZEOF_INT); - #if (LG_SIZEOF_INT == 8) return (unsigned int)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)-((int64_t)x)); #elif (LG_SIZEOF_INT == 4) @@ -170,8 +156,6 @@ ATOMIC_INLINE unsigned int atomic_fetch_and_sub_u(unsigned int *p, unsigned int ATOMIC_INLINE unsigned int atomic_cas_u(unsigned int *v, unsigned int old, unsigned int _new) { - assert(sizeof(unsigned int) == LG_SIZEOF_INT); - #if (LG_SIZEOF_INT == 8) return (unsigned int)atomic_cas_uint64((uint64_t *)v, (uint64_t)old, (uint64_t)_new); #elif (LG_SIZEOF_INT == 4) @@ -180,6 +164,18 @@ ATOMIC_INLINE unsigned int atomic_cas_u(unsigned int *v, unsigned int old, unsig } /******************************************************************************/ +/* Char operations. */ +ATOMIC_INLINE char atomic_fetch_and_or_char(char *p, char b) +{ + return (char)atomic_fetch_and_or_uint8((uint8_t *)p, (uint8_t)b); +} + +ATOMIC_INLINE char atomic_fetch_and_and_char(char *p, char b) +{ + return (char)atomic_fetch_and_and_uint8((uint8_t *)p, (uint8_t)b); +} + +/******************************************************************************/ /* Pointer operations. */ ATOMIC_INLINE void *atomic_cas_ptr(void **v, void *old, void *_new) @@ -193,11 +189,16 @@ ATOMIC_INLINE void *atomic_cas_ptr(void **v, void *old, void *_new) /******************************************************************************/ /* float operations. */ +ATOMIC_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t), "sizeof(float) != sizeof(uint32_t)"); -ATOMIC_INLINE float atomic_add_and_fetch_fl(float *p, const float x) +ATOMIC_INLINE float atomic_cas_float(float *v, float old, float _new) { - assert(sizeof(float) == sizeof(uint32_t)); + uint32_t ret = atomic_cas_uint32((uint32_t *)v, *(uint32_t *)&old, *(uint32_t *)&_new); + return *(float *)&ret; +} +ATOMIC_INLINE float atomic_add_and_fetch_fl(float *p, const float x) +{ float oldval, newval; uint32_t prevval; diff --git a/intern/atomic/intern/atomic_ops_msvc.h b/intern/atomic/intern/atomic_ops_msvc.h index 034ac1e3e53..c24a9095735 100644 --- a/intern/atomic/intern/atomic_ops_msvc.h +++ b/intern/atomic/intern/atomic_ops_msvc.h @@ -43,6 +43,7 @@ /******************************************************************************/ /* 64-bit operations. */ #if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8) +/* Unsigned */ ATOMIC_INLINE uint64_t atomic_add_and_fetch_uint64(uint64_t *p, uint64_t x) { return InterlockedExchangeAdd64((int64_t *)p, (int64_t)x) + x; @@ -67,10 +68,37 @@ ATOMIC_INLINE uint64_t atomic_fetch_and_sub_uint64(uint64_t *p, uint64_t x) { return InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x)); } + +/* Signed */ +ATOMIC_INLINE int64_t atomic_add_and_fetch_int64(int64_t *p, int64_t x) +{ + return InterlockedExchangeAdd64(p, x) + x; +} + +ATOMIC_INLINE int64_t atomic_sub_and_fetch_int64(int64_t *p, int64_t x) +{ + return InterlockedExchangeAdd64(p, -x) - x; +} + +ATOMIC_INLINE int64_t atomic_cas_int64(int64_t *v, int64_t old, int64_t _new) +{ + return InterlockedCompareExchange64(v, _new, old); +} + +ATOMIC_INLINE int64_t atomic_fetch_and_add_int64(int64_t *p, int64_t x) +{ + return InterlockedExchangeAdd64(p, x); +} + +ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x) +{ + return InterlockedExchangeAdd64(p, -x); +} #endif /******************************************************************************/ /* 32-bit operations. */ +/* Unsigned */ ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x) { return InterlockedExchangeAdd(p, x) + x; @@ -101,9 +129,41 @@ ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x) return InterlockedAnd((long *)p, x); } +/* Signed */ +ATOMIC_INLINE int32_t atomic_add_and_fetch_int32(int32_t *p, int32_t x) +{ + return InterlockedExchangeAdd((long *)p, x) + x; +} + +ATOMIC_INLINE int32_t atomic_sub_and_fetch_int32(int32_t *p, int32_t x) +{ + return InterlockedExchangeAdd((long *)p, -x) - x; +} + +ATOMIC_INLINE int32_t atomic_cas_int32(int32_t *v, int32_t old, int32_t _new) +{ + return InterlockedCompareExchange((long *)v, _new, old); +} + +ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x) +{ + return InterlockedExchangeAdd((long *)p, x); +} + +ATOMIC_INLINE int32_t atomic_fetch_and_or_int32(int32_t *p, int32_t x) +{ + return InterlockedOr((long *)p, x); +} + +ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x) +{ + return InterlockedAnd((long *)p, x); +} + /******************************************************************************/ /* 8-bit operations. */ +/* Unsigned */ #pragma intrinsic(_InterlockedAnd8) ATOMIC_INLINE uint8_t atomic_fetch_and_and_uint8(uint8_t *p, uint8_t b) { @@ -124,4 +184,25 @@ ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b) #endif } +/* Signed */ +#pragma intrinsic(_InterlockedAnd8) +ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b) +{ +#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8) + return InterlockedAnd8((char *)p, (char)b); +#else + return _InterlockedAnd8((char *)p, (char)b); +#endif +} + +#pragma intrinsic(_InterlockedOr8) +ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b) +{ +#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8) + return InterlockedOr8((char *)p, (char)b); +#else + return _InterlockedOr8((char *)p, (char)b); +#endif +} + #endif /* __ATOMIC_OPS_MSVC_H__ */ diff --git a/intern/atomic/intern/atomic_ops_unix.h b/intern/atomic/intern/atomic_ops_unix.h index 0a3322ad2b1..783a30f743b 100644 --- a/intern/atomic/intern/atomic_ops_unix.h +++ b/intern/atomic/intern/atomic_ops_unix.h @@ -58,6 +58,7 @@ /* 64-bit operations. */ #if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8) # if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8)) +/* Unsigned */ ATOMIC_INLINE uint64_t atomic_add_and_fetch_uint64(uint64_t *p, uint64_t x) { return __sync_add_and_fetch(p, x); @@ -82,7 +83,35 @@ ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _ne { return __sync_val_compare_and_swap(v, old, _new); } + +/* Signed */ +ATOMIC_INLINE int64_t atomic_add_and_fetch_int64(int64_t *p, int64_t x) +{ + return __sync_add_and_fetch(p, x); +} + +ATOMIC_INLINE int64_t atomic_sub_and_fetch_int64(int64_t *p, int64_t x) +{ + return __sync_sub_and_fetch(p, x); +} + +ATOMIC_INLINE int64_t atomic_fetch_and_add_int64(int64_t *p, int64_t x) +{ + return __sync_fetch_and_add(p, x); +} + +ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x) +{ + return __sync_fetch_and_sub(p, x); +} + +ATOMIC_INLINE int64_t atomic_cas_int64(int64_t *v, int64_t old, int64_t _new) +{ + return __sync_val_compare_and_swap(v, old, _new); +} + # elif (defined(__amd64__) || defined(__x86_64__)) +/* Unsigned */ ATOMIC_INLINE uint64_t atomic_fetch_and_add_uint64(uint64_t *p, uint64_t x) { asm volatile ( @@ -124,6 +153,49 @@ ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _ne : "memory"); return ret; } + +/* Signed */ +ATOMIC_INLINE int64_t atomic_fetch_and_add_int64(int64_t *p, int64_t x) +{ + asm volatile ( + "lock; xaddq %0, %1;" + : "+r" (x), "=m" (*p) /* Outputs. */ + : "m" (*p) /* Inputs. */ + ); + return x; +} + +ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x) +{ + x = -x; + asm volatile ( + "lock; xaddq %0, %1;" + : "+r" (x), "=m" (*p) /* Outputs. */ + : "m" (*p) /* Inputs. */ + ); + return x; +} + +ATOMIC_INLINE int64_t atomic_add_and_fetch_int64(int64_t *p, int64_t x) +{ + return atomic_fetch_and_add_int64(p, x) + x; +} + +ATOMIC_INLINE int64_t atomic_sub_and_fetch_int64(int64_t *p, int64_t x) +{ + return atomic_fetch_and_sub_int64(p, x) - x; +} + +ATOMIC_INLINE int64_t atomic_cas_int64(int64_t *v, int64_t old, int64_t _new) +{ + int64_t ret; + asm volatile ( + "lock; cmpxchgq %2,%1" + : "=a" (ret), "+m" (*v) + : "r" (_new), "0" (old) + : "memory"); + return ret; +} # else # error "Missing implementation for 64-bit atomic operations" # endif @@ -132,6 +204,7 @@ ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _ne /******************************************************************************/ /* 32-bit operations. */ #if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4)) +/* Unsigned */ ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x) { return __sync_add_and_fetch(p, x); @@ -146,7 +219,25 @@ ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _ne { return __sync_val_compare_and_swap(v, old, _new); } + +/* Signed */ +ATOMIC_INLINE int32_t atomic_add_and_fetch_int32(int32_t *p, int32_t x) +{ + return __sync_add_and_fetch(p, x); +} + +ATOMIC_INLINE int32_t atomic_sub_and_fetch_int32(int32_t *p, int32_t x) +{ + return __sync_sub_and_fetch(p, x); +} + +ATOMIC_INLINE int32_t atomic_cas_int32(int32_t *v, int32_t old, int32_t _new) +{ + return __sync_val_compare_and_swap(v, old, _new); +} + #elif (defined(__i386__) || defined(__amd64__) || defined(__x86_64__)) +/* Unsigned */ ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x) { uint32_t ret = x; @@ -155,18 +246,18 @@ ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x) : "+r" (ret), "=m" (*p) /* Outputs. */ : "m" (*p) /* Inputs. */ ); - return ret+x; + return ret + x; } ATOMIC_INLINE uint32_t atomic_sub_and_fetch_uint32(uint32_t *p, uint32_t x) { - ret = (uint32_t)(-(int32_t)x); + uint32_t ret = (uint32_t)(-(int32_t)x); asm volatile ( "lock; xaddl %0, %1;" : "+r" (ret), "=m" (*p) /* Outputs. */ : "m" (*p) /* Inputs. */ ); - return ret-x; + return ret - x; } ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new) @@ -179,11 +270,47 @@ ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _ne : "memory"); return ret; } + +/* Signed */ +ATOMIC_INLINE int32_t atomic_add_and_fetch_int32(int32_t *p, int32_t x) +{ + int32_t ret = x; + asm volatile ( + "lock; xaddl %0, %1;" + : "+r" (ret), "=m" (*p) /* Outputs. */ + : "m" (*p) /* Inputs. */ + ); + return ret + x; +} + +ATOMIC_INLINE int32_t atomic_sub_and_fetch_int32(int32_t *p, int32_t x) +{ + int32_t ret = -x; + asm volatile ( + "lock; xaddl %0, %1;" + : "+r" (ret), "=m" (*p) /* Outputs. */ + : "m" (*p) /* Inputs. */ + ); + return ret - x; +} + +ATOMIC_INLINE int32_t atomic_cas_int32(int32_t *v, int32_t old, int32_t _new) +{ + int32_t ret; + asm volatile ( + "lock; cmpxchgl %2,%1" + : "=a" (ret), "+m" (*v) + : "r" (_new), "0" (old) + : "memory"); + return ret; +} + #else # error "Missing implementation for 32-bit atomic operations" #endif #if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4)) +/* Unsigned */ ATOMIC_INLINE uint32_t atomic_fetch_and_add_uint32(uint32_t *p, uint32_t x) { return __sync_fetch_and_add(p, x); @@ -199,6 +326,22 @@ ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x) return __sync_fetch_and_and(p, x); } +/* Signed */ +ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x) +{ + return __sync_fetch_and_add(p, x); +} + +ATOMIC_INLINE int32_t atomic_fetch_and_or_int32(int32_t *p, int32_t x) +{ + return __sync_fetch_and_or(p, x); +} + +ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x) +{ + return __sync_fetch_and_and(p, x); +} + #else # error "Missing implementation for 32-bit atomic operations" #endif @@ -206,6 +349,7 @@ ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x) /******************************************************************************/ /* 8-bit operations. */ #if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_1)) +/* Unsigned */ ATOMIC_INLINE uint8_t atomic_fetch_and_and_uint8(uint8_t *p, uint8_t b) { return __sync_fetch_and_and(p, b); @@ -214,6 +358,17 @@ ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b) { return __sync_fetch_and_or(p, b); } + +/* Signed */ +ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b) +{ + return __sync_fetch_and_and(p, b); +} +ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b) +{ + return __sync_fetch_and_or(p, b); +} + #else # error "Missing implementation for 8-bit atomic operations" #endif diff --git a/intern/atomic/intern/atomic_ops_utils.h b/intern/atomic/intern/atomic_ops_utils.h index c190b655e0a..621b3e95906 100644 --- a/intern/atomic/intern/atomic_ops_utils.h +++ b/intern/atomic/intern/atomic_ops_utils.h @@ -104,4 +104,31 @@ # error "Cannot find int size" #endif +/* Copied from BLI_utils... */ +/* C++ can't use _Static_assert, expects static_assert() but c++0x only, + * Coverity also errors out. */ +#if (!defined(__cplusplus)) && \ + (!defined(__COVERITY__)) && \ + (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */ +# define ATOMIC_STATIC_ASSERT(a, msg) __extension__ _Static_assert(a, msg); +#else +/* Code adapted from http://www.pixelbeat.org/programming/gcc/static_assert.html */ +/* Note we need the two concats below because arguments to ## are not expanded, so we need to + * expand __LINE__ with one indirection before doing the actual concatenation. */ +# define ATOMIC_ASSERT_CONCAT_(a, b) a##b +# define ATOMIC_ASSERT_CONCAT(a, b) ATOMIC_ASSERT_CONCAT_(a, b) + /* These can't be used after statements in c89. */ +# if defined(__COUNTER__) /* MSVC */ +# define ATOMIC_STATIC_ASSERT(a, msg) \ + ; enum { ATOMIC_ASSERT_CONCAT(static_assert_, __COUNTER__) = 1 / (int)(!!(a)) }; +# else /* older gcc, clang... */ + /* This can't be used twice on the same line so ensure if using in headers + * that the headers are not included twice (by wrapping in #ifndef...#endif) + * Note it doesn't cause an issue when used on same line of separate modules + * compiled with gcc -combine -fwhole-program. */ +# define ATOMIC_STATIC_ASSERT(a, msg) \ + ; enum { ATOMIC_ASSERT_CONCAT(assert_line_, __LINE__) = 1 / (int)(!!(a)) }; +# endif +#endif + #endif /* __ATOMIC_OPS_UTILS_H__ */ diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 5844c2480d6..dbf1bcece16 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -209,6 +209,10 @@ if(WITH_CYCLES_DEBUG) add_definitions(-DWITH_CYCLES_DEBUG) endif() +if(NOT OPENIMAGEIO_PUGIXML_FOUND) + add_definitions(-DWITH_SYSTEM_PUGIXML) +endif() + include_directories( SYSTEM ${BOOST_INCLUDE_DIR} diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 3a1c7205c34..f2db9271a89 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -358,7 +358,7 @@ static void xml_read_shader(XMLReadState& state, xml_node node) /* Background */ -static void xml_read_background(XMLReadState& state, pugi::xml_node node) +static void xml_read_background(XMLReadState& state, xml_node node) { /* Background Settings */ xml_read_node(state, state.scene->background, node); diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 3018fd5b316..1f97eff9bd0 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -234,10 +234,13 @@ def register_passes(engine, scene, srl): if srl.use_pass_environment: engine.register_pass(scene, srl, "Env", 3, "RGB", 'COLOR') crl = srl.cycles - if crl.pass_debug_bvh_traversed_nodes: engine.register_pass(scene, srl, "Debug BVH Traversed Nodes", 1, "X", 'VALUE') - if crl.pass_debug_bvh_traversed_instances: engine.register_pass(scene, srl, "Debug BVH Traversed Instances", 1, "X", 'VALUE') - if crl.pass_debug_bvh_intersections: engine.register_pass(scene, srl, "Debug BVH Intersections", 1, "X", 'VALUE') - if crl.pass_debug_ray_bounces: engine.register_pass(scene, srl, "Debug Ray Bounces", 1, "X", 'VALUE') + if crl.pass_debug_render_time: engine.register_pass(scene, srl, "Debug Render Time", 1, "X", 'VALUE') + if crl.pass_debug_bvh_traversed_nodes: engine.register_pass(scene, srl, "Debug BVH Traversed Nodes", 1, "X", 'VALUE') + if crl.pass_debug_bvh_traversed_instances: engine.register_pass(scene, srl, "Debug BVH Traversed Instances", 1, "X", 'VALUE') + if crl.pass_debug_bvh_intersections: engine.register_pass(scene, srl, "Debug BVH Intersections", 1, "X", 'VALUE') + if crl.pass_debug_ray_bounces: engine.register_pass(scene, srl, "Debug Ray Bounces", 1, "X", 'VALUE') + if crl.use_pass_volume_direct: engine.register_pass(scene, srl, "VolumeDir", 3, "RGB", 'COLOR') + if crl.use_pass_volume_indirect: engine.register_pass(scene, srl, "VolumeInd", 3, "RGB", 'COLOR') cscene = scene.cycles if crl.use_denoising and crl.denoising_store_passes and not cscene.use_progressive_refine: diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 2e149527066..e5084138a9c 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1189,6 +1189,24 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup): default=False, update=update_render_passes, ) + cls.pass_debug_render_time = BoolProperty( + name="Debug Render Time", + description="Render time in milliseconds per sample and pixel", + default=False, + update=update_render_passes, + ) + cls.use_pass_volume_direct = BoolProperty( + name="Volume Direct", + description="Deliver direct volumetric scattering pass", + default=False, + update=update_render_passes, + ) + cls.use_pass_volume_indirect = BoolProperty( + name="Volume Indirect", + description="Deliver indirect volumetric scattering pass", + default=False, + update=update_render_passes, + ) cls.use_denoising = BoolProperty( name="Use Denoising", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 67f1029acb9..03ca1ab6c7f 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -526,6 +526,10 @@ class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel): row.prop(rl, "use_pass_subsurface_direct", text="Direct", toggle=True) row.prop(rl, "use_pass_subsurface_indirect", text="Indirect", toggle=True) row.prop(rl, "use_pass_subsurface_color", text="Color", toggle=True) + col.label(text="Volume:") + row = col.row(align=True) + row.prop(crl, "use_pass_volume_direct", text="Direct", toggle=True) + row.prop(crl, "use_pass_volume_indirect", text="Indirect", toggle=True) col.separator() col.prop(rl, "use_pass_emit", text="Emission") @@ -537,8 +541,9 @@ class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel): sub.active = crl.use_denoising sub.prop(crl, "denoising_store_passes", text="Denoising") + col = layout.column() + col.prop(crl, "pass_debug_render_time") if _cycles.with_cycles_debug: - col = layout.column() col.prop(crl, "pass_debug_bvh_traversed_nodes") col.prop(crl, "pass_debug_bvh_traversed_instances") col.prop(crl, "pass_debug_bvh_intersections") diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index eb573b75e9e..f02d5496112 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -112,6 +112,7 @@ static uint object_ray_visibility(BL::Object& b_ob) void BlenderSync::sync_light(BL::Object& b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object& b_ob, + BL::DupliObject& b_dupli_ob, Transform& tfm, bool *use_portal) { @@ -193,6 +194,13 @@ void BlenderSync::sync_light(BL::Object& b_parent, light->max_bounces = get_int(clamp, "max_bounces"); + if(b_dupli_ob) { + light->random_id = b_dupli_ob.random_id(); + } + else { + light->random_id = hash_int_2d(hash_string(b_ob.name().c_str()), 0); + } + if(light->type == LIGHT_AREA) light->is_portal = get_boolean(clamp, "is_portal"); else @@ -271,7 +279,7 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, if(object_is_light(b_ob)) { /* don't use lamps for excluded layers used as mask layer */ if(!motion && !((layer_flag & render_layer.holdout_layer) && (layer_flag & render_layer.exclude_layer))) - sync_light(b_parent, persistent_id, b_ob, tfm, use_portal); + sync_light(b_parent, persistent_id, b_ob, b_dupli_ob, tfm, use_portal); return NULL; } diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 142fd5ef85b..e24ed31b926 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -496,11 +496,13 @@ PassType BlenderSync::get_pass_type(BL::RenderPass& b_pass) MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT); MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT); MAP_PASS("SubsurfaceDir", PASS_SUBSURFACE_DIRECT); + MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT); MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT); MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT); MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT); MAP_PASS("SubsurfaceInd", PASS_SUBSURFACE_INDIRECT); + MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT); MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR); MAP_PASS("GlossCol", PASS_GLOSSY_COLOR); @@ -518,6 +520,7 @@ PassType BlenderSync::get_pass_type(BL::RenderPass& b_pass) MAP_PASS("Debug BVH Intersections", PASS_BVH_INTERSECTIONS); MAP_PASS("Debug Ray Bounces", PASS_RAY_BOUNCES); #endif + MAP_PASS("Debug Render Time", PASS_RENDER_TIME); #undef MAP_PASS return PASS_NONE; @@ -604,6 +607,18 @@ array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, Pass::add(PASS_RAY_BOUNCES, passes); } #endif + if(get_boolean(crp, "pass_debug_render_time")) { + b_engine.add_pass("Debug Render Time", 1, "X", b_srlay.name().c_str()); + Pass::add(PASS_RENDER_TIME, passes); + } + if(get_boolean(crp, "use_pass_volume_direct")) { + b_engine.add_pass("VolumeDir", 3, "RGB", b_srlay.name().c_str()); + Pass::add(PASS_VOLUME_DIRECT, passes); + } + if(get_boolean(crp, "use_pass_volume_indirect")) { + b_engine.add_pass("VolumeInd", 3, "RGB", b_srlay.name().c_str()); + Pass::add(PASS_VOLUME_INDIRECT, passes); + } return passes; } diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 11e279b81c4..e7b71ae9310 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -131,6 +131,7 @@ private: void sync_light(BL::Object& b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object& b_ob, + BL::DupliObject& b_dupli_ob, Transform& tfm, bool *use_portal); void sync_background_light(bool use_portal); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 7557f584ebe..12094d58101 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -688,6 +688,8 @@ public: void path_trace(DeviceTask &task, RenderTile &tile, KernelGlobals *kg) { + scoped_timer timer(&tile.buffers->render_time); + float *render_buffer = (float*)tile.buffer; int start_sample = tile.start_sample; int end_sample = tile.start_sample + tile.num_samples; diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index a38340cb286..d8d787ba706 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -908,7 +908,7 @@ public: cmem->texobject = 0; cmem->array = array_3d; } - else if(mem.data_height > 1) { + else if(mem.data_height > 0) { /* 2D texture, using pitch aligned linear memory. */ int alignment = 0; cuda_assert(cuDeviceGetAttribute(&alignment, CU_DEVICE_ATTRIBUTE_TEXTURE_PITCH_ALIGNMENT, cuDevice)); @@ -962,7 +962,7 @@ public: resDesc.res.array.hArray = array_3d; resDesc.flags = 0; } - else if(mem.data_height > 1) { + else if(mem.data_height > 0) { resDesc.resType = CU_RESOURCE_TYPE_PITCH2D; resDesc.res.pitch2D.devPtr = mem.device_pointer; resDesc.res.pitch2D.format = format; @@ -1012,7 +1012,7 @@ public: if(array_3d) { cuda_assert(cuTexRefSetArray(texref, array_3d, CU_TRSA_OVERRIDE_FORMAT)); } - else if(mem.data_height > 1) { + else if(mem.data_height > 0) { CUDA_ARRAY_DESCRIPTOR array_desc; array_desc.Format = format; array_desc.Height = mem.data_height; @@ -1436,6 +1436,8 @@ public: void path_trace(DeviceTask& task, RenderTile& rtile, device_vector<WorkTile>& work_tiles) { + scoped_timer timer(&rtile.buffers->render_time); + if(have_error()) return; diff --git a/intern/cycles/device/opencl/opencl_mega.cpp b/intern/cycles/device/opencl/opencl_mega.cpp index 575ab73330e..ef39cfb5f7d 100644 --- a/intern/cycles/device/opencl/opencl_mega.cpp +++ b/intern/cycles/device/opencl/opencl_mega.cpp @@ -59,6 +59,8 @@ public: void path_trace(RenderTile& rtile, int sample) { + scoped_timer timer(&rtile.buffers->render_time); + /* Cast arguments to cl types. */ cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer); cl_mem d_buffer = CL_MEM_PTR(rtile.buffer); diff --git a/intern/cycles/device/opencl/opencl_split.cpp b/intern/cycles/device/opencl/opencl_split.cpp index 1073cfa6bf6..2d819080674 100644 --- a/intern/cycles/device/opencl/opencl_split.cpp +++ b/intern/cycles/device/opencl/opencl_split.cpp @@ -138,6 +138,8 @@ public: while(task->acquire_tile(this, tile)) { if(tile.task == RenderTile::PATH_TRACE) { assert(tile.task == RenderTile::PATH_TRACE); + scoped_timer timer(&tile.buffers->render_time); + split_kernel->path_trace(task, tile, kgbuffer, diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 0a3f9ff23fe..e4573024e85 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -36,6 +36,22 @@ CCL_NAMESPACE_BEGIN +/* Returns the square of the roughness of the closure if it has roughness, + * 0 for singular closures and 1 otherwise. */ +ccl_device_inline float bsdf_get_roughness_sqr(const ShaderClosure *sc) +{ + if(CLOSURE_IS_BSDF_SINGULAR(sc->type)) { + return 0.0f; + } + + if(CLOSURE_IS_BSDF_MICROFACET(sc->type)) { + MicrofacetBsdf *bsdf = (MicrofacetBsdf*) sc; + return bsdf->alpha_x*bsdf->alpha_y; + } + + return 1.0f; +} + ccl_device_forceinline int bsdf_sample(KernelGlobals *kg, ShaderData *sd, const ShaderClosure *sc, @@ -438,23 +454,5 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b) #endif } -/* Classifies a closure as diffuse-like or specular-like. - * This is needed for the denoising feature pass generation, - * which are written on the first bounce where more than 25% - * of the sampling weight belongs to diffuse-line closures. */ -ccl_device_inline bool bsdf_is_specular_like(ShaderClosure *sc) -{ - if(CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) { - return true; - } - - if(CLOSURE_IS_BSDF_MICROFACET(sc->type)) { - MicrofacetBsdf *bsdf = (MicrofacetBsdf*) sc; - return (bsdf->alpha_x*bsdf->alpha_y <= 0.075f*0.075f); - } - - return false; -} - CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index 6791c0b83cc..ec10e452148 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -119,7 +119,7 @@ ccl_device float bssrdf_cubic_eval(const float radius, const float sharpness, fl else { Rmy = powf(Rm, y); ry = powf(r, y); - ryinv = (r > 0.0f)? powf(r, 2.0f*y - 2.0f): 0.0f; + ryinv = (r > 0.0f)? powf(r, y - 1.0f): 0.0f; } const float Rmy5 = (Rmy*Rmy) * (Rmy*Rmy) * Rmy; diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index 1ffc143be34..a276096a745 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -244,6 +244,17 @@ ccl_device_inline float object_pass_id(KernelGlobals *kg, int object) return f.y; } +/* Per lamp random number for shader variation */ + +ccl_device_inline float lamp_random_number(KernelGlobals *kg, int lamp) +{ + if(lamp == LAMP_NONE) + return 0.0f; + + float4 f = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 4); + return f.y; +} + /* Per object random number for shader variation */ ccl_device_inline float object_random_number(KernelGlobals *kg, int object) diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 366f25422fd..7c1b2a015e1 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -187,7 +187,6 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass) L->color_glossy = make_float3(0.0f, 0.0f, 0.0f); L->color_transmission = make_float3(0.0f, 0.0f, 0.0f); L->color_subsurface = make_float3(0.0f, 0.0f, 0.0f); - L->color_scatter = make_float3(0.0f, 0.0f, 0.0f); L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f); L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index b31356905f2..29451b6b8b6 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -140,7 +140,7 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg, /* All closures contribute to the normal feature, but only diffuse-like ones to the albedo. */ normal += sc->N * sc->sample_weight; sum_weight += sc->sample_weight; - if(!bsdf_is_specular_like(sc)) { + if(bsdf_get_roughness_sqr(sc) > sqr(0.075f)) { albedo += sc->weight; sum_nonspecular_weight += sc->sample_weight; } @@ -170,19 +170,19 @@ ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg, PathRadiance *L) { int flag = kernel_data.film.pass_flag; - if(flag & PASS_BVH_TRAVERSED_NODES) { + if(flag & PASSMASK(BVH_TRAVERSED_NODES)) { kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_nodes, L->debug_data.num_bvh_traversed_nodes); } - if(flag & PASS_BVH_TRAVERSED_INSTANCES) { + if(flag & PASSMASK(BVH_TRAVERSED_INSTANCES)) { kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_instances, L->debug_data.num_bvh_traversed_instances); } - if(flag & PASS_BVH_INTERSECTIONS) { + if(flag & PASSMASK(BVH_INTERSECTIONS)) { kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_intersections, L->debug_data.num_bvh_intersections); } - if(flag & PASS_RAY_BOUNCES) { + if(flag & PASSMASK(RAY_BOUNCES)) { kernel_write_pass_float(buffer + kernel_data.film.pass_ray_bounces, L->debug_data.num_ray_bounces); } @@ -199,8 +199,9 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl return; int flag = kernel_data.film.pass_flag; + int light_flag = kernel_data.film.light_pass_flag; - if(!(flag & PASS_ALL)) + if(!((flag | light_flag) & PASS_ANY)) return; if(!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) { @@ -209,29 +210,29 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) { if(state->sample == 0) { - if(flag & PASS_DEPTH) { + if(flag & PASSMASK(DEPTH)) { float depth = camera_distance(kg, sd->P); kernel_write_pass_float(buffer + kernel_data.film.pass_depth, depth); } - if(flag & PASS_OBJECT_ID) { + if(flag & PASSMASK(OBJECT_ID)) { float id = object_pass_id(kg, sd->object); kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, id); } - if(flag & PASS_MATERIAL_ID) { + if(flag & PASSMASK(MATERIAL_ID)) { float id = shader_pass_id(kg, sd); kernel_write_pass_float(buffer + kernel_data.film.pass_material_id, id); } } - if(flag & PASS_NORMAL) { + if(flag & PASSMASK(NORMAL)) { float3 normal = shader_bsdf_average_normal(kg, sd); kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, normal); } - if(flag & PASS_UV) { + if(flag & PASSMASK(UV)) { float3 uv = primitive_uv(kg, sd); kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, uv); } - if(flag & PASS_MOTION) { + if(flag & PASSMASK(MOTION)) { float4 speed = primitive_motion_vector(kg, sd); kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, speed); kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, 1.0f); @@ -241,16 +242,16 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl } } - if(flag & (PASS_DIFFUSE_INDIRECT|PASS_DIFFUSE_COLOR|PASS_DIFFUSE_DIRECT)) + if(light_flag & PASSMASK_COMPONENT(DIFFUSE)) L->color_diffuse += shader_bsdf_diffuse(kg, sd)*throughput; - if(flag & (PASS_GLOSSY_INDIRECT|PASS_GLOSSY_COLOR|PASS_GLOSSY_DIRECT)) + if(light_flag & PASSMASK_COMPONENT(GLOSSY)) L->color_glossy += shader_bsdf_glossy(kg, sd)*throughput; - if(flag & (PASS_TRANSMISSION_INDIRECT|PASS_TRANSMISSION_COLOR|PASS_TRANSMISSION_DIRECT)) + if(light_flag & PASSMASK_COMPONENT(TRANSMISSION)) L->color_transmission += shader_bsdf_transmission(kg, sd)*throughput; - if(flag & (PASS_SUBSURFACE_INDIRECT|PASS_SUBSURFACE_COLOR|PASS_SUBSURFACE_DIRECT)) + if(light_flag & PASSMASK_COMPONENT(SUBSURFACE)) L->color_subsurface += shader_bsdf_subsurface(kg, sd)*throughput; - if(flag & PASS_MIST) { + if(light_flag & PASSMASK(MIST)) { /* bring depth into 0..1 range */ float mist_start = kernel_data.film.mist_start; float mist_inv_depth = kernel_data.film.mist_inv_depth; @@ -280,49 +281,53 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl ccl_device_inline void kernel_write_light_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L) { #ifdef __PASSES__ - int flag = kernel_data.film.pass_flag; + int light_flag = kernel_data.film.light_pass_flag; if(!kernel_data.film.use_light_pass) return; - if(flag & PASS_DIFFUSE_INDIRECT) + if(light_flag & PASSMASK(DIFFUSE_INDIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_indirect, L->indirect_diffuse); - if(flag & PASS_GLOSSY_INDIRECT) + if(light_flag & PASSMASK(GLOSSY_INDIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_indirect, L->indirect_glossy); - if(flag & PASS_TRANSMISSION_INDIRECT) + if(light_flag & PASSMASK(TRANSMISSION_INDIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_indirect, L->indirect_transmission); - if(flag & PASS_SUBSURFACE_INDIRECT) + if(light_flag & PASSMASK(SUBSURFACE_INDIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_indirect, L->indirect_subsurface); - if(flag & PASS_DIFFUSE_DIRECT) + if(light_flag & PASSMASK(VOLUME_INDIRECT)) + kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_indirect, L->indirect_scatter); + if(light_flag & PASSMASK(DIFFUSE_DIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_direct, L->direct_diffuse); - if(flag & PASS_GLOSSY_DIRECT) + if(light_flag & PASSMASK(GLOSSY_DIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_direct, L->direct_glossy); - if(flag & PASS_TRANSMISSION_DIRECT) + if(light_flag & PASSMASK(TRANSMISSION_DIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_direct, L->direct_transmission); - if(flag & PASS_SUBSURFACE_DIRECT) + if(light_flag & PASSMASK(SUBSURFACE_DIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_direct, L->direct_subsurface); + if(light_flag & PASSMASK(VOLUME_DIRECT)) + kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_direct, L->direct_scatter); - if(flag & PASS_EMISSION) + if(light_flag & PASSMASK(EMISSION)) kernel_write_pass_float3(buffer + kernel_data.film.pass_emission, L->emission); - if(flag & PASS_BACKGROUND) + if(light_flag & PASSMASK(BACKGROUND)) kernel_write_pass_float3(buffer + kernel_data.film.pass_background, L->background); - if(flag & PASS_AO) + if(light_flag & PASSMASK(AO)) kernel_write_pass_float3(buffer + kernel_data.film.pass_ao, L->ao); - if(flag & PASS_DIFFUSE_COLOR) + if(light_flag & PASSMASK(DIFFUSE_COLOR)) kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_color, L->color_diffuse); - if(flag & PASS_GLOSSY_COLOR) + if(light_flag & PASSMASK(GLOSSY_COLOR)) kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, L->color_glossy); - if(flag & PASS_TRANSMISSION_COLOR) + if(light_flag & PASSMASK(TRANSMISSION_COLOR)) kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, L->color_transmission); - if(flag & PASS_SUBSURFACE_COLOR) + if(light_flag & PASSMASK(SUBSURFACE_COLOR)) kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_color, L->color_subsurface); - if(flag & PASS_SHADOW) { + if(light_flag & PASSMASK(SHADOW)) { float4 shadow = L->shadow; shadow.w = kernel_data.film.pass_shadow_scale; kernel_write_pass_float4(buffer + kernel_data.film.pass_shadow, shadow); } - if(flag & PASS_MIST) + if(light_flag & PASSMASK(MIST)) kernel_write_pass_float(buffer + kernel_data.film.pass_mist, 1.0f - L->mist); #endif } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index c43cdedac3b..45c9764cc99 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -59,6 +59,11 @@ ccl_device_forceinline bool kernel_path_scene_intersect( { uint visibility = path_state_ray_visibility(kg, state); + if(path_state_ao_bounce(kg, state)) { + visibility = PATH_RAY_SHADOW; + ray->t = kernel_data.background.ao_distance; + } + #ifdef __HAIR__ float difl = 0.0f, extmax = 0.0f; uint lcg_state = 0; @@ -74,11 +79,6 @@ ccl_device_forceinline bool kernel_path_scene_intersect( lcg_state = lcg_state_init_addrspace(state, 0x51633e2d); } - if(path_state_ao_bounce(kg, state)) { - visibility = PATH_RAY_SHADOW; - ray->t = kernel_data.background.ao_distance; - } - bool hit = scene_intersect(kg, *ray, visibility, isect, &lcg_state, difl, extmax); #else bool hit = scene_intersect(kg, *ray, visibility, isect, NULL, 0.0f, 0.0f); @@ -185,7 +185,7 @@ ccl_device_forceinline bool kernel_path_background_setup( L->transparent += average(throughput); #ifdef __PASSES__ - if(!(kernel_data.film.pass_flag & PASS_BACKGROUND)) + if(!(kernel_data.film.light_pass_flag & PASSMASK(BACKGROUND))) #endif /* __PASSES__ */ return false; } diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 3c84938a349..eb2d87bd358 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -57,6 +57,7 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg, #ifdef __INSTANCING__ sd->object = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object; #endif + sd->lamp = LAMP_NONE; sd->type = isect->type; sd->flag = 0; @@ -265,6 +266,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg, #ifdef __INSTANCING__ sd->object = object; #endif + sd->lamp = LAMP_NONE; /* currently no access to bvh prim index for strand sd->prim*/ sd->prim = prim; #ifdef __UV__ @@ -286,6 +288,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg, else if(lamp != LAMP_NONE) { sd->ob_tfm = lamp_fetch_transform(kg, lamp, false); sd->ob_itfm = lamp_fetch_transform(kg, lamp, true); + sd->lamp = lamp; #endif } @@ -391,6 +394,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat #ifdef __INSTANCING__ sd->object = PRIM_NONE; #endif + sd->lamp = LAMP_NONE; sd->prim = PRIM_NONE; #ifdef __UV__ sd->u = 0.0f; @@ -431,6 +435,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s # ifdef __INSTANCING__ sd->object = PRIM_NONE; /* todo: fill this for texture coordinates */ # endif + sd->lamp = LAMP_NONE; sd->prim = PRIM_NONE; sd->type = PRIMITIVE_NONE; @@ -1190,6 +1195,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg, /* setup shaderdata from stack. it's mostly setup already in * shader_setup_from_volume, this switching should be quick */ sd->object = stack[i].object; + sd->lamp = LAMP_NONE; sd->shader = stack[i].shader; sd->flag &= ~SD_SHADER_FLAGS; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index e1fdd1340db..0b878f17880 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -368,43 +368,59 @@ typedef enum ClosureLabel { /* Render Passes */ +#define PASS_NAME_JOIN(a, b) a ## _ ## b +#define PASSMASK(pass) (1 << ((PASS_NAME_JOIN(PASS, pass)) % 32)) + +#define PASSMASK_COMPONENT(comp) (PASSMASK(PASS_NAME_JOIN(comp, DIRECT)) | \ + PASSMASK(PASS_NAME_JOIN(comp, INDIRECT)) | \ + PASSMASK(PASS_NAME_JOIN(comp, COLOR))) + typedef enum PassType { PASS_NONE = 0, - PASS_COMBINED = (1 << 0), - PASS_DEPTH = (1 << 1), - PASS_NORMAL = (1 << 2), - PASS_UV = (1 << 3), - PASS_OBJECT_ID = (1 << 4), - PASS_MATERIAL_ID = (1 << 5), - PASS_DIFFUSE_COLOR = (1 << 6), - PASS_GLOSSY_COLOR = (1 << 7), - PASS_TRANSMISSION_COLOR = (1 << 8), - PASS_DIFFUSE_INDIRECT = (1 << 9), - PASS_GLOSSY_INDIRECT = (1 << 10), - PASS_TRANSMISSION_INDIRECT = (1 << 11), - PASS_DIFFUSE_DIRECT = (1 << 12), - PASS_GLOSSY_DIRECT = (1 << 13), - PASS_TRANSMISSION_DIRECT = (1 << 14), - PASS_EMISSION = (1 << 15), - PASS_BACKGROUND = (1 << 16), - PASS_AO = (1 << 17), - PASS_SHADOW = (1 << 18), - PASS_MOTION = (1 << 19), - PASS_MOTION_WEIGHT = (1 << 20), - PASS_MIST = (1 << 21), - PASS_SUBSURFACE_DIRECT = (1 << 22), - PASS_SUBSURFACE_INDIRECT = (1 << 23), - PASS_SUBSURFACE_COLOR = (1 << 24), - PASS_LIGHT = (1 << 25), /* no real pass, used to force use_light_pass */ + + /* Main passes */ + PASS_COMBINED = 1, + PASS_DEPTH, + PASS_NORMAL, + PASS_UV, + PASS_OBJECT_ID, + PASS_MATERIAL_ID, + PASS_MOTION, + PASS_MOTION_WEIGHT, #ifdef __KERNEL_DEBUG__ - PASS_BVH_TRAVERSED_NODES = (1 << 26), - PASS_BVH_TRAVERSED_INSTANCES = (1 << 27), - PASS_BVH_INTERSECTIONS = (1 << 28), - PASS_RAY_BOUNCES = (1 << 29), + PASS_BVH_TRAVERSED_NODES, + PASS_BVH_TRAVERSED_INSTANCES, + PASS_BVH_INTERSECTIONS, + PASS_RAY_BOUNCES, #endif + PASS_RENDER_TIME, + PASS_CATEGORY_MAIN_END = 31, + + PASS_MIST = 32, + PASS_EMISSION, + PASS_BACKGROUND, + PASS_AO, + PASS_SHADOW, + PASS_LIGHT, /* no real pass, used to force use_light_pass */ + PASS_DIFFUSE_DIRECT, + PASS_DIFFUSE_INDIRECT, + PASS_DIFFUSE_COLOR, + PASS_GLOSSY_DIRECT, + PASS_GLOSSY_INDIRECT, + PASS_GLOSSY_COLOR, + PASS_TRANSMISSION_DIRECT, + PASS_TRANSMISSION_INDIRECT, + PASS_TRANSMISSION_COLOR, + PASS_SUBSURFACE_DIRECT, + PASS_SUBSURFACE_INDIRECT, + PASS_SUBSURFACE_COLOR, + PASS_VOLUME_DIRECT, + PASS_VOLUME_INDIRECT, + /* No Scatter color since it's tricky to define what it would even mean. */ + PASS_CATEGORY_LIGHT_END = 63, } PassType; -#define PASS_ALL (~0) +#define PASS_ANY (~0) typedef enum DenoisingPassOffsets { DENOISING_PASS_NORMAL = 0, @@ -509,7 +525,6 @@ typedef ccl_addr_space struct PathRadiance { float3 color_glossy; float3 color_transmission; float3 color_subsurface; - float3 color_scatter; float3 direct_diffuse; float3 direct_glossy; @@ -966,6 +981,8 @@ typedef ccl_addr_space struct ShaderData { float v; /* object id if there is one, ~0 otherwise */ int object; + /* lamp id if there is one, ~0 otherwise */ + int lamp; /* motion blur sample time */ float time; @@ -1186,6 +1203,7 @@ static_assert_align(KernelCamera, 16); typedef struct KernelFilm { float exposure; int pass_flag; + int light_pass_flag; int pass_stride; int use_light_pass; @@ -1208,11 +1226,13 @@ typedef struct KernelFilm { int pass_glossy_indirect; int pass_transmission_indirect; int pass_subsurface_indirect; + int pass_volume_indirect; int pass_diffuse_direct; int pass_glossy_direct; int pass_transmission_direct; int pass_subsurface_direct; + int pass_volume_direct; int pass_emission; int pass_background; @@ -1222,7 +1242,6 @@ typedef struct KernelFilm { int pass_shadow; float pass_shadow_scale; int filter_table_offset; - int pass_pad2; int pass_mist; float mist_start; @@ -1232,7 +1251,8 @@ typedef struct KernelFilm { int pass_denoising_data; int pass_denoising_clean; int denoising_flags; - int pad; + + int pad1, pad2, pad3; #ifdef __KERNEL_DEBUG__ int pass_bvh_traversed_nodes; diff --git a/intern/cycles/kernel/kernels/cuda/kernel_config.h b/intern/cycles/kernel/kernels/cuda/kernel_config.h index 7ae205b7e14..94f59ff38d9 100644 --- a/intern/cycles/kernel/kernels/cuda/kernel_config.h +++ b/intern/cycles/kernel/kernels/cuda/kernel_config.h @@ -73,9 +73,15 @@ /* tunable parameters */ # define CUDA_THREADS_BLOCK_WIDTH 16 -# define CUDA_KERNEL_MAX_REGISTERS 48 +/* CUDA 9.0 seems to cause slowdowns on high-end Pascal cards unless we increase the number of registers */ +# if __CUDACC_VER_MAJOR__ == 9 && __CUDA_ARCH__ >= 600 +# define CUDA_KERNEL_MAX_REGISTERS 64 +# else +# define CUDA_KERNEL_MAX_REGISTERS 48 +# endif # define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63 + /* unknown architecture */ #else # error "Unknown or unsupported CUDA architecture, can't determine launch bounds" diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index e3e85705ebc..597d25e9f30 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -232,7 +232,11 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O /* optimization: it's possible to not use a prepare function at all and * only initialize the actual class when accessing the closure component * data, but then we need to map the id to the class somehow */ +#if OSL_LIBRARY_VERSION_CODE >= 10900 + ss->register_closure(name, id, params, prepare, NULL); +#else ss->register_closure(name, id, params, prepare, NULL, 16); +#endif } void OSLShader::register_closures(OSLShadingSystem *ss_) diff --git a/intern/cycles/kernel/split/kernel_branched.h b/intern/cycles/kernel/split/kernel_branched.h index 6456636caaa..368a4395760 100644 --- a/intern/cycles/kernel/split/kernel_branched.h +++ b/intern/cycles/kernel/split/kernel_branched.h @@ -33,9 +33,9 @@ ccl_device_inline void kernel_split_branched_path_indirect_loop_init(KernelGloba BRANCHED_STORE(isect); BRANCHED_STORE(ray_state); - branched_state->sd = *kernel_split_sd(sd, ray_index); - for(int i = 0; i < branched_state->sd.num_closure; i++) { - branched_state->sd.closure[i] = kernel_split_sd(sd, ray_index)->closure[i]; + *kernel_split_sd(branched_state_sd, ray_index) = *kernel_split_sd(sd, ray_index); + for(int i = 0; i < kernel_split_sd(branched_state_sd, ray_index)->num_closure; i++) { + kernel_split_sd(branched_state_sd, ray_index)->closure[i] = kernel_split_sd(sd, ray_index)->closure[i]; } #undef BRANCHED_STORE @@ -60,9 +60,9 @@ ccl_device_inline void kernel_split_branched_path_indirect_loop_end(KernelGlobal BRANCHED_RESTORE(isect); BRANCHED_RESTORE(ray_state); - *kernel_split_sd(sd, ray_index) = branched_state->sd; - for(int i = 0; i < branched_state->sd.num_closure; i++) { - kernel_split_sd(sd, ray_index)->closure[i] = branched_state->sd.closure[i]; + *kernel_split_sd(sd, ray_index) = *kernel_split_sd(branched_state_sd, ray_index); + for(int i = 0; i < kernel_split_sd(branched_state_sd, ray_index)->num_closure; i++) { + kernel_split_sd(sd, ray_index)->closure[i] = kernel_split_sd(branched_state_sd, ray_index)->closure[i]; } #undef BRANCHED_RESTORE @@ -83,10 +83,17 @@ ccl_device_inline bool kernel_split_branched_indirect_start_shared(KernelGlobals } #define SPLIT_DATA_ENTRY(type, name, num) \ - kernel_split_state.name[inactive_ray] = kernel_split_state.name[ray_index]; + if(num) { \ + kernel_split_state.name[inactive_ray] = kernel_split_state.name[ray_index]; \ + } SPLIT_DATA_ENTRIES_BRANCHED_SHARED #undef SPLIT_DATA_ENTRY + *kernel_split_sd(sd, inactive_ray) = *kernel_split_sd(sd, ray_index); + for(int i = 0; i < kernel_split_sd(sd, ray_index)->num_closure; i++) { + kernel_split_sd(sd, inactive_ray)->closure[i] = kernel_split_sd(sd, ray_index)->closure[i]; + } + kernel_split_state.branched_state[inactive_ray].shared_sample_count = 0; kernel_split_state.branched_state[inactive_ray].original_ray = ray_index; kernel_split_state.branched_state[inactive_ray].waiting_on_shared_samples = false; diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h index bb6bf1cc7e6..75a0af7567b 100644 --- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h +++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h @@ -145,7 +145,7 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, if(kernel_split_branched_path_surface_indirect_light_iter(kg, ray_index, 1.0f, - &kernel_split_state.branched_state[ray_index].sd, + kernel_split_sd(branched_state_sd, ray_index), true, true)) { @@ -190,7 +190,7 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, if(kernel_split_branched_path_surface_indirect_light_iter(kg, ray_index, 1.0f, - &kernel_split_state.branched_state[ray_index].sd, + kernel_split_sd(branched_state_sd, ray_index), true, true)) { diff --git a/intern/cycles/kernel/split/kernel_split_data.h b/intern/cycles/kernel/split/kernel_split_data.h index fa2f0b20a83..9297e1e0ad5 100644 --- a/intern/cycles/kernel/split/kernel_split_data.h +++ b/intern/cycles/kernel/split/kernel_split_data.h @@ -34,7 +34,7 @@ ccl_device_inline uint64_t split_data_buffer_size(KernelGlobals *kg, size_t num_ uint64_t closure_size = sizeof(ShaderClosure) * (kernel_data.integrator.max_closures-1); #ifdef __BRANCHED_PATH__ - size += align_up(closure_size * num_elements, 16); + size += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16); #endif size += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16); @@ -60,7 +60,8 @@ ccl_device_inline void split_data_init(KernelGlobals *kg, uint64_t closure_size = sizeof(ShaderClosure) * (kernel_data.integrator.max_closures-1); #ifdef __BRANCHED_PATH__ - p += align_up(closure_size * num_elements, 16); + split_data->_branched_state_sd = (ShaderData*)p; + p += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16); #endif split_data->_sd = (ShaderData*)p; diff --git a/intern/cycles/kernel/split/kernel_split_data_types.h b/intern/cycles/kernel/split/kernel_split_data_types.h index dab0bf72fcf..9970ec1315c 100644 --- a/intern/cycles/kernel/split/kernel_split_data_types.h +++ b/intern/cycles/kernel/split/kernel_split_data_types.h @@ -85,13 +85,11 @@ typedef ccl_global struct SplitBranchedState { int shared_sample_count; /* number of branched samples shared with other threads */ int original_ray; /* index of original ray when sharing branched samples */ bool waiting_on_shared_samples; - - /* Must be last in to allow for dynamic size of closures */ - struct ShaderData sd; } SplitBranchedState; #define SPLIT_DATA_BRANCHED_ENTRIES \ - SPLIT_DATA_ENTRY( SplitBranchedState, branched_state, 1) + SPLIT_DATA_ENTRY( SplitBranchedState, branched_state, 1) \ + SPLIT_DATA_ENTRY(ShaderData, _branched_state_sd, 0) #else #define SPLIT_DATA_BRANCHED_ENTRIES #endif /* __BRANCHED_PATH__ */ diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h index 887c3e313d1..5bf7483e9a2 100644 --- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h +++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h @@ -37,7 +37,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it { SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index]; - ShaderData *sd = &branched_state->sd; + ShaderData *sd = kernel_split_sd(branched_state_sd, ray_index); PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]); diff --git a/intern/cycles/kernel/svm/svm_bevel.h b/intern/cycles/kernel/svm/svm_bevel.h index 65afe1f74ec..bbbc8dce2cf 100644 --- a/intern/cycles/kernel/svm/svm_bevel.h +++ b/intern/cycles/kernel/svm/svm_bevel.h @@ -198,7 +198,7 @@ ccl_device_noinline float3 svm_bevel( /* Normalize. */ float3 N = safe_normalize(sum_N); - return is_zero(N) ? sd->N : N; + return is_zero(N) ? sd->N : (sd->flag & SD_BACKFACING) ? -N : N; } ccl_device void svm_node_bevel( diff --git a/intern/cycles/kernel/svm/svm_brick.h b/intern/cycles/kernel/svm/svm_brick.h index 14245cf0522..90fa2a99b67 100644 --- a/intern/cycles/kernel/svm/svm_brick.h +++ b/intern/cycles/kernel/svm/svm_brick.h @@ -18,9 +18,9 @@ CCL_NAMESPACE_BEGIN /* Brick */ -ccl_device_noinline float brick_noise(int n) /* fast integer noise */ +ccl_device_noinline float brick_noise(uint n) /* fast integer noise */ { - int nn; + uint nn; n = (n + 1013) & 0x7fffffff; n = (n >> 13) ^ n; nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index cce4e89e715..9af4a0182d9 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -90,7 +90,15 @@ ccl_device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *s } case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break; case NODE_INFO_MAT_INDEX: data = shader_pass_id(kg, sd); break; - case NODE_INFO_OB_RANDOM: data = object_random_number(kg, sd->object); break; + case NODE_INFO_OB_RANDOM: { + if(sd->lamp != LAMP_NONE) { + data = lamp_random_number(kg, sd->lamp); + } + else { + data = object_random_number(kg, sd->object); + } + break; + } default: data = 0.0f; break; } diff --git a/intern/cycles/kernel/svm/svm_gradient.h b/intern/cycles/kernel/svm/svm_gradient.h index 53d7b4f812c..74e36e70427 100644 --- a/intern/cycles/kernel/svm/svm_gradient.h +++ b/intern/cycles/kernel/svm/svm_gradient.h @@ -46,7 +46,10 @@ ccl_device float svm_gradient(float3 p, NodeGradientType type) return atan2f(y, x) / M_2PI_F + 0.5f; } else { - float r = fmaxf(1.0f - sqrtf(x*x + y*y + z*z), 0.0f); + /* Bias a little bit for the case where p is a unit length vector, + * to get exactly zero instead of a small random value depending + * on float precision. */ + float r = fmaxf(0.999999f - sqrtf(x*x + y*y + z*z), 0.0f); if(type == NODE_BLEND_QUADRATIC_SPHERE) return r*r; diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index f08ec76c055..c7fe7948422 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -465,13 +465,16 @@ typedef enum ClosureType { #define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID) #define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSLUCENT_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID) #define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID || type == CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID) +#define CLOSURE_IS_BSDF_SINGULAR(type) (type == CLOSURE_BSDF_REFLECTION_ID || \ + type == CLOSURE_BSDF_REFRACTION_ID || \ + type == CLOSURE_BSDF_TRANSPARENT_ID) #define CLOSURE_IS_BSDF_TRANSPARENT(type) (type == CLOSURE_BSDF_TRANSPARENT_ID) -#define CLOSURE_IS_BSDF_ANISOTROPIC(type) (type >= CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID) #define CLOSURE_IS_BSDF_MULTISCATTER(type) (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID ||\ type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID || \ type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) -#define CLOSURE_IS_BSDF_MICROFACET(type) ((type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID) ||\ - (type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)) +#define CLOSURE_IS_BSDF_MICROFACET(type) ((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID) ||\ + (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) ||\ + (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID)) #define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_BURLEY_ID) #define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_BURLEY_ID) #define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index ac675dc7b39..5c7729ec89f 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -116,7 +116,7 @@ RenderTile::RenderTile() RenderBuffers::RenderBuffers(Device *device) : buffer(device, "RenderBuffers", MEM_READ_WRITE), - map_neighbor_copied(false) + map_neighbor_copied(false), render_time(0.0f) { } @@ -236,10 +236,17 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int int size = params.width*params.height; - if(components == 1) { + if(components == 1 && type == PASS_RENDER_TIME) { + /* Render time is not stored by kernel, but measured per tile. */ + float val = (float) (1000.0 * render_time/(params.width * params.height * sample)); + for(int i = 0; i < size; i++, pixels++) { + pixels[0] = val; + } + } + else if(components == 1) { assert(pass.components == components); - /* scalar */ + /* Scalar */ if(type == PASS_DEPTH) { for(int i = 0; i < size; i++, in += pass_stride, pixels++) { float f = *in; diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h index 9fa0cdd4e27..028bfb83735 100644 --- a/intern/cycles/render/buffers.h +++ b/intern/cycles/render/buffers.h @@ -75,6 +75,7 @@ public: /* float buffer */ device_vector<float> buffer; bool map_neighbor_copied; + double render_time; explicit RenderBuffers(Device *device); ~RenderBuffers(); diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index c8213d258d5..6c8c929c2f9 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -85,83 +85,81 @@ void Pass::add(PassType type, array<Pass>& passes) pass.components = 1; pass.filter = false; break; - case PASS_DIFFUSE_COLOR: - case PASS_GLOSSY_COLOR: - case PASS_TRANSMISSION_COLOR: - case PASS_SUBSURFACE_COLOR: - pass.components = 4; - break; - case PASS_DIFFUSE_INDIRECT: + + case PASS_EMISSION: + case PASS_BACKGROUND: pass.components = 4; pass.exposure = true; - pass.divide_type = PASS_DIFFUSE_COLOR; break; - case PASS_GLOSSY_INDIRECT: + case PASS_AO: pass.components = 4; - pass.exposure = true; - pass.divide_type = PASS_GLOSSY_COLOR; break; - case PASS_TRANSMISSION_INDIRECT: + case PASS_SHADOW: pass.components = 4; - pass.exposure = true; - pass.divide_type = PASS_TRANSMISSION_COLOR; + pass.exposure = false; break; - case PASS_SUBSURFACE_INDIRECT: + case PASS_LIGHT: + /* This isn't a real pass, used by baking to see whether + * light data is needed or not. + * + * Set components to 0 so pass sort below happens in a + * determined way. + */ + pass.components = 0; + break; +#ifdef WITH_CYCLES_DEBUG + case PASS_BVH_TRAVERSED_NODES: + case PASS_BVH_TRAVERSED_INSTANCES: + case PASS_BVH_INTERSECTIONS: + case PASS_RAY_BOUNCES: + pass.components = 1; + pass.exposure = false; + break; +#endif + case PASS_RENDER_TIME: + /* This pass is handled entirely on the host side. */ + pass.components = 0; + break; + + case PASS_DIFFUSE_COLOR: + case PASS_GLOSSY_COLOR: + case PASS_TRANSMISSION_COLOR: + case PASS_SUBSURFACE_COLOR: pass.components = 4; - pass.exposure = true; - pass.divide_type = PASS_SUBSURFACE_COLOR; break; case PASS_DIFFUSE_DIRECT: + case PASS_DIFFUSE_INDIRECT: pass.components = 4; pass.exposure = true; pass.divide_type = PASS_DIFFUSE_COLOR; break; case PASS_GLOSSY_DIRECT: + case PASS_GLOSSY_INDIRECT: pass.components = 4; pass.exposure = true; pass.divide_type = PASS_GLOSSY_COLOR; break; case PASS_TRANSMISSION_DIRECT: + case PASS_TRANSMISSION_INDIRECT: pass.components = 4; pass.exposure = true; pass.divide_type = PASS_TRANSMISSION_COLOR; break; case PASS_SUBSURFACE_DIRECT: + case PASS_SUBSURFACE_INDIRECT: pass.components = 4; pass.exposure = true; pass.divide_type = PASS_SUBSURFACE_COLOR; break; - - case PASS_EMISSION: - case PASS_BACKGROUND: + case PASS_VOLUME_DIRECT: + case PASS_VOLUME_INDIRECT: pass.components = 4; pass.exposure = true; break; - case PASS_AO: - pass.components = 4; - break; - case PASS_SHADOW: - pass.components = 4; - pass.exposure = false; - break; - case PASS_LIGHT: - /* This isn't a real pass, used by baking to see whether - * light data is needed or not. - * - * Set components to 0 so pass sort below happens in a - * determined way. - */ - pass.components = 0; - break; -#ifdef WITH_CYCLES_DEBUG - case PASS_BVH_TRAVERSED_NODES: - case PASS_BVH_TRAVERSED_INSTANCES: - case PASS_BVH_INTERSECTIONS: - case PASS_RAY_BOUNCES: - pass.components = 1; - pass.exposure = false; + + default: + assert(false); break; -#endif } passes.push_back_slow(pass); @@ -318,7 +316,19 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) for(size_t i = 0; i < passes.size(); i++) { Pass& pass = passes[i]; - kfilm->pass_flag |= pass.type; + + if(pass.type == PASS_NONE) + continue; + + int pass_flag = (1 << (pass.type % 32)); + if(pass.type <= PASS_CATEGORY_MAIN_END) { + kfilm->pass_flag |= pass_flag; + } + else { + assert(pass.type <= PASS_CATEGORY_LIGHT_END); + kfilm->use_light_pass = 1; + kfilm->light_pass_flag |= pass_flag; + } switch(pass.type) { case PASS_COMBINED: @@ -327,10 +337,6 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) case PASS_DEPTH: kfilm->pass_depth = kfilm->pass_stride; break; - case PASS_MIST: - kfilm->pass_mist = kfilm->pass_stride; - kfilm->use_light_pass = 1; - break; case PASS_NORMAL: kfilm->pass_normal = kfilm->pass_stride; break; @@ -349,74 +355,67 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) case PASS_MATERIAL_ID: kfilm->pass_material_id = kfilm->pass_stride; break; + + case PASS_MIST: + kfilm->pass_mist = kfilm->pass_stride; + break; + case PASS_EMISSION: + kfilm->pass_emission = kfilm->pass_stride; + break; + case PASS_BACKGROUND: + kfilm->pass_background = kfilm->pass_stride; + break; + case PASS_AO: + kfilm->pass_ao = kfilm->pass_stride; + break; + case PASS_SHADOW: + kfilm->pass_shadow = kfilm->pass_stride; + break; + + case PASS_LIGHT: + break; + case PASS_DIFFUSE_COLOR: kfilm->pass_diffuse_color = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; case PASS_GLOSSY_COLOR: kfilm->pass_glossy_color = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; case PASS_TRANSMISSION_COLOR: kfilm->pass_transmission_color = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; case PASS_SUBSURFACE_COLOR: kfilm->pass_subsurface_color = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; case PASS_DIFFUSE_INDIRECT: kfilm->pass_diffuse_indirect = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; case PASS_GLOSSY_INDIRECT: kfilm->pass_glossy_indirect = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; case PASS_TRANSMISSION_INDIRECT: kfilm->pass_transmission_indirect = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; case PASS_SUBSURFACE_INDIRECT: kfilm->pass_subsurface_indirect = kfilm->pass_stride; - kfilm->use_light_pass = 1; + break; + case PASS_VOLUME_INDIRECT: + kfilm->pass_volume_indirect = kfilm->pass_stride; break; case PASS_DIFFUSE_DIRECT: kfilm->pass_diffuse_direct = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; case PASS_GLOSSY_DIRECT: kfilm->pass_glossy_direct = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; case PASS_TRANSMISSION_DIRECT: kfilm->pass_transmission_direct = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; case PASS_SUBSURFACE_DIRECT: kfilm->pass_subsurface_direct = kfilm->pass_stride; - kfilm->use_light_pass = 1; break; - - case PASS_EMISSION: - kfilm->pass_emission = kfilm->pass_stride; - kfilm->use_light_pass = 1; - break; - case PASS_BACKGROUND: - kfilm->pass_background = kfilm->pass_stride; - kfilm->use_light_pass = 1; - break; - case PASS_AO: - kfilm->pass_ao = kfilm->pass_stride; - kfilm->use_light_pass = 1; - break; - case PASS_SHADOW: - kfilm->pass_shadow = kfilm->pass_stride; - kfilm->use_light_pass = 1; - break; - - case PASS_LIGHT: - kfilm->use_light_pass = 1; + case PASS_VOLUME_DIRECT: + kfilm->pass_volume_direct = kfilm->pass_stride; break; #ifdef WITH_CYCLES_DEBUG @@ -433,8 +432,11 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) kfilm->pass_ray_bounces = kfilm->pass_stride; break; #endif + case PASS_RENDER_TIME: + break; - case PASS_NONE: + default: + assert(false); break; } diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 9358b40a689..482442cce29 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -723,6 +723,7 @@ void ImageManager::device_load_image(Device *device, *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ + thread_scoped_lock device_lock(device_mutex); float *pixels = (float*)tex_img->alloc(1, 1); pixels[0] = TEX_IMAGE_MISSING_R; @@ -748,6 +749,7 @@ void ImageManager::device_load_image(Device *device, *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ + thread_scoped_lock device_lock(device_mutex); float *pixels = (float*)tex_img->alloc(1, 1); pixels[0] = TEX_IMAGE_MISSING_R; @@ -770,6 +772,7 @@ void ImageManager::device_load_image(Device *device, *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ + thread_scoped_lock device_lock(device_mutex); uchar *pixels = (uchar*)tex_img->alloc(1, 1); pixels[0] = (TEX_IMAGE_MISSING_R * 255); @@ -794,6 +797,7 @@ void ImageManager::device_load_image(Device *device, texture_limit, *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ + thread_scoped_lock device_lock(device_mutex); uchar *pixels = (uchar*)tex_img->alloc(1, 1); pixels[0] = (TEX_IMAGE_MISSING_R * 255); @@ -815,6 +819,7 @@ void ImageManager::device_load_image(Device *device, texture_limit, *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ + thread_scoped_lock device_lock(device_mutex); half *pixels = (half*)tex_img->alloc(1, 1); pixels[0] = TEX_IMAGE_MISSING_R; @@ -839,6 +844,7 @@ void ImageManager::device_load_image(Device *device, texture_limit, *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ + thread_scoped_lock device_lock(device_mutex); half *pixels = (half*)tex_img->alloc(1, 1); pixels[0] = TEX_IMAGE_MISSING_R; diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index b37a0768b53..b62453cf5fc 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -134,6 +134,7 @@ NODE_DEFINE(Light) SOCKET_INT(samples, "Samples", 1); SOCKET_INT(max_bounces, "Max Bounces", 1024); + SOCKET_UINT(random_id, "Random ID", 0); SOCKET_BOOLEAN(is_portal, "Is Portal", false); SOCKET_BOOLEAN(is_enabled, "Is Enabled", true); @@ -638,6 +639,7 @@ void LightManager::device_update_points(Device *, int shader_id = scene->shader_manager->get_shader_id(shader); float samples = __int_as_float(light->samples); float max_bounces = __int_as_float(light->max_bounces); + float random = (float)light->random_id * (1.0f/(float)0xFFFFFFFF); if(!light->cast_shadow) shader_id &= ~SHADER_CAST_SHADOW; @@ -758,7 +760,7 @@ void LightManager::device_update_points(Device *, light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); } - light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); + light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, random, 0.0f, 0.0f); Transform tfm = light->tfm; Transform itfm = transform_inverse(tfm); diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index 7e9014eb823..97b7b971c73 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -70,6 +70,7 @@ public: Shader *shader; int samples; int max_bounces; + uint random_id; void tag_update(Scene *scene); diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index fb04d49bcd9..39ce6a93982 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -518,6 +518,11 @@ ccl_device float safe_modulo(float a, float b) return (b != 0.0f)? fmodf(a, b): 0.0f; } +ccl_device_inline float sqr(float a) +{ + return a * a; +} + ccl_device_inline float beta(float x, float y) { #ifndef __KERNEL_OPENCL__ diff --git a/intern/cycles/util/util_xml.h b/intern/cycles/util/util_xml.h index e1a28df9433..6f06f17937b 100644 --- a/intern/cycles/util/util_xml.h +++ b/intern/cycles/util/util_xml.h @@ -23,10 +23,19 @@ CCL_NAMESPACE_BEGIN -using OIIO_NAMESPACE::pugi::xml_node; -using OIIO_NAMESPACE::pugi::xml_attribute; +OIIO_NAMESPACE_USING + +#ifdef WITH_SYSTEM_PUGIXML +# define PUGIXML_NAMESPACE pugi +#else +# define PUGIXML_NAMESPACE OIIO_NAMESPACE::pugi +#endif + +using PUGIXML_NAMESPACE::xml_attribute; +using PUGIXML_NAMESPACE::xml_document; +using PUGIXML_NAMESPACE::xml_node; +using PUGIXML_NAMESPACE::xml_parse_result; CCL_NAMESPACE_END #endif /* __UTIL_XML_H__ */ - diff --git a/intern/eigen/intern/eigenvalues.cc b/intern/eigen/intern/eigenvalues.cc index 57942a4dc55..b516443c421 100644 --- a/intern/eigen/intern/eigenvalues.cc +++ b/intern/eigen/intern/eigenvalues.cc @@ -28,7 +28,7 @@ #define __EIGEN3_EIGENVALUES_C_API_CC__ /* Eigen gives annoying huge amount of warnings here, silence them! */ -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic ignored "-Wlogical-op" #endif diff --git a/intern/eigen/intern/svd.cc b/intern/eigen/intern/svd.cc index 04929cff798..7c331d25aa7 100644 --- a/intern/eigen/intern/svd.cc +++ b/intern/eigen/intern/svd.cc @@ -28,7 +28,7 @@ #define __EIGEN3_SVD_C_API_CC__ /* Eigen gives annoying huge amount of warnings here, silence them! */ -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic ignored "-Wlogical-op" #endif diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c index f832b356ffe..ebf699c2428 100644 --- a/intern/mikktspace/mikktspace.c +++ b/intern/mikktspace/mikktspace.c @@ -447,305 +447,132 @@ typedef struct { int index; } STmpVert; -static const int g_iCells = 2048; -static const float g_iCells_fl = 2048.0f; +static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn); -#ifdef _MSC_VER -# define NOINLINE __declspec(noinline) -#else -# define NOINLINE __attribute__ ((noinline)) -#endif +typedef unsigned int uint; -// it is IMPORTANT that this function is called to evaluate the hash since -// inlining could potentially reorder instructions and generate different -// results for the same effective input value fVal. -static NOINLINE int FindGridCell(const float fMin, const float fMax, const float fVal) +static uint float_as_uint(const float v) { - const float fIndex = g_iCells_fl * ((fVal-fMin)/(fMax-fMin)); - const int iIndex = (int)fIndex; - return iIndex < g_iCells ? (iIndex >= 0 ? iIndex : 0) : (g_iCells - 1); + return *((uint*)(&v)); } -static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in); -static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries); -static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn); +#define HASH(x, y, z) (((x) * 73856093) ^ ((y) * 19349663) ^ ((z) * 83492791)) +#define HASH_F(x, y, z) HASH(float_as_uint(x), float_as_uint(y), float_as_uint(z)) -static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) +/* Sort comp and data based on comp. + * comp2 and data2 are used as temporary storage. */ +static void radixsort_pair(uint *comp, int *data, uint *comp2, int *data2, int n) { + int shift = 0; + for(int pass = 0; pass < 4; pass++, shift+=8) { + int bins[257] = {0}; + /* Count number of elements per bin. */ + for(int i = 0; i < n; i++) { + bins[((comp[i] >> shift) & 0xff) + 1]++; + } + /* Compute prefix sum to find position of each bin in the sorted array. */ + for(int i = 2; i < 256; i++) { + bins[i] += bins[i-1]; + } + /* Insert the elements in their correct location based on their bin. */ + for(int i = 0; i < n; i++) { + int pos = bins[(comp[i] >> shift) & 0xff]++; + comp2[pos] = comp[i]; + data2[pos] = data[i]; + } - // Generate bounding box - int * piHashTable=NULL, * piHashCount=NULL, * piHashOffsets=NULL, * piHashCount2=NULL; - STmpVert * pTmpVert = NULL; - int i=0, iChannel=0, k=0, e=0; - int iMaxCount=0; - SVec3 vMin = GetPosition(pContext, 0), vMax = vMin, vDim; - float fMin, fMax; - for (i=1; i<(iNrTrianglesIn*3); i++) - { - const int index = piTriList_in_and_out[i]; - - const SVec3 vP = GetPosition(pContext, index); - if (vMin.x > vP.x) vMin.x = vP.x; - else if (vMax.x < vP.x) vMax.x = vP.x; - if (vMin.y > vP.y) vMin.y = vP.y; - else if (vMax.y < vP.y) vMax.y = vP.y; - if (vMin.z > vP.z) vMin.z = vP.z; - else if (vMax.z < vP.z) vMax.z = vP.z; + /* Swap arrays. */ + int *tmpdata = data; data = data2; data2 = tmpdata; + uint *tmpcomp = comp; comp = comp2; comp2 = tmpcomp; } +} - vDim = vsub(vMax,vMin); - iChannel = 0; - fMin = vMin.x; fMax=vMax.x; - if (vDim.y>vDim.x && vDim.y>vDim.z) - { - iChannel=1; - fMin = vMin.y; - fMax = vMax.y; - } - else if (vDim.z>vDim.x) - { - iChannel=2; - fMin = vMin.z; - fMax = vMax.z; - } +/* Merge identical vertices. + * To find vertices with identical position, normal and texcoord, we calculate a hash of the 9 values. + * Then, by sorting based on that hash, identical elements (having identical hashes) will be moved next to each other. + * Since there might be hash collisions, the elements of each block are then compared with each other and duplicates + * are merged. + */ +static void GenerateSharedVerticesIndexList(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) +{ + int numVertices = iNrTrianglesIn*3; - // make allocations - piHashTable = (int *) malloc(sizeof(int[3])*iNrTrianglesIn); - piHashCount = (int *) malloc(sizeof(int)*g_iCells); - piHashOffsets = (int *) malloc(sizeof(int)*g_iCells); - piHashCount2 = (int *) malloc(sizeof(int)*g_iCells); + uint *hashes = (uint*) malloc(sizeof(uint)*numVertices); + int *indices = (int*) malloc(sizeof(int)*numVertices); + uint *temp_hashes = (uint*) malloc(sizeof(uint)*numVertices); + int *temp_indices = (int*) malloc(sizeof(int)*numVertices); + + if(hashes == NULL || indices == NULL || temp_hashes == NULL || temp_indices == NULL) { + free(hashes); + free(indices); + free(temp_hashes); + free(temp_indices); - if (piHashTable==NULL || piHashCount==NULL || piHashOffsets==NULL || piHashCount2==NULL) - { - if (piHashTable!=NULL) free(piHashTable); - if (piHashCount!=NULL) free(piHashCount); - if (piHashOffsets!=NULL) free(piHashOffsets); - if (piHashCount2!=NULL) free(piHashCount2); GenerateSharedVerticesIndexListSlow(piTriList_in_and_out, pContext, iNrTrianglesIn); return; } - memset(piHashCount, 0, sizeof(int)*g_iCells); - memset(piHashCount2, 0, sizeof(int)*g_iCells); - // count amount of elements in each cell unit - for (i=0; i<(iNrTrianglesIn*3); i++) - { + for (int i = 0; i < numVertices; i++) { const int index = piTriList_in_and_out[i]; - const SVec3 vP = GetPosition(pContext, index); - const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z); - const int iCell = FindGridCell(fMin, fMax, fVal); - ++piHashCount[iCell]; - } - // evaluate start index of each cell. - piHashOffsets[0]=0; - for (k=1; k<g_iCells; k++) - piHashOffsets[k]=piHashOffsets[k-1]+piHashCount[k-1]; - - // insert vertices - for (i=0; i<(iNrTrianglesIn*3); i++) - { - const int index = piTriList_in_and_out[i]; const SVec3 vP = GetPosition(pContext, index); - const float fVal = iChannel==0 ? vP.x : (iChannel==1 ? vP.y : vP.z); - const int iCell = FindGridCell(fMin, fMax, fVal); - int * pTable = NULL; - - assert(piHashCount2[iCell]<piHashCount[iCell]); - pTable = &piHashTable[piHashOffsets[iCell]]; - pTable[piHashCount2[iCell]] = i; // vertex i has been inserted. - ++piHashCount2[iCell]; - } - for (k=0; k<g_iCells; k++) - assert(piHashCount2[k] == piHashCount[k]); // verify the count - free(piHashCount2); - - // find maximum amount of entries in any hash entry - iMaxCount = piHashCount[0]; - for (k=1; k<g_iCells; k++) - if (iMaxCount<piHashCount[k]) - iMaxCount=piHashCount[k]; - pTmpVert = (STmpVert *) malloc(sizeof(STmpVert)*iMaxCount); + const uint hashP = HASH_F(vP.x, vP.y, vP.z); + const SVec3 vN = GetNormal(pContext, index); + const uint hashN = HASH_F(vN.x, vN.y, vN.z); - // complete the merge - for (k=0; k<g_iCells; k++) - { - // extract table of cell k and amount of entries in it - int * pTable = &piHashTable[piHashOffsets[k]]; - const int iEntries = piHashCount[k]; - if (iEntries < 2) continue; + const SVec3 vT = GetTexCoord(pContext, index); + const uint hashT = HASH_F(vT.x, vT.y, vT.z); - if (pTmpVert!=NULL) - { - for (e=0; e<iEntries; e++) - { - int i = pTable[e]; - const SVec3 vP = GetPosition(pContext, piTriList_in_and_out[i]); - pTmpVert[e].vert[0] = vP.x; pTmpVert[e].vert[1] = vP.y; - pTmpVert[e].vert[2] = vP.z; pTmpVert[e].index = i; - } - MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, 0, iEntries-1); - } - else - MergeVertsSlow(piTriList_in_and_out, pContext, pTable, iEntries); + hashes[i] = HASH(hashP, hashN, hashT); + indices[i] = i; } - if (pTmpVert!=NULL) { free(pTmpVert); } - free(piHashTable); - free(piHashCount); - free(piHashOffsets); -} - -static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], const SMikkTSpaceContext * pContext, const int iL_in, const int iR_in) -{ - // make bbox - int c=0, l=0, channel=0; - float fvMin[3], fvMax[3]; - float dx=0, dy=0, dz=0, fSep=0; - for (c=0; c<3; c++) - { fvMin[c]=pTmpVert[iL_in].vert[c]; fvMax[c]=fvMin[c]; } - for (l=(iL_in+1); l<=iR_in; l++) { - for (c=0; c<3; c++) { - if (fvMin[c]>pTmpVert[l].vert[c]) fvMin[c]=pTmpVert[l].vert[c]; - if (fvMax[c]<pTmpVert[l].vert[c]) fvMax[c]=pTmpVert[l].vert[c]; + radixsort_pair(hashes, indices, temp_hashes, temp_indices, numVertices); + + free(temp_hashes); + free(temp_indices); + + /* Process blocks of vertices with the same hash. + * Vertices in the block might still be separate, but we know for sure that + * vertices in different blocks will never be identical. */ + int blockstart = 0; + while (blockstart < numVertices) { + /* Find end of this block (exclusive). */ + uint hash = hashes[blockstart]; + int blockend = blockstart+1; + for(; blockend < numVertices; blockend++) { + if(hashes[blockend] != hash) break; } - } - - dx = fvMax[0]-fvMin[0]; - dy = fvMax[1]-fvMin[1]; - dz = fvMax[2]-fvMin[2]; - - channel = 0; - if (dy>dx && dy>dz) channel=1; - else if (dz>dx) channel=2; - - fSep = 0.5f*(fvMax[channel]+fvMin[channel]); - // stop if all vertices are NaNs - if (!isfinite(fSep)) - return; - - // terminate recursion when the separation/average value - // is no longer strictly between fMin and fMax values. - if (fSep>=fvMax[channel] || fSep<=fvMin[channel]) - { - // complete the weld - for (l=iL_in; l<=iR_in; l++) - { - int i = pTmpVert[l].index; - const int index = piTriList_in_and_out[i]; - const SVec3 vP = GetPosition(pContext, index); - const SVec3 vN = GetNormal(pContext, index); - const SVec3 vT = GetTexCoord(pContext, index); - - tbool bNotFound = TTRUE; - int l2=iL_in, i2rec=-1; - while (l2<l && bNotFound) - { - const int i2 = pTmpVert[l2].index; - const int index2 = piTriList_in_and_out[i2]; - const SVec3 vP2 = GetPosition(pContext, index2); - const SVec3 vN2 = GetNormal(pContext, index2); - const SVec3 vT2 = GetTexCoord(pContext, index2); - i2rec=i2; - - //if (vP==vP2 && vN==vN2 && vT==vT2) - if (vP.x==vP2.x && vP.y==vP2.y && vP.z==vP2.z && - vN.x==vN2.x && vN.y==vN2.y && vN.z==vN2.z && - vT.x==vT2.x && vT.y==vT2.y && vT.z==vT2.z) - bNotFound = TFALSE; - else - ++l2; - } - - // merge if previously found - if (!bNotFound) - piTriList_in_and_out[i] = piTriList_in_and_out[i2rec]; - } - } - else - { - int iL=iL_in, iR=iR_in; - assert((iR_in-iL_in)>0); // at least 2 entries - - // separate (by fSep) all points between iL_in and iR_in in pTmpVert[] - while (iL < iR) - { - tbool bReadyLeftSwap = TFALSE, bReadyRightSwap = TFALSE; - while ((!bReadyLeftSwap) && iL<iR) - { - assert(iL>=iL_in && iL<=iR_in); - bReadyLeftSwap = !(pTmpVert[iL].vert[channel]<fSep); - if (!bReadyLeftSwap) ++iL; - } - while ((!bReadyRightSwap) && iL<iR) - { - assert(iR>=iL_in && iR<=iR_in); - bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep; - if (!bReadyRightSwap) --iR; - } - assert( (iL<iR) || !(bReadyLeftSwap && bReadyRightSwap) ); - - if (bReadyLeftSwap && bReadyRightSwap) - { - const STmpVert sTmp = pTmpVert[iL]; - assert(iL<iR); - pTmpVert[iL] = pTmpVert[iR]; - pTmpVert[iR] = sTmp; - ++iL; --iR; + for(int i = blockstart; i < blockend; i++) { + int index1 = piTriList_in_and_out[indices[i]]; + const SVec3 vP = GetPosition(pContext, index1); + const SVec3 vN = GetNormal(pContext, index1); + const SVec3 vT = GetTexCoord(pContext, index1); + for(int i2 = i+1; i2 < blockend; i2++) { + int index2 = piTriList_in_and_out[indices[i2]]; + if(index1 == index2) continue; + + if(veq(vP, GetPosition(pContext, index2)) && + veq(vN, GetNormal(pContext, index2)) && + veq(vT, GetTexCoord(pContext, index2))) + { + piTriList_in_and_out[indices[i2]] = index1; + /* Once i2>i has been identified as a duplicate, we can stop since any + * i3>i2>i that is a duplicate of i (and therefore also i2) will also be + * compared to i2 and therefore be identified there anyways. */ + break; + } } } - assert(iL==(iR+1) || (iL==iR)); - if (iL==iR) - { - const tbool bReadyRightSwap = pTmpVert[iR].vert[channel]<fSep; - if (bReadyRightSwap) ++iL; - else --iR; - } - - // only need to weld when there is more than 1 instance of the (x,y,z) - if (iL_in < iR) - MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL_in, iR); // weld all left of fSep - if (iL < iR_in) - MergeVertsFast(piTriList_in_and_out, pTmpVert, pContext, iL, iR_in); // weld all right of (or equal to) fSep + /* Advance to next block. */ + blockstart = blockend; } -} - -static void MergeVertsSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int pTable[], const int iEntries) -{ - // this can be optimized further using a tree structure or more hashing. - int e=0; - for (e=0; e<iEntries; e++) - { - int i = pTable[e]; - const int index = piTriList_in_and_out[i]; - const SVec3 vP = GetPosition(pContext, index); - const SVec3 vN = GetNormal(pContext, index); - const SVec3 vT = GetTexCoord(pContext, index); - tbool bNotFound = TTRUE; - int e2=0, i2rec=-1; - while (e2<e && bNotFound) - { - const int i2 = pTable[e2]; - const int index2 = piTriList_in_and_out[i2]; - const SVec3 vP2 = GetPosition(pContext, index2); - const SVec3 vN2 = GetNormal(pContext, index2); - const SVec3 vT2 = GetTexCoord(pContext, index2); - i2rec = i2; - - if (veq(vP,vP2) && veq(vN,vN2) && veq(vT,vT2)) - bNotFound = TFALSE; - else - ++e2; - } - - // merge if previously found - if (!bNotFound) - piTriList_in_and_out[i] = piTriList_in_and_out[i2rec]; - } + free(hashes); + free(indices); } static void GenerateSharedVerticesIndexListSlow(int piTriList_in_and_out[], const SMikkTSpaceContext * pContext, const int iNrTrianglesIn) diff --git a/intern/smoke/intern/IMAGE.h b/intern/smoke/intern/IMAGE.h index a606fcddf72..79f71c6402a 100644 --- a/intern/smoke/intern/IMAGE.h +++ b/intern/smoke/intern/IMAGE.h @@ -48,27 +48,27 @@ template < class T > inline void CLAMP( T &a, T b=0., T c=1.) { if(a>c) { a=c; return; } } -template < class T > inline T MIN( T a, T b) { +template < class T > inline T MIN( const T& a, const T& b) { return (a < b) ? a : b; } -template < class T > inline T MAX( T a, T b) { +template < class T > inline T MAX( const T& a, const T& b) { return (a > b) ? a : b; } -template < class T > inline T MAX3( T a, T b, T c) { +template < class T > inline T MAX3( const T& a, const T& b, const T& c) { T max = (a > b) ? a : b; max = (max > c) ? max : c; return max; } -template < class T > inline float MAX3V( T vec) { +template < class T > inline float MAX3V( const T& vec) { float max = (vec[0] > vec[1]) ? vec[0] : vec[1]; max = (max > vec[2]) ? max : vec[2]; return max; } -template < class T > inline float MIN3V( T vec) { +template < class T > inline float MIN3V( const T& vec) { float min = (vec[0] < vec[1]) ? vec[0] : vec[1]; min = (min < vec[2]) ? min : vec[2]; return min; diff --git a/intern/smoke/intern/WTURBULENCE.cpp b/intern/smoke/intern/WTURBULENCE.cpp index 3d712d2124a..61389201796 100644 --- a/intern/smoke/intern/WTURBULENCE.cpp +++ b/intern/smoke/intern/WTURBULENCE.cpp @@ -245,7 +245,7 @@ void WTURBULENCE::initBlenderRNA(float *strength) // Takes the one-sided finite difference in both directions and // selects the smaller of the two ////////////////////////////////////////////////////////////////////// -static float minDx(int x, int y, int z, float* input, Vec3Int res) +static float minDx(int x, int y, int z, float* input, const Vec3Int& res) { const int index = x + y * res[0] + z * res[0] * res[1]; const int maxx = res[0]-2; @@ -280,7 +280,7 @@ static float minDx(int x, int y, int z, float* input, Vec3Int res) // Takes the one-sided finite difference in both directions and // selects the smaller of the two ////////////////////////////////////////////////////////////////////// -static float minDy(int x, int y, int z, float* input, Vec3Int res) +static float minDy(int x, int y, int z, float* input, const Vec3Int& res) { const int index = x + y * res[0] + z * res[0] * res[1]; const int maxy = res[1]-2; @@ -314,7 +314,7 @@ static float minDy(int x, int y, int z, float* input, Vec3Int res) // Takes the one-sided finite difference in both directions and // selects the smaller of the two ////////////////////////////////////////////////////////////////////// -static float minDz(int x, int y, int z, float* input, Vec3Int res) +static float minDz(int x, int y, int z, float* input, const Vec3Int& res) { const int slab = res[0]*res[1]; const int index = x + y * res[0] + z * slab; @@ -605,7 +605,7 @@ Vec3 WTURBULENCE::WVelocity(Vec3 orgPos) ////////////////////////////////////////////////////////////////////////////////////////// // Evaluate derivatives with Jacobian ////////////////////////////////////////////////////////////////////////////////////////// -Vec3 WTURBULENCE::WVelocityWithJacobian(Vec3 orgPos, float* xUnwarped, float* yUnwarped, float* zUnwarped) +Vec3 WTURBULENCE::WVelocityWithJacobian(const Vec3& orgPos, float* xUnwarped, float* yUnwarped, float* zUnwarped) { // arbitrarily offset evaluation points const Vec3 p1 = orgPos + Vec3(NOISE_TILE_SIZE/2.0,0,0); diff --git a/intern/smoke/intern/WTURBULENCE.h b/intern/smoke/intern/WTURBULENCE.h index 36635325f62..a00a818527a 100644 --- a/intern/smoke/intern/WTURBULENCE.h +++ b/intern/smoke/intern/WTURBULENCE.h @@ -62,7 +62,7 @@ struct WTURBULENCE // evaluate wavelet noise function Vec3 WVelocity(Vec3 p); - Vec3 WVelocityWithJacobian(Vec3 p, float* xUnwarped, float* yUnwarped, float* zUnwarped); + Vec3 WVelocityWithJacobian(const Vec3& p, float* xUnwarped, float* yUnwarped, float* zUnwarped); // access functions inline float* getDensityBig() { return _densityBig; } diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject c93ed11a47b3016cf59711ec16de2e2e94c30e9 +Subproject b3d9c97f487bff8b2423c903c14204ba5ca21a8 diff --git a/release/scripts/addons b/release/scripts/addons -Subproject 371960484a38fc64e0a2635170a41a0d8ab2f6b +Subproject 85a2b50e0e3d505f702a172efc0befa46e87d85 diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib -Subproject a8515cfdfe9a98127b592f36fcbe51b7e23b969 +Subproject c3991195ad6eac741db27dc9e8905efb224f219 diff --git a/release/scripts/modules/bpy_extras/anim_utils.py b/release/scripts/modules/bpy_extras/anim_utils.py index ea0bd77c0f0..75d2065a3d1 100644 --- a/release/scripts/modules/bpy_extras/anim_utils.py +++ b/release/scripts/modules/bpy_extras/anim_utils.py @@ -153,15 +153,29 @@ def bake_action_iter( # ------------------------------------------------------------------------- # Helper Functions and vars + # Note: BBONE_PROPS is a list so we can preserve the ordering + BBONE_PROPS = [ + 'bbone_curveinx', 'bbone_curveoutx', + 'bbone_curveiny', 'bbone_curveouty', + 'bbone_rollin', 'bbone_rollout', + 'bbone_scalein', 'bbone_scaleout', + 'bbone_easein', 'bbone_easeout' + ] + def pose_frame_info(obj): matrix = {} + bbones = {} for name, pbone in obj.pose.bones.items(): if do_visual_keying: # Get the final transform of the bone in its own local space... matrix[name] = obj.convert_space(pbone, pbone.matrix, 'POSE', 'LOCAL') else: matrix[name] = pbone.matrix_basis.copy() - return matrix + + # Bendy Bones + if pbone.bone.bbone_segments > 1: + bbones[name] = {bb_prop : getattr(pbone, bb_prop) for bb_prop in BBONE_PROPS} + return matrix, bbones if do_parents_clear: if do_visual_keying: @@ -214,7 +228,7 @@ def bake_action_iter( break if do_pose: - pose_info.append((frame, pose_frame_info(obj))) + pose_info.append((frame, *pose_frame_info(obj))) if do_object: obj_info.append((frame, obj_frame_info(obj))) @@ -255,7 +269,7 @@ def bake_action_iter( # create compatible eulers euler_prev = None - for (f, matrix) in pose_info: + for (f, matrix, bbones) in pose_info: pbone.matrix_basis = matrix[name].copy() pbone.keyframe_insert("location", -1, f, name, options) @@ -278,6 +292,14 @@ def bake_action_iter( pbone.keyframe_insert("scale", -1, f, name, options) + # Bendy Bones + if pbone.bone.bbone_segments > 1: + bbone_shape = bbones[name] + for bb_prop in BBONE_PROPS: + # update this property with value from bbone_shape, then key it + setattr(pbone, bb_prop, bbone_shape[bb_prop]) + pbone.keyframe_insert(bb_prop, -1, f, name, options) + # object. TODO. multiple objects if do_object: if do_constraint_clear: diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 2f3adf546b8..8093746c646 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -457,19 +457,19 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel): pbox.prop(ffmpeg, "max_b_frames", text="") pbox.enabled = ffmpeg.use_max_b_frames - split = layout.split() - split.enabled = ffmpeg.constant_rate_factor == 'NONE' - col = split.column() - col.label(text="Rate:") - col.prop(ffmpeg, "video_bitrate") - col.prop(ffmpeg, "minrate", text="Minimum") - col.prop(ffmpeg, "maxrate", text="Maximum") - col.prop(ffmpeg, "buffersize", text="Buffer") + if ffmpeg.constant_rate_factor == 'NONE': + split = layout.split() + col = split.column() + col.label(text="Rate:") + col.prop(ffmpeg, "video_bitrate") + col.prop(ffmpeg, "minrate", text="Minimum") + col.prop(ffmpeg, "maxrate", text="Maximum") + col.prop(ffmpeg, "buffersize", text="Buffer") - col = split.column() - col.label(text="Mux:") - col.prop(ffmpeg, "muxrate", text="Rate") - col.prop(ffmpeg, "packetsize", text="Packet Size") + col = split.column() + col.label(text="Mux:") + col.prop(ffmpeg, "muxrate", text="Rate") + col.prop(ffmpeg, "packetsize", text="Packet Size") layout.separator() @@ -477,10 +477,10 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel): if ffmpeg.format != 'MP3': layout.prop(ffmpeg, "audio_codec", text="Audio Codec") - row = layout.row() - row.enabled = ffmpeg.audio_codec != 'NONE' - row.prop(ffmpeg, "audio_bitrate") - row.prop(ffmpeg, "audio_volume", slider=True) + if ffmpeg.audio_codec != 'NONE': + row = layout.row() + row.prop(ffmpeg, "audio_bitrate") + row.prop(ffmpeg, "audio_volume", slider=True) class RENDER_PT_bake(RenderButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 1ca1da315b7..106e6695553 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -1128,6 +1128,8 @@ class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel): row.active = render.sequencer_gl_preview == 'SOLID' row.prop(render, "use_sequencer_gl_textured_solid") + col.prop(render, "use_sequencer_gl_dof") + class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel): bl_label = "View Settings" diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index c7e05a4173e..096c164d7d0 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1550,18 +1550,21 @@ class VIEW3D_MT_object_specials(Menu): layout.operator_context = 'INVOKE_REGION_WIN' if scene.render.use_shading_nodes: - try: - value = lamp.node_tree.nodes["Emission"].inputs["Strength"].default_value - except AttributeError: - value = None - - if value is not None: + emission_node = None + if lamp.node_tree: + for node in lamp.node_tree.nodes: + if getattr(node, "type", None) == 'EMISSION': + emission_node = node + break + + if emission_node is not None: props = layout.operator("wm.context_modal_mouse", text="Strength") props.data_path_iter = "selected_editable_objects" - props.data_path_item = "data.node_tree.nodes[\"Emission\"].inputs[\"Strength\"].default_value" + props.data_path_item = "data.node_tree" \ + ".nodes[\"" + emission_node.name + "\"]" \ + ".inputs[\"Strength\"].default_value" props.header_text = "Lamp Strength: %.3f" props.input_scale = 0.1 - del value if lamp.type == 'AREA': props = layout.operator("wm.context_modal_mouse", text="Size X") diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 12f15b8b90e..3792ac13d18 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -852,12 +852,12 @@ class VIEW3D_PT_tools_posemode(View3DPanel, Panel): draw_keyframing_tools(context, layout) - pchan = context.active_pose_bone - mpath = pchan.motion_path if pchan else None + ob = context.object + avs = ob.pose.animation_visualization col = layout.column(align=True) col.label(text="Motion Paths:") - if mpath: + if avs.motion_path.has_motion_paths: row = col.row(align=True) row.operator("pose.paths_update", text="Update") row.operator("pose.paths_clear", text="", icon='X') @@ -1810,12 +1810,6 @@ class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel): vpaint = toolsettings.vertex_paint col = layout.column() - col.label("Falloff:") - row = col.row() - row.prop(vpaint, "use_normal_falloff") - sub = row.row() - sub.active = (vpaint.use_normal_falloff) - sub.prop(vpaint, "normal_angle", text="") self.unified_paint_settings(col, context) diff --git a/source/blender/alembic/intern/abc_mball.h b/source/blender/alembic/intern/abc_mball.h index 46b61151216..9b943698416 100644 --- a/source/blender/alembic/intern/abc_mball.h +++ b/source/blender/alembic/intern/abc_mball.h @@ -25,7 +25,7 @@ #include "abc_object.h" -struct AbcMeshWriter; +class AbcMeshWriter; struct Main; struct MetaBall; struct Object; diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index ec0bfa6f5fa..647291382ef 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -48,10 +48,17 @@ void BKE_blender_version_string( char *version_str, size_t maxncpy, short version, short subversion, bool v_prefix, bool include_subversion); -void BKE_blender_userdef_set_data(struct UserDef *userdef); -void BKE_blender_userdef_free_data(struct UserDef *userdef); +void BKE_blender_userdef_data_swap(struct UserDef *userdef_dst, struct UserDef *userdef_src); +void BKE_blender_userdef_data_set(struct UserDef *userdef); +void BKE_blender_userdef_data_set_and_free(struct UserDef *userdef); -void BKE_blender_userdef_set_app_template(struct UserDef *userdef); +void BKE_blender_userdef_app_template_data_swap(struct UserDef *userdef_dst, struct UserDef *userdef_src); +void BKE_blender_userdef_app_template_data_set(struct UserDef *userdef); +void BKE_blender_userdef_app_template_data_set_and_free(struct UserDef *userdef); + +void BKE_blender_userdef_data_duplicate(struct UserDef *userdef_dst, struct UserDef *userdef_src); + +void BKE_blender_userdef_data_free(struct UserDef *userdef, bool clear_fonts); /* set this callback when a UI is running */ void BKE_blender_callback_test_break_set(void (*func)(void)); diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index ac58451e412..9ff164f60be 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -58,8 +58,8 @@ struct UserDef *BKE_blendfile_userdef_read_from_memory( const void *filebuf, int filelength, struct ReportList *reports); -int BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports); - +bool BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports); +bool BKE_blendfile_userdef_write_app_template(const char *filepath, struct ReportList *reports); /* partial blend file writing */ void BKE_blendfile_write_partial_tag_ID(struct ID *id, bool set); diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 657e99f05d1..6c9dc12b44f 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -421,11 +421,21 @@ struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seq struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); /* view3d draw callback, run when not in background view */ +/* NOTE: Keep in sync with V3D_OFSDRAW_* flags. */ +enum { + SEQ_OFSDRAW_NONE = (0), + SEQ_OFSDRAW_USE_BACKGROUND = (1 << 0), + SEQ_OFSDRAW_USE_FULL_SAMPLE = (1 << 1), + SEQ_OFSDRAW_USE_GPENCIL = (1 << 2), + SEQ_OFSDRAW_USE_SOLID_TEX = (1 << 2), + SEQ_OFSDRAW_USE_CAMERA_DOF = (1 << 3), +}; + typedef struct ImBuf *(*SequencerDrawView)( - struct Scene *, struct Object *, int, int, - unsigned int, int, bool, bool, bool, - int, int, bool, const char *, - struct GPUFX *, struct GPUOffScreen *, char[256]); + struct Scene *scene, struct Object *camera, int width, int height, + unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode, + int samples, const char *viewname, + struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]); extern SequencerDrawView sequencer_view3d_cb; /* copy/paste */ diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index f52bb2ab9cb..92170325113 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -125,6 +125,8 @@ typedef struct CCGDerivedMesh { struct CCGFace **gridFaces; struct DMFlagMat *gridFlagMats; unsigned int **gridHidden; + /* Elements in arrays above. */ + unsigned int numGrid; struct { struct MultiresModifierData *mmd; diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h deleted file mode 100644 index 7c1e0e97565..00000000000 --- a/source/blender/blenkernel/BKE_utildefines.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file BKE_utildefines.h - * \ingroup bke - * \brief blender format specific macros - * \note generic defines should go in BLI_utildefines.h - */ - - -#ifndef __BKE_UTILDEFINES_H__ -#define __BKE_UTILDEFINES_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define BKE_BIT_TEST_SET(value, test, flag) \ -{ \ - if (test) (value) |= flag; \ - else (value) &= ~flag; \ -} (void)0 - -#ifdef __cplusplus -} -#endif - -#endif /* __BKE_UTILDEFINES_H__ */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 74c69c5aeb9..96c653dee23 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -292,7 +292,6 @@ set(SRC BKE_texture.h BKE_tracking.h BKE_unit.h - BKE_utildefines.h BKE_world.h BKE_writeavi.h BKE_writeframeserver.h diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 6dd852c7875..8d4776dca0e 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -290,6 +290,33 @@ static bool get_path_user( } /** + * Special convenience exception for dev builds to allow overrides to the system path. + * With this, need for running 'make install' can be avoided, e.g. by symlinking SOURCE_DIR/release + * to EXECUTABLE_DIR/release, or by running Blender from source directory directly. + */ +static bool get_path_system_dev_build_exception( + char *targetpath, size_t targetpath_len, const char *relfolder) +{ + char cwd[FILE_MAX]; + + /* Try EXECUTABLE_DIR/release/folder_name. Allows symlinking release folder from source dir. */ + if (test_path(targetpath, targetpath_len, bprogdir, "release", relfolder)) { + return true; + } + /* Try CWD/release/folder_name. Allows executing Blender from any directory + * (usually source dir), even without a release dir in bprogdir. */ + if (BLI_current_working_dir(cwd, sizeof(cwd))) { + if (test_path(targetpath, targetpath_len, cwd, "release", relfolder)) { + return true; + } + } + /* never use if not existing. */ + targetpath[0] = '\0'; + + return false; +} + +/** * Returns the path of a folder within the Blender installation directory. * * \param targetpath String to return path @@ -305,7 +332,6 @@ static bool get_path_system( { char system_path[FILE_MAX]; const char *system_base_path; - char cwd[FILE_MAX]; char relfolder[FILE_MAX]; if (folder_name) { @@ -320,25 +346,9 @@ static bool get_path_system( relfolder[0] = '\0'; } - /* first allow developer only overrides to the system path - * these are only used when running blender from source */ - - /* try CWD/release/folder_name */ - if (BLI_current_working_dir(cwd, sizeof(cwd))) { - if (test_path(targetpath, targetpath_len, cwd, "release", relfolder)) { - return true; - } - } - /* try EXECUTABLE_DIR/release/folder_name */ - if (test_path(targetpath, targetpath_len, bprogdir, "release", relfolder)) { + if (get_path_system_dev_build_exception(targetpath, targetpath_len, relfolder)) { return true; } - /* never use if not existing. */ - targetpath[0] = '\0'; - - /* end developer overrides */ - - system_path[0] = '\0'; diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 2624019e63a..af46b6ec852 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -150,11 +150,21 @@ static void keymap_item_free(wmKeyMapItem *kmi) MEM_freeN(kmi->ptr); } -void BKE_blender_userdef_set_data(UserDef *userdef) +void BKE_blender_userdef_data_swap(UserDef *userdef_a, UserDef *userdef_b) { - /* only here free userdef themes... */ - BKE_blender_userdef_free_data(&U); - U = *userdef; + SWAP(UserDef, *userdef_a, *userdef_b); +} + +void BKE_blender_userdef_data_set(UserDef *userdef) +{ + BKE_blender_userdef_data_swap(&U, userdef); + BKE_blender_userdef_data_free(userdef, true); +} + +void BKE_blender_userdef_data_set_and_free(UserDef *userdef) +{ + BKE_blender_userdef_data_set(userdef); + MEM_freeN(userdef); } static void userdef_free_keymaps(UserDef *userdef) @@ -201,7 +211,7 @@ static void userdef_free_addons(UserDef *userdef) * When loading a new userdef from file, * or when exiting Blender. */ -void BKE_blender_userdef_free_data(UserDef *userdef) +void BKE_blender_userdef_data_free(UserDef *userdef, bool clear_fonts) { #define U _invalid_access_ /* ensure no accidental global access */ #ifdef U /* quiet warning */ @@ -210,12 +220,13 @@ void BKE_blender_userdef_free_data(UserDef *userdef) userdef_free_keymaps(userdef); userdef_free_addons(userdef); - for (uiFont *font = userdef->uifonts.first; font; font = font->next) { - BLF_unload_id(font->blf_id); + if (clear_fonts) { + for (uiFont *font = userdef->uifonts.first; font; font = font->next) { + BLF_unload_id(font->blf_id); + } + BLF_default_set(-1); } - BLF_default_set(-1); - BLI_freelistN(&userdef->autoexec_paths); BLI_freelistN(&userdef->uistyles); @@ -229,38 +240,55 @@ void BKE_blender_userdef_free_data(UserDef *userdef) * Write U from userdef. * This function defines which settings a template will override for the user preferences. */ -void BKE_blender_userdef_set_app_template(UserDef *userdef) +void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *userdef_b) { /* TODO: * - keymaps * - various minor settings (add as needed). */ -#define LIST_OVERRIDE(id) { \ - BLI_freelistN(&U.id); \ - BLI_movelisttolist(&U.id, &userdef->id); \ -} ((void)0) +#define DATA_SWAP(id) \ + { \ + UserDef userdef_tmp; \ + memcpy(&(userdef_tmp.id), &(userdef_a->id), sizeof(userdef_tmp.id)); \ + memcpy(&(userdef_a->id), &(userdef_b->id), sizeof(userdef_tmp.id)); \ + memcpy(&(userdef_b->id), &(userdef_tmp.id), sizeof(userdef_tmp.id)); \ + } -#define MEMCPY_OVERRIDE(id) \ - memcpy(U.id, userdef->id, sizeof(U.id)); +#define LIST_SWAP(id) { \ + SWAP(ListBase, userdef_a->id, userdef_b->id); \ +} ((void)0) /* for some types we need custom free functions */ - userdef_free_addons(&U); - userdef_free_keymaps(&U); + LIST_SWAP(addons); + LIST_SWAP(user_keymaps); + + LIST_SWAP(uistyles); + LIST_SWAP(uifonts); + LIST_SWAP(themes); + LIST_SWAP(addons); + LIST_SWAP(user_keymaps); + + DATA_SWAP(light); - LIST_OVERRIDE(uistyles); - LIST_OVERRIDE(uifonts); - LIST_OVERRIDE(themes); - LIST_OVERRIDE(addons); - LIST_OVERRIDE(user_keymaps); + DATA_SWAP(font_path_ui); + DATA_SWAP(font_path_ui_mono); - MEMCPY_OVERRIDE(light); +#undef SWAP_TYPELESS +#undef LIST_SWAP +#undef DATA_SWAP +} - MEMCPY_OVERRIDE(font_path_ui); - MEMCPY_OVERRIDE(font_path_ui_mono); +void BKE_blender_userdef_app_template_data_set(UserDef *userdef) +{ + BKE_blender_userdef_app_template_data_swap(&U, userdef); + BKE_blender_userdef_data_free(userdef, true); +} -#undef LIST_OVERRIDE -#undef MEMCPY_OVERRIDE +void BKE_blender_userdef_app_template_data_set_and_free(UserDef *userdef) +{ + BKE_blender_userdef_app_template_data_set(userdef); + MEM_freeN(userdef); } /* ***************** testing for break ************* */ diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 980df05aca2..cc992a4a520 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -226,11 +226,9 @@ static void setup_app_data( CTX_data_main_set(C, G.main); if (bfd->user) { - /* only here free userdef themes... */ - BKE_blender_userdef_free_data(&U); - - U = *bfd->user; + BKE_blender_userdef_data_set_and_free(bfd->user); + bfd->user = NULL; /* Security issue: any blend file could include a USER block. * @@ -241,8 +239,6 @@ static void setup_app_data( * enable scripts auto-execution by loading a '.blend' file. */ U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; - - MEM_freeN(bfd->user); } /* case G_FILE_NO_UI or no screens in file */ @@ -497,21 +493,48 @@ UserDef *BKE_blendfile_userdef_read_from_memory( } -/* only write the userdef in a .blend */ -int BKE_blendfile_userdef_write(const char *filepath, ReportList *reports) +/** + * Only write the userdef in a .blend + * \return success + */ +bool BKE_blendfile_userdef_write(const char *filepath, ReportList *reports) { Main *mainb = MEM_callocN(sizeof(Main), "empty main"); - int retval = 0; + bool ok = false; if (BLO_write_file(mainb, filepath, G_FILE_USERPREFS, reports, NULL)) { - retval = 1; + ok = true; } MEM_freeN(mainb); - return retval; + return ok; } +/** + * Only write the userdef in a .blend, merging with the existing blend file. + * \return success + * + * \note In the future we should re-evaluate user preferences, + * possibly splitting out system/hardware specific prefs. + */ +bool BKE_blendfile_userdef_write_app_template(const char *filepath, ReportList *reports) +{ + /* if it fails, overwrite is OK. */ + UserDef *userdef_default = BKE_blendfile_userdef_read(filepath, NULL); + if (userdef_default == NULL) { + return BKE_blendfile_userdef_write(filepath, reports); + } + + BKE_blender_userdef_app_template_data_swap(&U, userdef_default); + bool ok = BKE_blendfile_userdef_write(filepath, reports); + BKE_blender_userdef_app_template_data_swap(&U, userdef_default); + BKE_blender_userdef_data_free(userdef_default, false); + MEM_freeN(userdef_default); + return ok; +} + + /** \} */ diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index 79b3f89da20..8018629ef2a 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -52,11 +52,10 @@ #include "MEM_guardedalloc.h" #include "IMB_imbuf_types.h" -#include "BKE_bmfont.h" -#include "BKE_bmfont_types.h" - #include "BLI_utildefines.h" +#include "BKE_bmfont.h" +#include "BKE_bmfont_types.h" #include "BKE_global.h" void printfGlyph(bmGlyph *glyph) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index ee25be36855..21e28f5180c 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -801,8 +801,8 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa if ( cloth->bvhselftree ) { // search for overlapping collision pairs overlap = BLI_bvhtree_overlap(cloth->bvhselftree, cloth->bvhselftree, &result, NULL, NULL); - - // #pragma omp parallel for private(k, i, j) schedule(static) + + /* Could be parallelized (using BLI_task)... */ for ( k = 0; k < result; k++ ) { float temp[3]; float length = 0; @@ -1147,9 +1147,10 @@ static CollPair *cloth_point_collision( return collpair; } -static void cloth_points_objcollisions_nearcheck(ClothModifierData * clmd, CollisionModifierData *collmd, - CollPair **collisions, CollPair **collisions_index, - int numresult, BVHTreeOverlap *overlap, float epsilon, double dt) +static void cloth_points_objcollisions_nearcheck( + ClothModifierData *clmd, CollisionModifierData *collmd, + CollPair **collisions, CollPair **collisions_index, + int numresult, BVHTreeOverlap *overlap, float epsilon, double dt) { int i; @@ -1163,8 +1164,9 @@ static void cloth_points_objcollisions_nearcheck(ClothModifierData * clmd, Colli } } -static int cloth_points_objcollisions_resolve(ClothModifierData * clmd, CollisionModifierData *collmd, PartDeflect *pd, - CollPair *collisions, CollPair *collisions_index, float dt) +static int cloth_points_objcollisions_resolve( + ClothModifierData *clmd, CollisionModifierData *collmd, PartDeflect *pd, + CollPair *collisions, CollPair *collisions_index, float dt) { Cloth *cloth = clmd->clothObject; int i = 0, mvert_num = clmd->clothObject->mvert_num; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 382b26abbc6..9c85a26b58a 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1775,7 +1775,7 @@ void driver_variable_name_validate(DriverVar *dvar) /* 1) Must start with a letter */ /* XXX: We assume that valid unicode letters in other languages are ok too, hence the blacklisting */ - if (ELEM(dvar->name[0], '0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) { + if (IN_RANGE_INCL(dvar->name[0], '0', '9')) { dvar->flag |= DVAR_FLAG_INVALID_START_NUM; } else if (dvar->name[0] == '_') { diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c index e45a938a4fc..686fe3bda93 100644 --- a/source/blender/blenkernel/intern/freestyle.c +++ b/source/blender/blenkernel/intern/freestyle.c @@ -34,14 +34,14 @@ #include "DNA_freestyle_types.h" #include "DNA_group_types.h" -#include "BKE_freestyle.h" -#include "BKE_library.h" -#include "BKE_linestyle.h" - #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_string_utils.h" +#include "BKE_freestyle.h" +#include "BKE_library.h" +#include "BKE_linestyle.h" + // function declarations static FreestyleLineSet *alloc_lineset(void); static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset, const int flag); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 7e259b38842..b84a494c70e 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -2383,10 +2383,10 @@ void BKE_library_filepath_set(Library *lib, const char *filepath) void BKE_id_tag_set_atomic(ID *id, int tag) { - atomic_fetch_and_or_uint32((uint32_t *)&id->tag, tag); + atomic_fetch_and_or_int32(&id->tag, tag); } void BKE_id_tag_clear_atomic(ID *id, int tag) { - atomic_fetch_and_and_uint32((uint32_t *)&id->tag, ~tag); + atomic_fetch_and_and_int32(&id->tag, ~tag); } diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 13ec970c65c..104bb0c07a6 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -80,6 +80,7 @@ #include "BLI_math.h" #include "BLI_rect.h" +#include "BLI_task.h" #include "BLI_listbase.h" #include "BLI_linklist.h" @@ -1423,15 +1424,39 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x return value; } + +typedef struct MaskRasterizeBufferData { + MaskRasterHandle *mr_handle; + float x_inv, y_inv; + float x_px_ofs, y_px_ofs; + uint width; + + float *buffer; +} MaskRasterizeBufferData; + +static void maskrasterize_buffer_cb(void *userdata, int y) +{ + MaskRasterizeBufferData *data = userdata; + + MaskRasterHandle *mr_handle = data->mr_handle; + float *buffer = data->buffer; + + const uint width = data->width; + const float x_inv = data->x_inv; + const float x_px_ofs = data->x_px_ofs; + + uint i = (uint)y * width; + float xy[2]; + xy[1] = ((float)y * data->y_inv) + data->y_px_ofs; + for (uint x = 0; x < width; x++, i++) { + xy[0] = ((float)x * x_inv) + x_px_ofs; + + buffer[i] = BKE_maskrasterize_handle_sample(mr_handle, xy); + } +} + /** - * \brief Rasterize a buffer from a single mask - * - * We could get some speedup by inlining #BKE_maskrasterize_handle_sample - * and calculating each layer then blending buffers, but this function is only - * used by the sequencer - so better have the caller thread. - * - * Since #BKE_maskrasterize_handle_sample is used threaded elsewhere, - * we can simply use openmp here for some speedup. + * \brief Rasterize a buffer from a single mask (threaded execution). */ void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle, const unsigned int width, const unsigned int height, @@ -1439,33 +1464,15 @@ void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle, { const float x_inv = 1.0f / (float)width; const float y_inv = 1.0f / (float)height; - const float x_px_ofs = x_inv * 0.5f; - const float y_px_ofs = y_inv * 0.5f; -#ifdef _MSC_VER - int y; /* msvc requires signed for some reason */ - - /* ignore sign mismatch */ -# pragma warning(push) -# pragma warning(disable:4018) -#else - unsigned int y; -#endif - -#pragma omp parallel for private(y) - for (y = 0; y < height; y++) { - unsigned int i = y * width; - unsigned int x; - float xy[2]; - xy[1] = ((float)y * y_inv) + y_px_ofs; - for (x = 0; x < width; x++, i++) { - xy[0] = ((float)x * x_inv) + x_px_ofs; - - buffer[i] = BKE_maskrasterize_handle_sample(mr_handle, xy); - } - } - -#ifdef _MSC_VER -# pragma warning(pop) -#endif + MaskRasterizeBufferData data = { + .mr_handle = mr_handle, + .x_inv = x_inv, + .y_inv = y_inv, + .x_px_ofs = x_inv * 0.5f, + .y_px_ofs = y_inv * 0.5f, + .width = width, + .buffer = buffer + }; + BLI_task_parallel_range(0, (int)height, &data, maskrasterize_buffer_cb, height * width > 10000); } diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index b0580f75044..f321c94bf00 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -1482,6 +1482,7 @@ void BKE_mesh_remap_calc_loops_from_dm( for (i = vert_to_refelem_map_src[nearest.index].count; i--;) { const int index_src = vert_to_refelem_map_src[nearest.index].indices[i]; + BLI_assert(index_src != -1); const float dot = dot_v3v3(nors_src[index_src], *nor_dst); pidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ? @@ -1522,7 +1523,12 @@ void BKE_mesh_remap_calc_loops_from_dm( } } } - if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { + if (best_index_src == -1) { + /* We found no item to map back from closest vertex... */ + best_nor_dot = -1.0f; + hit_dist = FLT_MAX; + } + else if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { /* Our best_index_src is a poly one for now! * Have to find its loop matching our closest vertex. */ mp_src = &polys_src[best_index_src]; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index c64a183a511..f231f8f61c9 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -330,14 +330,14 @@ void BKE_object_free_derived_caches(Object *ob) Mesh *me = ob->data; if (me && me->bb) { - atomic_fetch_and_or_uint32((uint *)&me->bb->flag, BOUNDBOX_DIRTY); + atomic_fetch_and_or_int32(&me->bb->flag, BOUNDBOX_DIRTY); } } else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { Curve *cu = ob->data; if (cu && cu->bb) { - atomic_fetch_and_or_uint32((uint *)&cu->bb->flag, BOUNDBOX_DIRTY); + atomic_fetch_and_or_int32(&cu->bb->flag, BOUNDBOX_DIRTY); } } diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c index f31ba34a984..4d97121e2a3 100644 --- a/source/blender/blenkernel/intern/outliner_treehash.c +++ b/source/blender/blenkernel/intern/outliner_treehash.c @@ -28,14 +28,14 @@ #include <stdlib.h> -#include "BKE_outliner_treehash.h" - #include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_mempool.h" #include "DNA_outliner_types.h" +#include "BKE_outliner_treehash.h" + #include "MEM_guardedalloc.h" typedef struct TseGroup { diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index aa8ab07518f..39d1d8e8510 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1007,9 +1007,7 @@ static void pbvh_update_normals_store_task_cb(void *userdata, const int n) MVert *mvert = &bvh->verts[v]; /* mvert is shared between nodes, hence between threads. */ - if (atomic_fetch_and_and_uint8( - (uint8_t *)&mvert->flag, (uint8_t)~ME_VERT_PBVH_UPDATE) & ME_VERT_PBVH_UPDATE) - { + if (atomic_fetch_and_and_char(&mvert->flag, (char)~ME_VERT_PBVH_UPDATE) & ME_VERT_PBVH_UPDATE) { normalize_v3(vnors[v]); normal_float_to_short_v3(mvert->no, vnors[v]); } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 9b0db300e6d..9e8e202c2bc 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3295,11 +3295,18 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) { char err_out[256] = "unknown"; - int width = (scene->r.xsch * scene->r.size) / 100; - int height = (scene->r.ysch * scene->r.size) / 100; + const int width = (scene->r.xsch * scene->r.size) / 100; + const int height = (scene->r.ysch * scene->r.size) / 100; const bool use_background = (scene->r.alphamode == R_ADDSKY); const char *viewname = BKE_scene_multiview_render_view_name_get(&scene->r, context->view_id); + unsigned int draw_flags = SEQ_OFSDRAW_NONE; + draw_flags |= (use_gpencil) ? SEQ_OFSDRAW_USE_GPENCIL : 0; + draw_flags |= (use_background) ? SEQ_OFSDRAW_USE_BACKGROUND : 0; + draw_flags |= (context->gpu_full_samples) ? SEQ_OFSDRAW_USE_FULL_SAMPLE : 0; + draw_flags |= (context->scene->r.seq_flag & R_SEQ_SOLID_TEX) ? SEQ_OFSDRAW_USE_SOLID_TEX : 0; + draw_flags |= (context->scene->r.seq_flag & R_SEQ_CAMERA_DOF) ? SEQ_OFSDRAW_USE_CAMERA_DOF : 0; + /* for old scene this can be uninitialized, * should probably be added to do_versions at some point if the functionality stays */ if (context->scene->r.seq_prev_type == 0) @@ -3309,11 +3316,8 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay); ibuf = sequencer_view3d_cb( /* set for OpenGL render (NULL when scrubbing) */ - scene, camera, width, height, IB_rect, - context->scene->r.seq_prev_type, - (context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0, - use_gpencil, use_background, scene->r.alphamode, - context->gpu_samples, context->gpu_full_samples, viewname, + scene, camera, width, height, IB_rect, draw_flags, context->scene->r.seq_prev_type, + scene->r.alphamode, context->gpu_samples, viewname, context->gpu_fx, context->gpu_offscreen, err_out); if (ibuf == NULL) { fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 0cdc97c829f..f8025f8df84 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -4031,10 +4031,12 @@ static void ccgDM_release(DerivedMesh *dm) if (ccgdm->gridOffset) MEM_freeN(ccgdm->gridOffset); if (ccgdm->gridFlagMats) MEM_freeN(ccgdm->gridFlagMats); if (ccgdm->gridHidden) { - int i, numGrids = dm->getNumGrids(dm); - for (i = 0; i < numGrids; i++) { - if (ccgdm->gridHidden[i]) + /* Using dm->getNumGrids(dm) accesses freed memory */ + uint numGrids = ccgdm->numGrid; + for (uint i = 0; i < numGrids; i++) { + if (ccgdm->gridHidden[i]) { MEM_freeN(ccgdm->gridHidden[i]); + } } MEM_freeN(ccgdm->gridHidden); } @@ -4338,6 +4340,7 @@ static void ccgdm_create_grids(DerivedMesh *dm) ccgdm->gridFaces = gridFaces; ccgdm->gridOffset = gridOffset; ccgdm->gridFlagMats = gridFlagMats; + ccgdm->numGrid = numGrids; } static CCGElem **ccgDM_getGridData(DerivedMesh *dm) diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 30981ed8f23..4ff4a129768 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -30,6 +30,7 @@ */ #include <stdlib.h> +#include "atomic_ops.h" #include "MEM_guardedalloc.h" @@ -38,6 +39,7 @@ #include "BLI_utildefines.h" #include "BLI_listbase.h" +#include "BLI_task.h" #include "BLI_threads.h" #include "BLI_math.h" @@ -86,6 +88,8 @@ typedef struct AutoTrackContext { int sync_frame; bool first_sync; SpinLock spin_lock; + + bool step_ok; } AutoTrackContext; static void normalized_to_libmv_frame(const float normalized[2], @@ -379,81 +383,94 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip, return context; } -bool BKE_autotrack_context_step(AutoTrackContext *context) +static void autotrack_context_step_cb(void *userdata, int track) { + AutoTrackContext *context = userdata; const int frame_delta = context->backwards ? -1 : 1; - bool ok = false; - int track; - -#pragma omp parallel for if (context->num_tracks > 1) - for (track = 0; track < context->num_tracks; ++track) { - AutoTrackOptions *options = &context->options[track]; - if (options->is_failed) { - continue; - } - libmv_Marker libmv_current_marker, - libmv_reference_marker, - libmv_tracked_marker; - libmv_TrackRegionResult libmv_result; - const int frame = BKE_movieclip_remap_scene_to_clip_frame( - context->clips[options->clip_index], - context->user.framenr); + + AutoTrackOptions *options = &context->options[track]; + if (options->is_failed) { + return; + } + libmv_Marker libmv_current_marker, + libmv_reference_marker, + libmv_tracked_marker; + libmv_TrackRegionResult libmv_result; + const int frame = BKE_movieclip_remap_scene_to_clip_frame( + context->clips[options->clip_index], + context->user.framenr); + BLI_spin_lock(&context->spin_lock); + const bool has_marker = libmv_autoTrackGetMarker(context->autotrack, + options->clip_index, + frame, + options->track_index, + &libmv_current_marker); + BLI_spin_unlock(&context->spin_lock); + /* Check whether we've got marker to sync with. */ + if (!has_marker) { + return; + } + /* Check whether marker is going outside of allowed frame margin. */ + if (!tracking_check_marker_margin(&libmv_current_marker, + options->track->margin, + context->frame_width, + context->frame_height)) + { + return; + } + libmv_tracked_marker = libmv_current_marker; + libmv_tracked_marker.frame = frame + frame_delta; + /* Update reference frame. */ + if (options->use_keyframe_match) { + libmv_tracked_marker.reference_frame = + libmv_current_marker.reference_frame; + libmv_autoTrackGetMarker(context->autotrack, + options->clip_index, + libmv_tracked_marker.reference_frame, + options->track_index, + &libmv_reference_marker); + } + else { + libmv_tracked_marker.reference_frame = frame; + libmv_reference_marker = libmv_current_marker; + } + /* Perform actual tracking. */ + if (libmv_autoTrackMarker(context->autotrack, + &options->track_region_options, + &libmv_tracked_marker, + &libmv_result)) + { BLI_spin_lock(&context->spin_lock); - const bool has_marker = libmv_autoTrackGetMarker(context->autotrack, - options->clip_index, - frame, - options->track_index, - &libmv_current_marker); + libmv_autoTrackAddMarker(context->autotrack, &libmv_tracked_marker); BLI_spin_unlock(&context->spin_lock); - /* Check whether we've got marker to sync with. */ - if (!has_marker) { - continue; - } - /* Check whether marker is going outside of allowed frame margin. */ - if (!tracking_check_marker_margin(&libmv_current_marker, - options->track->margin, - context->frame_width, - context->frame_height)) - { - continue; - } - libmv_tracked_marker = libmv_current_marker; - libmv_tracked_marker.frame = frame + frame_delta; - /* Update reference frame. */ - if (options->use_keyframe_match) { - libmv_tracked_marker.reference_frame = - libmv_current_marker.reference_frame; - libmv_autoTrackGetMarker(context->autotrack, - options->clip_index, - libmv_tracked_marker.reference_frame, - options->track_index, - &libmv_reference_marker); - } - else { - libmv_tracked_marker.reference_frame = frame; - libmv_reference_marker = libmv_current_marker; - } - /* Perform actual tracking. */ - if (libmv_autoTrackMarker(context->autotrack, - &options->track_region_options, - &libmv_tracked_marker, - &libmv_result)) - { - BLI_spin_lock(&context->spin_lock); - libmv_autoTrackAddMarker(context->autotrack, &libmv_tracked_marker); - BLI_spin_unlock(&context->spin_lock); - } - else { - options->is_failed = true; - options->failed_frame = frame + frame_delta; - } - ok = true; } + else { + options->is_failed = true; + options->failed_frame = frame + frame_delta; + } + + /* Note: Atomic is probably not actually needed here, I doubt we could get + * any other result than a true bool anyway. + * But for sake of consistency, and since it costs nothing... + */ + atomic_fetch_and_or_uint8((uint8_t *)&context->step_ok, true); +} + +bool BKE_autotrack_context_step(AutoTrackContext *context) +{ + const int frame_delta = context->backwards ? -1 : 1; + context->step_ok = false; + + BLI_task_parallel_range(0, context->num_tracks, + context, + autotrack_context_step_cb, + context->num_tracks > 1); + /* Advance the frame. */ BLI_spin_lock(&context->spin_lock); context->user.framenr += frame_delta; BLI_spin_unlock(&context->spin_lock); - return ok; + return context->step_ok; } void BKE_autotrack_context_sync(AutoTrackContext *context) @@ -555,8 +572,9 @@ void BKE_autotrack_context_finish(AutoTrackContext *context) if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { int track; for (track = 0; track < context->num_tracks; ++track) { - if (BKE_tracking_plane_track_has_point_track(plane_track, - context->options[track].track)) + if (BKE_tracking_plane_track_has_point_track( + plane_track, + context->options[track].track)) { BKE_tracking_track_plane_from_existing_motion( plane_track, diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index b8dfb217c16..edddeb41cc8 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -41,13 +41,14 @@ #include "BLI_utildefines.h" #include "BLI_sort_utils.h" +#include "BLI_ghash.h" #include "BLI_math_vector.h" #include "BLI_math.h" +#include "BLI_task.h" #include "BKE_tracking.h" #include "BKE_movieclip.h" #include "BKE_fcurve.h" -#include "BLI_ghash.h" #include "MEM_guardedalloc.h" #include "IMB_imbuf_types.h" @@ -1491,6 +1492,35 @@ void BKE_tracking_stabilization_data_get(MovieClip *clip, discard_stabilization_working_context(ctx); } + +typedef void (*interpolation_func)(struct ImBuf *, struct ImBuf *, float, float, int, int); + +typedef struct TrackingStabilizeFrameInterpolationData { + ImBuf *ibuf; + ImBuf *tmpibuf; + float (*mat)[4]; + + interpolation_func interpolation; +} TrackingStabilizeFrameInterpolationData; + +static void tracking_stabilize_frame_interpolation_cb(void *userdata, int j) +{ + TrackingStabilizeFrameInterpolationData *data = userdata; + ImBuf *ibuf = data->ibuf; + ImBuf *tmpibuf = data->tmpibuf; + float (*mat)[4] = data->mat; + + interpolation_func interpolation = data->interpolation; + + for (int i = 0; i < tmpibuf->x; i++) { + float vec[3] = {i, j, 0.0f}; + + mul_v3_m4v3(vec, mat, vec); + + interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j); + } +} + /* Stabilize given image buffer using stabilization data for a specified * frame number. * @@ -1511,8 +1541,8 @@ ImBuf *BKE_tracking_stabilize_frame(MovieClip *clip, int width = ibuf->x, height = ibuf->y; float pixel_aspect = tracking->camera.pixel_aspect; float mat[4][4]; - int j, filter = tracking->stabilization.filter; - void (*interpolation)(struct ImBuf *, struct ImBuf *, float, float, int, int) = NULL; + int filter = tracking->stabilization.filter; + interpolation_func interpolation = NULL; int ibuf_flags; if (translation) @@ -1563,24 +1593,14 @@ ImBuf *BKE_tracking_stabilize_frame(MovieClip *clip, /* fallback to default interpolation method */ interpolation = nearest_interpolation; - /* This function is only used for display in clip editor and - * sequencer only, which would only benefit of using threads - * here. - * - * But need to keep an eye on this if the function will be - * used in other cases. - */ -#pragma omp parallel for if (tmpibuf->y > 128) - for (j = 0; j < tmpibuf->y; j++) { - int i; - for (i = 0; i < tmpibuf->x; i++) { - float vec[3] = {i, j, 0.0f}; - - mul_v3_m4v3(vec, mat, vec); - - interpolation(ibuf, tmpibuf, vec[0], vec[1], i, j); - } - } + TrackingStabilizeFrameInterpolationData data = { + .ibuf = ibuf, .tmpibuf = tmpibuf, .mat = mat, + .interpolation = interpolation + }; + BLI_task_parallel_range(0, tmpibuf->y, + &data, + tracking_stabilize_frame_interpolation_cb, + tmpibuf->y > 128); if (tmpibuf->rect_float) tmpibuf->userflags |= IB_RECT_INVALID; diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index b42a36a3567..2720c0058b7 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -257,6 +257,10 @@ void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp, const unsigned int nentries_reserve); void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp); +/* When set's are used for key & value. */ +void *BLI_gset_lookup(GSet *gh, const void *key) ATTR_WARN_UNUSED_RESULT; +void *BLI_gset_pop_key(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT; + GSet *BLI_gset_ptr_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; GSet *BLI_gset_ptr_new(const char *info); GSet *BLI_gset_str_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index b06944e4985..1e931e6f0d7 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -50,12 +50,14 @@ void *BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED void *BLI_findstring(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); void *BLI_findstring_ptr(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); void *BLI_findptr(const struct ListBase *listbase, const void *ptr, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +void *BLI_listbase_bytes_find(const ListBase *listbase, const void *bytes, const size_t bytes_size, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2); /* find backwards */ void *BLI_rfindlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); void *BLI_rfindstring(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); void *BLI_rfindstring_ptr(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); void *BLI_rfindptr(const struct ListBase *listbase, const void *ptr, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +void *BLI_listbase_bytes_rfind(const ListBase *listbase, const void *bytes, const size_t bytes_size, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2); void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1); void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1); @@ -77,6 +79,7 @@ int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1); void BLI_listbase_swaplinks(struct ListBase *listbase, void *vlinka, void *vlinkb) ATTR_NONNULL(1, 2); +void BLI_listbases_swaplinks(struct ListBase *listbasea, struct ListBase *listbaseb, void *vlinka, void *vlinkb) ATTR_NONNULL(2, 3); void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1, 2); void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1, 2); diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 5e6b1256d30..34fc52c12c0 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -141,7 +141,11 @@ MINLINE void float_to_byte_dither_v3(unsigned char b[3], const float f[3], float #define rgba_char_args_set_fl(col, r, g, b, a) \ rgba_char_args_set(col, (r) * 255, (g) * 255, (b) * 255, (a) * 255) +#define rgba_float_args_set_ch(col, r, g, b, a) \ + rgba_float_args_set(col, (r) / 255.0f, (g) / 255.0f, (b) / 255.0f, (a) / 255.0f) + MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const char b, const char a); +MINLINE void rgba_float_args_set(float col[4], const float r, const float g, const float b, const float a); MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, const char b, const char a); MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack); diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index d0dfad2a02f..173ef6861e6 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -210,6 +210,7 @@ void scale_m4_fl(float R[4][4], float scale); float mat3_to_scale(float M[3][3]); float mat4_to_scale(float M[4][4]); +float mat4_to_xy_scale(float M[4][4]); void size_to_mat3(float R[3][3], const float size[3]); void size_to_mat4(float R[4][4], const float size[3]); diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 4fdb33926a2..3f603311530 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -151,6 +151,7 @@ MINLINE void negate_v3_short(short r[3]); MINLINE void negate_v3_db(double r[3]); MINLINE void invert_v2(float r[2]); +MINLINE void invert_v3(float r[3]); MINLINE void abs_v2(float r[2]); MINLINE void abs_v2_v2(float r[2], const float a[2]); @@ -311,6 +312,7 @@ void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]); void ortho_v3_v3(float out[3], const float v[3]); void ortho_v2_v2(float out[2], const float v[2]); void bisect_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3]); +void rotate_v2_v2fl(float r[2], const float p[2], const float angle); void rotate_v3_v3v3fl(float v[3], const float p[3], const float axis[3], const float angle); void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], const float angle); @@ -326,6 +328,7 @@ void print_vn(const char *str, const float v[], const int n); #define print_v4_id(v) print_v4(STRINGIFY(v), v) #define print_vn_id(v, n) print_vn(STRINGIFY(v), v, n) +MINLINE void normal_float_to_short_v2(short r[2], const float n[2]); MINLINE void normal_short_to_float_v3(float r[3], const short n[3]); MINLINE void normal_float_to_short_v3(short r[3], const float n[3]); diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h index 0c754f551e0..b68ca6b1f2b 100644 --- a/source/blender/blenlib/BLI_mempool.h +++ b/source/blender/blenlib/BLI_mempool.h @@ -71,6 +71,8 @@ typedef struct BLI_mempool_iter { BLI_mempool *pool; struct BLI_mempool_chunk *curchunk; unsigned int curindex; + + struct BLI_mempool_chunk **curchunk_threaded_shared; } BLI_mempool_iter; /* flag */ @@ -87,6 +89,9 @@ enum { void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) ATTR_NONNULL(); void *BLI_mempool_iterstep(BLI_mempool_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +BLI_mempool_iter *BLI_mempool_iter_threadsafe_create(BLI_mempool *pool, const size_t num_iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BLI_mempool_iter_threadsafe_free(BLI_mempool_iter *iter_arr) ATTR_NONNULL(); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index f36d2faa1b8..69b23b2473f 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -101,4 +101,16 @@ RNG_THREAD_ARRAY *BLI_rng_threaded_new(void); void BLI_rng_threaded_free(struct RNG_THREAD_ARRAY *rngarr) ATTR_NONNULL(1); int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread) ATTR_WARN_UNUSED_RESULT; +/** Low-discrepancy sequences **/ + +/** Return the _n_th number of the given low-discrepancy sequence. */ +void BLI_halton_1D(unsigned int prime, double offset, int n, double *r); +void BLI_halton_2D(unsigned int prime[2], double offset[2], int n, double *r); +void BLI_halton_3D(unsigned int prime[3], double offset[3], int n, double *r); +void BLI_hammersley_1D(unsigned int n, double *r); + +/** Return the whole low-discrepancy sequence up to _n_. */ +void BLI_halton_2D_sequence(unsigned int prime[2], double offset[2], int n, double *r); +void BLI_hammersley_2D_sequence(unsigned int n, double *r); + #endif /* __BLI_RAND_H__ */ diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index 721327d26a8..ccfa2b6e2e7 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -35,6 +35,8 @@ extern "C" { #include "BLI_threads.h" #include "BLI_utildefines.h" +struct BLI_mempool; + /* Task Scheduler * * Central scheduler that holds running threads ready to execute tasks. A single @@ -150,6 +152,15 @@ void BLI_task_parallel_listbase( TaskParallelListbaseFunc func, const bool use_threading); +typedef struct MempoolIterData MempoolIterData; +typedef void (*TaskParallelMempoolFunc)(void *userdata, + MempoolIterData *iter); +void BLI_task_parallel_mempool( + struct BLI_mempool *mempool, + void *userdata, + TaskParallelMempoolFunc func, + const bool use_threading); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 0b1b4d8ee8c..60da6b39cbe 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -111,8 +111,10 @@ void BLI_mutex_unlock(ThreadMutex *mutex); /* Spin Lock */ -#ifdef __APPLE__ +#if defined(__APPLE__) typedef OSSpinLock SpinLock; +#elif defined(_MSC_VER) +typedef volatile int SpinLock; #else typedef pthread_spinlock_t SpinLock; #endif diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 66c7f247f61..ee1acc5afdd 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -509,6 +509,16 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size); #define SET_UINT_IN_POINTER(i) ((void *)(uintptr_t)(i)) #define GET_UINT_FROM_POINTER(i) ((void)0, ((unsigned int)(uintptr_t)(i))) +/* Set flag from a single test */ +#define SET_FLAG_FROM_TEST(value, test, flag) \ +{ \ + if (test) { \ + (value) |= (flag); \ + } \ + else { \ + (value) &= ~(flag); \ + } \ +} ((void)0) /* Macro to convert a value to string in the preprocessor * STRINGIFY_ARG: gives the argument as a string @@ -609,6 +619,9 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size); /* BLI_assert(), default only to print * for aborting need to define WITH_ASSERT_ABORT */ +/* For 'abort' only. */ +#include <stdlib.h> + #ifndef NDEBUG # include "BLI_system.h" # ifdef WITH_ASSERT_ABORT @@ -647,10 +660,29 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size); (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */ # define BLI_STATIC_ASSERT(a, msg) __extension__ _Static_assert(a, msg); #else - /* TODO msvc, clang */ -# define BLI_STATIC_ASSERT(a, msg) +/* Code adapted from http://www.pixelbeat.org/programming/gcc/static_assert.html */ +/* Note we need the two concats below because arguments to ## are not expanded, so we need to + * expand __LINE__ with one indirection before doing the actual concatenation. */ +# define ASSERT_CONCAT_(a, b) a##b +# define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) + /* These can't be used after statements in c89. */ +# if defined(__COUNTER__) /* MSVC */ +# define BLI_STATIC_ASSERT(a, msg) \ + ; enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1 / (int)(!!(a)) }; +# else /* older gcc, clang... */ + /* This can't be used twice on the same line so ensure if using in headers + * that the headers are not included twice (by wrapping in #ifndef...#endif) + * Note it doesn't cause an issue when used on same line of separate modules + * compiled with gcc -combine -fwhole-program. */ +# define BLI_STATIC_ASSERT(a, msg) \ + ; enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1 / (int)(!!(a)) }; +# endif #endif + +#define BLI_STATIC_ASSERT_ALIGN(st, align) \ + BLI_STATIC_ASSERT((sizeof(st) % (align) == 0), "Structure must be strictly aligned") + /* hints for branch prediction, only use in code that runs a _lot_ where */ #ifdef __GNUC__ # define LIKELY(x) __builtin_expect(!!(x), 1) diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 1b2a27e33d8..28e98c17a9d 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -53,7 +53,7 @@ #define GHASH_USE_MODULO_BUCKETS /* Also used by smallhash! */ -const unsigned int hashsizes[] = { +const uint hashsizes[] = { 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, @@ -103,16 +103,16 @@ struct GHash { Entry **buckets; struct BLI_mempool *entrypool; - unsigned int nbuckets; - unsigned int limit_grow, limit_shrink; + uint nbuckets; + uint limit_grow, limit_shrink; #ifdef GHASH_USE_MODULO_BUCKETS - unsigned int cursize, size_min; + uint cursize, size_min; #else - unsigned int bucket_mask, bucket_bit, bucket_bit_min; + uint bucket_mask, bucket_bit, bucket_bit_min; #endif - unsigned int nentries; - unsigned int flag; + uint nentries; + uint flag; }; @@ -141,7 +141,7 @@ BLI_INLINE void ghash_entry_copy( /** * Get the full hash for a key. */ -BLI_INLINE unsigned int ghash_keyhash(GHash *gh, const void *key) +BLI_INLINE uint ghash_keyhash(GHash *gh, const void *key) { return gh->hashfp(key); } @@ -149,7 +149,7 @@ BLI_INLINE unsigned int ghash_keyhash(GHash *gh, const void *key) /** * Get the full hash for an entry. */ -BLI_INLINE unsigned int ghash_entryhash(GHash *gh, const Entry *e) +BLI_INLINE uint ghash_entryhash(GHash *gh, const Entry *e) { return gh->hashfp(e->key); } @@ -157,7 +157,7 @@ BLI_INLINE unsigned int ghash_entryhash(GHash *gh, const Entry *e) /** * Get the bucket-index for an already-computed full hash. */ -BLI_INLINE unsigned int ghash_bucket_index(GHash *gh, const unsigned int hash) +BLI_INLINE uint ghash_bucket_index(GHash *gh, const uint hash) { #ifdef GHASH_USE_MODULO_BUCKETS return hash % gh->nbuckets; @@ -169,7 +169,7 @@ BLI_INLINE unsigned int ghash_bucket_index(GHash *gh, const unsigned int hash) /** * Find the index of next used bucket, starting from \a curr_bucket (\a gh is assumed non-empty). */ -BLI_INLINE unsigned int ghash_find_next_bucket_index(GHash *gh, unsigned int curr_bucket) +BLI_INLINE uint ghash_find_next_bucket_index(GHash *gh, uint curr_bucket) { if (curr_bucket >= gh->nbuckets) { curr_bucket = 0; @@ -194,12 +194,12 @@ BLI_INLINE unsigned int ghash_find_next_bucket_index(GHash *gh, unsigned int cur /** * Expand buckets to the next size up or down. */ -static void ghash_buckets_resize(GHash *gh, const unsigned int nbuckets) +static void ghash_buckets_resize(GHash *gh, const uint nbuckets) { Entry **buckets_old = gh->buckets; Entry **buckets_new; - const unsigned int nbuckets_old = gh->nbuckets; - unsigned int i; + const uint nbuckets_old = gh->nbuckets; + uint i; BLI_assert((gh->nbuckets != nbuckets) || !gh->buckets); // printf("%s: %d -> %d\n", __func__, nbuckets_old, nbuckets); @@ -261,9 +261,9 @@ static void ghash_buckets_resize(GHash *gh, const unsigned int nbuckets) * or small enough to require less buckets, and resize \a gh accordingly. */ static void ghash_buckets_expand( - GHash *gh, const unsigned int nentries, const bool user_defined) + GHash *gh, const uint nentries, const bool user_defined) { - unsigned int new_nbuckets; + uint new_nbuckets; if (LIKELY(gh->buckets && (nentries < gh->limit_grow))) { return; @@ -305,9 +305,9 @@ static void ghash_buckets_expand( } static void ghash_buckets_contract( - GHash *gh, const unsigned int nentries, const bool user_defined, const bool force_shrink) + GHash *gh, const uint nentries, const bool user_defined, const bool force_shrink) { - unsigned int new_nbuckets; + uint new_nbuckets; if (!(force_shrink || (gh->flag & GHASH_FLAG_ALLOW_SHRINK))) { return; @@ -355,7 +355,7 @@ static void ghash_buckets_contract( /** * Clear and reset \a gh buckets, reserve again buckets for given number of entries. */ -BLI_INLINE void ghash_buckets_reset(GHash *gh, const unsigned int nentries) +BLI_INLINE void ghash_buckets_reset(GHash *gh, const uint nentries) { MEM_SAFE_FREE(gh->buckets); @@ -383,7 +383,7 @@ BLI_INLINE void ghash_buckets_reset(GHash *gh, const unsigned int nentries) * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times. */ BLI_INLINE Entry *ghash_lookup_entry_ex( - GHash *gh, const void *key, const unsigned int bucket_index) + GHash *gh, const void *key, const uint bucket_index) { Entry *e; /* If we do not store GHash, not worth computing it for each entry here! @@ -404,7 +404,7 @@ BLI_INLINE Entry *ghash_lookup_entry_ex( */ BLI_INLINE Entry *ghash_lookup_entry_prev_ex( GHash *gh, const void *key, - Entry **r_e_prev, const unsigned int bucket_index) + Entry **r_e_prev, const uint bucket_index) { /* If we do not store GHash, not worth computing it for each entry here! * Typically, comparison function will be quicker, and since it's needed in the end anyway... */ @@ -424,13 +424,13 @@ BLI_INLINE Entry *ghash_lookup_entry_prev_ex( */ BLI_INLINE Entry *ghash_lookup_entry(GHash *gh, const void *key) { - const unsigned int hash = ghash_keyhash(gh, key); - const unsigned int bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); return ghash_lookup_entry_ex(gh, key, bucket_index); } static GHash *ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, - const unsigned int nentries_reserve, const unsigned int flag) + const uint nentries_reserve, const uint flag) { GHash *gh = MEM_mallocN(sizeof(*gh), info); @@ -451,7 +451,7 @@ static GHash *ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, * Takes hash and bucket_index arguments to avoid calling #ghash_keyhash and #ghash_bucket_index multiple times. */ BLI_INLINE void ghash_insert_ex( - GHash *gh, void *key, void *val, const unsigned int bucket_index) + GHash *gh, void *key, void *val, const uint bucket_index) { GHashEntry *e = BLI_mempool_alloc(gh->entrypool); @@ -470,7 +470,7 @@ BLI_INLINE void ghash_insert_ex( * Insert function that takes a pre-allocated entry. */ BLI_INLINE void ghash_insert_ex_keyonly_entry( - GHash *gh, void *key, const unsigned int bucket_index, + GHash *gh, void *key, const uint bucket_index, Entry *e) { BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); @@ -486,7 +486,7 @@ BLI_INLINE void ghash_insert_ex_keyonly_entry( * Insert function that doesn't set the value (use for GSet) */ BLI_INLINE void ghash_insert_ex_keyonly( - GHash *gh, void *key, const unsigned int bucket_index) + GHash *gh, void *key, const uint bucket_index) { Entry *e = BLI_mempool_alloc(gh->entrypool); @@ -502,8 +502,8 @@ BLI_INLINE void ghash_insert_ex_keyonly( BLI_INLINE void ghash_insert(GHash *gh, void *key, void *val) { - const unsigned int hash = ghash_keyhash(gh, key); - const unsigned int bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); ghash_insert_ex(gh, key, val, bucket_index); } @@ -512,8 +512,8 @@ BLI_INLINE bool ghash_insert_safe( GHash *gh, void *key, void *val, const bool override, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { - const unsigned int hash = ghash_keyhash(gh, key); - const unsigned int bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); @@ -541,8 +541,8 @@ BLI_INLINE bool ghash_insert_safe_keyonly( GHash *gh, void *key, const bool override, GHashKeyFreeFP keyfreefp) { - const unsigned int hash = ghash_keyhash(gh, key); - const unsigned int bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); Entry *e = ghash_lookup_entry_ex(gh, key, bucket_index); BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0); @@ -568,7 +568,7 @@ BLI_INLINE bool ghash_insert_safe_keyonly( static Entry *ghash_remove_ex( GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, - const unsigned int bucket_index) + const uint bucket_index) { Entry *e_prev; Entry *e = ghash_lookup_entry_prev_ex(gh, key, &e_prev, bucket_index); @@ -601,7 +601,7 @@ static Entry *ghash_remove_ex( */ static Entry *ghash_pop(GHash *gh, GHashIterState *state) { - unsigned int curr_bucket = state->curr_bucket; + uint curr_bucket = state->curr_bucket; if (gh->nentries == 0) { return NULL; } @@ -626,7 +626,7 @@ static void ghash_free_cb( GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { - unsigned int i; + uint i; BLI_assert(keyfreefp || valfreefp); BLI_assert(!valfreefp || !(gh->flag & GHASH_FLAG_IS_GSET)); @@ -651,9 +651,9 @@ static void ghash_free_cb( static GHash *ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp) { GHash *gh_new; - unsigned int i; + uint i; /* This allows us to be sure to get the same number of buckets in gh_new as in ghash. */ - const unsigned int reserve_nentries_new = MAX2(GHASH_LIMIT_GROW(gh->nbuckets) - 1, gh->nentries); + const uint reserve_nentries_new = MAX2(GHASH_LIMIT_GROW(gh->nbuckets) - 1, gh->nentries); BLI_assert(!valcopyfp || !(gh->flag & GHASH_FLAG_IS_GSET)); @@ -700,7 +700,7 @@ static GHash *ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP val * \return An empty GHash. */ GHash *BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, - const unsigned int nentries_reserve) + const uint nentries_reserve) { return ghash_new(hashfp, cmpfp, info, nentries_reserve, 0); } @@ -724,7 +724,7 @@ GHash *BLI_ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcop /** * Reserve given amount of entries (resize \a gh accordingly if needed). */ -void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve) +void BLI_ghash_reserve(GHash *gh, const uint nentries_reserve) { ghash_buckets_expand(gh, nentries_reserve, true); ghash_buckets_contract(gh, nentries_reserve, true, false); @@ -733,7 +733,7 @@ void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve) /** * \return size of the GHash. */ -unsigned int BLI_ghash_size(GHash *gh) +uint BLI_ghash_size(GHash *gh) { return gh->nentries; } @@ -771,8 +771,8 @@ bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreef */ void *BLI_ghash_replace_key(GHash *gh, void *key) { - const unsigned int hash = ghash_keyhash(gh, key); - const unsigned int bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); if (e != NULL) { void *key_prev = e->e.key; @@ -843,8 +843,8 @@ void **BLI_ghash_lookup_p(GHash *gh, const void *key) */ bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) { - const unsigned int hash = ghash_keyhash(gh, key); - const unsigned int bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); const bool haskey = (e != NULL); @@ -866,8 +866,8 @@ bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) bool BLI_ghash_ensure_p_ex( GHash *gh, const void *key, void ***r_key, void ***r_val) { - const unsigned int hash = ghash_keyhash(gh, key); - const unsigned int bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index); const bool haskey = (e != NULL); @@ -893,8 +893,8 @@ bool BLI_ghash_ensure_p_ex( */ bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { - const unsigned int hash = ghash_keyhash(gh, key); - const unsigned int bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); Entry *e = ghash_remove_ex(gh, key, keyfreefp, valfreefp, bucket_index); if (e) { BLI_mempool_free(gh->entrypool, e); @@ -916,8 +916,8 @@ bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHas */ void *BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) { - const unsigned int hash = ghash_keyhash(gh, key); - const unsigned int bucket_index = ghash_bucket_index(gh, hash); + const uint hash = ghash_keyhash(gh, key); + const uint bucket_index = ghash_bucket_index(gh, hash); GHashEntry *e = (GHashEntry *)ghash_remove_ex(gh, key, keyfreefp, NULL, bucket_index); BLI_assert(!(gh->flag & GHASH_FLAG_IS_GSET)); if (e) { @@ -975,7 +975,7 @@ bool BLI_ghash_pop( * \param nentries_reserve Optionally reserve the number of members that the hash will hold. */ void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, - const unsigned int nentries_reserve) + const uint nentries_reserve) { if (keyfreefp || valfreefp) ghash_free_cb(gh, keyfreefp, valfreefp); @@ -1013,7 +1013,7 @@ void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreef /** * Sets a GHash flag. */ -void BLI_ghash_flag_set(GHash *gh, unsigned int flag) +void BLI_ghash_flag_set(GHash *gh, uint flag) { gh->flag |= flag; } @@ -1021,7 +1021,7 @@ void BLI_ghash_flag_set(GHash *gh, unsigned int flag) /** * Clear a GHash flag. */ -void BLI_ghash_flag_clear(GHash *gh, unsigned int flag) +void BLI_ghash_flag_clear(GHash *gh, uint flag) { gh->flag &= ~flag; } @@ -1162,19 +1162,19 @@ bool BLI_ghashIterator_done(GHashIterator *ghi) #if 0 /* works but slower */ -unsigned int BLI_ghashutil_ptrhash(const void *key) +uint BLI_ghashutil_ptrhash(const void *key) { - return (unsigned int)(intptr_t)key; + return (uint)(intptr_t)key; } #else /* based python3.3's pointer hashing function */ -unsigned int BLI_ghashutil_ptrhash(const void *key) +uint BLI_ghashutil_ptrhash(const void *key) { size_t y = (size_t)key; /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid * excessive hash collisions for dicts and sets */ y = (y >> 4) | (y << (8 * sizeof(void *) - 4)); - return (unsigned int)y; + return (uint)y; } #endif bool BLI_ghashutil_ptrcmp(const void *a, const void *b) @@ -1182,9 +1182,9 @@ bool BLI_ghashutil_ptrcmp(const void *a, const void *b) return (a != b); } -unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]) +uint BLI_ghashutil_uinthash_v4(const uint key[4]) { - unsigned int hash; + uint hash; hash = key[0]; hash *= 37; hash += key[1]; @@ -1194,17 +1194,17 @@ unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]) hash += key[3]; return hash; } -unsigned int BLI_ghashutil_uinthash_v4_murmur(const unsigned int key[4]) +uint BLI_ghashutil_uinthash_v4_murmur(const uint key[4]) { return BLI_hash_mm2((const unsigned char *)key, sizeof(int) * 4 /* sizeof(key) */, 0); } bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b) { - return (memcmp(a, b, sizeof(unsigned int[4])) != 0); + return (memcmp(a, b, sizeof(uint[4])) != 0); } -unsigned int BLI_ghashutil_uinthash(unsigned int key) +uint BLI_ghashutil_uinthash(uint key) { key += ~(key << 16); key ^= (key >> 5); @@ -1216,7 +1216,7 @@ unsigned int BLI_ghashutil_uinthash(unsigned int key) return key; } -unsigned int BLI_ghashutil_inthash_p(const void *ptr) +uint BLI_ghashutil_inthash_p(const void *ptr) { uintptr_t key = (uintptr_t)ptr; @@ -1227,17 +1227,17 @@ unsigned int BLI_ghashutil_inthash_p(const void *ptr) key += ~(key << 9); key ^= (key >> 17); - return (unsigned int)(key & 0xffffffff); + return (uint)(key & 0xffffffff); } -unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr) +uint BLI_ghashutil_inthash_p_murmur(const void *ptr) { uintptr_t key = (uintptr_t)ptr; return BLI_hash_mm2((const unsigned char *)&key, sizeof(key), 0); } -unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr) +uint BLI_ghashutil_inthash_p_simple(const void *ptr) { return GET_UINT_FROM_POINTER(ptr); } @@ -1261,29 +1261,29 @@ size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b) * * note: this is the same hash method that glib 2.34.0 uses. */ -unsigned int BLI_ghashutil_strhash_n(const char *key, size_t n) +uint BLI_ghashutil_strhash_n(const char *key, size_t n) { const signed char *p; - unsigned int h = 5381; + uint h = 5381; for (p = (const signed char *)key; n-- && *p != '\0'; p++) { - h = (h << 5) + h + (unsigned int)*p; + h = (uint)((h << 5) + h) + (uint)*p; } return h; } -unsigned int BLI_ghashutil_strhash_p(const void *ptr) +uint BLI_ghashutil_strhash_p(const void *ptr) { const signed char *p; - unsigned int h = 5381; + uint h = 5381; for (p = ptr; *p != '\0'; p++) { - h = (h << 5) + h + (unsigned int)*p; + h = (uint)((h << 5) + h) + (uint)*p; } return h; } -unsigned int BLI_ghashutil_strhash_p_murmur(const void *ptr) +uint BLI_ghashutil_strhash_p_murmur(const void *ptr) { const unsigned char *key = ptr; @@ -1302,10 +1302,10 @@ GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second) return pair; } -unsigned int BLI_ghashutil_pairhash(const void *ptr) +uint BLI_ghashutil_pairhash(const void *ptr) { const GHashPair *pair = ptr; - unsigned int hash = BLI_ghashutil_ptrhash(pair->first); + uint hash = BLI_ghashutil_ptrhash(pair->first); return hash ^ BLI_ghashutil_ptrhash(pair->second); } @@ -1329,7 +1329,7 @@ void BLI_ghashutil_pairfree(void *ptr) /** \name Convenience GHash Creation Functions * \{ */ -GHash *BLI_ghash_ptr_new_ex(const char *info, const unsigned int nentries_reserve) +GHash *BLI_ghash_ptr_new_ex(const char *info, const uint nentries_reserve) { return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve); } @@ -1338,7 +1338,7 @@ GHash *BLI_ghash_ptr_new(const char *info) return BLI_ghash_ptr_new_ex(info, 0); } -GHash *BLI_ghash_str_new_ex(const char *info, const unsigned int nentries_reserve) +GHash *BLI_ghash_str_new_ex(const char *info, const uint nentries_reserve) { return BLI_ghash_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve); } @@ -1347,7 +1347,7 @@ GHash *BLI_ghash_str_new(const char *info) return BLI_ghash_str_new_ex(info, 0); } -GHash *BLI_ghash_int_new_ex(const char *info, const unsigned int nentries_reserve) +GHash *BLI_ghash_int_new_ex(const char *info, const uint nentries_reserve) { return BLI_ghash_new_ex(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, info, nentries_reserve); } @@ -1356,7 +1356,7 @@ GHash *BLI_ghash_int_new(const char *info) return BLI_ghash_int_new_ex(info, 0); } -GHash *BLI_ghash_pair_new_ex(const char *info, const unsigned int nentries_reserve) +GHash *BLI_ghash_pair_new_ex(const char *info, const uint nentries_reserve) { return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve); } @@ -1376,7 +1376,7 @@ GHash *BLI_ghash_pair_new(const char *info) /** \name GSet Functions * \{ */ GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, - const unsigned int nentries_reserve) + const uint nentries_reserve) { return (GSet *)ghash_new(hashfp, cmpfp, info, nentries_reserve, GHASH_FLAG_IS_GSET); } @@ -1394,7 +1394,7 @@ GSet *BLI_gset_copy(GSet *gs, GHashKeyCopyFP keycopyfp) return (GSet *)ghash_copy((GHash *)gs, keycopyfp, NULL); } -unsigned int BLI_gset_size(GSet *gs) +uint BLI_gset_size(GSet *gs) { return ((GHash *)gs)->nentries; } @@ -1405,8 +1405,8 @@ unsigned int BLI_gset_size(GSet *gs) */ void BLI_gset_insert(GSet *gs, void *key) { - const unsigned int hash = ghash_keyhash((GHash *)gs, key); - const unsigned int bucket_index = ghash_bucket_index((GHash *)gs, hash); + const uint hash = ghash_keyhash((GHash *)gs, key); + const uint bucket_index = ghash_bucket_index((GHash *)gs, hash); ghash_insert_ex_keyonly((GHash *)gs, key, bucket_index); } @@ -1429,8 +1429,8 @@ bool BLI_gset_add(GSet *gs, void *key) */ bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key) { - const unsigned int hash = ghash_keyhash((GHash *)gs, key); - const unsigned int bucket_index = ghash_bucket_index((GHash *)gs, hash); + const uint hash = ghash_keyhash((GHash *)gs, key); + const uint bucket_index = ghash_bucket_index((GHash *)gs, hash); GSetEntry *e = (GSetEntry *)ghash_lookup_entry_ex((GHash *)gs, key, bucket_index); const bool haskey = (e != NULL); @@ -1505,7 +1505,7 @@ bool BLI_gset_pop( } void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp, - const unsigned int nentries_reserve) + const uint nentries_reserve) { BLI_ghash_clear_ex((GHash *)gs, keyfreefp, NULL, nentries_reserve); @@ -1521,23 +1521,58 @@ void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp) BLI_ghash_free((GHash *)gs, keyfreefp, NULL); } -void BLI_gset_flag_set(GSet *gs, unsigned int flag) +void BLI_gset_flag_set(GSet *gs, uint flag) { ((GHash *)gs)->flag |= flag; } -void BLI_gset_flag_clear(GSet *gs, unsigned int flag) +void BLI_gset_flag_clear(GSet *gs, uint flag) { ((GHash *)gs)->flag &= ~flag; } /** \} */ +/** \name GSet Combined Key/Value Usage + * + * \note Not typical ``set`` use, only use when the pointer identity matters. + * This can be useful when the key references data stored outside the GSet. + * \{ */ + +/** + * Returns the pointer to the key if it's found. + */ +void *BLI_gset_lookup(GSet *gs, const void *key) +{ + Entry *e = ghash_lookup_entry((GHash *)gs, key); + return e ? e->key : NULL; +} + +/** + * Returns the pointer to the key if it's found, removing it from the GSet. + * \node Caller must handle freeing. + */ +void *BLI_gset_pop_key(GSet *gs, const void *key) +{ + const uint hash = ghash_keyhash((GHash *)gs, key); + const uint bucket_index = ghash_bucket_index((GHash *)gs, hash); + Entry *e = ghash_remove_ex((GHash *)gs, key, NULL, NULL, bucket_index); + if (e) { + void *key_ret = e->key; + BLI_mempool_free(((GHash *)gs)->entrypool, e); + return key_ret; + } + else { + return NULL; + } +} + +/** \} */ /** \name Convenience GSet Creation Functions * \{ */ -GSet *BLI_gset_ptr_new_ex(const char *info, const unsigned int nentries_reserve) +GSet *BLI_gset_ptr_new_ex(const char *info, const uint nentries_reserve) { return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, nentries_reserve); } @@ -1546,7 +1581,7 @@ GSet *BLI_gset_ptr_new(const char *info) return BLI_gset_ptr_new_ex(info, 0); } -GSet *BLI_gset_str_new_ex(const char *info, const unsigned int nentries_reserve) +GSet *BLI_gset_str_new_ex(const char *info, const uint nentries_reserve) { return BLI_gset_new_ex(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, info, nentries_reserve); } @@ -1555,7 +1590,7 @@ GSet *BLI_gset_str_new(const char *info) return BLI_gset_str_new_ex(info, 0); } -GSet *BLI_gset_pair_new_ex(const char *info, const unsigned int nentries_reserve) +GSet *BLI_gset_pair_new_ex(const char *info, const uint nentries_reserve) { return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, nentries_reserve); } @@ -1595,7 +1630,7 @@ double BLI_ghash_calc_quality_ex( double *r_prop_empty_buckets, double *r_prop_overloaded_buckets, int *r_biggest_bucket) { double mean; - unsigned int i; + uint i; if (gh->nentries == 0) { if (r_load) { diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index b02811616dd..5b13f129ad4 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -41,6 +41,8 @@ #include <string.h> #include <stdlib.h> +#include "atomic_ops.h" + #include "BLI_utildefines.h" #include "BLI_mempool.h" /* own include */ @@ -553,7 +555,7 @@ void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr) } /** - * Create a new mempool iterator, \a BLI_MEMPOOL_ALLOW_ITER flag must be set. + * Initialize a new mempool iterator, \a BLI_MEMPOOL_ALLOW_ITER flag must be set. */ void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) { @@ -562,6 +564,47 @@ void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) iter->pool = pool; iter->curchunk = pool->chunks; iter->curindex = 0; + + iter->curchunk_threaded_shared = NULL; +} + +/** + * Initialize an array of mempool iterators, \a BLI_MEMPOOL_ALLOW_ITER flag must be set. + * + * This is used in threaded code, to generate as much iterators as needed (each task should have its own), + * such that each iterator goes over its own single chunk, and only getting the next chunk to iterate over has to be + * protected against concurrency (which can be done in a lockless way). + * + * To be used when creating a task for each single item in the pool is totally overkill. + * + * See BLI_task_parallel_mempool implementation for detailed usage example. + */ +BLI_mempool_iter *BLI_mempool_iter_threadsafe_create(BLI_mempool *pool, const size_t num_iter) +{ + BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); + + BLI_mempool_iter *iter_arr = MEM_mallocN(sizeof(*iter_arr) * num_iter, __func__); + BLI_mempool_chunk **curchunk_threaded_shared = MEM_mallocN(sizeof(void *), __func__); + + BLI_mempool_iternew(pool, iter_arr); + + *curchunk_threaded_shared = iter_arr->curchunk; + iter_arr->curchunk_threaded_shared = curchunk_threaded_shared; + + for (size_t i = 1; i < num_iter; i++) { + iter_arr[i] = iter_arr[0]; + *curchunk_threaded_shared = iter_arr[i].curchunk = (*curchunk_threaded_shared) ? (*curchunk_threaded_shared)->next : NULL; + } + + return iter_arr; +} + +void BLI_mempool_iter_threadsafe_free(BLI_mempool_iter *iter_arr) +{ + BLI_assert(iter_arr->curchunk_threaded_shared != NULL); + + MEM_freeN(iter_arr->curchunk_threaded_shared); + MEM_freeN(iter_arr); } #if 0 @@ -571,15 +614,28 @@ static void *bli_mempool_iternext(BLI_mempool_iter *iter) { void *ret = NULL; - if (!iter->curchunk || !iter->pool->totused) return NULL; + if (iter->curchunk == NULL || !iter->pool->totused) { + return ret; + } ret = ((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex); iter->curindex++; if (iter->curindex == iter->pool->pchunk) { - iter->curchunk = iter->curchunk->next; iter->curindex = 0; + if (iter->curchunk_threaded_shared) { + while (1) { + iter->curchunk = *iter->curchunk_threaded_shared; + if (iter->curchunk == NULL) { + return ret; + } + if (atomic_cas_ptr((void **)iter->curchunk_threaded_shared, iter->curchunk, iter->curchunk->next) == iter->curchunk) { + break; + } + } + } + iter->curchunk = iter->curchunk->next; } return ret; @@ -620,8 +676,18 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter) } else { iter->curindex = 0; + if (iter->curchunk_threaded_shared) { + for (iter->curchunk = *iter->curchunk_threaded_shared; + (iter->curchunk != NULL) && + (atomic_cas_ptr((void **)iter->curchunk_threaded_shared, iter->curchunk, iter->curchunk->next) != iter->curchunk); + iter->curchunk = *iter->curchunk_threaded_shared); + + if (UNLIKELY(iter->curchunk == NULL)) { + return (ret->freeword == FREEWORD) ? NULL : ret; + } + } iter->curchunk = iter->curchunk->next; - if (iter->curchunk == NULL) { + if (UNLIKELY(iter->curchunk == NULL)) { return (ret->freeword == FREEWORD) ? NULL : ret; } curnode = CHUNK_DATA(iter->curchunk); diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index 46dcee48eda..d2cf0cf49a2 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -170,6 +170,34 @@ void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb) } /** + * Swaps \a vlinka and \a vlinkb from their respective lists. Assumes they are both already in their lista! + */ +void BLI_listbases_swaplinks(ListBase *listbasea, ListBase *listbaseb, void *vlinka, void *vlinkb) +{ + Link *linka = vlinka; + Link *linkb = vlinkb; + Link linkc = {NULL}; + + if (!linka || !linkb) { + return; + } + + /* Temporary link to use as placeholder of the links positions */ + BLI_insertlinkafter(listbasea, linka, &linkc); + + /* Bring linka into linkb position */ + BLI_remlink(listbasea, linka); + BLI_insertlinkafter(listbaseb, linkb, linka); + + /* Bring linkb into linka position */ + BLI_remlink(listbaseb, linkb); + BLI_insertlinkafter(listbasea, &linkc, linkb); + + /* Remove temporary link */ + BLI_remlink(listbasea, &linkc); +} + +/** * Removes the head from \a listbase and returns it. */ void *BLI_pophead(ListBase *listbase) @@ -664,6 +692,46 @@ void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset) } /** + * Finds the first element of listbase which contains the specified bytes + * at the specified offset, returning NULL if not found. + */ +void *BLI_listbase_bytes_find(const ListBase *listbase, const void *bytes, const size_t bytes_size, const int offset) +{ + Link *link = NULL; + const void *ptr_iter; + + for (link = listbase->first; link; link = link->next) { + ptr_iter = (const void *)(((const char *)link) + offset); + + if (memcmp(bytes, ptr_iter, bytes_size) == 0) { + return link; + } + } + + return NULL; +} +/* same as above but find reverse */ +/** + * Finds the last element of listbase which contains the specified bytes + * at the specified offset, returning NULL if not found. + */ +void *BLI_listbase_bytes_rfind(const ListBase *listbase, const void *bytes, const size_t bytes_size, const int offset) +{ + Link *link = NULL; + const void *ptr_iter; + + for (link = listbase->last; link; link = link->prev) { + ptr_iter = (const void *)(((const char *)link) + offset); + + if (memcmp(bytes, ptr_iter, bytes_size) == 0) { + return link; + } + } + + return NULL; +} + +/** * Returns the 0-based index of the first element of listbase which contains the specified * null-terminated string at the specified offset, or -1 if not found. */ diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index 01a805a09b6..bc3a1ee3e90 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -239,6 +239,14 @@ MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const c col[3] = a; } +MINLINE void rgba_float_args_set(float col[4], const float r, const float g, const float b, const float a) +{ + col[0] = r; + col[1] = g; + col[2] = b; + col[3] = a; +} + MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, const char b, const char a) { if (col[3] == 0) { diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index d1a219c196a..311d963f64d 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -1523,6 +1523,15 @@ float mat4_to_scale(float mat[4][4]) return len_v3(unit_vec); } +/** Return 2D scale (in XY plane) of given mat4. */ +float mat4_to_xy_scale(float M[4][4]) +{ + /* unit length vector in xy plane */ + float unit_vec[3] = {(float)M_SQRT1_2, (float)M_SQRT1_2, 0.0f}; + mul_mat3_m4_v3(M, unit_vec); + return len_v3(unit_vec); +} + void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]) { /* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */ @@ -1625,6 +1634,7 @@ void translate_m4(float mat[4][4], float Tx, float Ty, float Tz) mat[3][2] += (Tx * mat[0][2] + Ty * mat[1][2] + Tz * mat[2][2]); } +/* TODO: enum for axis? */ /** * Rotate a matrix in-place. * diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 5f44c93e169..05562502278 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -850,6 +850,20 @@ void ortho_v2_v2(float out[2], const float v[2]) } /** + * Rotate a point \a p by \a angle around origin (0, 0) + */ +void rotate_v2_v2fl(float r[2], const float p[2], const float angle) +{ + const float co = cosf(angle); + const float si = sinf(angle); + + BLI_assert(r != p); + + r[0] = co * p[0] - si * p[1]; + r[1] = si * p[0] + co * p[1]; +} + +/** * Rotate a point \a p by \a angle around an arbitrary unit length \a axis. * http://local.wasp.uwa.edu.au/~pbourke/geometry/ */ diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index ee5e8651bd3..08687a1ab47 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -658,6 +658,14 @@ MINLINE void invert_v2(float r[2]) r[1] = 1.0f / r[1]; } +MINLINE void invert_v3(float r[3]) +{ + BLI_assert(!ELEM(0.0f, r[0], r[1], r[2])); + r[0] = 1.0f / r[0]; + r[1] = 1.0f / r[1]; + r[2] = 1.0f / r[2]; +} + MINLINE void abs_v2(float r[2]) { r[0] = fabsf(r[0]); @@ -960,6 +968,12 @@ MINLINE float normalize_v3(float n[3]) return normalize_v3_v3(n, n); } +MINLINE void normal_float_to_short_v2(short out[2], const float in[2]) +{ + out[0] = (short) (in[0] * 32767.0f); + out[1] = (short) (in[1] * 32767.0f); +} + MINLINE void normal_short_to_float_v3(float out[3], const short in[3]) { out[0] = in[0] * (1.0f / 32767.0f); diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index 40d9a3da3d9..1a178db1413 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -41,6 +41,9 @@ #include "BLI_rand.h" #include "BLI_math.h" +/* defines BLI_INLINE */ +#include "BLI_utildefines.h" + #include "BLI_sys_types.h" #include "BLI_strict_flags.h" @@ -353,3 +356,101 @@ int BLI_rng_thread_rand(RNG_THREAD_ARRAY *rngarr, int thread) return BLI_rng_get_int(&rngarr->rng_tab[thread]); } +/* ********* Low-discrepancy sequences ************** */ + +/* incremental halton sequence generator, from: + * "Instant Radiosity", Keller A. */ +BLI_INLINE double halton_ex(double invprimes, double *offset) +{ + double e = fabs((1.0 - *offset) - 1e-10); + + if (invprimes >= e) { + double lasth; + double h = invprimes; + + do { + lasth = h; + h *= invprimes; + } while (h >= e); + + *offset += ((lasth + h) - 1.0); + } + else { + *offset += invprimes; + } + + return *offset; +} + +void BLI_halton_1D(unsigned int prime, double offset, int n, double *r) +{ + const double invprime = 1.0 / (double)prime; + + for (int s = 0; s < n; s++) { + *r = halton_ex(invprime, &offset); + } +} + +void BLI_halton_2D(unsigned int prime[2], double offset[2], int n, double *r) +{ + const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]}; + + for (int s = 0; s < n; s++) { + for (int i = 0; i < 2; i++) { + r[i] = halton_ex(invprimes[i], &offset[i]); + } + } +} + +void BLI_halton_3D(unsigned int prime[3], double offset[3], int n, double *r) +{ + const double invprimes[3] = {1.0 / (double)prime[0], 1.0 / (double)prime[1], 1.0 / (double)prime[2]}; + + for (int s = 0; s < n; s++) { + for (int i = 0; i < 3; i++) { + r[i] = halton_ex(invprimes[i], &offset[i]); + } + } +} + +void BLI_halton_2D_sequence(unsigned int prime[2], double offset[2], int n, double *r) +{ + const double invprimes[2] = {1.0 / (double)prime[0], 1.0 / (double)prime[1]}; + + for (int s = 0; s < n; s++) { + for (int i = 0; i < 2; i++) { + r[s * 2 + i] = halton_ex(invprimes[i], &offset[i]); + } + } +} + + +/* From "Sampling with Hammersley and Halton Points" TT Wong + * Appendix: Source Code 1 */ +BLI_INLINE double radical_inverse(unsigned int n) +{ + double u = 0; + + /* This reverse the bitwise representation + * around the decimal point. */ + for (double p = 0.5; n; p *= 0.5, n >>= 1) { + if (n & 1) { + u += p; + } + } + + return u; +} + +void BLI_hammersley_1D(unsigned int n, double *r) +{ + *r = radical_inverse(n); +} + +void BLI_hammersley_2D_sequence(unsigned int n, double *r) +{ + for (unsigned int s = 0; s < n; s++) { + r[s * 2 + 0] = (double)(s + 0.5) / (double)n; + r[s * 2 + 1] = radical_inverse(s); + } +} diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index a48c8b074dd..e31659c35d9 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -389,11 +389,7 @@ LinkNode *BLI_file_read_as_lines(const char *name) for (i = 0; i <= size; i++) { if (i == size || buf[i] == '\n') { char *line = BLI_strdupn(&buf[last], i - last); - BLI_linklist_append(&lines, line); - /* faster to build singly-linked list in reverse order */ - /* alternatively, could process buffer in reverse order so - * list ends up right way round to start with */ last = i + 1; } } diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 863622f2546..ecb977c6e61 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -50,8 +50,8 @@ int BLI_cpu_support_sse2(void) "pushl %%ebx\n\t" "cpuid\n\t" "popl %%ebx\n\t" - : "=d" (d) - : "a" (1)); + : "=d" (d) + : "a" (1)); return (d & 0x04000000) != 0; #elif (defined(_MSC_VER) && defined(_M_IX86)) /* also check cpuid for MSVC x86 */ diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c index e050f3148b8..eb7f186702b 100644 --- a/source/blender/blenlib/intern/task.c +++ b/source/blender/blenlib/intern/task.c @@ -32,6 +32,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_mempool.h" #include "BLI_task.h" #include "BLI_threads.h" @@ -1003,8 +1004,7 @@ BLI_INLINE bool parallel_range_next_iter_get( ParallelRangeState * __restrict state, int * __restrict iter, int * __restrict count) { - uint32_t uval = atomic_fetch_and_add_uint32((uint32_t *)(&state->iter), state->chunk_size); - int previter = *(int32_t *)&uval; + int previter = atomic_fetch_and_add_int32(&state->iter, state->chunk_size); *iter = previter; *count = max_ii(0, min_ii(state->chunk_size, state->stop - previter)); @@ -1124,7 +1124,7 @@ static void task_parallel_range_ex( } num_tasks = min_ii(num_tasks, (stop - start) / state.chunk_size); - atomic_fetch_and_add_uint32((uint32_t *)(&state.iter), 0); + atomic_fetch_and_add_int32(&state.iter, 0); if (use_userdata_chunk) { userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks); @@ -1355,3 +1355,89 @@ void BLI_task_parallel_listbase( BLI_spin_end(&state.lock); } + + +typedef struct ParallelMempoolState { + void *userdata; + TaskParallelMempoolFunc func; +} ParallelMempoolState; + +static void parallel_mempool_func( + TaskPool * __restrict pool, + void *taskdata, + int UNUSED(threadid)) +{ + ParallelMempoolState * __restrict state = BLI_task_pool_userdata(pool); + BLI_mempool_iter *iter = taskdata; + MempoolIterData *item; + + while ((item = BLI_mempool_iterstep(iter)) != NULL) { + state->func(state->userdata, item); + } +} + +/** + * This function allows to parallelize for loops over Mempool items. + * + * \param pool The iterable BLI_mempool to loop over. + * \param userdata Common userdata passed to all instances of \a func. + * \param func Callback function. + * \param use_threading If \a true, actually split-execute loop in threads, else just do a sequential forloop + * (allows caller to use any kind of test to switch on parallelization or not). + * + * \note There is no static scheduling here. + */ +void BLI_task_parallel_mempool( + BLI_mempool *mempool, + void *userdata, + TaskParallelMempoolFunc func, + const bool use_threading) +{ + TaskScheduler *task_scheduler; + TaskPool *task_pool; + ParallelMempoolState state; + int i, num_threads, num_tasks; + + if (BLI_mempool_count(mempool) == 0) { + return; + } + + if (!use_threading) { + BLI_mempool_iter iter; + BLI_mempool_iternew(mempool, &iter); + + for (void *item = BLI_mempool_iterstep(&iter); item != NULL; item = BLI_mempool_iterstep(&iter)) { + func(userdata, item); + } + return; + } + + task_scheduler = BLI_task_scheduler_get(); + task_pool = BLI_task_pool_create(task_scheduler, &state); + num_threads = BLI_task_scheduler_num_threads(task_scheduler); + + /* The idea here is to prevent creating task for each of the loop iterations + * and instead have tasks which are evenly distributed across CPU cores and + * pull next item to be crunched using the threaded-aware BLI_mempool_iter. + */ + num_tasks = num_threads * 2; + + state.userdata = userdata; + state.func = func; + + BLI_mempool_iter *mempool_iterators = BLI_mempool_iter_threadsafe_create(mempool, (size_t)num_tasks); + + for (i = 0; i < num_tasks; i++) { + /* Use this pool's pre-allocated tasks. */ + BLI_task_pool_push_from_thread(task_pool, + parallel_mempool_func, + &mempool_iterators[i], false, + TASK_PRIORITY_HIGH, + task_pool->thread_id); + } + + BLI_task_pool_work_and_wait(task_pool); + BLI_task_pool_free(task_pool); + + BLI_mempool_iter_threadsafe_free(mempool_iterators); +} diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index abf611d1245..2f961701801 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -472,8 +472,10 @@ void BLI_mutex_free(ThreadMutex *mutex) void BLI_spin_init(SpinLock *spin) { -#ifdef __APPLE__ +#if defined(__APPLE__) *spin = OS_SPINLOCK_INIT; +#elif defined(_MSC_VER) + *spin = 0; #else pthread_spin_init(spin, 0); #endif @@ -481,8 +483,14 @@ void BLI_spin_init(SpinLock *spin) void BLI_spin_lock(SpinLock *spin) { -#ifdef __APPLE__ +#if defined(__APPLE__) OSSpinLockLock(spin); +#elif defined(_MSC_VER) + while (InterlockedExchangeAcquire(spin, 1)) { + while (*spin) { + /* pass */ + } + } #else pthread_spin_lock(spin); #endif @@ -490,21 +498,24 @@ void BLI_spin_lock(SpinLock *spin) void BLI_spin_unlock(SpinLock *spin) { -#ifdef __APPLE__ +#if defined(__APPLE__) OSSpinLockUnlock(spin); +#elif defined(_MSC_VER) + _ReadWriteBarrier(); + *spin = 0; #else pthread_spin_unlock(spin); #endif } -#ifndef __APPLE__ -void BLI_spin_end(SpinLock *spin) +#if defined(__APPLE__) || defined(_MSC_VER) +void BLI_spin_end(SpinLock *UNUSED(spin)) { - pthread_spin_destroy(spin); } #else -void BLI_spin_end(SpinLock *UNUSED(spin)) +void BLI_spin_end(SpinLock *spin) { + pthread_spin_destroy(spin); } #endif diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 646cf978453..fb45fdc8136 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7298,7 +7298,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc) sseq->scopes.sep_waveform_ibuf = NULL; sseq->scopes.vector_ibuf = NULL; sseq->scopes.histogram_ibuf = NULL; - + sseq->compositor = NULL; } else if (sl->spacetype == SPACE_BUTS) { SpaceButs *sbuts = (SpaceButs *)sl; diff --git a/source/blender/blentranslation/msgfmt/msgfmt.c b/source/blender/blentranslation/msgfmt/msgfmt.c index 3abce7b1d3f..49f850f200c 100644 --- a/source/blender/blentranslation/msgfmt/msgfmt.c +++ b/source/blender/blentranslation/msgfmt/msgfmt.c @@ -184,7 +184,8 @@ typedef struct Offset { } Offset; /* Return the generated binary output. */ -static char *generate(GHash *messages, size_t *r_output_size) { +static char *generate(GHash *messages, size_t *r_output_size) +{ const uint32_t num_keys = BLI_ghash_size(messages); /* Get list of sorted keys. */ diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index ea24da86626..5245d24a075 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -30,6 +30,7 @@ set(INC ../blentranslation ../makesdna ../../../intern/guardedalloc + ../../../intern/atomic ../../../intern/eigen ../../../extern/rangetree ) @@ -39,6 +40,7 @@ set(INC_SYS ) set(SRC + # Naming convention for BMesh operators is: bmo_*action*_*details*.c operators/bmo_beautify.c operators/bmo_bevel.c operators/bmo_bisect_plane.c @@ -67,6 +69,7 @@ set(SRC operators/bmo_poke.c operators/bmo_primitive.c operators/bmo_removedoubles.c + operators/bmo_rotate_edges.c operators/bmo_similar.c operators/bmo_smooth_laplacian.c operators/bmo_split_edges.c diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 00f8eb6df40..96b2eb17c4c 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -36,12 +36,13 @@ #include "DNA_meshdata_types.h" #include "BLI_alloca.h" +#include "BLI_linklist.h" #include "BLI_math.h" +#include "BLI_memarena.h" +#include "BLI_task.h" #include "BKE_customdata.h" #include "BKE_multires.h" -#include "BLI_memarena.h" -#include "BLI_linklist.h" #include "bmesh.h" #include "intern/bmesh_private.h" @@ -401,13 +402,78 @@ static void bm_loop_flip_disp( disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d; } + +typedef struct BMLoopInterpMultiresData { + BMLoop *l_dst; + BMLoop *l_src_first; + int cd_loop_mdisp_offset; + + MDisps *md_dst; + const float *f_src_center; + + float *axis_x, *axis_y; + float *v1, *v4; + float *e1, *e2; + + int res; + float d; +} BMLoopInterpMultiresData; + +static void loop_interp_multires_cb(void *userdata, int ix) +{ + BMLoopInterpMultiresData *data = userdata; + + BMLoop *l_first = data->l_src_first; + BMLoop *l_dst = data->l_dst; + const int cd_loop_mdisp_offset = data->cd_loop_mdisp_offset; + + MDisps *md_dst = data->md_dst; + const float *f_src_center = data->f_src_center; + + float *axis_x = data->axis_x; + float *axis_y = data->axis_y; + + float *v1 = data->v1; + float *v4 = data->v4; + float *e1 = data->e1; + float *e2 = data->e2; + + const int res = data->res; + const float d = data->d; + + float x = d * ix, y; + int iy; + for (y = 0.0f, iy = 0; iy < res; y += d, iy++) { + BMLoop *l_iter = l_first; + float co1[3], co2[3], co[3]; + + madd_v3_v3v3fl(co1, v1, e1, y); + madd_v3_v3v3fl(co2, v4, e2, y); + interp_v3_v3v3(co, co1, co2, x); + + do { + MDisps *md_src; + float src_axis_x[3], src_axis_y[3]; + float uv[2]; + + md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset); + + if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) { + old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]); + bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]); + + break; + } + } while ((l_iter = l_iter->next) != l_first); + } +} + void BM_loop_interp_multires_ex( BMesh *UNUSED(bm), BMLoop *l_dst, const BMFace *f_src, const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset) { MDisps *md_dst; - float d, v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3]; - int ix, res; + float v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3]; float axis_x[3], axis_y[3]; /* ignore 2-edged faces */ @@ -433,38 +499,15 @@ void BM_loop_interp_multires_ex( mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y); - res = (int)sqrt(md_dst->totdisp); - d = 1.0f / (float)(res - 1); -#pragma omp parallel for if (res > 3) - for (ix = 0; ix < res; ix++) { - float x = d * ix, y; - int iy; - for (y = 0.0f, iy = 0; iy < res; y += d, iy++) { - BMLoop *l_iter; - BMLoop *l_first; - float co1[3], co2[3], co[3]; - - madd_v3_v3v3fl(co1, v1, e1, y); - madd_v3_v3v3fl(co2, v4, e2, y); - interp_v3_v3v3(co, co1, co2, x); - - l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); - do { - MDisps *md_src; - float src_axis_x[3], src_axis_y[3]; - float uv[2]; - - md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset); - - if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) { - old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]); - bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]); - - break; - } - } while ((l_iter = l_iter->next) != l_first); - } - } + const int res = (int)sqrt(md_dst->totdisp); + BMLoopInterpMultiresData data = { + .l_dst = l_dst, .l_src_first = BM_FACE_FIRST_LOOP(f_src), + .cd_loop_mdisp_offset = cd_loop_mdisp_offset, + .md_dst = md_dst, .f_src_center = f_src_center, + .axis_x = axis_x, .axis_y = axis_y, .v1 = v1, .v4 = v4, .e1 = e1, .e2 = e2, + .res = res, .d = 1.0f / (float)(res - 1) + }; + BLI_task_parallel_range(0, res, &data, loop_interp_multires_cb, res > 5); } /** diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h index e68440021e6..88985d639cf 100644 --- a/source/blender/bmesh/intern/bmesh_iterators_inline.h +++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h @@ -182,4 +182,38 @@ BLI_INLINE void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *da } } +/** + * \brief Parallel (threaded) iterator, only available for most basic itertypes (verts/edges/faces of mesh). + * + * Uses BLI_task_parallel_mempool to iterate over all items of underlying matching mempool. + * + * \note You have to include BLI_task.h before BMesh includes to be able to use this function! + */ + +#ifdef __BLI_TASK_H__ + +ATTR_NONNULL(1) +BLI_INLINE void BM_iter_parallel( + BMesh *bm, const char itype, TaskParallelMempoolFunc func, void *userdata, const bool use_threading) +{ + /* inlining optimizes out this switch when called with the defined type */ + switch ((BMIterType)itype) { + case BM_VERTS_OF_MESH: + BLI_task_parallel_mempool(bm->vpool, userdata, func, use_threading); + break; + case BM_EDGES_OF_MESH: + BLI_task_parallel_mempool(bm->epool, userdata, func, use_threading); + break; + case BM_FACES_OF_MESH: + BLI_task_parallel_mempool(bm->fpool, userdata, func, use_threading); + break; + default: + /* should never happen */ + BLI_assert(0); + break; + } +} + +#endif /* __BLI_TASK_H__ */ + #endif /* __BMESH_ITERATORS_INLINE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 7f2032d5f53..432c82afe4a 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -57,7 +57,6 @@ static void recount_totsels(BMesh *bm) tots[1] = &bm->totedgesel; tots[2] = &bm->totfacesel; -#pragma omp parallel for schedule(static) if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) for (i = 0; i < 3; i++) { BMIter iter; BMElem *ele; @@ -253,44 +252,34 @@ void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode) if (selectmode & SCE_SELECT_VERTEX) { /* both loops only set edge/face flags and read off verts */ -#pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT) - { -#pragma omp section + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && + BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && + !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && - BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && - !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) - { - BM_elem_flag_enable(e, BM_ELEM_SELECT); - } - else { - BM_elem_flag_disable(e, BM_ELEM_SELECT); - } - } + BM_elem_flag_enable(e, BM_ELEM_SELECT); } -#pragma omp section - { - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - bool ok = true; - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { - ok = false; - break; - } - } while ((l_iter = l_iter->next) != l_first); - } - else { + else { + BM_elem_flag_disable(e, BM_ELEM_SELECT); + } + } + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + bool ok = true; + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { ok = false; + break; } - - BM_elem_flag_set(f, BM_ELEM_SELECT, ok); - } + } while ((l_iter = l_iter->next) != l_first); } + else { + ok = false; + } + + BM_elem_flag_set(f, BM_ELEM_SELECT, ok); } - /* end sections */ } else if (selectmode & SCE_SELECT_EDGE) { BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { @@ -375,42 +364,31 @@ void BM_mesh_select_flush(BMesh *bm) bool ok; - /* we can use 2 sections here because the second loop isnt checking edge selection */ -#pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT) - { -#pragma omp section + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && + BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && + !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && - BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && - !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) - { - BM_elem_flag_enable(e, BM_ELEM_SELECT); - } - } + BM_elem_flag_enable(e, BM_ELEM_SELECT); } - -#pragma omp section - { - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - ok = true; - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { - ok = false; - break; - } - } while ((l_iter = l_iter->next) != l_first); - } - else { + } + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + ok = true; + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { ok = false; + break; } + } while ((l_iter = l_iter->next) != l_first); + } + else { + ok = false; + } - if (ok) { - BM_elem_flag_enable(f, BM_ELEM_SELECT); - } - } + if (ok) { + BM_elem_flag_enable(f, BM_ELEM_SELECT); } } @@ -1107,8 +1085,6 @@ void BM_mesh_elem_hflag_disable_test( { /* fast path for deselect all, avoid topology loops * since we know all will be de-selected anyway. */ - -#pragma omp parallel for schedule(static) if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) for (i = 0; i < 3; i++) { BMIter iter; BMElem *ele; diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 2ff670c770e..67db51446df 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -35,6 +35,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_stack.h" +#include "BLI_task.h" #include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" @@ -42,6 +43,8 @@ #include "BKE_mesh.h" #include "BKE_multires.h" +#include "atomic_ops.h" + #include "intern/bmesh_private.h" /* used as an extern, defined in bmesh.h */ @@ -112,37 +115,24 @@ void BM_mesh_elem_toolflags_ensure(BMesh *bm) bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totedge, 512, BLI_MEMPOOL_NOP); bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totface, 512, BLI_MEMPOOL_NOP); -#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) - { -#pragma omp section - { - BLI_mempool *toolflagpool = bm->vtoolflagpool; - BMIter iter; - BMVert_OFlag *ele; - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - ele->oflags = BLI_mempool_calloc(toolflagpool); - } - } -#pragma omp section - { - BLI_mempool *toolflagpool = bm->etoolflagpool; - BMIter iter; - BMEdge_OFlag *ele; - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - ele->oflags = BLI_mempool_calloc(toolflagpool); - } - } -#pragma omp section - { - BLI_mempool *toolflagpool = bm->ftoolflagpool; - BMIter iter; - BMFace_OFlag *ele; - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - ele->oflags = BLI_mempool_calloc(toolflagpool); - } - } + BMIter iter; + BMVert_OFlag *v_olfag; + BLI_mempool *toolflagpool = bm->vtoolflagpool; + BM_ITER_MESH (v_olfag, &iter, bm, BM_VERTS_OF_MESH) { + v_olfag->oflags = BLI_mempool_calloc(toolflagpool); + } + + BMEdge_OFlag *e_olfag; + toolflagpool = bm->etoolflagpool; + BM_ITER_MESH (e_olfag, &iter, bm, BM_EDGES_OF_MESH) { + e_olfag->oflags = BLI_mempool_calloc(toolflagpool); } + BMFace_OFlag *f_olfag; + toolflagpool = bm->ftoolflagpool; + BM_ITER_MESH (f_olfag, &iter, bm, BM_FACES_OF_MESH) { + f_olfag->oflags = BLI_mempool_calloc(toolflagpool); + } bm->totflags = 1; } @@ -318,96 +308,163 @@ void BM_mesh_free(BMesh *bm) MEM_freeN(bm); } + /** * Helpers for #BM_mesh_normals_update and #BM_verts_calc_normal_vcos */ -static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const float (*vcos)[3]) + +typedef struct BMEdgesCalcVectorsData { + /* Read-only data. */ + const float (*vcos)[3]; + + /* Read-write data, but no need to protect it, no concurrency to fear here. */ + float (*edgevec)[3]; +} BMEdgesCalcVectorsData; + + +static void mesh_edges_calc_vectors_cb(void *userdata, MempoolIterData *mp_e) { - BMIter eiter; - BMEdge *e; - int index; + BMEdgesCalcVectorsData *data = userdata; + BMEdge *e = (BMEdge *)mp_e; - if (vcos) { - BM_mesh_elem_index_ensure(bm, BM_VERT); + if (e->l) { + const float *v1_co = data->vcos ? data->vcos[BM_elem_index_get(e->v1)] : e->v1->co; + const float *v2_co = data->vcos ? data->vcos[BM_elem_index_get(e->v2)] : e->v2->co; + sub_v3_v3v3(data->edgevec[BM_elem_index_get(e)], v2_co, v1_co); + normalize_v3(data->edgevec[BM_elem_index_get(e)]); } + else { + /* the edge vector will not be needed when the edge has no radial */ + } +} - BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, index) { - BM_elem_index_set(e, index); /* set_inline */ +static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const float (*vcos)[3]) +{ + BM_mesh_elem_index_ensure(bm, BM_EDGE | (vcos ? BM_VERT : 0)); - if (e->l) { - const float *v1_co = vcos ? vcos[BM_elem_index_get(e->v1)] : e->v1->co; - const float *v2_co = vcos ? vcos[BM_elem_index_get(e->v2)] : e->v2->co; - sub_v3_v3v3(edgevec[index], v2_co, v1_co); - normalize_v3(edgevec[index]); - } - else { - /* the edge vector will not be needed when the edge has no radial */ - } + BMEdgesCalcVectorsData data = { + .vcos = vcos, + .edgevec = edgevec + }; + + BM_iter_parallel(bm, BM_EDGES_OF_MESH, mesh_edges_calc_vectors_cb, &data, bm->totedge >= BM_OMP_LIMIT); +} + + +typedef struct BMVertsCalcNormalsData { + /* Read-only data. */ + const float (*fnos)[3]; + const float (*edgevec)[3]; + const float (*vcos)[3]; + + /* Read-write data, protected by an atomic-based fake spinlock-like system... */ + float (*vnos)[3]; +} BMVertsCalcNormalsData; + +static void mesh_verts_calc_normals_accum_cb(void *userdata, MempoolIterData *mp_f) +{ + BMVertsCalcNormalsData *data = userdata; + BMFace *f = (BMFace *)mp_f; + + const float *f_no = data->fnos ? data->fnos[BM_elem_index_get(f)] : f->no; + + BMLoop *l_first, *l_iter; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const float *e1diff, *e2diff; + float dotprod; + float fac; + + /* calculate the dot product of the two edges that + * meet at the loop's vertex */ + e1diff = data->edgevec[BM_elem_index_get(l_iter->prev->e)]; + e2diff = data->edgevec[BM_elem_index_get(l_iter->e)]; + dotprod = dot_v3v3(e1diff, e2diff); + + /* edge vectors are calculated from e->v1 to e->v2, so + * adjust the dot product if one but not both loops + * actually runs from from e->v2 to e->v1 */ + if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) { + dotprod = -dotprod; + } + + fac = saacos(-dotprod); + + /* accumulate weighted face normal into the vertex's normal */ + float *v_no = data->vnos ? data->vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no; + + /* This block is a lockless threadsafe madd_v3_v3fl. + * It uses the first float of the vector as a sort of cheap spinlock, + * assuming FLT_MAX is a safe 'illegal' value that cannot be set here otherwise. + * It also assumes that collisions between threads are highly unlikely, + * else performances would be quite bad here. */ + float virtual_lock = v_no[0]; + while (true) { + /* This loops until following conditions are met: + * - v_no[0] has same value as virtual_lock (i.e. it did not change since last try). + * - v_no[0] was not FLT_MAX, i.e. it was not locked by another thread. + */ + const float vl = atomic_cas_float(&v_no[0], virtual_lock, FLT_MAX); + if (vl == virtual_lock && vl != FLT_MAX) { + break; + } + virtual_lock = vl; + } + BLI_assert(v_no[0] == FLT_MAX); + /* Now we own that normal value, and can change it. + * But first scalar of the vector must not be changed yet, it's our lock! */ + virtual_lock += f_no[0] * fac; + v_no[1] += f_no[1] * fac; + v_no[2] += f_no[2] * fac; + /* Second atomic operation to 'release' our lock on that vector and set its first scalar value. */ + /* Note that we do not need to loop here, since we 'locked' v_no[0], + * nobody should have changed it in the mean time. */ + virtual_lock = atomic_cas_float(&v_no[0], FLT_MAX, virtual_lock); + BLI_assert(virtual_lock == FLT_MAX); + + } while ((l_iter = l_iter->next) != l_first); +} + +static void mesh_verts_calc_normals_normalize_cb(void *userdata, MempoolIterData *mp_v) +{ + BMVertsCalcNormalsData *data = userdata; + BMVert *v = (BMVert *)mp_v; + + float *v_no = data->vnos ? data->vnos[BM_elem_index_get(v)] : v->no; + if (UNLIKELY(normalize_v3(v_no) == 0.0f)) { + const float *v_co = data->vcos ? data->vcos[BM_elem_index_get(v)] : v->co; + normalize_v3_v3(v_no, v_co); } - bm->elem_index_dirty &= ~BM_EDGE; } static void bm_mesh_verts_calc_normals( BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3], const float (*vcos)[3], float (*vnos)[3]) { - BM_mesh_elem_index_ensure(bm, (vnos) ? (BM_EDGE | BM_VERT) : BM_EDGE); + BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE) | ((vnos || vcos) ? BM_VERT : 0)); - /* add weighted face normals to vertices */ - { - BMIter fiter; - BMFace *f; - int i; - - BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) { - BMLoop *l_first, *l_iter; - const float *f_no = fnos ? fnos[i] : f->no; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const float *e1diff, *e2diff; - float dotprod; - float fac; - float *v_no = vnos ? vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no; - - /* calculate the dot product of the two edges that - * meet at the loop's vertex */ - e1diff = edgevec[BM_elem_index_get(l_iter->prev->e)]; - e2diff = edgevec[BM_elem_index_get(l_iter->e)]; - dotprod = dot_v3v3(e1diff, e2diff); - - /* edge vectors are calculated from e->v1 to e->v2, so - * adjust the dot product if one but not both loops - * actually runs from from e->v2 to e->v1 */ - if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) { - dotprod = -dotprod; - } + BMVertsCalcNormalsData data = { + .fnos = fnos, + .edgevec = edgevec, + .vcos = vcos, + .vnos = vnos + }; - fac = saacos(-dotprod); + BM_iter_parallel(bm, BM_FACES_OF_MESH, mesh_verts_calc_normals_accum_cb, &data, bm->totface >= BM_OMP_LIMIT); - /* accumulate weighted face normal into the vertex's normal */ - madd_v3_v3fl(v_no, f_no, fac); - } while ((l_iter = l_iter->next) != l_first); - } - } + /* normalize the accumulated vertex normals */ + BM_iter_parallel(bm, BM_VERTS_OF_MESH, mesh_verts_calc_normals_normalize_cb, &data, bm->totvert >= BM_OMP_LIMIT); +} - /* normalize the accumulated vertex normals */ - { - BMIter viter; - BMVert *v; - int i; - - BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { - float *v_no = vnos ? vnos[i] : v->no; - if (UNLIKELY(normalize_v3(v_no) == 0.0f)) { - const float *v_co = vcos ? vcos[i] : v->co; - normalize_v3_v3(v_no, v_co); - } - } - } +static void mesh_faces_calc_normals_cb(void *UNUSED(userdata), MempoolIterData *mp_f) +{ + BMFace *f = (BMFace *)mp_f; + + BM_face_normal_update(f); } + /** * \brief BMesh Compute Normals * @@ -417,43 +474,27 @@ void BM_mesh_normals_update(BMesh *bm) { float (*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__); -#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) - { -#pragma omp section - { - /* calculate all face normals */ - BMIter fiter; - BMFace *f; - int i; - - BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) { - BM_elem_index_set(f, i); /* set_inline */ - BM_face_normal_update(f); - } - bm->elem_index_dirty &= ~BM_FACE; - } -#pragma omp section - { - /* Zero out vertex normals */ - BMIter viter; - BMVert *v; - int i; - - BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { - BM_elem_index_set(v, i); /* set_inline */ - zero_v3(v->no); - } - bm->elem_index_dirty &= ~BM_VERT; - } -#pragma omp section - { - /* Compute normalized direction vectors for each edge. - * Directions will be used for calculating the weights of the face normals on the vertex normals. - */ - bm_mesh_edges_calc_vectors(bm, edgevec, NULL); - } + /* Parallel mempool iteration does not allow to generate indices inline anymore... */ + BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE)); + + /* calculate all face normals */ + BM_iter_parallel(bm, BM_FACES_OF_MESH, mesh_faces_calc_normals_cb, NULL, bm->totface >= BM_OMP_LIMIT); + + /* Zero out vertex normals */ + BMIter viter; + BMVert *v; + int i; + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + BM_elem_index_set(v, i); /* set_inline */ + zero_v3(v->no); } - /* end omp */ + bm->elem_index_dirty &= ~BM_VERT; + + /* Compute normalized direction vectors for each edge. + * Directions will be used for calculating the weights of the face normals on the vertex normals. + */ + bm_mesh_edges_calc_vectors(bm, edgevec, NULL); /* Add weighted face normals to vertices, and normalize vert normals. */ bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, NULL, NULL, NULL); @@ -1104,94 +1145,78 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype) BM_ELEM_INDEX_VALIDATE(bm, "Should Never Fail!", __func__); #endif - if (htype_needed == 0) { + if (0 && htype_needed == 0) { goto finally; } - /* skip if we only need to operate on one element */ -#pragma omp parallel sections if ((!ELEM(htype_needed, BM_VERT, BM_EDGE, BM_FACE, BM_LOOP, BM_FACE | BM_LOOP)) && \ - (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)) - { -#pragma omp section + if (htype & BM_VERT) { + if (bm->elem_index_dirty & BM_VERT) { + BMIter iter; + BMElem *ele; - { - if (htype & BM_VERT) { - if (bm->elem_index_dirty & BM_VERT) { - BMIter iter; - BMElem *ele; - - int index; - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, index) { - BM_elem_index_set(ele, index); /* set_ok */ - } - BLI_assert(index == bm->totvert); - } - else { - // printf("%s: skipping vert index calc!\n", __func__); - } + int index; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, index) { + BM_elem_index_set(ele, index); /* set_ok */ } + BLI_assert(index == bm->totvert); + } + else { + // printf("%s: skipping vert index calc!\n", __func__); } + } -#pragma omp section - { - if (htype & BM_EDGE) { - if (bm->elem_index_dirty & BM_EDGE) { - BMIter iter; - BMElem *ele; - - int index; - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, index) { - BM_elem_index_set(ele, index); /* set_ok */ - } - BLI_assert(index == bm->totedge); - } - else { - // printf("%s: skipping edge index calc!\n", __func__); - } + if (htype & BM_EDGE) { + if (bm->elem_index_dirty & BM_EDGE) { + BMIter iter; + BMElem *ele; + + int index; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, index) { + BM_elem_index_set(ele, index); /* set_ok */ } + BLI_assert(index == bm->totedge); } + else { + // printf("%s: skipping edge index calc!\n", __func__); + } + } -#pragma omp section - { - if (htype & (BM_FACE | BM_LOOP)) { - if (bm->elem_index_dirty & (BM_FACE | BM_LOOP)) { - BMIter iter; - BMElem *ele; - - const bool update_face = (htype & BM_FACE) && (bm->elem_index_dirty & BM_FACE); - const bool update_loop = (htype & BM_LOOP) && (bm->elem_index_dirty & BM_LOOP); + if (htype & (BM_FACE | BM_LOOP)) { + if (bm->elem_index_dirty & (BM_FACE | BM_LOOP)) { + BMIter iter; + BMElem *ele; - int index; - int index_loop = 0; + const bool update_face = (htype & BM_FACE) && (bm->elem_index_dirty & BM_FACE); + const bool update_loop = (htype & BM_LOOP) && (bm->elem_index_dirty & BM_LOOP); - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, index) { - if (update_face) { - BM_elem_index_set(ele, index); /* set_ok */ - } + int index; + int index_loop = 0; - if (update_loop) { - BMLoop *l_iter, *l_first; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, index) { + if (update_face) { + BM_elem_index_set(ele, index); /* set_ok */ + } - l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)ele); - do { - BM_elem_index_set(l_iter, index_loop++); /* set_ok */ - } while ((l_iter = l_iter->next) != l_first); - } - } + if (update_loop) { + BMLoop *l_iter, *l_first; - BLI_assert(index == bm->totface); - if (update_loop) { - BLI_assert(index_loop == bm->totloop); - } - } - else { - // printf("%s: skipping face/loop index calc!\n", __func__); + l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)ele); + do { + BM_elem_index_set(l_iter, index_loop++); /* set_ok */ + } while ((l_iter = l_iter->next) != l_first); } } + + BLI_assert(index == bm->totface); + if (update_loop) { + BLI_assert(index_loop == bm->totloop); + } + } + else { + // printf("%s: skipping face/loop index calc!\n", __func__); } } - finally: bm->elem_index_dirty &= ~htype; } @@ -1363,28 +1388,16 @@ void BM_mesh_elem_table_ensure(BMesh *bm, const char htype) } } - /* skip if we only need to operate on one element */ -#pragma omp parallel sections if ((!ELEM(htype_needed, BM_VERT, BM_EDGE, BM_FACE)) && \ - (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT)) - { -#pragma omp section - { - if (htype_needed & BM_VERT) { - BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)bm->vtable, bm->totvert); - } - } -#pragma omp section - { - if (htype_needed & BM_EDGE) { - BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)bm->etable, bm->totedge); - } - } -#pragma omp section - { - if (htype_needed & BM_FACE) { - BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)bm->ftable, bm->totface); - } - } + if (htype_needed & BM_VERT) { + BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)bm->vtable, bm->totvert); + } + + if (htype_needed & BM_EDGE) { + BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)bm->etable, bm->totedge); + } + + if (htype_needed & BM_FACE) { + BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)bm->ftable, bm->totface); } finally: diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 44445aae25a..0f672a9ff2a 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -550,37 +550,30 @@ static int bmo_mesh_flag_count( { int count_vert = 0, count_edge = 0, count_face = 0; -#pragma omp parallel sections if ((bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) && \ - (ELEM(htype, BM_VERT, BM_EDGE, BM_FACE) == 0)) - { -#pragma omp section - if (htype & BM_VERT) { - BMIter iter; - BMVert *ele; - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - if (BMO_vert_flag_test_bool(bm, ele, oflag) == test_for_enabled) { - count_vert++; - } + if (htype & BM_VERT) { + BMIter iter; + BMVert *ele; + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + if (BMO_vert_flag_test_bool(bm, ele, oflag) == test_for_enabled) { + count_vert++; } } -#pragma omp section - if (htype & BM_EDGE) { - BMIter iter; - BMEdge *ele; - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - if (BMO_edge_flag_test_bool(bm, ele, oflag) == test_for_enabled) { - count_edge++; - } + } + if (htype & BM_EDGE) { + BMIter iter; + BMEdge *ele; + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + if (BMO_edge_flag_test_bool(bm, ele, oflag) == test_for_enabled) { + count_edge++; } } -#pragma omp section - if (htype & BM_FACE) { - BMIter iter; - BMFace *ele; - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - if (BMO_face_flag_test_bool(bm, ele, oflag) == test_for_enabled) { - count_face++; - } + } + if (htype & BM_FACE) { + BMIter iter; + BMFace *ele; + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + if (BMO_face_flag_test_bool(bm, ele, oflag) == test_for_enabled) { + count_face++; } } } @@ -601,33 +594,25 @@ int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag) void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char htype, const short oflag) { - -#pragma omp parallel sections if ((bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) && \ - (ELEM(htype, BM_VERT, BM_EDGE, BM_FACE) == 0)) - { -#pragma omp section - if (htype & BM_VERT) { - BMIter iter; - BMVert *ele; - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - BMO_vert_flag_disable(bm, ele, oflag); - } + if (htype & BM_VERT) { + BMIter iter; + BMVert *ele; + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + BMO_vert_flag_disable(bm, ele, oflag); } -#pragma omp section - if (htype & BM_EDGE) { - BMIter iter; - BMEdge *ele; - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - BMO_edge_flag_disable(bm, ele, oflag); - } + } + if (htype & BM_EDGE) { + BMIter iter; + BMEdge *ele; + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + BMO_edge_flag_disable(bm, ele, oflag); } -#pragma omp section - if (htype & BM_FACE) { - BMIter iter; - BMFace *ele; - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - BMO_face_flag_disable(bm, ele, oflag); - } + } + if (htype & BM_FACE) { + BMIter iter; + BMFace *ele; + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + BMO_face_flag_disable(bm, ele, oflag); } } } @@ -1236,57 +1221,38 @@ static void bmo_flag_layer_alloc(BMesh *bm) bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, bm->totedge, 512, BLI_MEMPOOL_NOP); bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, bm->totface, 512, BLI_MEMPOOL_NOP); -#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) - { -#pragma omp section - { - BMIter iter; - BMVert_OFlag *ele; - int i; - - BLI_mempool *newpool = bm->vtoolflagpool; - - /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */ - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { - void *oldflags = ele->oflags; - ele->oflags = BLI_mempool_calloc(newpool); - memcpy(ele->oflags, oldflags, old_totflags_size); - BM_elem_index_set(&ele->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); - } - } -#pragma omp section - { - BMIter iter; - BMEdge_OFlag *ele; - int i; - - BLI_mempool *newpool = bm->etoolflagpool; - - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { - void *oldflags = ele->oflags; - ele->oflags = BLI_mempool_calloc(newpool); - memcpy(ele->oflags, oldflags, old_totflags_size); - BM_elem_index_set(&ele->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); - } - } -#pragma omp section - { - BMIter iter; - BMFace_OFlag *ele; - int i; - - BLI_mempool *newpool = bm->ftoolflagpool; - - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { - void *oldflags = ele->oflags; - ele->oflags = BLI_mempool_calloc(newpool); - memcpy(ele->oflags, oldflags, old_totflags_size); - BM_elem_index_set(&ele->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); - } - } + /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */ + BMIter iter; + int i; + + BMVert_OFlag *v_oflag; + BLI_mempool *newpool = bm->vtoolflagpool; + BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) { + void *oldflags = v_oflag->oflags; + v_oflag->oflags = BLI_mempool_calloc(newpool); + memcpy(v_oflag->oflags, oldflags, old_totflags_size); + BM_elem_index_set(&v_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag); + } + + BMEdge_OFlag *e_oflag; + newpool = bm->etoolflagpool; + BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) { + void *oldflags = e_oflag->oflags; + e_oflag->oflags = BLI_mempool_calloc(newpool); + memcpy(e_oflag->oflags, oldflags, old_totflags_size); + BM_elem_index_set(&e_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag); + } + + BMFace_OFlag *f_oflag; + newpool = bm->ftoolflagpool; + BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) { + void *oldflags = f_oflag->oflags; + f_oflag->oflags = BLI_mempool_calloc(newpool); + memcpy(f_oflag->oflags, oldflags, old_totflags_size); + BM_elem_index_set(&f_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag); } BLI_mempool_destroy(voldpool); @@ -1315,57 +1281,38 @@ static void bmo_flag_layer_free(BMesh *bm) bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, BLI_MEMPOOL_NOP); bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, BLI_MEMPOOL_NOP); -#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) - { -#pragma omp section - { - BMIter iter; - BMVert_OFlag *ele; - int i; - - BLI_mempool *newpool = bm->vtoolflagpool; - - /* now go through and memcpy all the flag */ - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { - void *oldflags = ele->oflags; - ele->oflags = BLI_mempool_alloc(newpool); - memcpy(ele->oflags, oldflags, new_totflags_size); - BM_elem_index_set(&ele->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); - } - } -#pragma omp section - { - BMIter iter; - BMEdge_OFlag *ele; - int i; - - BLI_mempool *newpool = bm->etoolflagpool; - - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { - void *oldflags = ele->oflags; - ele->oflags = BLI_mempool_alloc(newpool); - memcpy(ele->oflags, oldflags, new_totflags_size); - BM_elem_index_set(&ele->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); - } - } -#pragma omp section - { - BMIter iter; - BMFace_OFlag *ele; - int i; - - BLI_mempool *newpool = bm->ftoolflagpool; - - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { - void *oldflags = ele->oflags; - ele->oflags = BLI_mempool_alloc(newpool); - memcpy(ele->oflags, oldflags, new_totflags_size); - BM_elem_index_set(&ele->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); - } - } + /* now go through and memcpy all the flag */ + BMIter iter; + int i; + + BMVert_OFlag *v_oflag; + BLI_mempool *newpool = bm->vtoolflagpool; + BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) { + void *oldflags = v_oflag->oflags; + v_oflag->oflags = BLI_mempool_alloc(newpool); + memcpy(v_oflag->oflags, oldflags, new_totflags_size); + BM_elem_index_set(&v_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag); + } + + BMEdge_OFlag *e_oflag; + newpool = bm->etoolflagpool; + BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) { + void *oldflags = e_oflag->oflags; + e_oflag->oflags = BLI_mempool_alloc(newpool); + memcpy(e_oflag->oflags, oldflags, new_totflags_size); + BM_elem_index_set(&e_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag); + } + + BMFace_OFlag *f_oflag; + newpool = bm->ftoolflagpool; + BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) { + void *oldflags = f_oflag->oflags; + f_oflag->oflags = BLI_mempool_alloc(newpool); + memcpy(f_oflag->oflags, oldflags, new_totflags_size); + BM_elem_index_set(&f_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag); } BLI_mempool_destroy(voldpool); @@ -1383,38 +1330,32 @@ static void bmo_flag_layer_clear(BMesh *bm) const int totflags_offset = bm->totflags - 1; -#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) + /* now go through and memcpy all the flag */ { - /* now go through and memcpy all the flag */ -#pragma omp section - { - BMIter iter; - BMVert_OFlag *ele; - int i; - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { - ele->oflags[totflags_offset] = zero_flag; - BM_elem_index_set(&ele->base, i); /* set_inline */ - } + BMIter iter; + BMVert_OFlag *ele; + int i; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { + ele->oflags[totflags_offset] = zero_flag; + BM_elem_index_set(&ele->base, i); /* set_inline */ } -#pragma omp section - { - BMIter iter; - BMEdge_OFlag *ele; - int i; - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { - ele->oflags[totflags_offset] = zero_flag; - BM_elem_index_set(&ele->base, i); /* set_inline */ - } + } + { + BMIter iter; + BMEdge_OFlag *ele; + int i; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { + ele->oflags[totflags_offset] = zero_flag; + BM_elem_index_set(&ele->base, i); /* set_inline */ } -#pragma omp section - { - BMIter iter; - BMFace_OFlag *ele; - int i; - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { - ele->oflags[totflags_offset] = zero_flag; - BM_elem_index_set(&ele->base, i); /* set_inline */ - } + } + { + BMIter iter; + BMFace_OFlag *ele; + int i; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { + ele->oflags[totflags_offset] = zero_flag; + BM_elem_index_set(&ele->base, i); /* set_inline */ } } diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index bf5fc18935d..66fcd739839 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -510,6 +510,18 @@ void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3]) } /** + * expands bounds (min/max must be initialized). + */ +void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3]) +{ + const BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + minmax_v3v3_v3(min, max, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); +} + +/** * computes center of face in 3d. uses center of bounding box. */ void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3]) diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 4ec8ea59018..a40da2bfbfa 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -57,6 +57,8 @@ void BM_face_calc_center_mean_vcos( float const (*vertexCos)[3]) ATTR_NONNULL(); void BM_face_calc_center_mean_weighted(const BMFace *f, float center[3]) ATTR_NONNULL(); +void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3]); + void BM_face_normal_update(BMFace *f) ATTR_NONNULL(); void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL(); diff --git a/source/blender/bmesh/operators/bmo_rotate_edges.c b/source/blender/bmesh/operators/bmo_rotate_edges.c new file mode 100644 index 00000000000..dd6bf77dd3c --- /dev/null +++ b/source/blender/bmesh/operators/bmo_rotate_edges.c @@ -0,0 +1,272 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/operators/bmo_rotate_edge.c + * \ingroup bmesh + * + * Rotate edges topology that share two faces. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_heap.h" + +#include "bmesh.h" + +#include "intern/bmesh_operators_private.h" /* own include */ + +#define EDGE_OUT 1 +#define FACE_MARK 1 + +/** + * Rotate edges where every edge has it's own faces (we can rotate in any order). + */ +static void bm_rotate_edges_simple( + BMesh *bm, BMOperator *op, + const short check_flag, const bool use_ccw) +{ + BMOIter siter; + BMEdge *e; + + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { + /** + * this ends up being called twice, could add option to not to call check in + * #BM_edge_rotate to get some extra speed */ + if (BM_edge_rotate_check(e)) { + BMEdge *e_rotate = BM_edge_rotate(bm, e, use_ccw, check_flag); + if (e_rotate != NULL) { + BMO_edge_flag_enable(bm, e_rotate, EDGE_OUT); + } + } + } +} + + +/** + * Edge length is just a way of ordering that's independent of order in the edges argument, + * we could use some other method since ideally all edges will be rotated, + * this just happens to be simple to calculate. + */ +static float bm_edge_calc_rotate_cost(const BMEdge *e) +{ + return -BM_edge_calc_length_squared(e); +} + +/** + * Check if this edge is a boundary: Are more than one of the connected faces edges rotating too? + */ +static float bm_edge_rotate_is_boundary(const BMEdge *e) +{ + /* Number of adjacent shared faces. */ + int count = 0; + BMLoop *l_radial_iter = e->l; + do { + /* Skip this edge. */ + BMLoop *l_iter = l_radial_iter->next; + do { + BMEdge *e_iter = l_iter->e; + const int e_iter_index = BM_elem_index_get(e_iter); + if ((e_iter_index != -1)) { + if (count == 1) { + return false; + } + count += 1; + break; + } + } while ((l_iter = l_iter->next) != l_radial_iter); + } while ((l_radial_iter = l_radial_iter->radial_next) != e->l); + return true; +} + +/** + * Rotate edges where edges share faces, + * edges which could not rotate need to be re-considered after neighbors are rotated. + */ +static void bm_rotate_edges_shared( + BMesh *bm, BMOperator *op, + short check_flag, const bool use_ccw, const int edges_len) +{ + Heap *heap = BLI_heap_new_ex(edges_len); + HeapNode **eheap_table = MEM_mallocN(sizeof(*eheap_table) * edges_len, __func__); + int edges_len_rotate = 0; + + { + BMIter iter; + BMEdge *e; + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_elem_index_set(e, -1); /* set_dirty! */ + } + bm->elem_index_dirty |= BM_EDGE; + } + + { + BMOIter siter; + BMEdge *e; + uint i; + BMO_ITER_INDEX (e, &siter, op->slots_in, "edges", BM_EDGE, i) { + BM_elem_index_set(e, BM_edge_is_manifold(e) ? i : -1); /* set_dirty! */ + eheap_table[i] = NULL; + } + } + + /* First operate on boundary edges, this is often all that's needed, + * regions that have no boundaries are handles after. */ + enum { + PASS_TYPE_BOUNDARY = 0, + PASS_TYPE_ALL = 1, + PASS_TYPE_DONE = 2, + }; + uint pass_type = PASS_TYPE_BOUNDARY; + + + while ((pass_type != PASS_TYPE_DONE) && (edges_len_rotate != edges_len)) { + BLI_assert(BLI_heap_is_empty(heap)); + { + BMOIter siter; + BMEdge *e; + uint i; + BMO_ITER_INDEX (e, &siter, op->slots_in, "edges", BM_EDGE, i) { + BLI_assert(eheap_table[i] == NULL); + + bool ok = (BM_elem_index_get(e) != -1) && BM_edge_rotate_check(e); + + if (ok) { + if (pass_type == PASS_TYPE_BOUNDARY) { + ok = bm_edge_rotate_is_boundary(e); + } + } + + if (ok) { + float cost = bm_edge_calc_rotate_cost(e); + if (pass_type == PASS_TYPE_BOUNDARY) { + /* Trick to ensure once started, non boundaries are handled before other boundary edges. + * This means the first longest boundary defines the starting point which is rotated + * until all its connected edges are exhausted and the next boundary is popped off the heap. + * + * Without this we may rotate from different starting points and meet in the middle + * with obviously uneven topology. + * + * Move from negative to positive value, inverting so large values are still handled first. + */ + cost = cost != 0.0f ? -1.0f / cost : FLT_MAX; + } + eheap_table[i] = BLI_heap_insert(heap, cost, e); + } + } + } + + if (BLI_heap_is_empty(heap)) { + pass_type += 1; + continue; + } + + const int edges_len_rotate_prev = edges_len_rotate; + while (!BLI_heap_is_empty(heap)) { + BMEdge *e_best = BLI_heap_popmin(heap); + eheap_table[BM_elem_index_get(e_best)] = NULL; + + /* No problem if this fails, re-evaluate if faces connected to this edge are touched. */ + if (BM_edge_rotate_check(e_best)) { + BMEdge *e_rotate = BM_edge_rotate(bm, e_best, use_ccw, check_flag); + if (e_rotate != NULL) { + BMO_edge_flag_enable(bm, e_rotate, EDGE_OUT); + + /* invalidate so we don't try touch this again. */ + BM_elem_index_set(e_rotate, -1); /* set_dirty! */ + + edges_len_rotate += 1; + + /* Note: we could validate all edges which have not been rotated + * (not just previously degenerate edges). + * However there is no real need - they can be left until they're popped off the queue. */ + + /* We don't know the exact topology after rotating the edge, + * so loop over all faces attached to the new edge, typically this will only be two faces. */ + BMLoop *l_radial_iter = e_rotate->l; + do { + /* Skip this edge. */ + BMLoop *l_iter = l_radial_iter->next; + do { + BMEdge *e_iter = l_iter->e; + const int e_iter_index = BM_elem_index_get(e_iter); + if ((e_iter_index != -1) && (eheap_table[e_iter_index] == NULL)) { + if (BM_edge_rotate_check(e_iter)) { + /* Previously degenerate, now valid. */ + float cost = bm_edge_calc_rotate_cost(e_iter); + eheap_table[e_iter_index] = BLI_heap_insert(heap, cost, e_iter); + } + } + } while ((l_iter = l_iter->next) != l_radial_iter); + } while ((l_radial_iter = l_radial_iter->radial_next) != e_rotate->l); + } + } + } + + /* If no actions were taken, move onto the next pass. */ + if (edges_len_rotate == edges_len_rotate_prev) { + pass_type += 1; + continue; + } + } + + BLI_heap_free(heap, NULL); + MEM_freeN(eheap_table); +} + +void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) +{ + BMOIter siter; + BMEdge *e; + const int edges_len = BMO_slot_buffer_count(op->slots_in, "edges"); + const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); + const bool is_single = (edges_len == 1); + short check_flag = is_single ? + BM_EDGEROT_CHECK_EXISTS : + BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE; + + bool is_simple = true; + if (is_single == false) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { + BMFace *f_pair[2]; + if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) { + for (uint i = 0; i < ARRAY_SIZE(f_pair); i += 1) { + if (BMO_face_flag_test(bm, f_pair[i], FACE_MARK)) { + is_simple = false; + break; + } + BMO_face_flag_enable(bm, f_pair[i], FACE_MARK); + } + if (is_simple == false) { + break; + } + } + } + } + + if (is_simple) { + bm_rotate_edges_simple(bm, op, use_ccw, check_flag); + } + else { + bm_rotate_edges_shared(bm, op, check_flag, use_ccw, edges_len); + } + + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); +} diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index aa1e4bc7523..e9ee1e6e552 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -121,60 +121,6 @@ void bmo_reverse_faces_exec(BMesh *bm, BMOperator *op) } } -void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) -{ - BMOIter siter; - BMEdge *e, *e2; - const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); - const bool is_single = BMO_slot_buffer_count(op->slots_in, "edges") == 1; - short check_flag = is_single ? - BM_EDGEROT_CHECK_EXISTS : - BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE; - -#define EDGE_OUT 1 -#define FACE_TAINT 1 - - BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { - /** - * this ends up being called twice, could add option to not to call check in - * #BM_edge_rotate to get some extra speed */ - if (BM_edge_rotate_check(e)) { - BMFace *fa, *fb; - if (BM_edge_face_pair(e, &fa, &fb)) { - - /* check we're untouched */ - if (BMO_face_flag_test(bm, fa, FACE_TAINT) == false && - BMO_face_flag_test(bm, fb, FACE_TAINT) == false) - { - - /* don't touch again (faces will be freed so run before rotating the edge) */ - BMO_face_flag_enable(bm, fa, FACE_TAINT); - BMO_face_flag_enable(bm, fb, FACE_TAINT); - - if (!(e2 = BM_edge_rotate(bm, e, use_ccw, check_flag))) { - - BMO_face_flag_disable(bm, fa, FACE_TAINT); - BMO_face_flag_disable(bm, fb, FACE_TAINT); -#if 0 - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Could not rotate edge"); - return; -#endif - - continue; - } - - BMO_edge_flag_enable(bm, e2, EDGE_OUT); - } - } - } - } - - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); - -#undef EDGE_OUT -#undef FACE_TAINT - -} #define SEL_FLAG 1 #define SEL_ORIG 2 diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cpp b/source/blender/compositor/operations/COM_KeyingOperation.cpp index e2566d2f4f0..fa0ef70fca6 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingOperation.cpp @@ -67,15 +67,16 @@ void KeyingOperation::deinitExecution() void KeyingOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { - float pixelColor[4]; - float screenColor[4]; + float pixel_color[4]; + float screen_color[4]; - this->m_pixelReader->readSampled(pixelColor, x, y, sampler); - this->m_screenReader->readSampled(screenColor, x, y, sampler); + this->m_pixelReader->readSampled(pixel_color, x, y, sampler); + this->m_screenReader->readSampled(screen_color, x, y, sampler); - const int primary_channel = max_axis_v3(screenColor); + const int primary_channel = max_axis_v3(screen_color); + const float min_pixel_color = min_fff(pixel_color[0], pixel_color[1], pixel_color[2]); - if (pixelColor[primary_channel] > 1.0f) { + if (min_pixel_color > 1.0f) { /* overexposure doesn't happen on screen itself and usually happens * on light sources in the shot, this need to be checked separately * because saturation and falloff calculation is based on the fact @@ -84,8 +85,8 @@ void KeyingOperation::executePixelSampled(float output[4], float x, float y, Pix output[0] = 1.0f; } else { - float saturation = get_pixel_saturation(pixelColor, this->m_screenBalance, primary_channel); - float screen_saturation = get_pixel_saturation(screenColor, this->m_screenBalance, primary_channel); + float saturation = get_pixel_saturation(pixel_color, this->m_screenBalance, primary_channel); + float screen_saturation = get_pixel_saturation(screen_color, this->m_screenBalance, primary_channel); if (saturation < 0) { /* means main channel of pixel is different from screen, diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index c915b7ef076..b268822f659 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -141,12 +141,12 @@ void DEG_add_scene_relation(struct DepsNodeHandle *node, struct Scene *scene, eDepsSceneComponentType component, const char *description); -void DEG_add_object_relation(struct DepsNodeHandle *node, struct - Object *ob, +void DEG_add_object_relation(struct DepsNodeHandle *node, + struct Object *object, eDepsObjectComponentType component, const char *description); void DEG_add_bone_relation(struct DepsNodeHandle *handle, - struct Object *ob, + struct Object *object, const char *bone_name, eDepsObjectComponentType component, const char *description); @@ -164,7 +164,7 @@ typedef bool (*DEG_CollobjFilterFunction)(struct Object *obj, struct ModifierDat void DEG_add_collision_relations(struct DepsNodeHandle *handle, struct Scene *scene, - struct Object *ob, + struct Object *object, struct Group *group, int layer, unsigned int modifier_type, @@ -173,7 +173,7 @@ void DEG_add_collision_relations(struct DepsNodeHandle *handle, const char *name); void DEG_add_forcefield_relations(struct DepsNodeHandle *handle, struct Scene *scene, - struct Object *ob, + struct Object *object, struct EffectorWeights *eff, bool add_absorption, int skip_forcefield, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 7ac94141f39..c4150e8af7a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -120,7 +120,7 @@ struct BuilderWalkUserData { }; static void modifier_walk(void *user_data, - struct Object * /*ob*/, + struct Object * /*object*/, struct Object **obpoin, int /*cb_flag*/) { @@ -190,9 +190,9 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( const char *name, int name_tag) { - OperationDepsNode *op_node = comp_node->has_operation(opcode, - name, - name_tag); + OperationDepsNode *op_node = comp_node->find_operation(opcode, + name, + name_tag); if (op_node == NULL) { op_node = comp_node->add_operation(op, opcode, name, name_tag); graph_->operations.push_back(op_node); @@ -262,7 +262,7 @@ OperationDepsNode *DepsgraphNodeBuilder::find_operation_node( int name_tag) { ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name); - return comp_node->has_operation(opcode, name, name_tag); + return comp_node->find_operation(opcode, name, name_tag); } OperationDepsNode *DepsgraphNodeBuilder::find_operation_node( @@ -309,12 +309,12 @@ void DepsgraphNodeBuilder::build_group(Base *base, Group *group) } } -void DepsgraphNodeBuilder::build_object(Base *base, Object *ob) +void DepsgraphNodeBuilder::build_object(Base *base, Object *object) { - const bool has_object = (ob->id.tag & LIB_TAG_DOIT); + const bool has_object = (object->id.tag & LIB_TAG_DOIT); IDDepsNode *id_node = (has_object) - ? graph_->find_id_node(&ob->id) - : add_id_node(&ob->id); + ? graph_->find_id_node(&object->id) + : add_id_node(&object->id); /* Update node layers. * Do it for both new and existing ID nodes. This is so because several * bases might be sharing same object. @@ -322,7 +322,7 @@ void DepsgraphNodeBuilder::build_object(Base *base, Object *ob) if (base != NULL) { id_node->layers |= base->lay; } - if (ob->type == OB_CAMERA) { + if (object->type == OB_CAMERA) { /* Camera should always be updated, it used directly by viewport. * * TODO(sergey): Make it only for active scene camera. @@ -333,126 +333,124 @@ void DepsgraphNodeBuilder::build_object(Base *base, Object *ob) if (has_object) { return; } - ob->id.tag |= LIB_TAG_DOIT; - ob->customdata_mask = 0; - - /* Standard components. */ - build_object_transform(ob); - - if (ob->parent != NULL) { - build_object(NULL, ob->parent); + object->id.tag |= LIB_TAG_DOIT; + object->customdata_mask = 0; + /* Transform. */ + build_object_transform(object); + /* Parent. */ + if (object->parent != NULL) { + build_object(NULL, object->parent); } - if (ob->modifiers.first != NULL) { + /* Modifiers. */ + if (object->modifiers.first != NULL) { BuilderWalkUserData data; data.builder = this; - modifiers_foreachObjectLink(ob, modifier_walk, &data); + modifiers_foreachObjectLink(object, modifier_walk, &data); } - if (ob->constraints.first != NULL) { + /* Constraints. */ + if (object->constraints.first != NULL) { BuilderWalkUserData data; data.builder = this; - BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data); + BKE_constraints_id_loop(&object->constraints, constraint_walk, &data); } - /* Object data. */ - if (ob->data != NULL) { - /* type-specific data... */ - switch (ob->type) { - case OB_MESH: /* Geometry */ - case OB_CURVE: - case OB_FONT: - case OB_SURF: - case OB_MBALL: - case OB_LATTICE: - build_obdata_geom(ob); - /* TODO(sergey): Only for until we support granular - * update of curves. - */ - if (ob->type == OB_FONT) { - Curve *curve = (Curve *)ob->data; - if (curve->textoncurve) { - id_node->eval_flags |= DAG_EVAL_NEED_CURVE_PATH; - } - } - break; - - case OB_ARMATURE: /* Pose */ - if (ID_IS_LINKED(ob) && ob->proxy_from != NULL) { - build_proxy_rig(ob); - } - else { - build_rig(ob); - } - break; - - case OB_LAMP: /* Lamp */ - build_lamp(ob); - break; - - case OB_CAMERA: /* Camera */ - build_camera(ob); - break; - - default: - { - ID *obdata = (ID *)ob->data; - if ((obdata->tag & LIB_TAG_DOIT) == 0) { - build_animdata(obdata); - } - break; - } - } - } - + build_object_data(object); /* Build animation data, * * Do it now because it's possible object data will affect * on object's level animation, for example in case of rebuilding * pose for proxy. */ - build_animdata(&ob->id); - - /* particle systems */ - if (ob->particlesystem.first != NULL) { - build_particles(ob); + build_animdata(&object->id); + /* Particle systems. */ + if (object->particlesystem.first != NULL) { + build_particles(object); } - /* Grease pencil. */ - if (ob->gpd != NULL) { - build_gpencil(ob->gpd); + if (object->gpd != NULL) { + build_gpencil(object->gpd); } - /* Object that this is a proxy for. */ - if (ob->proxy) { - ob->proxy->proxy_from = ob; - build_object(base, ob->proxy); + if (object->proxy) { + object->proxy->proxy_from = object; + build_object(base, object->proxy); } - /* Object dupligroup. */ - if (ob->dup_group != NULL) { - build_group(base, ob->dup_group); + if (object->dup_group != NULL) { + build_group(base, object->dup_group); } } -void DepsgraphNodeBuilder::build_object_transform(Object *ob) +void DepsgraphNodeBuilder::build_object_data(Object *object) +{ + if (object->data == NULL) { + return; + } + IDDepsNode *id_node = graph_->find_id_node(&object->id); + /* type-specific data... */ + switch (object->type) { + case OB_MESH: /* Geometry */ + case OB_CURVE: + case OB_FONT: + case OB_SURF: + case OB_MBALL: + case OB_LATTICE: + build_obdata_geom(object); + /* TODO(sergey): Only for until we support granular + * update of curves. + */ + if (object->type == OB_FONT) { + Curve *curve = (Curve *)object->data; + if (curve->textoncurve) { + id_node->eval_flags |= DAG_EVAL_NEED_CURVE_PATH; + } + } + break; + case OB_ARMATURE: + if (ID_IS_LINKED(object) && object->proxy_from != NULL) { + build_proxy_rig(object); + } + else { + build_rig(object); + } + break; + case OB_LAMP: + build_lamp(object); + break; + case OB_CAMERA: + build_camera(object); + break; + default: + { + ID *obdata = (ID *)object->data; + if ((obdata->tag & LIB_TAG_DOIT) == 0) { + build_animdata(obdata); + } + break; + } + } +} + +void DepsgraphNodeBuilder::build_object_transform(Object *object) { OperationDepsNode *op_node; /* local transforms (from transform channels - loc/rot/scale + deltas) */ - op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, - function_bind(BKE_object_eval_local_transform, _1, scene_, ob), + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_object_eval_local_transform, _1, scene_, object), DEG_OPCODE_TRANSFORM_LOCAL); op_node->set_as_entry(); /* object parent */ - if (ob->parent) { - add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, - function_bind(BKE_object_eval_parent, _1, scene_, ob), + if (object->parent) { + add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_object_eval_parent, _1, scene_, object), DEG_OPCODE_TRANSFORM_PARENT); } /* object constraints */ - if (ob->constraints.first) { - build_object_constraints(ob); + if (object->constraints.first) { + build_object_constraints(object); } /* Temporary uber-update node, which does everything. @@ -462,13 +460,13 @@ void DepsgraphNodeBuilder::build_object_transform(Object *ob) * * TODO(sergey): Get rid of this node. */ - add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, - function_bind(BKE_object_eval_uber_transform, _1, scene_, ob), + add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_object_eval_uber_transform, _1, scene_, object), DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL); /* object transform is done */ - op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, - function_bind(BKE_object_eval_done, _1, ob), + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_object_eval_done, _1, object), DEG_OPCODE_TRANSFORM_FINAL); op_node->set_as_exit(); } @@ -490,11 +488,11 @@ void DepsgraphNodeBuilder::build_object_transform(Object *ob) * * -- Aligorith, August 2013 */ -void DepsgraphNodeBuilder::build_object_constraints(Object *ob) +void DepsgraphNodeBuilder::build_object_constraints(Object *object) { /* create node for constraint stack */ - add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, - function_bind(BKE_object_eval_constraints, _1, scene_, ob), + add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_object_eval_constraints, _1, scene_, object), DEG_OPCODE_TRANSFORM_CONSTRAINTS); } @@ -632,21 +630,21 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) /* objects - simulation participants */ if (rbw->group) { LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) { - Object *ob = go->ob; + Object *object = go->ob; - if (!ob || (ob->type != OB_MESH)) + if (!object || (object->type != OB_MESH)) continue; /* 2) create operation for flushing results */ /* object's transform component - where the rigidbody operation lives */ - add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, - function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, ob), + add_operation_node(&object->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, object), DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY); } } } -void DepsgraphNodeBuilder::build_particles(Object *ob) +void DepsgraphNodeBuilder::build_particles(Object *object) { /** * Particle Systems Nodes @@ -665,17 +663,17 @@ void DepsgraphNodeBuilder::build_particles(Object *ob) /* component for all particle systems */ ComponentDepsNode *psys_comp = - add_component_node(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES); + add_component_node(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES); add_operation_node(psys_comp, function_bind(BKE_particle_system_eval_init, _1, scene_, - ob), + object), DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT); /* particle systems */ - LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) { + LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) { ParticleSettings *part = psys->part; /* particle settings */ @@ -717,9 +715,9 @@ void DepsgraphNodeBuilder::build_shapekeys(Key *key) /* ObData Geometry Evaluation */ // XXX: what happens if the datablock is shared! -void DepsgraphNodeBuilder::build_obdata_geom(Object *ob) +void DepsgraphNodeBuilder::build_obdata_geom(Object *object) { - ID *obdata = (ID *)ob->data; + ID *obdata = (ID *)object->data; OperationDepsNode *op_node; /* TODO(sergey): This way using this object's properties as driver target @@ -727,7 +725,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob) * * Does this depend on other nodes? */ - op_node = add_operation_node(&ob->id, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PARAMETERS_EVAL); @@ -740,16 +738,16 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob) * * TODO(sergey): Get rid of this node. */ - op_node = add_operation_node(&ob->id, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_GEOMETRY, - function_bind(BKE_object_eval_uber_data, - _1, - scene_, - ob), + function_bind(BKE_object_eval_uber_data, + _1, + scene_, + object), DEG_OPCODE_GEOMETRY_UBEREVAL); op_node->set_as_exit(); - op_node = add_operation_node(&ob->id, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_GEOMETRY, NULL, DEG_OPCODE_PLACEHOLDER, @@ -759,22 +757,22 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob) // TODO: "Done" operation /* Cloyth modifier. */ - LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) { + LINKLIST_FOREACH (ModifierData *, md, &object->modifiers) { if (md->type == eModifierType_Cloth) { - build_cloth(ob); + build_cloth(object); } } /* materials */ - for (int a = 1; a <= ob->totcol; a++) { - Material *ma = give_current_material(ob, a); + for (int a = 1; a <= object->totcol; a++) { + Material *ma = give_current_material(object, a); if (ma != NULL) { build_material(ma); } } /* geometry collision */ - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_LATTICE)) { + if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) { // add geometry collider relations } @@ -783,7 +781,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob) } /* ShapeKeys */ - Key *key = BKE_key_from_object(ob); + Key *key = BKE_key_from_object(object); if (key) { build_shapekeys(key); } @@ -793,10 +791,10 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob) /* Nodes for result of obdata's evaluation, and geometry * evaluation on object. */ - switch (ob->type) { + switch (object->type) { case OB_MESH: { - //Mesh *me = (Mesh *)ob->data; + //Mesh *me = (Mesh *)object->data; /* evaluation operations */ op_node = add_operation_node(obdata, @@ -812,11 +810,12 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob) case OB_MBALL: { - Object *mom = BKE_mball_basis_find(scene_, ob); - /* Motherball - mom depends on children! */ - if (mom == ob) { + Object *mom = BKE_mball_basis_find(scene_, object); + /* NOTE: Only the motherball gets evaluated, it's children are + * having empty placeholders for the correct relations being built. + */ + if (mom == object) { /* metaball evaluation operations */ - /* NOTE: only the motherball gets evaluated! */ op_node = add_operation_node(obdata, DEG_NODE_TYPE_GEOMETRY, function_bind(BKE_mball_eval_geometry, @@ -824,6 +823,13 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob) (MetaBall *)obdata), DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + } + else { + op_node = add_operation_node(obdata, + DEG_NODE_TYPE_GEOMETRY, + NULL, + DEG_OPCODE_PLACEHOLDER, + "Geometry Eval"); op_node->set_as_entry(); } break; @@ -854,7 +860,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob) if (cu->taperobj != NULL) { build_object(NULL, cu->taperobj); } - if (ob->type == OB_FONT && cu->textoncurve != NULL) { + if (object->type == OB_FONT && cu->textoncurve != NULL) { build_object(NULL, cu->textoncurve); } break; @@ -887,10 +893,10 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob) } /* Cameras */ -void DepsgraphNodeBuilder::build_camera(Object *ob) +void DepsgraphNodeBuilder::build_camera(Object *object) { /* TODO: Link scene-camera links in somehow... */ - Camera *cam = (Camera *)ob->data; + Camera *cam = (Camera *)object->data; ID *camera_id = &cam->id; if (camera_id->tag & LIB_TAG_DOIT) { return; @@ -905,15 +911,15 @@ void DepsgraphNodeBuilder::build_camera(Object *ob) if (cam->dof_ob != NULL) { /* TODO(sergey): For now parametrs are on object level. */ - add_operation_node(&ob->id, DEG_NODE_TYPE_PARAMETERS, NULL, + add_operation_node(&object->id, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PLACEHOLDER, "Camera DOF"); } } /* Lamps */ -void DepsgraphNodeBuilder::build_lamp(Object *ob) +void DepsgraphNodeBuilder::build_lamp(Object *object) { - Lamp *la = (Lamp *)ob->data; + Lamp *la = (Lamp *)object->data; ID *lamp_id = &la->id; if (lamp_id->tag & LIB_TAG_DOIT) { return; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index ec9fe6a40a2..2fa9ba01cc7 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -120,27 +120,28 @@ struct DepsgraphNodeBuilder { void build_scene(Scene *scene); void build_group(Base *base, Group *group); - void build_object(Base *base, Object *ob); - void build_object_transform(Object *ob); - void build_object_constraints(Object *ob); - void build_pose_constraints(Object *ob, bPoseChannel *pchan); + void build_object(Base *base, Object *object); + void build_object_data(Object *object); + void build_object_transform(Object *object); + void build_object_constraints(Object *object); + void build_pose_constraints(Object *object, bPoseChannel *pchan); void build_rigidbody(Scene *scene); - void build_particles(Object *ob); + void build_particles(Object *object); void build_cloth(Object *object); void build_animdata(ID *id); OperationDepsNode *build_driver(ID *id, FCurve *fcurve); - void build_ik_pose(Object *ob, + void build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con); - void build_splineik_pose(Object *ob, + void build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con); - void build_rig(Object *ob); - void build_proxy_rig(Object *ob); + void build_rig(Object *object); + void build_proxy_rig(Object *object); void build_shapekeys(Key *key); - void build_obdata_geom(Object *ob); - void build_camera(Object *ob); - void build_lamp(Object *ob); + void build_obdata_geom(Object *object); + void build_camera(Object *object); + void build_lamp(Object *object); void build_nodetree(bNodeTree *ntree); void build_material(Material *ma); void build_texture(Tex *tex); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index a1f20b1c683..caf6f60165c 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -64,16 +64,16 @@ extern "C" { namespace DEG { -void DepsgraphNodeBuilder::build_pose_constraints(Object *ob, bPoseChannel *pchan) +void DepsgraphNodeBuilder::build_pose_constraints(Object *object, bPoseChannel *pchan) { /* create node for constraint stack */ - add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, - function_bind(BKE_pose_constraints_evaluate, _1, scene_, ob, pchan), + add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, + function_bind(BKE_pose_constraints_evaluate, _1, scene_, object, pchan), DEG_OPCODE_BONE_CONSTRAINTS); } /* IK Solver Eval Steps */ -void DepsgraphNodeBuilder::build_ik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con) +void DepsgraphNodeBuilder::build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con) { bKinematicConstraint *data = (bKinematicConstraint *)con->data; @@ -83,20 +83,20 @@ void DepsgraphNodeBuilder::build_ik_pose(Object *ob, bPoseChannel *pchan, bConst return; } - if (has_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, + if (has_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER)) { return; } /* Operation node for evaluating/running IK Solver. */ - add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, - function_bind(BKE_pose_iktree_evaluate, _1, scene_, ob, rootchan), + add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, + function_bind(BKE_pose_iktree_evaluate, _1, scene_, object, rootchan), DEG_OPCODE_POSE_IK_SOLVER); } /* Spline IK Eval Steps */ -void DepsgraphNodeBuilder::build_splineik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con) +void DepsgraphNodeBuilder::build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con) { bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; @@ -106,15 +106,15 @@ void DepsgraphNodeBuilder::build_splineik_pose(Object *ob, bPoseChannel *pchan, /* Operation node for evaluating/running Spline IK Solver. * Store the "root bone" of this chain in the solver, so it knows where to start. */ - add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, - function_bind(BKE_pose_splineik_evaluate, _1, scene_, ob, rootchan), + add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, + function_bind(BKE_pose_splineik_evaluate, _1, scene_, object, rootchan), DEG_OPCODE_POSE_SPLINE_IK_SOLVER); } /* Pose/Armature Bones Graph */ -void DepsgraphNodeBuilder::build_rig(Object *ob) +void DepsgraphNodeBuilder::build_rig(Object *object) { - bArmature *arm = (bArmature *)ob->data; + bArmature *arm = (bArmature *)object->data; OperationDepsNode *op_node; /* animation and/or drivers linking posebones to base-armature used to define them @@ -135,22 +135,22 @@ void DepsgraphNodeBuilder::build_rig(Object *ob) } /* Rebuild pose if not up to date. */ - if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) { - BKE_pose_rebuild_ex(ob, arm, false); + if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) { + BKE_pose_rebuild_ex(object, arm, false); /* XXX: Without this animation gets lost in certain circumstances * after loading file. Need to investigate further since it does * not happen with simple scenes.. */ - if (ob->adt) { - ob->adt->recalc |= ADT_RECALC_ANIM; + if (object->adt) { + object->adt->recalc |= ADT_RECALC_ANIM; } } /* speed optimization for animation lookups */ - if (ob->pose) { - BKE_pose_channels_hash_make(ob->pose); - if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { - BKE_pose_update_constraint_flags(ob->pose); + if (object->pose) { + BKE_pose_channels_hash_make(object->pose); + if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { + BKE_pose_update_constraint_flags(object->pose); } } @@ -177,46 +177,46 @@ void DepsgraphNodeBuilder::build_rig(Object *ob) */ /* pose eval context */ - op_node = add_operation_node(&ob->id, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, - function_bind(BKE_pose_eval_init, _1, scene_, ob, ob->pose), + function_bind(BKE_pose_eval_init, _1, scene_, object, object->pose), DEG_OPCODE_POSE_INIT); op_node->set_as_entry(); - op_node = add_operation_node(&ob->id, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, - function_bind(BKE_pose_eval_init_ik, _1, scene_, ob, ob->pose), + function_bind(BKE_pose_eval_init_ik, _1, scene_, object, object->pose), DEG_OPCODE_POSE_INIT_IK); - op_node = add_operation_node(&ob->id, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, - function_bind(BKE_pose_eval_flush, _1, scene_, ob, ob->pose), + function_bind(BKE_pose_eval_flush, _1, scene_, object, object->pose), DEG_OPCODE_POSE_DONE); op_node->set_as_exit(); /* bones */ - LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { + LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { /* node for bone eval */ - op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, DEG_OPCODE_BONE_LOCAL); op_node->set_as_entry(); - add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, - function_bind(BKE_pose_eval_bone, _1, scene_, ob, pchan), + add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, + function_bind(BKE_pose_eval_bone, _1, scene_, object, pchan), DEG_OPCODE_BONE_POSE_PARENT); - add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, /* NOTE: dedicated noop for easier relationship construction */ DEG_OPCODE_BONE_READY); - op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, function_bind(BKE_pose_bone_done, _1, pchan), DEG_OPCODE_BONE_DONE); op_node->set_as_exit(); /* constraints */ if (pchan->constraints.first != NULL) { - build_pose_constraints(ob, pchan); + build_pose_constraints(object, pchan); } /** @@ -233,11 +233,11 @@ void DepsgraphNodeBuilder::build_rig(Object *ob) LINKLIST_FOREACH (bConstraint *, con, &pchan->constraints) { switch (con->type) { case CONSTRAINT_TYPE_KINEMATIC: - build_ik_pose(ob, pchan, con); + build_ik_pose(object, pchan, con); break; case CONSTRAINT_TYPE_SPLINEIK: - build_splineik_pose(ob, pchan, con); + build_splineik_pose(object, pchan, con); break; default: @@ -247,41 +247,41 @@ void DepsgraphNodeBuilder::build_rig(Object *ob) } } -void DepsgraphNodeBuilder::build_proxy_rig(Object *ob) +void DepsgraphNodeBuilder::build_proxy_rig(Object *object) { - ID *obdata = (ID *)ob->data; + ID *obdata = (ID *)object->data; OperationDepsNode *op_node; build_animdata(obdata); - BLI_assert(ob->pose != NULL); + BLI_assert(object->pose != NULL); /* speed optimization for animation lookups */ - BKE_pose_channels_hash_make(ob->pose); - if (ob->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { - BKE_pose_update_constraint_flags(ob->pose); + BKE_pose_channels_hash_make(object->pose); + if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { + BKE_pose_update_constraint_flags(object->pose); } - op_node = add_operation_node(&ob->id, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, - function_bind(BKE_pose_eval_proxy_copy, _1, ob), + function_bind(BKE_pose_eval_proxy_copy, _1, object), DEG_OPCODE_POSE_INIT); op_node->set_as_entry(); - LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { - op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, DEG_OPCODE_BONE_LOCAL); op_node->set_as_entry(); - add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, DEG_OPCODE_BONE_READY); - op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, DEG_OPCODE_BONE_DONE); op_node->set_as_exit(); } - op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, + op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, NULL, DEG_OPCODE_POSE_DONE); op_node->set_as_exit(); } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc index 1ea44093cd7..a7b2906cefd 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc @@ -83,8 +83,8 @@ void DepsgraphNodeBuilder::build_scene(Scene *scene) /* scene objects */ LINKLIST_FOREACH (Base *, base, &scene->base) { - Object *ob = base->object; - build_object(base, ob); + Object *object = base->object; + build_object(base, object); } /* rigidbody */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 3448525a50d..293f63e9db2 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -120,7 +120,7 @@ struct BuilderWalkUserData { }; static void modifier_walk(void *user_data, - struct Object * /*ob*/, + struct Object * /*object*/, struct Object **obpoin, int /*cb_flag*/) { @@ -175,6 +175,31 @@ static bool python_driver_depends_on_time(ChannelDriver *driver) return false; } +static bool particle_system_depends_on_time(ParticleSystem *psys) +{ + ParticleSettings *part = psys->part; + /* Non-hair particles we always consider dependent on time. */ + if (part->type != PART_HAIR) { + return true; + } + /* Dynamics always depends on time. */ + if (psys->flag & PSYS_HAIR_DYNAMICS) { + return true; + } + /* TODO(sergey): Check what else makes hair dependent on time. */ + return false; +} + +static bool object_particles_depends_on_time(Object *object) +{ + LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) { + if (particle_system_depends_on_time(psys)) { + return true; + } + } + return false; +} + /* **** General purpose functions **** */ RNAPathKey::RNAPathKey(ID *id, const char *path) : @@ -199,7 +224,7 @@ DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain, { } -TimeSourceDepsNode *DepsgraphRelationBuilder::find_node( +TimeSourceDepsNode *DepsgraphRelationBuilder::get_node( const TimeSourceKey &key) const { if (key.id) { @@ -211,7 +236,7 @@ TimeSourceDepsNode *DepsgraphRelationBuilder::find_node( } } -ComponentDepsNode *DepsgraphRelationBuilder::find_node( +ComponentDepsNode *DepsgraphRelationBuilder::get_node( const ComponentKey &key) const { IDDepsNode *id_node = graph_->find_id_node(key.id); @@ -225,38 +250,23 @@ ComponentDepsNode *DepsgraphRelationBuilder::find_node( return node; } -OperationDepsNode *DepsgraphRelationBuilder::find_node( +OperationDepsNode *DepsgraphRelationBuilder::get_node( const OperationKey &key) const { - IDDepsNode *id_node = graph_->find_id_node(key.id); - if (!id_node) { - fprintf(stderr, "find_node operation: Could not find ID\n"); - return NULL; - } - - ComponentDepsNode *comp_node = id_node->find_component(key.component_type, - key.component_name); - if (!comp_node) { - fprintf(stderr, "find_node operation: Could not find component\n"); - return NULL; - } - - OperationDepsNode *op_node = comp_node->find_operation(key.opcode, - key.name, - key.name_tag); - if (!op_node) { + OperationDepsNode *op_node = find_node(key); + if (op_node == NULL) { fprintf(stderr, "find_node_operation: Failed for (%s, '%s')\n", DEG_OPNAMES[key.opcode], key.name); } return op_node; } -DepsNode *DepsgraphRelationBuilder::find_node(const RNAPathKey &key) const +DepsNode *DepsgraphRelationBuilder::get_node(const RNAPathKey &key) const { return graph_->find_node_from_pointer(&key.ptr, key.prop); } -OperationDepsNode *DepsgraphRelationBuilder::has_node( +OperationDepsNode *DepsgraphRelationBuilder::find_node( const OperationKey &key) const { IDDepsNode *id_node = graph_->find_id_node(key.id); @@ -268,7 +278,12 @@ OperationDepsNode *DepsgraphRelationBuilder::has_node( if (!comp_node) { return NULL; } - return comp_node->has_operation(key.opcode, key.name, key.name_tag); + return comp_node->find_operation(key.opcode, key.name, key.name_tag); +} + +bool DepsgraphRelationBuilder::has_node(const OperationKey &key) const +{ + return find_node(key) != NULL; } void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc, @@ -302,10 +317,10 @@ void DepsgraphRelationBuilder::add_operation_relation( } } -void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name) +void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, Scene *scene, Object *object, Group *group, int layer, bool dupli, const char *name) { unsigned int numcollobj; - Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, eModifierType_Collision, dupli); + Object **collobjs = get_collisionobjects_ext(scene, object, group, layer, &numcollobj, eModifierType_Collision, dupli); for (unsigned int i = 0; i < numcollobj; i++) { @@ -322,19 +337,19 @@ void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, MEM_freeN(collobjs); } -void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name) +void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *object, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name) { - ListBase *effectors = pdInitEffectors(scene, ob, psys, eff, false); + ListBase *effectors = pdInitEffectors(scene, object, psys, eff, false); if (effectors) { for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) { - if (eff->ob != ob) { + if (eff->ob != object) { ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_TRANSFORM); add_relation(eff_key, key, name); } if (eff->psys) { - if (eff->ob != ob) { + if (eff->ob != object) { ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES); add_relation(eff_key, key, name); @@ -357,7 +372,7 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, } if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) { - add_collision_relations(key, scene, ob, NULL, eff->ob->lay, true, "Force Absorption"); + add_collision_relations(key, scene, object, NULL, eff->ob->lay, true, "Force Absorption"); } } } @@ -407,60 +422,63 @@ void DepsgraphRelationBuilder::build_group(Object *object, Group *group) group_id->tag |= LIB_TAG_DOIT; } -void DepsgraphRelationBuilder::build_object(Object *ob) +void DepsgraphRelationBuilder::build_object(Object *object) { - if (ob->id.tag & LIB_TAG_DOIT) { + if (object->id.tag & LIB_TAG_DOIT) { return; } - ob->id.tag |= LIB_TAG_DOIT; - + object->id.tag |= LIB_TAG_DOIT; /* Object Transforms */ - eDepsOperation_Code base_op = (ob->parent) ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL; - OperationKey base_op_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, base_op); - - OperationKey local_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); - OperationKey parent_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT); - OperationKey final_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); - - OperationKey ob_ubereval_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL); - - /* parenting */ - if (ob->parent != NULL) { - /* parent relationship */ - build_object_parent(ob); - - /* local -> parent */ - add_relation(local_transform_key, parent_transform_key, "[ObLocal -> ObParent]"); - } - - if (ob->modifiers.first != NULL) { + eDepsOperation_Code base_op = (object->parent) ? DEG_OPCODE_TRANSFORM_PARENT + : DEG_OPCODE_TRANSFORM_LOCAL; + OperationKey base_op_key(&object->id, DEG_NODE_TYPE_TRANSFORM, base_op); + OperationKey local_transform_key(&object->id, + DEG_NODE_TYPE_TRANSFORM, + DEG_OPCODE_TRANSFORM_LOCAL); + OperationKey parent_transform_key(&object->id, + DEG_NODE_TYPE_TRANSFORM, + DEG_OPCODE_TRANSFORM_PARENT); + OperationKey final_transform_key(&object->id, + DEG_NODE_TYPE_TRANSFORM, + DEG_OPCODE_TRANSFORM_FINAL); + OperationKey ob_ubereval_key(&object->id, + DEG_NODE_TYPE_TRANSFORM, + DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL); + /* Parenting. */ + if (object->parent != NULL) { + /* Parent relationship. */ + build_object_parent(object); + /* Local -> parent. */ + add_relation(local_transform_key, + parent_transform_key, + "[ObLocal -> ObParent]"); + } + /* Modifiers. */ + if (object->modifiers.first != NULL) { BuilderWalkUserData data; data.builder = this; - modifiers_foreachObjectLink(ob, modifier_walk, &data); + modifiers_foreachObjectLink(object, modifier_walk, &data); } - if (ob->constraints.first != NULL) { + /* Constraints. */ + if (object->constraints.first != NULL) { BuilderWalkUserData data; data.builder = this; - BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data); + BKE_constraints_id_loop(&object->constraints, constraint_walk, &data); } - - /* object constraints */ - if (ob->constraints.first != NULL) { - OperationKey constraint_key(&ob->id, + /* Object constraints. */ + if (object->constraints.first != NULL) { + OperationKey constraint_key(&object->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS); - - /* constraint relations */ - build_constraints(&ob->id, + /* Constraint relations. */ + build_constraints(&object->id, DEG_NODE_TYPE_TRANSFORM, "", - &ob->constraints, + &object->constraints, NULL); - /* operation order */ add_relation(base_op_key, constraint_key, "[ObBase-> Constraint Stack]"); add_relation(constraint_key, final_transform_key, "[ObConstraints -> Done]"); - // XXX add_relation(constraint_key, ob_ubereval_key, "Temp Ubereval"); add_relation(ob_ubereval_key, final_transform_key, "Temp Ubereval"); @@ -470,7 +488,7 @@ void DepsgraphRelationBuilder::build_object(Object *ob) * dependencies and avoid transitive relations which causes overhead. * But once we get rid of uber eval node this will need reconsideration. */ - if (ob->rigidbody_object == NULL) { + if (object->rigidbody_object == NULL) { /* Rigid body will hook up another node inbetween, so skip * relation here to avoid transitive relation. */ @@ -478,105 +496,98 @@ void DepsgraphRelationBuilder::build_object(Object *ob) } add_relation(ob_ubereval_key, final_transform_key, "Temp Ubereval"); } - - /* AnimData */ - build_animdata(&ob->id); - + /* Animation data */ + build_animdata(&object->id); // XXX: This should be hooked up by the build_animdata code - if (needs_animdata_node(&ob->id)) { - ComponentKey adt_key(&ob->id, DEG_NODE_TYPE_ANIMATION); + if (needs_animdata_node(&object->id)) { + ComponentKey adt_key(&object->id, DEG_NODE_TYPE_ANIMATION); add_relation(adt_key, local_transform_key, "Object Animation"); } - - /* object data */ - if (ob->data) { - ID *obdata_id = (ID *)ob->data; - - /* ob data animation */ - build_animdata(obdata_id); - - /* type-specific data... */ - switch (ob->type) { - case OB_MESH: /* Geometry */ - case OB_CURVE: - case OB_FONT: - case OB_SURF: - case OB_MBALL: - case OB_LATTICE: - { - build_obdata_geom(ob); - break; - } - - case OB_ARMATURE: /* Pose */ - if (ID_IS_LINKED(ob) && ob->proxy_from != NULL) { - build_proxy_rig(ob); - } - else { - build_rig(ob); - } - break; - - case OB_LAMP: /* Lamp */ - build_lamp(ob); - break; - - case OB_CAMERA: /* Camera */ - build_camera(ob); - break; - } - - Key *key = BKE_key_from_object(ob); - if (key != NULL) { - ComponentKey geometry_key((ID *)ob->data, DEG_NODE_TYPE_GEOMETRY); - ComponentKey key_key(&key->id, DEG_NODE_TYPE_GEOMETRY); - add_relation(key_key, geometry_key, "Shapekeys"); - } - } - + /* Object data. */ + build_object_data(object); /* Particle systems. */ - if (ob->particlesystem.first != NULL) { - build_particles(ob); + if (object->particlesystem.first != NULL) { + build_particles(object); } - /* Grease pencil. */ - if (ob->gpd != NULL) { - build_gpencil(ob->gpd); + if (object->gpd != NULL) { + build_gpencil(object->gpd); } - /* Object that this is a proxy for. */ - if (ob->proxy != NULL) { - ob->proxy->proxy_from = ob; - build_object(ob->proxy); + if (object->proxy != NULL) { + object->proxy->proxy_from = object; + build_object(object->proxy); /* TODO(sergey): This is an inverted relation, matches old depsgraph * behavior and need to be investigated if it still need to be inverted. */ - ComponentKey ob_pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE); - ComponentKey proxy_pose_key(&ob->proxy->id, DEG_NODE_TYPE_EVAL_POSE); + ComponentKey ob_pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE); + ComponentKey proxy_pose_key(&object->proxy->id, DEG_NODE_TYPE_EVAL_POSE); add_relation(ob_pose_key, proxy_pose_key, "Proxy"); } - /* Object dupligroup. */ - if (ob->dup_group != NULL) { - build_group(ob, ob->dup_group); + if (object->dup_group != NULL) { + build_group(object, object->dup_group); } } -void DepsgraphRelationBuilder::build_object_parent(Object *ob) +void DepsgraphRelationBuilder::build_object_data(Object *object) +{ + if (object->data == NULL) { + return; + } + ID *obdata_id = (ID *)object->data; + /* Object data animation. */ + build_animdata(obdata_id); + /* type-specific data. */ + switch (object->type) { + case OB_MESH: + case OB_CURVE: + case OB_FONT: + case OB_SURF: + case OB_MBALL: + case OB_LATTICE: + { + build_obdata_geom(object); + break; + } + case OB_ARMATURE: + if (ID_IS_LINKED(object) && object->proxy_from != NULL) { + build_proxy_rig(object); + } + else { + build_rig(object); + } + break; + case OB_LAMP: + build_lamp(object); + break; + case OB_CAMERA: + build_camera(object); + break; + } + Key *key = BKE_key_from_object(object); + if (key != NULL) { + ComponentKey geometry_key((ID *)object->data, DEG_NODE_TYPE_GEOMETRY); + ComponentKey key_key(&key->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(key_key, geometry_key, "Shapekeys"); + } +} + +void DepsgraphRelationBuilder::build_object_parent(Object *object) { /* XXX: for now, need to use the component key (not just direct to the parent op), * or else the matrix doesn't get reset/ */ // XXX: @sergey - it would be good if we got that backwards flushing working // when tagging for updates. - //OperationKey ob_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT); - ComponentKey ob_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); + //OperationKey ob_key(&object->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT); + ComponentKey ob_key(&object->id, DEG_NODE_TYPE_TRANSFORM); /* type-specific links */ - switch (ob->partype) { + switch (object->partype) { case PARSKEL: /* Armature Deform (Virtual Modifier) */ { - ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM); add_relation(parent_key, ob_key, "Armature Deform Parent"); break; } @@ -584,7 +595,7 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob) case PARVERT1: /* Vertex Parent */ case PARVERT3: { - ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY); + ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_GEOMETRY); add_relation(parent_key, ob_key, "Vertex Parent"); /* XXX not sure what this is for or how you could be done properly - lukas */ @@ -593,17 +604,17 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob) parent_node->customdata_mask |= CD_MASK_ORIGINDEX; } - ComponentKey transform_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey transform_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM); add_relation(transform_key, ob_key, "Vertex Parent TFM"); break; } case PARBONE: /* Bone Parent */ { - ComponentKey parent_bone_key(&ob->parent->id, + ComponentKey parent_bone_key(&object->parent->id, DEG_NODE_TYPE_BONE, - ob->parsubstr); - OperationKey parent_transform_key(&ob->parent->id, + object->parsubstr); + OperationKey parent_transform_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); add_relation(parent_bone_key, ob_key, "Bone Parent"); @@ -613,35 +624,35 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob) default: { - if (ob->parent->type == OB_LATTICE) { + if (object->parent->type == OB_LATTICE) { /* Lattice Deform Parent - Virtual Modifier */ // XXX: no virtual modifiers should be left! - ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); - ComponentKey geom_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY); + ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey geom_key(&object->parent->id, DEG_NODE_TYPE_GEOMETRY); add_relation(parent_key, ob_key, "Lattice Deform Parent"); add_relation(geom_key, ob_key, "Lattice Deform Parent Geom"); } - else if (ob->parent->type == OB_CURVE) { - Curve *cu = (Curve *)ob->parent->data; + else if (object->parent->type == OB_CURVE) { + Curve *cu = (Curve *)object->parent->data; if (cu->flag & CU_PATH) { /* Follow Path */ - ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY); + ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_GEOMETRY); add_relation(parent_key, ob_key, "Curve Follow Parent"); - ComponentKey transform_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey transform_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM); add_relation(transform_key, ob_key, "Curve Follow TFM"); } else { /* Standard Parent */ - ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM); add_relation(parent_key, ob_key, "Curve Parent"); } } else { /* Standard Parent */ - ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey parent_key(&object->parent->id, DEG_NODE_TYPE_TRANSFORM); add_relation(parent_key, ob_key, "Parent"); } break; @@ -649,7 +660,7 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob) } /* exception case: parent is duplivert */ - if ((ob->type == OB_MBALL) && (ob->parent->transflag & OB_DUPLIVERTS)) { + if ((object->type == OB_MBALL) && (object->parent->transflag & OB_DUPLIVERTS)) { //dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Duplivert"); } } @@ -982,11 +993,11 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) /* TODO: ideally, if this is for a constraint, it goes to said * constraint. */ - Object *ob = (Object *)id; + Object *object = (Object *)id; char *bone_name; bone_name = BLI_str_quoted_substrN(rna_path, "pose.bones["); - pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + pchan = BKE_pose_channel_find_name(object->pose, bone_name); if (bone_name) { MEM_freeN(bone_name); @@ -1021,12 +1032,12 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) IDDepsNode *to_node = (IDDepsNode *)rel->to; /* We only care about objects with pose data which use this. */ if (GS(to_node->id->name) == ID_OB) { - Object *ob = (Object *)to_node->id; - /* NOTE: ob->pose may be NULL. */ + Object *object = (Object *)to_node->id; + /* NOTE: object->pose may be NULL. */ bPoseChannel *pchan = BKE_pose_channel_find_name( - ob->pose, bone_name); + object->pose, bone_name); if (pchan != NULL) { - OperationKey bone_key(&ob->id, + OperationKey bone_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); @@ -1105,9 +1116,9 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) } /* Special handling for directly-named bones. */ if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) { - Object *ob = (Object *)dtar->id; + Object *object = (Object *)dtar->id; bPoseChannel *target_pchan = - BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); + BKE_pose_channel_find_name(object->pose, dtar->pchan_name); if (target_pchan != NULL) { /* Get node associated with bone. */ // XXX: watch the space! @@ -1148,11 +1159,11 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) /* Workaround for ensuring that local bone transforms don't end * up having to wait for pose eval to finish (to prevent cycles). */ - Object *ob = (Object *)dtar->id; + Object *object = (Object *)dtar->id; char *bone_name = BLI_str_quoted_substrN(dtar->rna_path, "pose.bones["); bPoseChannel *target_pchan = - BKE_pose_channel_find_name(ob->pose, bone_name); + BKE_pose_channel_find_name(object->pose, bone_name); if (bone_name != NULL) { MEM_freeN(bone_name); bone_name = NULL; @@ -1242,8 +1253,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* objects - simulation participants */ if (rbw->group) { LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) { - Object *ob = go->ob; - if (ob == NULL || ob->type != OB_MESH) { + Object *object = go->ob; + if (object == NULL || object->type != OB_MESH) { continue; } @@ -1255,10 +1266,10 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) * XXX: there's probably a difference between passive and active * - passive don't change, so may need to know full transform... */ - OperationKey rbo_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY); + OperationKey rbo_key(&object->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY); - eDepsOperation_Code trans_opcode = ob->parent ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL; - OperationKey trans_op(&ob->id, DEG_NODE_TYPE_TRANSFORM, trans_opcode); + eDepsOperation_Code trans_opcode = object->parent ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL; + OperationKey trans_op(&object->id, DEG_NODE_TYPE_TRANSFORM, trans_opcode); add_relation(sim_key, rbo_key, "Rigidbody Sim Eval -> RBO Sync"); @@ -1270,8 +1281,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) * - Later, it might be good to include a constraint in the stack allowing us * to control whether rigidbody eval gets interleaved into the constraint stack */ - if (ob->constraints.first) { - OperationKey constraint_key(&ob->id, + if (object->constraints.first) { + OperationKey constraint_key(&object->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS); add_relation(rbo_key, constraint_key, "RBO Sync -> Ob Constraints"); @@ -1282,7 +1293,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) * NOTE: Currently we consider final here an ubereval node. * If it is gone we'll need to reconsider relation here. */ - OperationKey uber_key(&ob->id, + OperationKey uber_key(&object->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL); add_relation(rbo_key, uber_key, "RBO Sync -> Uber (Temp)"); @@ -1296,17 +1307,17 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* constraints */ if (rbw->constraints) { LINKLIST_FOREACH (GroupObject *, go, &rbw->constraints->gobject) { - Object *ob = go->ob; - if (ob == NULL || !ob->rigidbody_constraint) { + Object *object = go->ob; + if (object == NULL || !object->rigidbody_constraint) { continue; } - RigidBodyCon *rbc = ob->rigidbody_constraint; + RigidBodyCon *rbc = object->rigidbody_constraint; /* final result of the constraint object's transform controls how the * constraint affects the physics sim for these objects */ - ComponentKey trans_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey trans_key(&object->id, DEG_NODE_TYPE_TRANSFORM); OperationKey ob1_key(&rbc->ob1->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY); OperationKey ob2_key(&rbc->ob2->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_TRANSFORM_COPY); @@ -1320,32 +1331,31 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) } } -void DepsgraphRelationBuilder::build_particles(Object *ob) +void DepsgraphRelationBuilder::build_particles(Object *object) { TimeSourceKey time_src_key; - OperationKey obdata_ubereval_key(&ob->id, + OperationKey obdata_ubereval_key(&object->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); - OperationKey eval_init_key(&ob->id, + OperationKey eval_init_key(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT); - /* TODO(sergey): Are all particle systems depends on time? - * Hair without dynamics i.e. - */ - add_relation(time_src_key, eval_init_key, "TimeSrc -> PSys"); + if (object_particles_depends_on_time(object)) { + add_relation(time_src_key, eval_init_key, "TimeSrc -> PSys"); + } /* particle systems */ - LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) { + LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) { ParticleSettings *part = psys->part; /* particle settings */ build_animdata(&part->id); /* this particle system */ - OperationKey psys_key(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL, psys->name); + OperationKey psys_key(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL, psys->name); /* XXX: if particle system is later re-enabled, we must do full rebuild? */ - if (!psys_check_enabled(ob, psys, G.is_rendering)) + if (!psys_check_enabled(object, psys, G.is_rendering)) continue; add_relation(eval_init_key, psys_key, "Init -> PSys"); @@ -1358,14 +1368,14 @@ void DepsgraphRelationBuilder::build_particles(Object *ob) /* collisions */ if (part->type != PART_HAIR) { - add_collision_relations(psys_key, scene_, ob, part->collision_group, ob->lay, true, "Particle Collision"); + add_collision_relations(psys_key, scene_, object, part->collision_group, object->lay, true, "Particle Collision"); } else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd && psys->clmd->coll_parms) { - add_collision_relations(psys_key, scene_, ob, psys->clmd->coll_parms->group, ob->lay | scene_->lay, true, "Hair Collision"); + add_collision_relations(psys_key, scene_, object, psys->clmd->coll_parms->group, object->lay | scene_->lay, true, "Hair Collision"); } /* effectors */ - add_forcefield_relations(psys_key, scene_, ob, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field"); + add_forcefield_relations(psys_key, scene_, object, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field"); /* boids */ if (part->boids) { @@ -1397,7 +1407,7 @@ void DepsgraphRelationBuilder::build_particles(Object *ob) * TODO(sergey): This relation should be altered once real granular update * is implemented. */ - ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM); add_relation(transform_key, obdata_ubereval_key, "Partcile Eval"); /* pointcache */ @@ -1461,27 +1471,27 @@ void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key) * re-evaluation of the individual instances of this geometry. */ // TODO: Materials and lighting should probably get their own component, instead of being lumped under geometry? -void DepsgraphRelationBuilder::build_obdata_geom(Object *ob) +void DepsgraphRelationBuilder::build_obdata_geom(Object *object) { - ID *obdata = (ID *)ob->data; + ID *obdata = (ID *)object->data; /* Init operation of object-level geometry evaluation. */ - OperationKey geom_init_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init"); + OperationKey geom_init_key(&object->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init"); /* get nodes for result of obdata's evaluation, and geometry evaluation on object */ ComponentKey obdata_geom_key(obdata, DEG_NODE_TYPE_GEOMETRY); - ComponentKey geom_key(&ob->id, DEG_NODE_TYPE_GEOMETRY); + ComponentKey geom_key(&object->id, DEG_NODE_TYPE_GEOMETRY); /* link components to each other */ add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data"); /* Modifiers */ - if (ob->modifiers.first != NULL) { - OperationKey obdata_ubereval_key(&ob->id, + if (object->modifiers.first != NULL) { + OperationKey obdata_ubereval_key(&object->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); - LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) { + LINKLIST_FOREACH (ModifierData *, md, &object->modifiers) { const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type); if (mti->updateDepsgraph) { @@ -1490,11 +1500,11 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob) md, bmain_, scene_, - ob, + object, reinterpret_cast< ::DepsNodeHandle* >(&handle)); } - if (BKE_object_modifier_use_time(ob, md)) { + if (BKE_object_modifier_use_time(object, md)) { TimeSourceKey time_src_key; add_relation(time_src_key, obdata_ubereval_key, "Time Source"); @@ -1504,22 +1514,22 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob) * for either the modifier needing time, or that it is animated. */ /* XXX: Remove this hack when these links are added as part of build_animdata() instead */ - if (modifier_dependsOnTime(md) == false && needs_animdata_node(&ob->id)) { - ComponentKey animation_key(&ob->id, DEG_NODE_TYPE_ANIMATION); + if (modifier_dependsOnTime(md) == false && needs_animdata_node(&object->id)) { + ComponentKey animation_key(&object->id, DEG_NODE_TYPE_ANIMATION); add_relation(animation_key, obdata_ubereval_key, "Modifier Animation"); } } if (md->type == eModifierType_Cloth) { - build_cloth(ob, md); + build_cloth(object, md); } } } /* materials */ - if (ob->totcol) { - for (int a = 1; a <= ob->totcol; a++) { - Material *ma = give_current_material(ob, a); + if (object->totcol) { + for (int a = 1; a <= object->totcol; a++) { + Material *ma = give_current_material(object, a); if (ma != NULL) { build_material(ma); } @@ -1527,7 +1537,7 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob) } /* geometry collision */ - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_LATTICE)) { + if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) { // add geometry collider relations } @@ -1535,9 +1545,9 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob) * * TODO(sergey): Get rid of this node. */ - if (ob->type != OB_ARMATURE) { + if (object->type != OB_ARMATURE) { /* Armatures does no longer require uber node. */ - OperationKey obdata_ubereval_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); + OperationKey obdata_ubereval_key(&object->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval"); } @@ -1552,33 +1562,41 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob) add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done"); /* type-specific node/links */ - switch (ob->type) { + switch (object->type) { case OB_MESH: /* NOTE: This is compatibility code to support particle systems * * for viewport being properly rendered in final render mode. * This relation is similar to what dag_object_time_update_flags() - * was doing for mesh objects with particle system/ + * was doing for mesh objects with particle system. * * Ideally we need to get rid of this relation. */ - if (ob->particlesystem.first != NULL) { + if (object_particles_depends_on_time(object)) { TimeSourceKey time_key; - OperationKey obdata_ubereval_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); + OperationKey obdata_ubereval_key(&object->id, + DEG_NODE_TYPE_GEOMETRY, + DEG_OPCODE_GEOMETRY_UBEREVAL); add_relation(time_key, obdata_ubereval_key, "Legacy particle time"); } break; case OB_MBALL: { - Object *mom = BKE_mball_basis_find(scene_, ob); + Object *mom = BKE_mball_basis_find(scene_, object); + ComponentKey mom_geom_key(&mom->id, DEG_NODE_TYPE_GEOMETRY); /* motherball - mom depends on children! */ - if (mom != ob) { - /* non-motherball -> cannot be directly evaluated! */ - ComponentKey mom_key(&mom->id, DEG_NODE_TYPE_GEOMETRY); - ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); - add_relation(geom_key, mom_key, "Metaball Motherball"); - add_relation(transform_key, mom_key, "Metaball Motherball"); + if (mom == object) { + ComponentKey mom_transform_key(&mom->id, + DEG_NODE_TYPE_TRANSFORM); + add_relation(mom_transform_key, + mom_geom_key, + "Metaball Motherball Transform -> Geometry"); + } + else { + ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(geom_key, mom_geom_key, "Metaball Motherball"); + add_relation(transform_key, mom_geom_key, "Metaball Motherball"); } break; } @@ -1600,7 +1618,7 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob) build_object(cu->taperobj); add_relation(taperob_key, geom_key, "Curve Taper"); } - if (ob->type == OB_FONT) { + if (object->type == OB_FONT) { if (cu->textoncurve) { ComponentKey textoncurve_key(&cu->textoncurve->id, DEG_NODE_TYPE_GEOMETRY); build_object(cu->textoncurve); @@ -1622,7 +1640,7 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob) } /* ShapeKeys */ - Key *key = BKE_key_from_object(ob); + Key *key = BKE_key_from_object(object); if (key) { build_shapekeys(obdata, key); } @@ -1640,9 +1658,9 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *ob) /* Cameras */ // TODO: Link scene-camera links in somehow... -void DepsgraphRelationBuilder::build_camera(Object *ob) +void DepsgraphRelationBuilder::build_camera(Object *object) { - Camera *cam = (Camera *)ob->data; + Camera *cam = (Camera *)object->data; ID *camera_id = &cam->id; if (camera_id->tag & LIB_TAG_DOIT) { return; @@ -1658,16 +1676,16 @@ void DepsgraphRelationBuilder::build_camera(Object *ob) /* DOF */ if (cam->dof_ob) { - ComponentKey ob_param_key(&ob->id, DEG_NODE_TYPE_PARAMETERS); + ComponentKey ob_param_key(&object->id, DEG_NODE_TYPE_PARAMETERS); ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM); add_relation(dof_ob_key, ob_param_key, "Camera DOF"); } } /* Lamps */ -void DepsgraphRelationBuilder::build_lamp(Object *ob) +void DepsgraphRelationBuilder::build_lamp(Object *object) { - Lamp *la = (Lamp *)ob->data; + Lamp *la = (Lamp *)object->data; ID *lamp_id = &la->id; if (lamp_id->tag & LIB_TAG_DOIT) { return; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 86227f4aaf8..68762043e5e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -186,8 +186,9 @@ struct DepsgraphRelationBuilder void build_scene(Scene *scene); void build_group(Object *object, Group *group); - void build_object(Object *ob); - void build_object_parent(Object *ob); + void build_object(Object *object); + void build_object_data(Object *object); + void build_object_parent(Object *object); void build_constraints(ID *id, eDepsNode_Type component_type, const char *component_subdata, @@ -197,22 +198,22 @@ struct DepsgraphRelationBuilder void build_driver(ID *id, FCurve *fcurve); void build_world(World *world); void build_rigidbody(Scene *scene); - void build_particles(Object *ob); + void build_particles(Object *object); void build_cloth(Object *object, ModifierData *md); - void build_ik_pose(Object *ob, + void build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map); - void build_splineik_pose(Object *ob, + void build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map); - void build_rig(Object *ob); - void build_proxy_rig(Object *ob); + void build_rig(Object *object); + void build_proxy_rig(Object *object); void build_shapekeys(ID *obdata, Key *key); - void build_obdata_geom(Object *ob); - void build_camera(Object *ob); - void build_lamp(Object *ob); + void build_obdata_geom(Object *object); + void build_camera(Object *object); + void build_lamp(Object *object); void build_nodetree(bNodeTree *ntree); void build_material(Material *ma); void build_texture(Tex *tex); @@ -225,14 +226,14 @@ struct DepsgraphRelationBuilder void add_collision_relations(const OperationKey &key, Scene *scene, - Object *ob, + Object *object, Group *group, int layer, bool dupli, const char *name); void add_forcefield_relations(const OperationKey &key, Scene *scene, - Object *ob, + Object *object, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, @@ -244,11 +245,13 @@ struct DepsgraphRelationBuilder Depsgraph *getGraph(); protected: - TimeSourceDepsNode *find_node(const TimeSourceKey &key) const; - ComponentDepsNode *find_node(const ComponentKey &key) const; + TimeSourceDepsNode *get_node(const TimeSourceKey &key) const; + ComponentDepsNode *get_node(const ComponentKey &key) const; + OperationDepsNode *get_node(const OperationKey &key) const; + DepsNode *get_node(const RNAPathKey &key) const; + OperationDepsNode *find_node(const OperationKey &key) const; - DepsNode *find_node(const RNAPathKey &key) const; - OperationDepsNode *has_node(const OperationKey &key) const; + bool has_node(const OperationKey &key) const; void add_time_relation(TimeSourceDepsNode *timesrc, DepsNode *node_to, @@ -292,7 +295,7 @@ struct DepsNodeHandle template <typename KeyType> OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType& key) { - DepsNode *node = find_node(key); + DepsNode *node = get_node(key); return node != NULL ? node->get_exit_operation() : NULL; } @@ -301,8 +304,8 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from, const KeyTo &key_to, const char *description) { - DepsNode *node_from = find_node(key_from); - DepsNode *node_to = find_node(key_to); + DepsNode *node_from = get_node(key_from); + DepsNode *node_to = get_node(key_to); OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL; OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL; if (op_from && op_to) { @@ -311,7 +314,6 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from, else { if (!op_from) { /* XXX TODO handle as error or report if needed */ - node_from = find_node(key_from); fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n", description, key_from.identifier().c_str()); } @@ -336,14 +338,12 @@ void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from, const KeyTo &key_to, const char *description) { - TimeSourceDepsNode *time_from = find_node(key_from); - DepsNode *node_to = find_node(key_to); + TimeSourceDepsNode *time_from = get_node(key_from); + DepsNode *node_to = get_node(key_to); OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL; - if (time_from && op_to) { + if (time_from != NULL && op_to != NULL) { add_time_relation(time_from, op_to, description); } - else { - } } template <typename KeyType> @@ -352,10 +352,10 @@ void DepsgraphRelationBuilder::add_node_handle_relation( const DepsNodeHandle *handle, const char *description) { - DepsNode *node_from = find_node(key_from); + DepsNode *node_from = get_node(key_from); OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL; OperationDepsNode *op_to = handle->node->get_entry_operation(); - if (op_from && op_to) { + if (op_from != NULL && op_to != NULL) { add_operation_relation(op_from, op_to, description); } else { @@ -375,7 +375,7 @@ DepsNodeHandle DepsgraphRelationBuilder::create_node_handle( const KeyType &key, const char *default_name) { - return DepsNodeHandle(this, find_node(key), default_name); + return DepsNodeHandle(this, get_node(key), default_name); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc index 6ff21393ed6..cdc98ad6b6a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -71,7 +71,7 @@ extern "C" { namespace DEG { /* IK Solver Eval Steps */ -void DepsgraphRelationBuilder::build_ik_pose(Object *ob, +void DepsgraphRelationBuilder::build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map) @@ -86,10 +86,10 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, if (rootchan == NULL) { return; } - OperationKey pchan_local_key(&ob->id, DEG_NODE_TYPE_BONE, + OperationKey pchan_local_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); - OperationKey init_ik_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT_IK); - OperationKey solver_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, + OperationKey init_ik_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT_IK); + OperationKey solver_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER); @@ -107,10 +107,10 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, * testing IK solver. */ // FIXME: geometry targets... - ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE); + ComponentKey pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE); if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) { /* TODO(sergey): This is only for until granular update stores intermediate result. */ - if (data->tar != ob) { + if (data->tar != object) { /* different armature - can just read the results */ ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_BONE, data->subtarget); add_relation(target_key, pose_key, con->name); @@ -140,7 +140,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, add_relation(target_key, pose_key, con->name); } - if ((data->tar == ob) && (data->subtarget[0])) { + if ((data->tar == object) && (data->subtarget[0])) { /* Prevent target's constraints from linking to anything from same * chain that it controls. */ @@ -181,7 +181,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, bPoseChannel *parchan = pchan; /* exclude tip from chain? */ if (!(data->flag & CONSTRAINT_IK_TIP)) { - OperationKey tip_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, + OperationKey tip_transforms_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_LOCAL); add_relation(solver_key, tip_transforms_key, "IK Solver Result"); parchan = pchan->parent; @@ -189,7 +189,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, root_map->add_bone(parchan->name, rootchan->name); - OperationKey parchan_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, + OperationKey parchan_transforms_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); add_relation(parchan_transforms_key, solver_key, "IK Solver Owner"); @@ -205,14 +205,14 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, * grab the result with IK solver results... */ if (parchan != pchan) { - OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); + OperationKey parent_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); add_relation(parent_key, solver_key, "IK Chain Parent"); - OperationKey done_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + OperationKey done_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); add_relation(solver_key, done_key, "IK Chain Result"); } else { - OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + OperationKey final_transforms_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); add_relation(solver_key, final_transforms_key, "IK Solver Result"); } parchan->flag |= POSE_DONE; @@ -228,20 +228,20 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, parchan = parchan->parent; } - OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + OperationKey flush_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); add_relation(solver_key, flush_key, "PoseEval Result-Bone Link"); } /* Spline IK Eval Steps */ -void DepsgraphRelationBuilder::build_splineik_pose(Object *ob, +void DepsgraphRelationBuilder::build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map) { bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data); - OperationKey transforms_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); - OperationKey solver_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER); + OperationKey transforms_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); + OperationKey solver_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER); /* attach owner to IK Solver too * - assume that owner is always part of chain @@ -257,12 +257,12 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob, */ // TODO: the bigggest point here is that we need the curve PATH and not just the general geometry... ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_GEOMETRY); - ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE); + ComponentKey pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE); add_relation(target_key, pose_key, "[Curve.Path -> Spline IK] DepsRel"); } pchan->flag |= POSE_DONE; - OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + OperationKey final_transforms_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); add_relation(solver_key, final_transforms_key, "Spline IK Result"); root_map->add_bone(pchan->name, rootchan->name); @@ -279,15 +279,15 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob, * grab the result with IK solver results... */ if (parchan != pchan) { - OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); + OperationKey parent_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); add_relation(parent_key, solver_key, "Spline IK Solver Update"); - OperationKey done_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + OperationKey done_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); add_relation(solver_key, done_key, "IK Chain Result"); } parchan->flag |= POSE_DONE; - OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + OperationKey final_transforms_key(&object->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); add_relation(solver_key, final_transforms_key, "Spline IK Solver Result"); root_map->add_bone(parchan->name, rootchan->name); @@ -297,22 +297,22 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob, if ((segcount == data->chainlen) || (segcount > 255)) break; /* 255 is weak */ } - OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + OperationKey flush_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); add_relation(solver_key, flush_key, "PoseEval Result-Bone Link"); } /* Pose/Armature Bones Graph */ -void DepsgraphRelationBuilder::build_rig(Object *ob) +void DepsgraphRelationBuilder::build_rig(Object *object) { /* Armature-Data */ - bArmature *arm = (bArmature *)ob->data; + bArmature *arm = (bArmature *)object->data; // TODO: selection status? /* attach links between pose operations */ - OperationKey init_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); - OperationKey init_ik_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT_IK); - OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + OperationKey init_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); + OperationKey init_ik_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT_IK); + OperationKey flush_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); add_relation(init_key, init_ik_key, "Pose Init -> Pose Init IK"); add_relation(init_ik_key, flush_key, "Pose Init IK -> Pose Cleanup"); @@ -324,8 +324,8 @@ void DepsgraphRelationBuilder::build_rig(Object *ob) "Armature Eval"); add_relation(armature_key, init_key, "Data dependency"); - if (needs_animdata_node(&ob->id)) { - ComponentKey animation_key(&ob->id, DEG_NODE_TYPE_ANIMATION); + if (needs_animdata_node(&object->id)) { + ComponentKey animation_key(&object->id, DEG_NODE_TYPE_ANIMATION); add_relation(animation_key, init_key, "Rig Animation"); } @@ -346,16 +346,16 @@ void DepsgraphRelationBuilder::build_rig(Object *ob) */ RootPChanMap root_map; bool pose_depends_on_local_transform = false; - LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { + LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { LINKLIST_FOREACH (bConstraint *, con, &pchan->constraints) { switch (con->type) { case CONSTRAINT_TYPE_KINEMATIC: - build_ik_pose(ob, pchan, con, &root_map); + build_ik_pose(object, pchan, con, &root_map); pose_depends_on_local_transform = true; break; case CONSTRAINT_TYPE_SPLINEIK: - build_splineik_pose(ob, pchan, con, &root_map); + build_splineik_pose(object, pchan, con, &root_map); pose_depends_on_local_transform = true; break; @@ -381,17 +381,17 @@ void DepsgraphRelationBuilder::build_rig(Object *ob) /* TODO(sergey): Once partial updates are possible use relation between * object transform and solver itself in it's build function. */ - ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE); - ComponentKey local_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE); + ComponentKey local_transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM); add_relation(local_transform_key, pose_key, "Local Transforms"); } /* links between operations for each bone */ - LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { - OperationKey bone_local_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); - OperationKey bone_pose_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT); - OperationKey bone_ready_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); - OperationKey bone_done_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + OperationKey bone_local_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); + OperationKey bone_pose_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT); + OperationKey bone_ready_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); + OperationKey bone_done_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); pchan->flag &= ~POSE_DONE; @@ -413,17 +413,17 @@ void DepsgraphRelationBuilder::build_rig(Object *ob) parent_key_opcode = DEG_OPCODE_BONE_DONE; } - OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->parent->name, parent_key_opcode); + OperationKey parent_key(&object->id, DEG_NODE_TYPE_BONE, pchan->parent->name, parent_key_opcode); add_relation(parent_key, bone_pose_key, "[Parent Bone -> Child Bone]"); } /* constraints */ if (pchan->constraints.first != NULL) { /* constraints stack and constraint dependencies */ - build_constraints(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map); + build_constraints(&object->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map); /* pose -> constraints */ - OperationKey constraints_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS); + OperationKey constraints_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS); add_relation(bone_pose_key, constraints_key, "Constraints Stack"); /* constraints -> ready */ @@ -447,14 +447,14 @@ void DepsgraphRelationBuilder::build_rig(Object *ob) } } -void DepsgraphRelationBuilder::build_proxy_rig(Object *ob) +void DepsgraphRelationBuilder::build_proxy_rig(Object *object) { - OperationKey pose_init_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); - OperationKey pose_done_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); - LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { - OperationKey bone_local_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); - OperationKey bone_ready_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); - OperationKey bone_done_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + OperationKey pose_init_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); + OperationKey pose_done_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + LINKLIST_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + OperationKey bone_local_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); + OperationKey bone_ready_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); + OperationKey bone_done_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local"); add_relation(bone_local_key, bone_ready_key, "Local -> Ready"); add_relation(bone_ready_key, bone_done_key, "Ready -> Done"); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc index bedcb5aa223..bface46c201 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc @@ -78,8 +78,8 @@ void DepsgraphRelationBuilder::build_scene(Scene *scene) /* scene objects */ LINKLIST_FOREACH (Base *, base, &scene->base) { - Object *ob = base->object; - build_object(ob); + Object *object = base->object; + build_object(object); } /* rigidbody */ diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index aa21f0995be..a17b083feb9 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -144,19 +144,19 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, return true; } else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) { - Object *ob = (Object *)ptr->id.data; + Object *object = (Object *)ptr->id.data; bConstraint *con = (bConstraint *)ptr->data; /* object or bone? */ - if (BLI_findindex(&ob->constraints, con) != -1) { + if (BLI_findindex(&object->constraints, con) != -1) { /* object transform */ // XXX: for now, we can't address the specific constraint or the constraint stack... *type = DEG_NODE_TYPE_TRANSFORM; return true; } - else if (ob->pose) { + else if (object->pose) { bPoseChannel *pchan; - for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) { + for (pchan = (bPoseChannel *)object->pose->chanbase.first; pchan; pchan = pchan->next) { if (BLI_findindex(&pchan->constraints, con) != -1) { /* bone transforms */ *type = DEG_NODE_TYPE_BONE; @@ -180,7 +180,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, return true; } else if (ptr->type == &RNA_Object) { - //Object *ob = (Object *)ptr->data; + //Object *object = (Object *)ptr->data; /* Transforms props? */ if (prop) { diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index fb762505ed2..4b3d4190dcd 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -124,12 +124,12 @@ void DEG_add_scene_relation(DepsNodeHandle *handle, } void DEG_add_object_relation(DepsNodeHandle *handle, - Object *ob, + Object *object, eDepsObjectComponentType component, const char *description) { DEG::eDepsNode_Type type = deg_build_object_component_type(component); - DEG::ComponentKey comp_key(&ob->id, type); + DEG::ComponentKey comp_key(&object->id, type); DEG::DepsNodeHandle *deg_handle = get_handle(handle); deg_handle->builder->add_node_handle_relation(comp_key, deg_handle, @@ -150,13 +150,13 @@ void DEG_add_object_cache_relation(DepsNodeHandle *handle, } void DEG_add_bone_relation(DepsNodeHandle *handle, - Object *ob, + Object *object, const char *bone_name, eDepsObjectComponentType component, const char *description) { DEG::eDepsNode_Type type = deg_build_object_component_type(component); - DEG::ComponentKey comp_key(&ob->id, type, bone_name); + DEG::ComponentKey comp_key(&object->id, type, bone_name); DEG::DepsNodeHandle *deg_handle = get_handle(handle); /* XXX: "Geometry Eval" might not always be true, but this only gets called * from modifier building now. @@ -314,7 +314,7 @@ void DEG_scene_graph_free(Scene *scene) void DEG_add_collision_relations(DepsNodeHandle *handle, Scene *scene, - Object *ob, + Object *object, Group *group, int layer, unsigned int modifier_type, @@ -323,7 +323,7 @@ void DEG_add_collision_relations(DepsNodeHandle *handle, const char *name) { unsigned int numcollobj; - Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli); + Object **collobjs = get_collisionobjects_ext(scene, object, group, layer, &numcollobj, modifier_type, dupli); for (unsigned int i = 0; i < numcollobj; i++) { Object *ob1 = collobjs[i]; @@ -340,17 +340,17 @@ void DEG_add_collision_relations(DepsNodeHandle *handle, void DEG_add_forcefield_relations(DepsNodeHandle *handle, Scene *scene, - Object *ob, + Object *object, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name) { - ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false); + ListBase *effectors = pdInitEffectors(scene, object, NULL, effector_weights, false); if (effectors) { for (EffectorCache *eff = (EffectorCache*)effectors->first; eff; eff = eff->next) { - if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) { + if (eff->ob != object && eff->pd->forcefield != skip_forcefield) { DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_TRANSFORM, name); if (eff->psys) { @@ -376,7 +376,7 @@ void DEG_add_forcefield_relations(DepsNodeHandle *handle, if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) { DEG_add_collision_relations(handle, scene, - ob, + object, NULL, eff->ob->lay, eModifierType_Collision, diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 0adbadeebba..83fc756654f 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -178,6 +178,7 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) case DEG_NODE_TYPE_PARAMETERS: case DEG_NODE_TYPE_SEQUENCER: /* Ignore, does not translate to object component. */ + BLI_assert(!"This should never happen!"); break; case DEG_NODE_TYPE_ANIMATION: object->recalc |= OB_RECALC_TIME; diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc index e87c87813e3..010f12409b4 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc @@ -87,8 +87,8 @@ bool ComponentDepsNode::OperationIDKey::operator==( const OperationIDKey &other) const { return (opcode == other.opcode) && - (STREQ(name, other.name)) && - (name_tag == other.name_tag); + (STREQ(name, other.name)) && + (name_tag == other.name_tag); } static unsigned int comp_node_hash_key(const void *key_v) @@ -165,36 +165,62 @@ string ComponentDepsNode::identifier() const OperationDepsNode *ComponentDepsNode::find_operation(OperationIDKey key) const { - OperationDepsNode *node = reinterpret_cast<OperationDepsNode *>(BLI_ghash_lookup(operations_map, &key)); - if (node != NULL) { - return node; + OperationDepsNode *node; + if (operations_map != NULL) { + node = (OperationDepsNode *)BLI_ghash_lookup(operations_map, &key); } else { - fprintf(stderr, "%s: find_operation(%s) failed\n", - this->identifier().c_str(), key.identifier().c_str()); - BLI_assert(!"Request for non-existing operation, should not happen"); - return NULL; + BLI_assert(key.name_tag == -1); + foreach (OperationDepsNode *op_node, operations) { + if (op_node->opcode == key.opcode && + STREQ(op_node->name, key.name)) + { + node = op_node; + break; + } + } } + return node; } OperationDepsNode *ComponentDepsNode::find_operation(eDepsOperation_Code opcode, - const char *name, - int name_tag) const + const char *name, + int name_tag) const { OperationIDKey key(opcode, name, name_tag); return find_operation(key); } -OperationDepsNode *ComponentDepsNode::has_operation(OperationIDKey key) const +OperationDepsNode *ComponentDepsNode::get_operation(OperationIDKey key) const { - return reinterpret_cast<OperationDepsNode *>(BLI_ghash_lookup(operations_map, &key)); + OperationDepsNode *node = find_operation(key); + if (node == NULL) { + fprintf(stderr, "%s: find_operation(%s) failed\n", + this->identifier().c_str(), key.identifier().c_str()); + BLI_assert(!"Request for non-existing operation, should not happen"); + return NULL; + } + return node; } -OperationDepsNode *ComponentDepsNode::has_operation(eDepsOperation_Code opcode, +OperationDepsNode *ComponentDepsNode::get_operation(eDepsOperation_Code opcode, const char *name, int name_tag) const { OperationIDKey key(opcode, name, name_tag); + return get_operation(key); +} + +bool ComponentDepsNode::has_operation(OperationIDKey key) const +{ + return find_operation(key) != NULL; +} + +bool ComponentDepsNode::has_operation(eDepsOperation_Code opcode, + const char *name, + int name_tag) const +{ + OperationIDKey key(opcode, name, name_tag); return has_operation(key); } @@ -203,7 +229,7 @@ OperationDepsNode *ComponentDepsNode::add_operation(const DepsEvalOperationCb& o const char *name, int name_tag) { - OperationDepsNode *op_node = has_operation(opcode, name, name_tag); + OperationDepsNode *op_node = find_operation(opcode, name, name_tag); if (!op_node) { DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_OPERATION); op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name); @@ -333,40 +359,25 @@ void ComponentDepsNode::finalize_build() operations_map = NULL; } -/* Parameter Component Defines ============================ */ - -DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEG_NODE_TYPE_PARAMETERS, "Parameters Component"); -static DepsNodeFactoryImpl<ParametersComponentDepsNode> DNTI_PARAMETERS; - -/* Animation Component Defines ============================ */ - -DEG_DEPSNODE_DEFINE(AnimationComponentDepsNode, DEG_NODE_TYPE_ANIMATION, "Animation Component"); -static DepsNodeFactoryImpl<AnimationComponentDepsNode> DNTI_ANIMATION; - -/* Transform Component Defines ============================ */ - -DEG_DEPSNODE_DEFINE(TransformComponentDepsNode, DEG_NODE_TYPE_TRANSFORM, "Transform Component"); -static DepsNodeFactoryImpl<TransformComponentDepsNode> DNTI_TRANSFORM; - -/* Proxy Component Defines ================================ */ - -DEG_DEPSNODE_DEFINE(ProxyComponentDepsNode, DEG_NODE_TYPE_PROXY, "Proxy Component"); -static DepsNodeFactoryImpl<ProxyComponentDepsNode> DNTI_PROXY; - -/* Geometry Component Defines ============================= */ +/* Register all components. =============================== */ -DEG_DEPSNODE_DEFINE(GeometryComponentDepsNode, DEG_NODE_TYPE_GEOMETRY, "Geometry Component"); -static DepsNodeFactoryImpl<GeometryComponentDepsNode> DNTI_GEOMETRY; +#define DEG_COMPONENT_DEFINE(name, NAME) \ + DEG_DEPSNODE_DEFINE(name ## ComponentDepsNode, \ + DEG_NODE_TYPE_ ## NAME, \ + #name " Component"); \ +static DepsNodeFactoryImpl<name ## ComponentDepsNode> DNTI_ ## NAME -/* Sequencer Component Defines ============================ */ -DEG_DEPSNODE_DEFINE(SequencerComponentDepsNode, DEG_NODE_TYPE_SEQUENCER, "Sequencer Component"); -static DepsNodeFactoryImpl<SequencerComponentDepsNode> DNTI_SEQUENCER; - -/* Pose Component ========================================= */ - -DEG_DEPSNODE_DEFINE(PoseComponentDepsNode, DEG_NODE_TYPE_EVAL_POSE, "Pose Eval Component"); -static DepsNodeFactoryImpl<PoseComponentDepsNode> DNTI_EVAL_POSE; +DEG_COMPONENT_DEFINE(Animation, ANIMATION); +DEG_COMPONENT_DEFINE(Cache, CACHE); +DEG_COMPONENT_DEFINE(Geometry, GEOMETRY); +DEG_COMPONENT_DEFINE(Parameters, PARAMETERS); +DEG_COMPONENT_DEFINE(Particles, EVAL_PARTICLES); +DEG_COMPONENT_DEFINE(Proxy, PROXY); +DEG_COMPONENT_DEFINE(Pose, EVAL_POSE); +DEG_COMPONENT_DEFINE(Sequencer, SEQUENCER); +DEG_COMPONENT_DEFINE(Shading, SHADING); +DEG_COMPONENT_DEFINE(Transform, TRANSFORM); /* Bone Component ========================================= */ @@ -383,28 +394,11 @@ void BoneComponentDepsNode::init(const ID *id, const char *subdata) //this->name = subdata; /* bone-specific node data */ - Object *ob = (Object *)id; - this->pchan = BKE_pose_channel_find_name(ob->pose, subdata); + Object *object = (Object *)id; + this->pchan = BKE_pose_channel_find_name(object->pose, subdata); } -DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEG_NODE_TYPE_BONE, "Bone Component"); -static DepsNodeFactoryImpl<BoneComponentDepsNode> DNTI_BONE; - -/* Particles Component Defines ============================ */ - -DEG_DEPSNODE_DEFINE(ParticlesComponentDepsNode, DEG_NODE_TYPE_EVAL_PARTICLES, "Particles Component"); -static DepsNodeFactoryImpl<ParticlesComponentDepsNode> DNTI_EVAL_PARTICLES; - -/* Shading Component Defines ============================ */ - -DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEG_NODE_TYPE_SHADING, "Shading Component"); -static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING; - -/* Cache Component Defines ============================ */ - -DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEG_NODE_TYPE_CACHE, "Cache Component"); -static DepsNodeFactoryImpl<CacheComponentDepsNode> DNTI_CACHE; - +DEG_COMPONENT_DEFINE(Bone, BONE); /* Node Types Register =================================== */ diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h index 4ef7dad3ac6..1c21a71737f 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_component.h +++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h @@ -74,18 +74,26 @@ struct ComponentDepsNode : public DepsNode { string identifier() const; - /* Find an existing operation, will throw an assert() if it does not exist. */ + /* Find an existing operation, if requested operation does not exist + * NULL will be returned. + */ OperationDepsNode *find_operation(OperationIDKey key) const; OperationDepsNode *find_operation(eDepsOperation_Code opcode, - const char *name, - int name_tag) const; + const char *name, + int name_tag) const; - /* Check operation exists and return it. */ - OperationDepsNode *has_operation(OperationIDKey key) const; - OperationDepsNode *has_operation(eDepsOperation_Code opcode, + /* Find an existing operation, will throw an assert() if it does not exist. */ + OperationDepsNode *get_operation(OperationIDKey key) const; + OperationDepsNode *get_operation(eDepsOperation_Code opcode, const char *name, int name_tag) const; + /* Check operation exists and return it. */ + bool has_operation(OperationIDKey key) const; + bool has_operation(eDepsOperation_Code opcode, + const char *name, + int name_tag) const; + /** * Create a new node for representing an operation and add this to graph * \warning If an existing node is found, it will be modified. This helps @@ -158,33 +166,21 @@ struct ComponentDepsNode : public DepsNode { /* ---------------------------------------- */ -struct ParametersComponentDepsNode : public ComponentDepsNode { - DEG_DEPSNODE_DECLARE; -}; - -struct AnimationComponentDepsNode : public ComponentDepsNode { - DEG_DEPSNODE_DECLARE; -}; - -struct TransformComponentDepsNode : public ComponentDepsNode { - DEG_DEPSNODE_DECLARE; -}; - -struct ProxyComponentDepsNode : public ComponentDepsNode { - DEG_DEPSNODE_DECLARE; -}; - -struct GeometryComponentDepsNode : public ComponentDepsNode { - DEG_DEPSNODE_DECLARE; -}; - -struct SequencerComponentDepsNode : public ComponentDepsNode { - DEG_DEPSNODE_DECLARE; -}; - -struct PoseComponentDepsNode : public ComponentDepsNode { - DEG_DEPSNODE_DECLARE; -}; +#define DEG_COMPONENT_DECLARE_GENERIC(name) \ + struct name ## ComponentDepsNode : public ComponentDepsNode { \ + DEG_DEPSNODE_DECLARE; \ + } + +DEG_COMPONENT_DECLARE_GENERIC(Animation); +DEG_COMPONENT_DECLARE_GENERIC(Cache); +DEG_COMPONENT_DECLARE_GENERIC(Geometry); +DEG_COMPONENT_DECLARE_GENERIC(Parameters); +DEG_COMPONENT_DECLARE_GENERIC(Particles); +DEG_COMPONENT_DECLARE_GENERIC(Proxy); +DEG_COMPONENT_DECLARE_GENERIC(Pose); +DEG_COMPONENT_DECLARE_GENERIC(Sequencer); +DEG_COMPONENT_DECLARE_GENERIC(Shading); +DEG_COMPONENT_DECLARE_GENERIC(Transform); /* Bone Component */ struct BoneComponentDepsNode : public ComponentDepsNode { @@ -195,19 +191,6 @@ struct BoneComponentDepsNode : public ComponentDepsNode { DEG_DEPSNODE_DECLARE; }; -struct ParticlesComponentDepsNode : public ComponentDepsNode { - DEG_DEPSNODE_DECLARE; -}; - -struct ShadingComponentDepsNode : public ComponentDepsNode { - DEG_DEPSNODE_DECLARE; -}; - -struct CacheComponentDepsNode : public ComponentDepsNode { - DEG_DEPSNODE_DECLARE; -}; - - void deg_register_component_depsnodes(); } // namespace DEG diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 25f1e206be5..82f24c91df1 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -34,11 +34,9 @@ #include "MEM_guardedalloc.h" -#include "BKE_depsgraph.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_listbase.h" -#include "BKE_library.h" #include "DNA_anim_types.h" #include "DNA_object_types.h" @@ -52,11 +50,13 @@ #include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_gpencil.h" #include "BKE_context.h" #include "BKE_mask.h" #include "BKE_global.h" +#include "BKE_library.h" #include "UI_view2d.h" diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 30aaee8cbd9..04398e88499 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -133,10 +133,13 @@ int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, f float cfra = (float)CFRA; int changed_tot = 0; - /* sanity check */ - if (markers == NULL) + /* sanity check - no markers, or locked markers */ + if ((scene->toolsettings->lock_markers) || + (markers == NULL)) + { return changed_tot; - + } + /* affect selected markers - it's unlikely that we will want to affect all in this way? */ for (marker = markers->first; marker; marker = marker->next) { if (marker->flag & SELECT) { diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 97f53561bfe..bf5d4ec0300 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -448,6 +448,18 @@ void sample_fcurve(FCurve *fcu) /* check if selected, and which end this is */ if (BEZT_ISSEL_ANY(bezt)) { if (start) { + /* If next bezt is also selected, don't start sampling yet, + * but instead wait for that one to reconsider, to avoid + * changing the curve when sampling consecutive segments + * (T53229) + */ + if (i < fcu->totvert - 1) { + BezTriple *next = &fcu->bezt[i + 1]; + if (BEZT_ISSEL_ANY(next)) { + continue; + } + } + /* set end */ end = bezt; @@ -480,8 +492,8 @@ void sample_fcurve(FCurve *fcu) i += (range - 1); } - /* bezt was selected, so it now marks the start of a whole new chain to search */ - start = bezt; + /* the current selection island has ended, so start again from scratch */ + start = NULL; end = NULL; } else { diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index e419100bd04..368d54fc3ad 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -944,9 +944,16 @@ static int armature_extrude_exec(bContext *C, wmOperator *op) } } /* if only one bone, make this one active */ - if (totbone == 1 && first) arm->act_edbone = first; + if (totbone == 1 && first) { + arm->act_edbone = first; + } + else { + arm->act_edbone = newbone; + } - if (totbone == 0) return OPERATOR_CANCELLED; + if (totbone == 0) { + return OPERATOR_CANCELLED; + } /* Transform the endpoints */ ED_armature_sync_selection(arm->edbo); diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index ab9a3e068d0..a2fbfe645f7 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -1564,17 +1564,18 @@ void ARMATURE_OT_hide(wmOperatorType *ot) RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected"); } -static int armature_reveal_exec(bContext *C, wmOperator *UNUSED(op)) +static int armature_reveal_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); bArmature *arm = obedit->data; EditBone *ebone; + const bool select = RNA_boolean_get(op->ptr, "select"); for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { if (arm->layer & ebone->layer) { if (ebone->flag & BONE_HIDDEN_A) { if (!(ebone->flag & BONE_UNSELECTABLE)) { - ebone->flag |= (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); + SET_FLAG_FROM_TEST(ebone->flag, select, (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL)); } ebone->flag &= ~BONE_HIDDEN_A; } @@ -1593,7 +1594,7 @@ void ARMATURE_OT_reveal(wmOperatorType *ot) /* identifiers */ ot->name = "Reveal Bones"; ot->idname = "ARMATURE_OT_reveal"; - ot->description = "Unhide all bones that have been tagged to be hidden in Edit Mode"; + ot->description = "Reveal all bones hidden in Edit Mode"; /* api callbacks */ ot->exec = armature_reveal_exec; @@ -1602,4 +1603,5 @@ void ARMATURE_OT_reveal(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 93185971492..07ff7f15ce4 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -38,7 +38,7 @@ #include "BLI_string_utils.h" #include "BKE_context.h" -//#include "BKE_deform.h" +#include "BKE_action.h" #include "BKE_report.h" #include "BIF_gl.h" @@ -801,6 +801,7 @@ enum { SIMEDBONE_PREFIX, SIMEDBONE_SUFFIX, SIMEDBONE_LAYER, + SIMEDBONE_SHAPE, }; static const EnumPropertyItem prop_similar_types[] = { @@ -812,6 +813,7 @@ static const EnumPropertyItem prop_similar_types[] = { {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""}, {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""}, {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""}, + {SIMEDBONE_SHAPE, "SHAPE", 0, "Shape", ""}, {0, NULL, 0, NULL, NULL} }; @@ -914,7 +916,27 @@ static void select_similar_suffix(bArmature *arm, EditBone *ebone_act) } } -static void is_ancestor(EditBone * bone, EditBone * ancestor) +/** Use for matching any pose channel data. */ +static void select_similar_data_pchan( + bArmature *arm, Object *obj, EditBone *ebone_active, + const size_t bytes_size, const int offset) +{ + const bPoseChannel *pchan_active = BKE_pose_channel_find_name(obj->pose, ebone_active->name); + const char *data_active = (const char *)POINTER_OFFSET(pchan_active, offset); + for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (EBONE_SELECTABLE(arm, ebone)) { + const bPoseChannel *pchan = BKE_pose_channel_find_name(obj->pose, ebone->name); + if (pchan) { + const char *data_test = (const char *)POINTER_OFFSET(pchan, offset); + if (memcmp(data_active, data_test, bytes_size) == 0) { + ED_armature_ebone_select_set(ebone, true); + } + } + } + } +} + +static void is_ancestor(EditBone *bone, EditBone *ancestor) { if (bone->temp.ebone == ancestor || bone->temp.ebone == NULL) return; @@ -1006,6 +1028,11 @@ static int armature_select_similar_exec(bContext *C, wmOperator *op) case SIMEDBONE_LAYER: select_similar_layer(arm, ebone_act); break; + case SIMEDBONE_SHAPE: + select_similar_data_pchan( + arm, obedit, ebone_act, + sizeof(void *), offsetof(bPoseChannel, custom)); + break; } WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index c49a370c286..acbf23ecf82 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -265,8 +265,8 @@ void POSE_OT_paths_calculate(wmOperatorType *ot) static int pose_update_paths_poll(bContext *C) { if (ED_operator_posemode_exclusive(C)) { - bPoseChannel *pchan = CTX_data_active_pose_bone(C); - return (pchan && pchan->mpath); + Object *ob = CTX_data_active_object(C); + return (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0; } return false; @@ -1098,16 +1098,18 @@ void POSE_OT_hide(wmOperatorType *ot) RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", ""); } -static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr)) +static int show_pose_bone_cb(Object *ob, Bone *bone, void *data) { + const bool select = GET_INT_FROM_POINTER(data); + bArmature *arm = ob->data; if (arm->layer & bone->layer) { if (bone->flag & BONE_HIDDEN_P) { - bone->flag &= ~BONE_HIDDEN_P; if (!(bone->flag & BONE_UNSELECTABLE)) { - bone->flag |= BONE_SELECTED; + SET_FLAG_FROM_TEST(bone->flag, select, BONE_SELECTED); } + bone->flag &= ~BONE_HIDDEN_P; } } @@ -1115,12 +1117,13 @@ static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr)) } /* active object is armature in posemode, poll checked */ -static int pose_reveal_exec(bContext *C, wmOperator *UNUSED(op)) +static int pose_reveal_exec(bContext *C, wmOperator *op) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); bArmature *arm = ob->data; + const bool select = RNA_boolean_get(op->ptr, "select"); - bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone_cb); + bone_looper(ob, arm->bonebase.first, SET_INT_IN_POINTER(select), show_pose_bone_cb); /* note, notifier might evolve */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); @@ -1133,7 +1136,7 @@ void POSE_OT_reveal(wmOperatorType *ot) /* identifiers */ ot->name = "Reveal Selected"; ot->idname = "POSE_OT_reveal"; - ot->description = "Unhide all bones that have been tagged to be hidden in Pose Mode"; + ot->description = "Reveal all bones hidden in Pose Mode"; /* api callbacks */ ot->exec = pose_reveal_exec; @@ -1141,6 +1144,8 @@ void POSE_OT_reveal(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } /* ********************************************** */ diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 2d86610e065..3707b914ecb 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -484,12 +484,15 @@ static int pose_paste_exec(bContext *C, wmOperator *op) bPoseChannel *chan; const bool flip = RNA_boolean_get(op->ptr, "flipped"); bool selOnly = RNA_boolean_get(op->ptr, "selected_mask"); + /* Get KeyingSet to use. */ KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID); + /* Sanity checks. */ if (ELEM(NULL, ob, ob->pose)) { return OPERATOR_CANCELLED; } + /* Read copy buffer .blend file. */ char str[FILE_MAX]; Main *tmp_bmain = BKE_main_new(); @@ -505,6 +508,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op) BKE_main_free(tmp_bmain); return OPERATOR_CANCELLED; } + Object *object_from = tmp_bmain->object.first; bPose *pose_from = object_from->pose; if (pose_from == NULL) { @@ -512,6 +516,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op) BKE_main_free(tmp_bmain); return OPERATOR_CANCELLED; } + /* If selOnly option is enabled, if user hasn't selected any bones, * just go back to default behavior to be more in line with other * pose tools. @@ -521,6 +526,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op) selOnly = false; } } + /* Safely merge all of the channels in the buffer pose into any * existing pose. */ @@ -535,8 +541,15 @@ static int pose_paste_exec(bContext *C, wmOperator *op) } } BKE_main_free(tmp_bmain); + /* Update event for pose and deformation children. */ DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + + /* Recalculate paths if any of the bones have paths... */ + if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { + ED_pose_recalculate_paths(scene, ob); + } + /* Notifiers for updates, */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 4916c206a85..fc363475608 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2926,7 +2926,7 @@ void CURVE_OT_hide(wmOperatorType *ot) /********************** reveal operator *********************/ -static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) +static int reveal_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); ListBase *editnurb = object_editcurve_get(obedit); @@ -2934,6 +2934,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) BPoint *bp; BezTriple *bezt; int a; + const bool select = RNA_boolean_get(op->ptr, "select"); for (nu = editnurb->first; nu; nu = nu->next) { nu->hide = 0; @@ -2942,7 +2943,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) a = nu->pntsu; while (a--) { if (bezt->hide) { - select_beztriple(bezt, SELECT, SELECT, HIDDEN); + select_beztriple(bezt, select, SELECT, HIDDEN); bezt->hide = 0; } bezt++; @@ -2953,7 +2954,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) a = nu->pntsu * nu->pntsv; while (a--) { if (bp->hide) { - select_bpoint(bp, SELECT, SELECT, HIDDEN); + select_bpoint(bp, select, SELECT, HIDDEN); bp->hide = 0; } bp++; @@ -2972,7 +2973,7 @@ void CURVE_OT_reveal(wmOperatorType *ot) /* identifiers */ ot->name = "Reveal Hidden"; ot->idname = "CURVE_OT_reveal"; - ot->description = "Show again hidden control points"; + ot->description = "Reveal hidden control points"; /* api callbacks */ ot->exec = reveal_exec; @@ -2980,6 +2981,8 @@ void CURVE_OT_reveal(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } /********************** subdivide operator *********************/ diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 93c9d21e717..5bd5c9c74b9 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -423,18 +423,59 @@ static int gp_reveal_poll(bContext *C) return ED_gpencil_data_get_active(C) != NULL; } -static int gp_reveal_exec(bContext *C, wmOperator *UNUSED(op)) +static void gp_reveal_select_frame(bContext *C, bGPDframe *frame, bool select) +{ + bGPDstroke *gps; + for (gps = frame->strokes.first; gps; gps = gps->next) { + + /* only deselect strokes that are valid in this view */ + if (ED_gpencil_stroke_can_use(C, gps)) { + + /* (de)select points */ + int i; + bGPDspoint *pt; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + SET_FLAG_FROM_TEST(pt->flag, select, GP_SPOINT_SELECT); + } + + /* (de)select stroke */ + SET_FLAG_FROM_TEST(gps->flag, select, GP_STROKE_SELECT); + } + } +} + +static int gp_reveal_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl; - + const bool select = RNA_boolean_get(op->ptr, "select"); + /* sanity checks */ if (gpd == NULL) return OPERATOR_CANCELLED; - /* make all layers visible */ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - gpl->flag &= ~GP_LAYER_HIDE; + + if (gpl->flag & GP_LAYER_HIDE) { + gpl->flag &= ~GP_LAYER_HIDE; + + /* select or deselect if requested, only on hidden layers */ + if (gpd->flag & GP_DATA_STROKE_EDITMODE) { + if (select) { + /* select all strokes on active frame only (same as select all operator) */ + if (gpl->actframe) { + gp_reveal_select_frame(C, gpl->actframe, true); + } + } + else { + /* deselect strokes on all frames (same as deselect all operator) */ + bGPDframe *gpf; + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + gp_reveal_select_frame(C, gpf, false); + } + } + } + } } /* notifiers */ @@ -456,6 +497,9 @@ void GPENCIL_OT_reveal(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } /* ***************** Lock/Unlock All Layers ************************ */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index cff198db6c0..f54356dfed3 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -2745,6 +2745,8 @@ static const EnumPropertyItem prop_gpencil_drawmodes[] = { void GPENCIL_OT_draw(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Grease Pencil Draw"; ot->idname = "GPENCIL_OT_draw"; @@ -2761,11 +2763,12 @@ void GPENCIL_OT_draw(wmOperatorType *ot) ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; /* settings for drawing */ - PropertyRNA *prop; ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements"); + prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); /* NOTE: wait for input is enabled by default, so that all UI code can work properly without needing users to know about this */ - RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately"); + prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index c867df2d01a..84698b33e25 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -75,7 +75,6 @@ struct BMFace *EDBM_verts_mirror_get_face(struct BMEditMesh *em, struct BMFace * void EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVert *v); void EDBM_verts_mirror_cache_end(struct BMEditMesh *em); -void EDBM_mesh_ensure_valid_dm_hack(struct Scene *scene, struct BMEditMesh *em); void EDBM_mesh_normals_update(struct BMEditMesh *em); void EDBM_mesh_clear(struct BMEditMesh *em); @@ -103,7 +102,7 @@ void undo_push_mesh(struct bContext *C, const char *name); bool EDBM_vert_color_check(struct BMEditMesh *em); void EDBM_mesh_hide(struct BMEditMesh *em, bool swap); -void EDBM_mesh_reveal(struct BMEditMesh *em); +void EDBM_mesh_reveal(struct BMEditMesh *em, bool select); void EDBM_update_generic(struct BMEditMesh *em, const bool do_tessface, const bool is_destructive); @@ -205,7 +204,7 @@ void paintface_select_linked(struct bContext *C, struct Object *ob, const int mv bool paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]); void paintface_hide(struct Object *ob, const bool unselected); -void paintface_reveal(struct Object *ob); +void paintface_reveal(struct Object *ob, const bool select); void paintvert_deselect_all_visible(struct Object *ob, int action, bool flush_flags); void paintvert_select_ungrouped(struct Object *ob, bool extend, bool flush_flags); diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 535683823bf..354a9655a48 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -101,7 +101,8 @@ void ED_uvedit_live_unwrap_end(short cancel); void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit); void ED_uvedit_pack_islands(struct Scene *scene, struct Object *ob, struct BMesh *bm, bool selected, bool correct_aspect, bool do_rotate); -void ED_uvedit_unwrap_cube_project(struct Object *ob, struct BMesh *bm, float cube_size, bool use_select); +void ED_uvedit_unwrap_cube_project( + struct BMesh *bm, float cube_size, bool use_select, const float center[3]); /* single call up unwrap using scene settings, used for edge tag unwrapping */ void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 85fb0ee4447..2cc928117c5 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -367,15 +367,27 @@ void ED_view3d_draw_setup_view( struct wmWindow *win, struct Scene *scene, struct ARegion *ar, struct View3D *v3d, float viewmat[4][4], float winmat[4][4], const struct rcti *rect); +enum { + V3D_OFSDRAW_NONE = (0), + + V3D_OFSDRAW_USE_BACKGROUND = (1 << 0), + V3D_OFSDRAW_USE_FULL_SAMPLE = (1 << 1), + + /* Only works with ED_view3d_draw_offscreen_imbuf_simple(). */ + V3D_OFSDRAW_USE_GPENCIL = (1 << 2), + V3D_OFSDRAW_USE_SOLID_TEX = (1 << 2), + V3D_OFSDRAW_USE_CAMERA_DOF = (1 << 3), +}; + struct ImBuf *ED_view3d_draw_offscreen_imbuf( struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, - unsigned int flag, bool draw_background, - int alpha_mode, int samples, bool full_samples, const char *viewname, + unsigned int flag, unsigned int draw_flags, + int alpha_mode, int samples, const char *viewname, struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]); struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple( struct Scene *scene, struct Object *camera, int width, int height, - unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background, - int alpha_mode, int samples, bool full_samples, const char *viewname, + unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode, + int samples, const char *viewname, struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]); struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index be7eb2bf9ed..407c19a3860 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -658,87 +658,18 @@ void ED_mask_draw(const bContext *C, draw_masklays(C, mask, draw_flag, draw_type, width, height, xscale * aspx, yscale * aspy); } -typedef struct ThreadedMaskRasterizeState { - MaskRasterHandle *handle; - float *buffer; - int width, height; -} ThreadedMaskRasterizeState; - -typedef struct ThreadedMaskRasterizeData { - int start_scanline; - int num_scanlines; -} ThreadedMaskRasterizeData; - -static void mask_rasterize_func(TaskPool * __restrict pool, void *taskdata, int UNUSED(threadid)) +static float *mask_rasterize(Mask *mask, const int width, const int height) { - ThreadedMaskRasterizeState *state = (ThreadedMaskRasterizeState *) BLI_task_pool_userdata(pool); - ThreadedMaskRasterizeData *data = (ThreadedMaskRasterizeData *) taskdata; - int scanline; - const float x_inv = 1.0f / (float)state->width; - const float y_inv = 1.0f / (float)state->height; - const float x_px_ofs = x_inv * 0.5f; - const float y_px_ofs = y_inv * 0.5f; - - for (scanline = 0; scanline < data->num_scanlines; scanline++) { - float xy[2]; - int x, y = data->start_scanline + scanline; - - xy[1] = ((float)y * y_inv) + y_px_ofs; - - for (x = 0; x < state->width; x++) { - int index = y * state->width + x; - - xy[0] = ((float)x * x_inv) + x_px_ofs; - - state->buffer[index] = BKE_maskrasterize_handle_sample(state->handle, xy); - } - } -} - -static float *threaded_mask_rasterize(Mask *mask, const int width, const int height) -{ - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - TaskPool *task_pool; MaskRasterHandle *handle; - ThreadedMaskRasterizeState state; - float *buffer; - int i, num_threads = BLI_task_scheduler_num_threads(task_scheduler), scanlines_per_thread; - - buffer = MEM_mallocN(sizeof(float) * height * width, "rasterized mask buffer"); + float *buffer = MEM_mallocN(sizeof(float) * height * width, "rasterized mask buffer"); /* Initialize rasterization handle. */ handle = BKE_maskrasterize_handle_new(); BKE_maskrasterize_handle_init(handle, mask, width, height, true, true, true); - state.handle = handle; - state.buffer = buffer; - state.width = width; - state.height = height; - - task_pool = BLI_task_pool_create(task_scheduler, &state); - - scanlines_per_thread = height / num_threads; - for (i = 0; i < num_threads; i++) { - ThreadedMaskRasterizeData *data = MEM_mallocN(sizeof(ThreadedMaskRasterizeData), - "threaded mask rasterize data"); - - data->start_scanline = i * scanlines_per_thread; - - if (i < num_threads - 1) { - data->num_scanlines = scanlines_per_thread; - } - else { - data->num_scanlines = height - data->start_scanline; - } - - BLI_task_pool_push(task_pool, mask_rasterize_func, data, true, TASK_PRIORITY_LOW); - } - - /* work and wait until tasks are done */ - BLI_task_pool_work_and_wait(task_pool); + BKE_maskrasterize_buffer(handle, width, height, buffer); /* Free memory. */ - BLI_task_pool_free(task_pool); BKE_maskrasterize_handle_free(handle); return buffer; @@ -802,7 +733,7 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, } if (draw_flag & MASK_DRAWFLAG_OVERLAY) { - float *buffer = threaded_mask_rasterize(mask, width, height); + float *buffer = mask_rasterize(mask, width, height); int format; if (overlay_mode == MASK_OVERLAY_ALPHACHANNEL) { diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 101ef70fb70..97d5ee1eff0 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1937,16 +1937,17 @@ void MASK_OT_handle_type_set(wmOperatorType *ot) /* ********* clear/set restrict view *********/ -static int mask_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op)) +static int mask_hide_view_clear_exec(bContext *C, wmOperator *op) { Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; bool changed = false; + const bool select = RNA_boolean_get(op->ptr, "select"); for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { if (masklay->restrictflag & OB_RESTRICT_VIEW) { - ED_mask_layer_select_set(masklay, true); + ED_mask_layer_select_set(masklay, select); masklay->restrictflag &= ~OB_RESTRICT_VIEW; changed = true; } @@ -1977,6 +1978,8 @@ void MASK_OT_hide_view_clear(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } static int mask_hide_view_set_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 6c6c106b19a..87c8c55b0a1 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -42,7 +42,6 @@ #include "BKE_mesh.h" #include "BKE_context.h" #include "BKE_editmesh.h" -#include "BKE_utildefines.h" #include "BIF_gl.h" @@ -139,7 +138,7 @@ void paintface_hide(Object *ob, const bool unselected) } -void paintface_reveal(Object *ob) +void paintface_reveal(Object *ob, const bool select) { Mesh *me; MPoly *mpoly; @@ -152,8 +151,8 @@ void paintface_reveal(Object *ob) a = me->totpoly; while (a--) { if (mpoly->flag & ME_HIDE) { - mpoly->flag |= ME_FACE_SEL; - mpoly->flag -= ME_HIDE; + SET_FLAG_FROM_TEST(mpoly->flag, select, ME_FACE_SEL); + mpoly->flag &= ~ME_HIDE; } mpoly++; } @@ -231,7 +230,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const unsigned int index, for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++) { if (BLI_BITMAP_TEST(poly_tag, a)) { - BKE_BIT_TEST_SET(mp->flag, select, ME_FACE_SEL); + SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL); } } diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 2af05a9ad8d..68fd4212004 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -335,11 +335,12 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event) * ideally this will never happen and should be checked for above */ opdata->mcenter[0] = opdata->mcenter[1] = 0; } - edbm_bevel_calc_initial_length(op, event, false); /* for OFFSET_VALUE only, the scale is the size of a pixel under the mouse in 3d space */ opdata->scale[OFFSET_VALUE] = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f; + edbm_bevel_calc_initial_length(op, event, false); + edbm_bevel_update_header(C, op); if (!edbm_bevel_calc(op)) { @@ -622,6 +623,7 @@ void MESH_OT_bevel(wmOperatorType *ot) RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures"); prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f); RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); RNA_def_int(ot->srna, "segments", 1, 1, SEGMENTS_HARD_MAX, "Segments", "Segments for curved edge", 1, 8); RNA_def_float(ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile", "Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index f1c1e4105d0..b9192f58a1b 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -517,9 +517,6 @@ static int ringsel_init(bContext *C, wmOperator *op, bool do_cut) lcd->num.unit_type[0] = B_UNIT_NONE; lcd->num.unit_type[1] = B_UNIT_NONE; - /* XXX, temp, workaround for [# ] */ - EDBM_mesh_ensure_valid_dm_hack(scene, lcd->em); - em_setup_viewcontext(C, &lcd->vc); ED_region_tag_redraw(lcd->ar); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index bf25f7ee7d1..4b4f1b2afea 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -1531,7 +1531,9 @@ void MESH_OT_flip_normals(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* only accepts 1 selected edge, or 2 selected faces */ +/** + * Rotate the edges between selected faces, otherwise rotate the selected edges. + */ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -1652,12 +1654,13 @@ void MESH_OT_hide(wmOperatorType *ot) RNA_def_boolean(ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected"); } -static int edbm_reveal_exec(bContext *C, wmOperator *UNUSED(op)) +static int edbm_reveal_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); - - EDBM_mesh_reveal(em); + const bool select = RNA_boolean_get(op->ptr, "select"); + + EDBM_mesh_reveal(em, select); EDBM_update_generic(em, true, false); @@ -1677,6 +1680,8 @@ void MESH_OT_reveal(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index c8151862b6c..44aca23e2cc 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -52,7 +52,7 @@ #include "BKE_editmesh.h" #include "BKE_editmesh_bvh.h" -#include "BKE_object.h" /* XXX. only for EDBM_mesh_ensure_valid_dm_hack() which will be removed */ +#include "BKE_object.h" /* XXX. only for EDBM_mesh_load(). */ #include "WM_api.h" #include "WM_types.h" @@ -107,21 +107,6 @@ void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess) BKE_editmesh_tessface_calc(em); } -/* hack to workaround multiple operators being called within the same event loop without an update - * see: [#31811] */ -void EDBM_mesh_ensure_valid_dm_hack(Scene *scene, BMEditMesh *em) -{ - if ((((ID *)em->ob->data)->tag & LIB_TAG_ID_RECALC) || - (em->ob->recalc & OB_RECALC_DATA)) - { - /* since we may not have done selection flushing */ - if ((em->ob->recalc & OB_RECALC_DATA) == 0) { - DAG_id_tag_update(&em->ob->id, OB_RECALC_DATA); - } - BKE_object_handle_update(G.main->eval_ctx, scene, em->ob); - } -} - void EDBM_mesh_normals_update(BMEditMesh *em) { BM_mesh_normals_update(em->bm); @@ -412,6 +397,7 @@ void EDBM_mesh_load(Object *ob) * of freed data on scene update, especially in cases when there are dependency * cycles. */ + /* for (Object *other_object = G.main->object.first; other_object != NULL; other_object = other_object->id.next) @@ -420,6 +406,7 @@ void EDBM_mesh_load(Object *ob) BKE_object_free_derived_caches(other_object); } } + */ } /** @@ -1225,7 +1212,7 @@ void EDBM_mesh_hide(BMEditMesh *em, bool swap) } -void EDBM_mesh_reveal(BMEditMesh *em) +void EDBM_mesh_reveal(BMEditMesh *em, bool select) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -1240,7 +1227,6 @@ void EDBM_mesh_reveal(BMEditMesh *em) /* Use tag flag to remember what was hidden before all is revealed. * BM_ELEM_HIDDEN --> BM_ELEM_TAG */ -#pragma omp parallel for schedule(static) if (em->bm->totvert + em->bm->totedge + em->bm->totface >= BM_OMP_LIMIT) for (i = 0; i < 3; i++) { BMIter iter; BMElem *ele; @@ -1264,7 +1250,7 @@ void EDBM_mesh_reveal(BMEditMesh *em) BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) { if (BM_elem_flag_test(ele, BM_ELEM_TAG)) { - BM_elem_select_set(em->bm, ele, true); + BM_elem_select_set(em->bm, ele, select); } } } diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 009aa921e11..5b4078b98b7 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -542,19 +542,21 @@ void MBALL_OT_hide_metaelems(wmOperatorType *ot) /***************************** Unhide operator *****************************/ /* Unhide all edited MetaElems */ -static int reveal_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) +static int reveal_metaelems_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); MetaBall *mb = (MetaBall *)obedit->data; - MetaElem *ml; - - ml = mb->editelems->first; + const bool select = RNA_boolean_get(op->ptr, "select"); + bool changed = false; - if (ml) { - while (ml) { + for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) { + if (ml->flag & MB_HIDE) { + SET_FLAG_FROM_TEST(ml->flag, select, SELECT); ml->flag &= ~MB_HIDE; - ml = ml->next; + changed = true; } + } + if (changed) { WM_event_add_notifier(C, NC_GEOM | ND_DATA, mb); DAG_id_tag_update(obedit->data, 0); } @@ -575,6 +577,9 @@ void MBALL_OT_reveal_metaelems(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } /* Select MetaElement with mouse click (user can select radius circle or diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 4e949c82a9f..d7c7976c344 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -133,7 +133,7 @@ Object *ED_object_active_context(bContext *C) /* ********* clear/set restrict view *********/ -static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op)) +static int object_hide_view_clear_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); ScrArea *sa = CTX_wm_area(C); @@ -141,12 +141,13 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); Base *base; bool changed = false; + const bool select = RNA_boolean_get(op->ptr, "select"); /* XXX need a context loop to handle such cases */ for (base = FIRSTBASE; base; base = base->next) { if ((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) { if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) { - base->flag |= SELECT; + SET_FLAG_FROM_TEST(base->flag, select, SELECT); } base->object->flag = base->flag; base->object->restrictflag &= ~OB_RESTRICT_VIEW; @@ -176,6 +177,8 @@ void OBJECT_OT_hide_view_clear(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } static int object_hide_view_set_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c index ac8d438d9e6..57053ddc020 100644 --- a/source/blender/editors/object/object_lattice.c +++ b/source/blender/editors/object/object_lattice.c @@ -57,7 +57,6 @@ #include "BKE_lattice.h" #include "BKE_deform.h" #include "BKE_report.h" -#include "BKE_utildefines.h" #include "ED_lattice.h" #include "ED_object.h" @@ -369,7 +368,7 @@ static int lattice_select_more_less(bContext *C, const bool select) lattice_test_bitmap_uvw(lt, selpoints, u, v, w + 1, select) || lattice_test_bitmap_uvw(lt, selpoints, u, v, w - 1, select)) { - BKE_BIT_TEST_SET(bp->f1, select, SELECT); + SET_FLAG_FROM_TEST(bp->f1, select, SELECT); } } bp++; diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 5fe5a884354..9b9f77a1dbb 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -374,13 +374,6 @@ void ED_keymap_object(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "OBJECT_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "clear_delta", false); - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_location_clear", GKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "clear_delta", true); - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_rotation_clear", RKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "clear_delta", true); - kmi = WM_keymap_add_item(keymap, "OBJECT_OT_scale_clear", SKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "clear_delta", true); - WM_keymap_verify_item(keymap, "OBJECT_OT_origin_clear", OKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 199d5e0fbfa..da66ec44235 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -1950,11 +1950,12 @@ void PARTICLE_OT_hide(wmOperatorType *ot) /*************************** reveal operator **************************/ -static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) +static int reveal_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_active_object(C); Scene *scene= CTX_data_scene(C); - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit = PE_get_current(scene, ob); + const bool select = RNA_boolean_get(op->ptr, "select"); POINT_P; KEY_K; LOOP_POINTS { @@ -1962,8 +1963,9 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) point->flag &= ~PEP_HIDE; point->flag |= PEP_EDIT_RECALC; - LOOP_KEYS - key->flag |= PEK_SELECT; + LOOP_KEYS { + SET_FLAG_FROM_TEST(key->flag, select, PEK_SELECT); + } } } @@ -1986,6 +1988,9 @@ void PARTICLE_OT_reveal(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } /************************ select less operator ************************/ diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index a27026878e1..1133b5f79d1 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -353,11 +353,15 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) ImBuf *ibuf_view; const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL; + unsigned int draw_flags = V3D_OFSDRAW_NONE; + draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0; + if (view_context) { + draw_flags |= (draw_bgpic) ? V3D_OFSDRAW_USE_BACKGROUND : 0; + ibuf_view = ED_view3d_draw_offscreen_imbuf( scene, v3d, ar, sizex, sizey, - IB_rect, draw_bgpic, - alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname, + IB_rect, draw_flags, alpha_mode, oglrender->ofs_samples, viewname, oglrender->fx, oglrender->ofs, err_out); /* for stamp only */ @@ -366,10 +370,11 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) } } else { + draw_flags |= (V3D_OFSDRAW_USE_GPENCIL | V3D_OFSDRAW_USE_BACKGROUND); ibuf_view = ED_view3d_draw_offscreen_imbuf_simple( scene, scene->camera, oglrender->sizex, oglrender->sizey, - IB_rect, OB_SOLID, false, true, true, - alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname, + IB_rect, draw_flags, OB_SOLID, + alpha_mode, oglrender->ofs_samples, viewname, oglrender->fx, oglrender->ofs, err_out); camera = scene->camera; } @@ -679,6 +684,15 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) oglrender->fx = GPU_fx_compositor_create(); } } + else if (is_sequencer) { + /* NOTE: We allow animation of DoF setting for flexibility in edits, so + * we can't check in advance whether we need FX compositor or not. + * We just always allocated it and make sure it doesn't add extra + * overhead rather than memory allocation here if it's not really + * needed. + */ + oglrender->fx = GPU_fx_compositor_create(); + } /* create render */ oglrender->re = RE_NewSceneRender(scene); diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c index 0ee78d61fb8..337f7a1ef2b 100644 --- a/source/blender/editors/sculpt_paint/paint_curve.c +++ b/source/blender/editors/sculpt_paint/paint_curve.c @@ -33,13 +33,13 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" +#include "BLI_math_vector.h" +#include "BLI_string.h" + #include "BKE_context.h" #include "BKE_main.h" #include "BKE_paint.h" -#include "BLI_math_vector.h" -#include "BLI_string.h" - #include "ED_paint.h" #include "ED_view3d.h" diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index d14b75149c9..6fa45f1932a 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -5460,7 +5460,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) ibuf = ED_view3d_draw_offscreen_imbuf( scene, CTX_wm_view3d(C), CTX_wm_region(C), - w, h, IB_rect, false, R_ALPHAPREMUL, 0, false, NULL, + w, h, IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL, NULL, NULL, err_out); if (!ibuf) { /* Mostly happens when OpenGL offscreen buffer was failed to create, */ @@ -5904,7 +5904,7 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op)) })); /* select all uv loops first - pack parameters needs this to make sure charts are registered */ ED_uvedit_select_all(bm); - ED_uvedit_unwrap_cube_project(ob, bm, 1.0, false); + ED_uvedit_unwrap_cube_project(bm, 1.0, false, NULL); /* set the margin really quickly before the packing operation*/ scene->toolsettings->uvcalc_margin = 0.001f; ED_uvedit_pack_islands(scene, ob, bm, false, false, true); diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 8304e782b07..1c2ab442e95 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -749,10 +749,11 @@ void PAINT_OT_face_select_hide(wmOperatorType *ot) RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects"); } -static int face_select_reveal_exec(bContext *C, wmOperator *UNUSED(op)) +static int face_select_reveal_exec(bContext *C, wmOperator *op) { + const bool select = RNA_boolean_get(op->ptr, "select"); Object *ob = CTX_data_active_object(C); - paintface_reveal(ob); + paintface_reveal(ob, select); ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; } @@ -768,5 +769,5 @@ void PAINT_OT_face_select_reveal(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects"); + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 985cca7c4af..df6bd01144d 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -64,6 +64,7 @@ #include "ED_anim_api.h" #include "ED_keyframing.h" #include "ED_screen.h" +#include "ED_util.h" #include "UI_interface.h" #include "UI_resources.h" @@ -503,25 +504,28 @@ static void driver_remove_cb(bContext *C, void *ale_v, void *UNUSED(arg)) /* call API method to remove this driver */ ANIM_remove_driver(reports, id, fcu->rna_path, fcu->array_index, 0); + ED_undo_push(C, "Remove Driver"); } /* callback to add a target variable to the active driver */ -static void driver_add_var_cb(bContext *UNUSED(C), void *driver_v, void *UNUSED(arg)) +static void driver_add_var_cb(bContext *C, void *driver_v, void *UNUSED(arg)) { ChannelDriver *driver = (ChannelDriver *)driver_v; /* add a new variable */ driver_add_new_variable(driver); + ED_undo_push(C, "Add Driver Variable"); } /* callback to remove target variable from active driver */ -static void driver_delete_var_cb(bContext *UNUSED(C), void *driver_v, void *dvar_v) +static void driver_delete_var_cb(bContext *C, void *driver_v, void *dvar_v) { ChannelDriver *driver = (ChannelDriver *)driver_v; DriverVar *dvar = (DriverVar *)dvar_v; /* remove the active variable */ driver_free_variable_ex(driver, dvar); + ED_undo_push(C, "Delete Driver Variable"); } /* callback to report why a driver variable is invalid */ diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 5c670a216d8..62275abcd02 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -333,13 +333,14 @@ static void GRAPH_OT_hide(wmOperatorType *ot) /* ........ */ -static int graphview_curves_reveal_exec(bContext *C, wmOperator *UNUSED(op)) +static int graphview_curves_reveal_exec(bContext *C, wmOperator *op) { bAnimContext ac; ListBase anim_data = {NULL, NULL}; ListBase all_data = {NULL, NULL}; bAnimListElem *ale; int filter; + const bool select = RNA_boolean_get(op->ptr, "select"); /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) @@ -364,8 +365,11 @@ static int graphview_curves_reveal_exec(bContext *C, wmOperator *UNUSED(op)) continue; /* select if it is not visible */ - if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0) - ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_SELECT, ACHANNEL_SETFLAG_ADD); + if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0) { + ANIM_channel_setting_set( + &ac, ale, ACHANNEL_SETTING_SELECT, + select ? ACHANNEL_SETFLAG_ADD : ACHANNEL_SETFLAG_CLEAR); + } /* change the visibility setting */ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD); @@ -397,6 +401,8 @@ static void GRAPH_OT_reveal(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } /* ************************** registration - operator types **********************************/ diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index d2897c7264b..51ccaf6800a 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -433,7 +433,7 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * uiItemS(layout); - nr = (rl == NULL)? 1: 0; + nr = (rl == NULL) ? 1 : 0; ListBase added_passes; BLI_listbase_clear(&added_passes); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index f7df29ed2b6..24db8ba40fd 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1301,12 +1301,12 @@ static int image_open_exec(bContext *C, wmOperator *op) if (iod->iuser) { iuser = iod->iuser; } - else if (sa->spacetype == SPACE_IMAGE) { + else if (sa && sa->spacetype == SPACE_IMAGE) { SpaceImage *sima = sa->spacedata.first; ED_space_image_set(sima, scene, obedit, ima); iuser = &sima->iuser; } - else if (sa->spacetype == SPACE_VIEW3D) { + else if (sa && sa->spacetype == SPACE_VIEW3D) { View3D *v3d = sa->spacedata.first; for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index ccc52f2dba8..ca7dbe4f73c 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -150,7 +150,13 @@ eOLDrawState tree_element_type_active( TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive); eOLDrawState tree_element_active(struct bContext *C, struct Scene *scene, SpaceOops *soops, TreeElement *te, const eOLSetState set, const bool handle_all_types); -int outliner_item_do_activate(struct bContext *C, int x, int y, bool extend, bool recursive); + +void outliner_item_do_activate_from_tree_element( + struct bContext *C, TreeElement *te, TreeStoreElem *tselem, + bool extend, bool recursive); +int outliner_item_do_activate_from_cursor( + struct bContext *C, const int mval[2], + bool extend, bool recursive); /* outliner_edit.c ---------------------------------------------- */ typedef void (*outliner_operation_cb)( diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 5cc83d3ee94..9f79b575966 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -816,7 +816,7 @@ eOLDrawState tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, Tr { switch (te->idcode) { /* Note: ID_OB only if handle_all_type is true, else objects are handled specially to allow multiple - * selection. See do_outliner_item_activate. */ + * selection. See do_outliner_item_activate_from_cursor. */ case ID_OB: if (handle_all_types) { return tree_element_set_active_object(C, scene, soops, te, set, false); @@ -892,10 +892,85 @@ eOLDrawState tree_element_type_active( /* ================================================ */ -static bool do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, - TreeElement *te, bool extend, bool recursive, const float mval[2]) +/** + * Action when clicking to activate an item (typically under the mouse cursor), + * but don't do any cursor intersection checks. + * + * Needed to run from operators accessed from a menu. + */ +static void do_outliner_item_activate_tree_element( + bContext *C, Scene *scene, SpaceOops *soops, + TreeElement *te, TreeStoreElem *tselem, + bool extend, bool recursive) +{ + /* always makes active object, except for some specific types. + * Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want + * to switch out of edit mode (see T48328 for details). */ + if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE)) { + tree_element_set_active_object( + C, scene, soops, te, + (extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, + recursive && tselem->type == 0); + } + + if (tselem->type == 0) { // the lib blocks + /* editmode? */ + if (te->idcode == ID_SCE) { + if (scene != (Scene *)tselem->id) { + ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id); + } + } + else if (te->idcode == ID_GR) { + Group *gr = (Group *)tselem->id; + GroupObject *gob; + + if (extend) { + int sel = BA_SELECT; + for (gob = gr->gobject.first; gob; gob = gob->next) { + if (gob->ob->flag & SELECT) { + sel = BA_DESELECT; + break; + } + } + + for (gob = gr->gobject.first; gob; gob = gob->next) { + ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel); + } + } + else { + BKE_scene_base_deselect_all(scene); + + for (gob = gr->gobject.first; gob; gob = gob->next) { + if ((gob->ob->flag & SELECT) == 0) + ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT); + } + } + + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + } + else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) { + WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL); + } + else { // rest of types + tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false); + } + + } + else { + tree_element_type_active( + C, scene, soops, te, tselem, + extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, + recursive); + } +} + +/** + * Activates tree items, also handles clicking on arrows. + */ +static bool do_outliner_item_activate_from_cursor( + bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, + TreeElement *te, bool extend, bool recursive, const float mval[2]) { - if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) { TreeStoreElem *tselem = TREESTORE(te); bool openclose = false; @@ -922,78 +997,49 @@ static bool do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Sp } /* name and first icon */ else if (mval[0] > te->xs + UI_UNIT_X && mval[0] < te->xend) { - - /* always makes active object, except for some specific types. - * Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want - * to switch out of edit mode (see T48328 for details). */ - if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE)) { - tree_element_set_active_object(C, scene, soops, te, - (extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, - recursive && tselem->type == 0); - } - - if (tselem->type == 0) { // the lib blocks - /* editmode? */ - if (te->idcode == ID_SCE) { - if (scene != (Scene *)tselem->id) { - ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id); - } - } - else if (te->idcode == ID_GR) { - Group *gr = (Group *)tselem->id; - GroupObject *gob; - - if (extend) { - int sel = BA_SELECT; - for (gob = gr->gobject.first; gob; gob = gob->next) { - if (gob->ob->flag & SELECT) { - sel = BA_DESELECT; - break; - } - } - - for (gob = gr->gobject.first; gob; gob = gob->next) { - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel); - } - } - else { - BKE_scene_base_deselect_all(scene); - - for (gob = gr->gobject.first; gob; gob = gob->next) { - if ((gob->ob->flag & SELECT) == 0) - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT); - } - } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) { - WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL); - } - else { // rest of types - tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false); - } - - } - else { - tree_element_type_active(C, scene, soops, te, tselem, - extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, - recursive); - } - + do_outliner_item_activate_tree_element( + C, scene, soops, + te, tselem, + extend, recursive); return true; } } for (te = te->subtree.first; te; te = te->next) { - if (do_outliner_item_activate(C, scene, ar, soops, te, extend, recursive, mval)) { + if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, mval)) { return true; } } return false; } -int outliner_item_do_activate(bContext *C, int x, int y, bool extend, bool recursive) +/** + * A version of #outliner_item_do_acticate_from_cursor that takes the tree element directly. + * and doesn't depend on the pointer position. + * + * This allows us to simulate clicking on an item without dealing with the mouse cursor. + */ +void outliner_item_do_activate_from_tree_element( + bContext *C, TreeElement *te, TreeStoreElem *tselem, + bool extend, bool recursive) +{ + Scene *scene = CTX_data_scene(C); + SpaceOops *soops = CTX_wm_space_outliner(C); + + do_outliner_item_activate_tree_element( + C, scene, soops, + te, tselem, + extend, recursive); +} + +/** + * Action to run when clicking in the outliner, + * + * May expend/collapse branches or activate items. + * */ +int outliner_item_do_activate_from_cursor( + bContext *C, const int mval[2], + bool extend, bool recursive) { Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); @@ -1001,7 +1047,7 @@ int outliner_item_do_activate(bContext *C, int x, int y, bool extend, bool recur TreeElement *te; float fmval[2]; - UI_view2d_region_to_view(&ar->v2d, x, y, &fmval[0], &fmval[1]); + UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fmval[0], &fmval[1]); if (!ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF) && !(soops->flag & SO_HIDE_RESTRICTCOLS) && @@ -1011,7 +1057,9 @@ int outliner_item_do_activate(bContext *C, int x, int y, bool extend, bool recur } for (te = soops->tree.first; te; te = te->next) { - if (do_outliner_item_activate(C, scene, ar, soops, te, extend, recursive, fmval)) break; + if (do_outliner_item_activate_from_cursor(C, scene, ar, soops, te, extend, recursive, fmval)) { + break; + } } if (te) { @@ -1046,9 +1094,7 @@ static int outliner_item_activate(bContext *C, wmOperator *op, const wmEvent *ev { bool extend = RNA_boolean_get(op->ptr, "extend"); bool recursive = RNA_boolean_get(op->ptr, "recursive"); - int x = event->mval[0]; - int y = event->mval[1]; - return outliner_item_do_activate(C, x, y, extend, recursive); + return outliner_item_do_activate_from_cursor(C, event->mval, extend, recursive); } void OUTLINER_OT_item_activate(wmOperatorType *ot) diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 3321c2669d8..cf9deeaedf8 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -372,17 +372,14 @@ static void object_select_cb( } static void object_select_hierarchy_cb( - bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *UNUSED(tselem), void *UNUSED(user_data)) + bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *te, + TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - /* From where do i get the x,y coordinate of the mouse event ? */ - wmWindow *win = CTX_wm_window(C); - int x = win->eventstate->mval[0]; - int y = win->eventstate->mval[1]; - outliner_item_do_activate(C, x, y, true, true); + /* Don't extend because this toggles, which is nice for Ctrl-Click but not for a menu item. + * it's especially confusing when multiple items are selected since some toggle on/off. */ + outliner_item_do_activate_from_tree_element(C, te, tselem, false, true); } - static void object_deselect_cb( bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 46f212e3679..258cbdfaffd 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -361,7 +361,7 @@ void SEQUENCER_OT_scene_strip_add(struct wmOperatorType *ot) sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", ""); - RNA_def_enum_funcs(prop, RNA_scene_itemf); + RNA_def_enum_funcs(prop, RNA_scene_without_active_itemf); RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); ot->prop = prop; } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 160aa157189..bb7e2d75482 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -60,6 +60,7 @@ #include "BIF_glutil.h" #include "GPU_basic_shader.h" +#include "GPU_compositing.h" #include "ED_anim_api.h" #include "ED_gpencil.h" @@ -908,7 +909,7 @@ void ED_sequencer_special_preview_clear(void) ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs, const char *viewname) { - SeqRenderData context; + SeqRenderData context = {0}; ImBuf *ibuf; int rectx, recty; float render_size; @@ -935,6 +936,12 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int rectx, recty, proxy_size, &context); context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); + if (scene->r.seq_flag & R_SEQ_CAMERA_DOF) { + if (sseq->compositor == NULL) { + sseq->compositor = GPU_fx_compositor_create(); + } + context.gpu_fx = sseq->compositor; + } /* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled * by Esc pressed somewhere in the past diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index f1d0f23f8af..6b50d3fecdf 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -60,6 +60,8 @@ #include "IMB_imbuf.h" +#include "GPU_compositing.h" + #include "sequencer_intern.h" // own include /**************************** common state *****************************/ @@ -218,6 +220,11 @@ static void sequencer_free(SpaceLink *sl) if (scopes->histogram_ibuf) IMB_freeImBuf(scopes->histogram_ibuf); + + if (sseq->compositor != NULL) { + GPU_fx_compositor_destroy(sseq->compositor); + sseq->compositor = NULL; + } } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 56508ea989a..9e220f4b141 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3286,14 +3286,16 @@ void ED_view3d_draw_setup_view( */ ImBuf *ED_view3d_draw_offscreen_imbuf( Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, - unsigned int flag, bool draw_background, - int alpha_mode, int samples, bool full_samples, const char *viewname, + unsigned int flag, unsigned int draw_flags, + int alpha_mode, int samples, const char *viewname, /* output vars */ GPUFX *fx, GPUOffScreen *ofs, char err_out[256]) { RegionView3D *rv3d = ar->regiondata; ImBuf *ibuf; const bool draw_sky = (alpha_mode == R_ADDSKY); + const bool draw_background = (draw_flags & V3D_OFSDRAW_USE_BACKGROUND); + const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE); /* view state */ GPUFXSettings fx_settings = v3d->fx_settings; @@ -3309,7 +3311,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( if (own_ofs) { /* bind */ - ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, err_out); + ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, err_out); if (ofs == NULL) { return NULL; } @@ -3354,7 +3356,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( } } - if ((samples && full_samples) == 0) { + if ((samples && use_full_sample) == 0) { /* Single-pass render, common case */ ED_view3d_draw_offscreen( scene, v3d, ar, sizex, sizey, NULL, winmat, @@ -3454,8 +3456,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( */ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( Scene *scene, Object *camera, int width, int height, - unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background, - int alpha_mode, int samples, bool full_samples, const char *viewname, + unsigned int flag, unsigned int draw_flags, int drawtype, + int alpha_mode, int samples, const char *viewname, GPUFX *fx, GPUOffScreen *ofs, char err_out[256]) { View3D v3d = {NULL}; @@ -3471,15 +3473,22 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( v3d.lay = scene->lay; v3d.drawtype = drawtype; v3d.flag2 = V3D_RENDER_OVERRIDE; - - if (use_gpencil) - v3d.flag2 |= V3D_SHOW_GPENCIL; - if (use_solid_tex) + if (draw_flags & V3D_OFSDRAW_USE_GPENCIL) { + v3d.flag2 |= V3D_SHOW_GPENCIL; + } + if (draw_flags & V3D_OFSDRAW_USE_SOLID_TEX) { v3d.flag2 |= V3D_SOLID_TEX; - - if (draw_background) + } + if (draw_flags & V3D_OFSDRAW_USE_BACKGROUND) { v3d.flag3 |= V3D_SHOW_WORLD; + } + if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) { + if (camera->type == OB_CAMERA) { + v3d.fx_settings.dof = &((Camera *)camera->data)->gpu_dof; + v3d.fx_settings.fx_flag |= GPU_FX_FLAG_DOF; + } + } rv3d.persp = RV3D_CAMOB; @@ -3507,9 +3516,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( invert_m4_m4(rv3d.persinv, rv3d.viewinv); return ED_view3d_draw_offscreen_imbuf( - scene, &v3d, &ar, width, height, flag, - draw_background, alpha_mode, samples, full_samples, viewname, - fx, ofs, err_out); + scene, &v3d, &ar, width, height, flag, draw_flags, + alpha_mode, samples, viewname, fx, ofs, err_out); } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 67597729d15..05cf552e5cc 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -70,8 +70,6 @@ #include "BKE_paint.h" #include "BKE_editmesh.h" #include "BKE_tracking.h" -#include "BKE_utildefines.h" - #include "BIF_gl.h" #include "BIF_glutil.h" @@ -726,7 +724,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)) { - BKE_BIT_TEST_SET(mv->flag, data->select, SELECT); + SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); } } static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) @@ -1672,7 +1670,7 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con BoxSelectUserData *data = userData; if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) { - BKE_BIT_TEST_SET(mv->flag, data->select, SELECT); + SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); } } static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) @@ -2498,7 +2496,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, CircleSelectUserData *data = userData; if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - BKE_BIT_TEST_SET(mv->flag, data->select, SELECT); + SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); } } static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 179b68dd270..277e01d1e2b 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -82,7 +82,6 @@ #include "BKE_editmesh.h" #include "BKE_tracking.h" #include "BKE_mask.h" -#include "BKE_utildefines.h" #include "ED_anim_api.h" #include "ED_armature.h" @@ -1208,7 +1207,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id)) && RNA_property_is_set(op->ptr, prop)) { - BKE_BIT_TEST_SET(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM); + SET_FLAG_FROM_TEST(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM); } } diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index c369068fe05..d69588e91c6 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -3761,7 +3761,7 @@ static void UV_OT_hide(wmOperatorType *ot) /****************** reveal operator ******************/ -static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op)) +static int uv_reveal_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); Object *obedit = CTX_data_edit_object(C); @@ -3777,12 +3777,14 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op)) const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const bool select = RNA_boolean_get(op->ptr, "select"); + /* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and * confuse our checks on selected verts. */ /* call the mesh function if we are in mesh sync sel */ if (ts->uv_flag & UV_SYNC_SELECTION) { - EDBM_mesh_reveal(em); + EDBM_mesh_reveal(em, select); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -3794,7 +3796,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op)) if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag |= MLOOPUV_VERTSEL; + SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); } /* BM_face_select_set(em->bm, efa, true); */ BM_elem_flag_enable(efa, BM_ELEM_TAG); @@ -3815,7 +3817,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op)) if (!totsel) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag |= MLOOPUV_VERTSEL; + SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); } /* BM_face_select_set(em->bm, efa, true); */ BM_elem_flag_enable(efa, BM_ELEM_TAG); @@ -3830,7 +3832,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op)) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag |= MLOOPUV_VERTSEL; + SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); } } /* BM_face_select_set(em->bm, efa, true); */ @@ -3846,7 +3848,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op)) if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag |= MLOOPUV_VERTSEL; + SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); } /* BM_face_select_set(em->bm, efa, true); */ BM_elem_flag_enable(efa, BM_ELEM_TAG); @@ -3860,7 +3862,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op)) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag |= MLOOPUV_VERTSEL; + SET_FLAG_FROM_TEST(luv->flag, select, MLOOPUV_VERTSEL); } } /* BM_face_select_set(em->bm, efa, true); */ @@ -3888,6 +3890,8 @@ static void UV_OT_reveal(wmOperatorType *ot) /* api callbacks */ ot->exec = uv_reveal_exec; ot->poll = ED_operator_uvedit; + + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } /******************** set 3d cursor operator ********************/ diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index b639a493b02..bc38a1cd3bb 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -868,46 +868,89 @@ void ED_uvedit_live_unwrap(Scene *scene, Object *obedit) #define POLAR_ZX 0 #define POLAR_ZY 1 -static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, - Object *ob, BMEditMesh *em) +static void uv_map_transform_calc_bounds(BMEditMesh *em, float r_min[3], float r_max[3]) { - const int around = (v3d) ? v3d->around : V3D_AROUND_CENTER_BOUNDS; + BMFace *efa; + BMIter iter; + INIT_MINMAX(r_min, r_max); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + BM_face_calc_bounds_expand(efa, r_min, r_max); + } + } +} + +static void uv_map_transform_calc_center_median(BMEditMesh *em, float r_center[3]) +{ + BMFace *efa; + BMIter iter; + uint center_accum_num = 0; + zero_v3(r_center); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + float center[3]; + BM_face_calc_center_mean(efa, center); + add_v3_v3(r_center, center); + center_accum_num += 1; + } + } + mul_v3_fl(r_center, 1.0f / (float)center_accum_num); +} +static void uv_map_transform_center( + Scene *scene, View3D *v3d, Object *ob, BMEditMesh *em, + float r_center[3], + float r_bounds[2][3]) +{ /* only operates on the edit object - this is all that's needed now */ + const int around = (v3d) ? v3d->around : V3D_AROUND_CENTER_BOUNDS; + + float bounds[2][3]; + INIT_MINMAX(bounds[0], bounds[1]); + bool is_minmax_set = false; switch (around) { case V3D_AROUND_CENTER_BOUNDS: /* bounding box center */ { - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - float min[3], max[3]; - - INIT_MINMAX(min, max); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - minmax_v3v3_v3(min, max, l->v->co); - } - } - } - mid_v3_v3v3(result, min, max); + uv_map_transform_calc_bounds(em, bounds[0], bounds[1]); + is_minmax_set = true; + mid_v3_v3v3(r_center, bounds[0], bounds[1]); + break; + } + case V3D_AROUND_CENTER_MEAN: + { + uv_map_transform_calc_center_median(em, r_center); break; } case V3D_AROUND_CURSOR: /* cursor center */ { - const float *curs = ED_view3d_cursor3d_get(scene, v3d); - /* shift to objects world */ - sub_v3_v3v3(result, curs, ob->obmat[3]); + invert_m4_m4(ob->imat, ob->obmat); + mul_v3_m4v3(r_center, ob->imat, ED_view3d_cursor3d_get(scene, v3d)); break; } + case V3D_AROUND_ACTIVE: + { + BMEditSelection ese; + if (BM_select_history_active_get(em->bm, &ese)) { + BM_editselection_center(&ese, r_center); + break; + } + ATTR_FALLTHROUGH; + } case V3D_AROUND_LOCAL_ORIGINS: /* object center */ - case V3D_AROUND_CENTER_MEAN: /* multiple objects centers, only one object here*/ default: - zero_v3(result); + zero_v3(r_center); break; } + + /* if this is passed, always set! */ + if (r_bounds) { + if (!is_minmax_set) { + uv_map_transform_calc_bounds(em, bounds[0], bounds[1]); + } + copy_v3_v3(r_bounds[0], bounds[0]); + copy_v3_v3(r_bounds[1], bounds[1]); + } } static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Object *ob, @@ -958,13 +1001,10 @@ static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Objec mul_m4_series(result, rotup, rotside, viewmatrix, rotobj); } -static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float rotmat[4][4]) +static void uv_map_transform(bContext *C, wmOperator *op, float rotmat[4][4]) { /* context checks are messy here, making it work in both 3d view and uv editor */ - Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BKE_editmesh_from_object(obedit); - View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); /* common operator properties */ int align = RNA_enum_get(op->ptr, "align"); @@ -972,8 +1012,6 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float float radius = RNA_struct_find_property(op->ptr, "radius") ? RNA_float_get(op->ptr, "radius") : 1.0f; float upangledeg, sideangledeg; - uv_map_transform_center(scene, v3d, center, obedit, em); - if (direction == VIEW_ON_EQUATOR) { upangledeg = 90.0f; sideangledeg = 0.0f; @@ -1476,6 +1514,7 @@ static int sphere_project_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); + View3D *v3d = CTX_wm_view3d(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); BMFace *efa; BMLoop *l; @@ -1493,7 +1532,8 @@ static int sphere_project_exec(bContext *C, wmOperator *op) cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - uv_map_transform(C, op, center, rotmat); + uv_map_transform(C, op, rotmat); + uv_map_transform_center(scene, v3d, obedit, em, center, NULL); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) @@ -1555,6 +1595,7 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); + View3D *v3d = CTX_wm_view3d(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); BMFace *efa; BMLoop *l; @@ -1572,12 +1613,13 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - uv_map_transform(C, op, center, rotmat); + uv_map_transform(C, op, rotmat); + uv_map_transform_center(scene, v3d, obedit, em, center, NULL); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) continue; - + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); @@ -1616,68 +1658,79 @@ void UV_OT_cylinder_project(wmOperatorType *ot) /******************* Cube Project operator ****************/ -void ED_uvedit_unwrap_cube_project(Object *ob, BMesh *bm, float cube_size, bool use_select) +void ED_uvedit_unwrap_cube_project(BMesh *bm, float cube_size, bool use_select, const float center[3]) { BMFace *efa; BMLoop *l; BMIter iter, liter; /* MTexPoly *tf; */ /* UNUSED */ MLoopUV *luv; - float *loc, dx, dy; + float loc[3]; int cox, coy; int cd_loop_uv_offset; cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - loc = ob->obmat[3]; + if (center) { + copy_v3_v3(loc, center); + } + else { + zero_v3(loc); + } /* choose x,y,z axis for projection depending on the largest normal * component, but clusters all together around the center of map. */ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - int first = 1; - /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) continue; axis_dominant_v3(&cox, &coy, efa->no); - dx = dy = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - luv->uv[0] = 0.5f + 0.5f * cube_size * (loc[cox] + l->v->co[cox]); - luv->uv[1] = 0.5f + 0.5f * cube_size * (loc[coy] + l->v->co[coy]); - - if (first) { - dx = floor(luv->uv[0]); - dy = floor(luv->uv[1]); - first = 0; - } - - - luv->uv[0] -= dx; - luv->uv[1] -= dy; + luv->uv[0] = 0.5f + 0.5f * cube_size * (l->v->co[cox] - loc[cox]); + luv->uv[1] = 0.5f + 0.5f * cube_size * (l->v->co[coy] - loc[coy]); } } - } static int cube_project_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); - float cube_size = RNA_float_get(op->ptr, "cube_size"); + PropertyRNA *prop_cube_size = RNA_struct_find_property(op->ptr, "cube_size"); + float cube_size = RNA_property_float_get(op->ptr, prop_cube_size); + float center[3]; + float bounds[2][3]; + float (*bounds_buf)[3] = NULL; /* add uvs if they don't exist yet */ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) { return OPERATOR_CANCELLED; } - ED_uvedit_unwrap_cube_project(obedit, em->bm, cube_size, true); + if (!RNA_property_is_set(op->ptr, prop_cube_size)) { + bounds_buf = bounds; + } + + uv_map_transform_center(scene, v3d, obedit, em, center, bounds_buf); + + /* calculate based on bounds */ + if (bounds_buf) { + float dims[3]; + sub_v3_v3v3(dims, bounds[1], bounds[0]); + cube_size = max_fff(UNPACK3(dims)); + cube_size = cube_size ? 2.0f / cube_size : 1.0f; + RNA_property_float_set(op->ptr, prop_cube_size, cube_size); + } + + ED_uvedit_unwrap_cube_project(em->bm, cube_size, true, center); + uv_map_clip_correct(scene, obedit, em, op); DAG_id_tag_update(obedit->data, 0); diff --git a/source/blender/freestyle/intern/system/StringUtils.h b/source/blender/freestyle/intern/system/StringUtils.h index e11798762e4..10748c45c19 100644 --- a/source/blender/freestyle/intern/system/StringUtils.h +++ b/source/blender/freestyle/intern/system/StringUtils.h @@ -35,7 +35,6 @@ #include <vector> extern "C" { -#include "BKE_utildefines.h" #include "BLI_string.h" #include "BLI_path_util.h" } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 4ac69119a6c..0a63fc216a0 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2971,7 +2971,10 @@ float calc_gradient(vec3 p, int gradient_type) return atan(y, x) / (M_PI * 2) + 0.5; } else { - float r = max(1.0 - sqrt(x * x + y * y + z * z), 0.0); + /* Bias a little bit for the case where p is a unit length vector, + * to get exactly zero instead of a small random value depending + * on float precision. */ + float r = max(0.999999 - sqrt(x * x + y * y + z * z), 0.0); if (gradient_type == 5) { /* quadratic sphere */ return r * r; } diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index e1b3abcf2f6..009258079ee 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -843,9 +843,9 @@ static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, int } static void index_rebuild_ffmpeg_proc_decoded_frame( - FFmpegIndexBuilderContext *context, - AVPacket * curr_packet, - AVFrame *in_frame) + FFmpegIndexBuilderContext *context, + AVPacket *curr_packet, + AVFrame *in_frame) { int i; unsigned long long s_pos = context->seek_pos; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 451869415e7..ca534e3e2a8 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -414,11 +414,13 @@ static bool imb_save_openexr_half( frameBuffer.insert("R", Slice(HALF, (char *) &to->r, xstride, ystride)); frameBuffer.insert("G", Slice(HALF, (char *) &to->g, xstride, ystride)); frameBuffer.insert("B", Slice(HALF, (char *) &to->b, xstride, ystride)); - if (is_alpha) + if (is_alpha) { frameBuffer.insert("A", Slice(HALF, (char *) &to->a, xstride, ystride)); - if (is_zbuf) + } + if (is_zbuf) { frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)(ibuf->zbuf_float + (height - 1) * width), - sizeof(float), sizeof(float) * -width)); + sizeof(float), sizeof(float) * -width)); + } if (ibuf->rect_float) { float *from; @@ -509,11 +511,13 @@ static bool imb_save_openexr_float( frameBuffer.insert("R", Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride)); frameBuffer.insert("G", Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride)); frameBuffer.insert("B", Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride)); - if (is_alpha) + if (is_alpha) { frameBuffer.insert("A", Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride)); - if (is_zbuf) + } + if (is_zbuf) { frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *) (ibuf->zbuf_float + (height - 1) * width), - sizeof(float), sizeof(float) * -width)); + sizeof(float), sizeof(float) * -width)); + } file.setFrameBuffer(frameBuffer); file.writePixels(height); @@ -1125,7 +1129,7 @@ void IMB_exr_read_channels(void *handle) ExrChannel *echan; for (echan = (ExrChannel *)data->channels.first; echan; echan = echan->next) { - if(echan->m->part_number != i) { + if (echan->m->part_number != i) { continue; } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 5250749fce3..923df70dd4d 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -339,7 +339,7 @@ enum { * Also used internally in readfile.c to mark datablocks needing do_versions. */ LIB_TAG_NEW = 1 << 8, /* RESET_BEFORE_USE free test flag. - * TODO make it a RESET_AFTER_USE too. */ + * TODO make it a RESET_AFTER_USE too. */ LIB_TAG_DOIT = 1 << 10, /* RESET_AFTER_USE tag existing data before linking so we know what is new. */ LIB_TAG_PRE_EXISTING = 1 << 11, diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b9f19a36072..90815b95d24 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1744,9 +1744,12 @@ typedef struct Scene { #define R_USE_WS_SHADING 0x8000000 /* use world space interpretation of lighting data */ /* seq_flag */ -// #define R_SEQ_GL_PREV 1 // UNUSED, we just use setting from seq_prev_type now. -// #define R_SEQ_GL_REND 2 // UNUSED, opengl render has its own operator now. -#define R_SEQ_SOLID_TEX 4 +enum { + // R_SEQ_GL_PREV = (1 << 1), // UNUSED, we just use setting from seq_prev_type now. + // R_SEQ_GL_REND = (1 << 2), // UNUSED, opengl render has its own operator now. + R_SEQ_SOLID_TEX = (1 << 3), + R_SEQ_CAMERA_DOF = (1 << 4), +}; /* displaymode */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index a0f77d61d1d..015583d898c 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -512,6 +512,9 @@ typedef struct SpaceSeq { char multiview_eye; /* multiview current eye - for internal use */ char pad2[7]; + + struct GPUFX *compositor; + void *pad3; } SpaceSeq; diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 2cea8715a65..17e30de4509 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -978,7 +978,7 @@ static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offs char str[SDNA_MAX_FILENAME_LENGTH], *cp; int firststruct; - if (debugSDNA > -1) { + if (debugSDNA > 0) { fflush(stdout); printf("Running makesdna at debug level %d\n", debugSDNA); } @@ -1074,7 +1074,7 @@ static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offs /* file writing */ - if (debugSDNA > -1) printf("Writing file ... "); + if (debugSDNA > 0) printf("Writing file ... "); if (nr_names == 0 || nr_structs == 0) { /* pass */ @@ -1184,7 +1184,7 @@ static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offs MEM_freeN(typelens_64); MEM_freeN(structs); - if (debugSDNA > -1) printf("done.\n"); + if (debugSDNA > 0) printf("done.\n"); return(0); } diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index b4b8dd7806e..0f4e20a02ab 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -237,6 +237,7 @@ const EnumPropertyItem *RNA_group_local_itemf(struct bContext *C, struct Pointer const EnumPropertyItem *RNA_image_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free); const EnumPropertyItem *RNA_image_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free); const EnumPropertyItem *RNA_scene_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free); +const EnumPropertyItem *RNA_scene_without_active_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free); const EnumPropertyItem *RNA_scene_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free); const EnumPropertyItem *RNA_movieclip_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free); const EnumPropertyItem *RNA_movieclip_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free); diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 2c558e56412..ff081a56b61 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -46,6 +46,14 @@ # endif #endif +/** + * Variable to control debug output of makesrna. + * debugSRNA: + * - 0 = no output, except errors + * - 1 = detail actions + */ +static int debugSRNA = 0; + /* stub for BLI_abort() */ #ifndef NDEBUG void BLI_system_backtrace(FILE *fp) @@ -62,7 +70,9 @@ void BLI_system_backtrace(FILE *fp) static int file_older(const char *file1, const char *file2) { struct stat st1, st2; - /* printf("compare: %s %s\n", file1, file2); */ + if (debugSRNA > 0) { + printf("compare: %s %s\n", file1, file2); + } if (stat(file1, &st1)) return 0; if (stat(file2, &st2)) return 0; @@ -4134,7 +4144,9 @@ int main(int argc, char **argv) return_status = 1; } else { - fprintf(stderr, "Running makesrna\n"); + if (debugSRNA > 0) { + fprintf(stderr, "Running makesrna\n"); + } makesrna_path = argv[0]; return_status = rna_preprocess(argv[1]); } diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c index 0ae07874853..2ba067629a9 100644 --- a/source/blender/makesrna/intern/rna_animviz.c +++ b/source/blender/makesrna/intern/rna_animviz.c @@ -174,6 +174,7 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use Bone Heads", "For PoseBone paths, use the bone head location when calculating this path"); + /* FIXME: Motion Paths are not currently editable... */ prop = RNA_def_property(srna, "is_modified", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_EDIT); RNA_def_property_ui_text(prop, "Edit Path", "Path is being edited"); @@ -364,6 +365,12 @@ static void rna_def_animviz_paths(BlenderRNA *brna) "(only for 'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */ + + /* Readonly Property - Do any motion paths exist/need updating? (Mainly for bone paths) */ + prop = RNA_def_property(srna, "has_motion_paths", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "path_bakeflag", MOTIONPATH_BAKE_HAS_PATHS); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* NOTE: This is really an internal state var for convenience, so don't allow edits! */ + RNA_def_property_ui_text(prop, "Has Motion Paths", "Are there any bone paths that will need updating (read-only)"); } /* --- */ diff --git a/source/blender/makesrna/intern/rna_cachefile.c b/source/blender/makesrna/intern/rna_cachefile.c index 81b0c539e33..73928d377f1 100644 --- a/source/blender/makesrna/intern/rna_cachefile.c +++ b/source/blender/makesrna/intern/rna_cachefile.c @@ -34,11 +34,11 @@ #ifdef RNA_RUNTIME +#include "BLI_string.h" + #include "BKE_cachefile.h" #include "BKE_depsgraph.h" -#include "BLI_string.h" - #include "DEG_depsgraph.h" #include "WM_api.h" diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 68cd2902acd..981ae75e7c5 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -39,8 +39,11 @@ #ifdef RNA_RUNTIME #include "BKE_camera.h" -#include "BKE_object.h" #include "BKE_depsgraph.h" +#include "BKE_object.h" +#include "BKE_sequencer.h" + +#include "WM_api.h" static float rna_Camera_angle_get(PointerRNA *ptr) { @@ -94,6 +97,14 @@ static void rna_Camera_dependency_update(Main *bmain, Scene *UNUSED(scene), Poin DAG_id_tag_update(&camera->id, 0); } +static void rna_Camera_dof_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) +{ + /* TODO(sergey): Can be more selective here. */ + BKE_sequencer_cache_cleanup(); + BKE_sequencer_preprocessed_cache_cleanup(); + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); +} + #else static void rna_def_camera_stereo_data(BlenderRNA *brna) @@ -323,7 +334,7 @@ void RNA_def_camera(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2); RNA_def_property_ui_text(prop, "DOF Distance", "Distance to the focus point for depth of field"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update"); /* Stereo Settings */ prop = RNA_def_property(srna, "stereo", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index cb5d731efc5..cb71cf756ec 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -175,7 +175,7 @@ static void rna_ImageUser_update(Main *UNUSED(bmain), Scene *scene, PointerRNA * BKE_image_user_frame_calc(iuser, scene->r.cfra, 0); - if(ptr->id.data) { + if (ptr->id.data) { /* Update material or texture for render preview. */ DAG_id_tag_update(ptr->id.data, 0); } diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index f4f4685d1bf..c266e0e7f31 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -52,13 +52,13 @@ #ifdef RNA_RUNTIME +#include "BLI_math.h" + #include "DNA_movieclip_types.h" #include "BKE_depsgraph.h" #include "BKE_mask.h" -#include "BLI_math.h" - #include "RNA_access.h" #include "WM_api.h" diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 41758758178..18fd4c64242 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -577,99 +577,100 @@ static void rna_MeshColor_color1_get(PointerRNA *ptr, float *values) { MCol *mcol = (MCol *)ptr->data; - values[2] = (&mcol[0].r)[0] / 255.0f; - values[1] = (&mcol[0].r)[1] / 255.0f; - values[0] = (&mcol[0].r)[2] / 255.0f; + values[3] = mcol[0].a / 255.0f; + values[2] = mcol[0].r / 255.0f; + values[1] = mcol[0].g / 255.0f; + values[0] = mcol[0].b / 255.0f; } static void rna_MeshColor_color1_set(PointerRNA *ptr, const float *values) { MCol *mcol = (MCol *)ptr->data; - (&mcol[0].r)[2] = round_fl_to_uchar_clamp(values[0] * 255.0f); - (&mcol[0].r)[1] = round_fl_to_uchar_clamp(values[1] * 255.0f); - (&mcol[0].r)[0] = round_fl_to_uchar_clamp(values[2] * 255.0f); - (&mcol[0].r)[3] = round_fl_to_uchar_clamp(values[3] * 255.0f); + mcol[0].a = round_fl_to_uchar_clamp(values[3] * 255.0f); + mcol[0].r = round_fl_to_uchar_clamp(values[2] * 255.0f); + mcol[0].g = round_fl_to_uchar_clamp(values[1] * 255.0f); + mcol[0].b = round_fl_to_uchar_clamp(values[0] * 255.0f); } static void rna_MeshColor_color2_get(PointerRNA *ptr, float *values) { MCol *mcol = (MCol *)ptr->data; - values[3] = (&mcol[1].r)[3] / 255.0f; - values[2] = (&mcol[1].r)[0] / 255.0f; - values[1] = (&mcol[1].r)[1] / 255.0f; - values[0] = (&mcol[1].r)[2] / 255.0f; + values[3] = mcol[1].a / 255.0f; + values[2] = mcol[1].r / 255.0f; + values[1] = mcol[1].g / 255.0f; + values[0] = mcol[1].b / 255.0f; } static void rna_MeshColor_color2_set(PointerRNA *ptr, const float *values) { MCol *mcol = (MCol *)ptr->data; - (&mcol[1].r)[2] = round_fl_to_uchar_clamp(values[0] * 255.0f); - (&mcol[1].r)[1] = round_fl_to_uchar_clamp(values[1] * 255.0f); - (&mcol[1].r)[0] = round_fl_to_uchar_clamp(values[2] * 255.0f); - (&mcol[1].r)[3] = round_fl_to_uchar_clamp(values[3] * 255.0f); + mcol[1].a = round_fl_to_uchar_clamp(values[3] * 255.0f); + mcol[1].r = round_fl_to_uchar_clamp(values[2] * 255.0f); + mcol[1].g = round_fl_to_uchar_clamp(values[1] * 255.0f); + mcol[1].b = round_fl_to_uchar_clamp(values[0] * 255.0f); } static void rna_MeshColor_color3_get(PointerRNA *ptr, float *values) { MCol *mcol = (MCol *)ptr->data; - values[3] = (&mcol[2].r)[3] / 255.0f; - values[2] = (&mcol[2].r)[0] / 255.0f; - values[1] = (&mcol[2].r)[1] / 255.0f; - values[0] = (&mcol[2].r)[2] / 255.0f; + values[3] = mcol[2].a / 255.0f; + values[2] = mcol[2].r / 255.0f; + values[1] = mcol[2].g / 255.0f; + values[0] = mcol[2].b / 255.0f; } static void rna_MeshColor_color3_set(PointerRNA *ptr, const float *values) { MCol *mcol = (MCol *)ptr->data; - (&mcol[2].r)[2] = round_fl_to_uchar_clamp(values[0] * 255.0f); - (&mcol[2].r)[1] = round_fl_to_uchar_clamp(values[1] * 255.0f); - (&mcol[2].r)[0] = round_fl_to_uchar_clamp(values[2] * 255.0f); - (&mcol[2].r)[3] = round_fl_to_uchar_clamp(values[3] * 255.0f); + mcol[2].a = round_fl_to_uchar_clamp(values[3] * 255.0f); + mcol[2].r = round_fl_to_uchar_clamp(values[2] * 255.0f); + mcol[2].g = round_fl_to_uchar_clamp(values[1] * 255.0f); + mcol[2].b = round_fl_to_uchar_clamp(values[0] * 255.0f); } static void rna_MeshColor_color4_get(PointerRNA *ptr, float *values) { MCol *mcol = (MCol *)ptr->data; - values[2] = (&mcol[3].r)[0] / 255.0f; - values[1] = (&mcol[3].r)[1] / 255.0f; - values[0] = (&mcol[3].r)[2] / 255.0f; - values[3] = (&mcol[3].r)[3] / 255.0f; + values[3] = mcol[3].a / 255.0f; + values[2] = mcol[3].r / 255.0f; + values[1] = mcol[3].g / 255.0f; + values[0] = mcol[3].b / 255.0f; } static void rna_MeshColor_color4_set(PointerRNA *ptr, const float *values) { MCol *mcol = (MCol *)ptr->data; - (&mcol[3].r)[2] = round_fl_to_uchar_clamp(values[0] * 255.0f); - (&mcol[3].r)[1] = round_fl_to_uchar_clamp(values[1] * 255.0f); - (&mcol[3].r)[0] = round_fl_to_uchar_clamp(values[2] * 255.0f); - (&mcol[3].r)[3] = round_fl_to_uchar_clamp(values[3] * 255.0f); + mcol[3].a = round_fl_to_uchar_clamp(values[3] * 255.0f); + mcol[3].r = round_fl_to_uchar_clamp(values[2] * 255.0f); + mcol[3].g = round_fl_to_uchar_clamp(values[1] * 255.0f); + mcol[3].b = round_fl_to_uchar_clamp(values[0] * 255.0f); } static void rna_MeshLoopColor_color_get(PointerRNA *ptr, float *values) { - MLoopCol *mcol = (MLoopCol *)ptr->data; + MLoopCol *mlcol = (MLoopCol *)ptr->data; - values[0] = (&mcol->r)[0] / 255.0f; - values[1] = (&mcol->r)[1] / 255.0f; - values[2] = (&mcol->r)[2] / 255.0f; - values[3] = (&mcol->r)[3] / 255.0f; + values[0] = mlcol->r / 255.0f; + values[1] = mlcol->g / 255.0f; + values[2] = mlcol->b / 255.0f; + values[3] = mlcol->a / 255.0f; } static void rna_MeshLoopColor_color_set(PointerRNA *ptr, const float *values) { - MLoopCol *mcol = (MLoopCol *)ptr->data; + MLoopCol *mlcol = (MLoopCol *)ptr->data; - (&mcol->r)[0] = round_fl_to_uchar_clamp(values[0] * 255.0f); - (&mcol->r)[1] = round_fl_to_uchar_clamp(values[1] * 255.0f); - (&mcol->r)[2] = round_fl_to_uchar_clamp(values[2] * 255.0f); - (&mcol->r)[3] = round_fl_to_uchar_clamp(values[3] * 255.0f); + mlcol->r = round_fl_to_uchar_clamp(values[0] * 255.0f); + mlcol->g = round_fl_to_uchar_clamp(values[1] * 255.0f); + mlcol->b = round_fl_to_uchar_clamp(values[2] * 255.0f); + mlcol->a = round_fl_to_uchar_clamp(values[3] * 255.0f); } static int rna_Mesh_texspace_editable(PointerRNA *ptr, const char **UNUSED(r_info)) diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 7fc0ffeb747..53fe84707d1 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -675,6 +675,7 @@ static void rna_Particle_reset_dependency(Main *bmain, Scene *scene, PointerRNA static void rna_Particle_change_type(Main *bmain, Scene *scene, PointerRNA *ptr) { particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET | PSYS_RECALC_TYPE); + DAG_relations_tag_update(bmain); } static void rna_Particle_change_physics(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -757,7 +758,7 @@ static void rna_Particle_target_redo(Main *UNUSED(bmain), Scene *UNUSED(scene), } } -static void rna_Particle_hair_dynamics(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; ParticleSystem *psys = (ParticleSystem *)ptr->data; @@ -769,10 +770,12 @@ static void rna_Particle_hair_dynamics(Main *bmain, Scene *scene, PointerRNA *pt psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; rna_Particle_redo(bmain, scene, ptr); } - else + else { WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL); + } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DAG_relations_tag_update(bmain); } static PointerRNA rna_particle_settings_get(PointerRNA *ptr) { @@ -3292,7 +3295,7 @@ static void rna_def_particle_system(BlenderRNA *brna) prop = RNA_def_property(srna, "use_hair_dynamics", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_HAIR_DYNAMICS); RNA_def_property_ui_text(prop, "Hair Dynamics", "Enable hair dynamics using cloth simulation"); - RNA_def_property_update(prop, 0, "rna_Particle_hair_dynamics"); + RNA_def_property_update(prop, 0, "rna_Particle_hair_dynamics_update"); prop = RNA_def_property(srna, "cloth", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "clmd"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index bc56ff251e8..fda92ff7c0d 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -990,6 +990,11 @@ static char *rna_RenderSettings_path(PointerRNA *UNUSED(ptr)) return BLI_sprintfN("render"); } +static char *rna_BakeSettings_path(PointerRNA *UNUSED(ptr)) +{ + return BLI_sprintfN("render.bake"); +} + static char *rna_ImageFormatSettings_path(PointerRNA *ptr) { ImageFormatData *imf = (ImageFormatData *)ptr->data; @@ -2128,6 +2133,14 @@ static void rna_GPUDOFSettings_blades_set(PointerRNA *ptr, const int value) dofsettings->num_blades = value; } +static void rna_GPUDOFSettings_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) +{ + /* TODO(sergey): Can be more selective here. */ + BKE_sequencer_cache_cleanup(); + BKE_sequencer_preprocessed_cache_cleanup(); + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); +} + static void rna_Stereo3dFormat_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { ID *id = ptr->id.data; @@ -4244,6 +4257,7 @@ static void rna_def_bake_data(BlenderRNA *brna) RNA_def_struct_sdna(srna, "BakeData"); RNA_def_struct_nested(brna, srna, "RenderSettings"); RNA_def_struct_ui_text(srna, "Bake Data", "Bake data for a Scene data-block"); + RNA_def_struct_path_func(srna, "rna_BakeSettings_path"); prop = RNA_def_property(srna, "cage_object", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "cage"); @@ -4903,37 +4917,37 @@ static void rna_def_gpu_dof_fx(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Focus distance", "Viewport depth of field focus distance"); RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update"); prop = RNA_def_property(srna, "focal_length", PROP_FLOAT, PROP_DISTANCE_CAMERA); RNA_def_property_ui_text(prop, "Focal Length", "Focal length for dof effect"); RNA_def_property_range(prop, 1.0f, FLT_MAX); RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update"); prop = RNA_def_property(srna, "sensor", PROP_FLOAT, PROP_DISTANCE_CAMERA); RNA_def_property_ui_text(prop, "Sensor", "Size of sensor"); RNA_def_property_range(prop, 1.0f, FLT_MAX); RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update"); prop = RNA_def_property(srna, "fstop", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_text(prop, "F-stop", "F-stop for dof effect"); RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update"); prop = RNA_def_property(srna, "blades", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "num_blades"); RNA_def_property_ui_text(prop, "Blades", "Blades for dof effect"); RNA_def_property_range(prop, 0, 16); RNA_def_property_int_funcs(prop, NULL, "rna_GPUDOFSettings_blades_set", NULL); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update"); prop = RNA_def_property(srna, "use_high_quality", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "high_quality", 1); RNA_def_property_ui_text(prop, "High Quality", "Use high quality depth of field"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update"); prop = RNA_def_property(srna, "is_hq_supported", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_gpu_is_hq_supported_get", NULL); @@ -5461,7 +5475,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) }; static const EnumPropertyItem ffmpeg_crf_items[] = { - {FFM_CRF_NONE, "NONE", 0, "None; use constant bit-rate", + {FFM_CRF_NONE, "NONE", 0, "None; use custom bitrate", "Use constant bit rate, rather than constant output quality"}, {FFM_CRF_LOSSLESS, "LOSSLESS", 0, "Lossless", ""}, {FFM_CRF_PERC_LOSSLESS, "PERC_LOSSLESS", 0, "Perceptually lossless", ""}, @@ -6460,6 +6474,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Textured Solid", "Draw face-assigned textures in solid draw method"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update"); + prop = RNA_def_property(srna, "use_sequencer_gl_dof", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_CAMERA_DOF); + RNA_def_property_ui_text(prop, "Depth of Field", "Use depth of field using the values from scene strip active camera"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update"); + /* layers */ prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "layers", NULL); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 28bd0f1b07f..9da27233e0e 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -27,6 +27,8 @@ #include <stdlib.h> +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "RNA_enum_types.h" @@ -46,7 +48,6 @@ #include "WM_api.h" #include "WM_types.h" -#include "BLI_utildefines.h" #include "bmesh.h" static const EnumPropertyItem particle_edit_hair_brush_items[] = { diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 8e54c708c05..77d7f7833c6 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -29,6 +29,9 @@ #include <stdlib.h> #include <limits.h> +#include "BLI_sys_types.h" +#include "BLI_threads.h" + #include "RNA_define.h" #include "RNA_enum_types.h" @@ -38,8 +41,6 @@ #include "BKE_smoke.h" #include "BKE_pointcache.h" -#include "BLI_threads.h" - #include "DNA_modifier_types.h" #include "DNA_object_force.h" #include "DNA_object_types.h" diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 40d1cfdfcb0..b4cdb158526 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -337,7 +337,9 @@ static void ntree_shader_link_builtin_group_normal( * some internal re-linking in order to avoid cycles. */ bNode *group_output_node = ntreeFindType(group_ntree, NODE_GROUP_OUTPUT); - BLI_assert(group_output_node != NULL); + if (group_output_node == NULL) { + return; + } bNodeSocket *group_output_node_displacement_socket = nodeFindSocket(group_output_node, SOCK_IN, diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c index 006bd0cc8bb..8748c884a25 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c @@ -66,7 +66,7 @@ static void node_shader_free_tex_pointdensity(bNode *node) MEM_freeN(point_density); } -static void node_shader_copy_tex_pointdensity(bNodeTree * UNUSED(dest_ntree), +static void node_shader_copy_tex_pointdensity(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node) { diff --git a/source/blender/physics/intern/eigen_utils.h b/source/blender/physics/intern/eigen_utils.h index e4a4f306aeb..8a5a9dbf5e9 100644 --- a/source/blender/physics/intern/eigen_utils.h +++ b/source/blender/physics/intern/eigen_utils.h @@ -32,7 +32,7 @@ * \ingroup bph */ -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(__clang__) # pragma GCC diagnostic push /* XXX suppress verbose warnings in eigen */ # pragma GCC diagnostic ignored "-Wlogical-op" diff --git a/source/blender/physics/intern/implicit_eigen.cpp b/source/blender/physics/intern/implicit_eigen.cpp index ff4c705ed61..afe1b441632 100644 --- a/source/blender/physics/intern/implicit_eigen.cpp +++ b/source/blender/physics/intern/implicit_eigen.cpp @@ -39,7 +39,7 @@ #ifdef __GNUC__ # pragma GCC diagnostic push /* XXX suppress verbose warnings in eigen */ -# pragma GCC diagnostic ignored "-Wlogical-op" +//# pragma GCC diagnostic ignored "-Wlogical-op" #endif #ifndef IMPLICIT_ENABLE_EIGEN_DEBUG diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index b01d3f89d4e..7984f625d96 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -370,12 +370,12 @@ PyObject *BPy_BMVertSkin_CreatePyObject(struct MVertSkin *mvertskin) static void mloopcol_to_float(const MLoopCol *mloopcol, float r_col[3]) { - rgb_uchar_to_float(r_col, (const unsigned char *)&mloopcol->r); + rgba_uchar_to_float(r_col, (const unsigned char *)&mloopcol->r); } static void mloopcol_from_float(MLoopCol *mloopcol, const float col[3]) { - rgb_float_to_uchar((unsigned char *)&mloopcol->r, col); + rgba_float_to_uchar((unsigned char *)&mloopcol->r, col); } static unsigned char mathutils_bmloopcol_cb_index = -1; @@ -436,8 +436,8 @@ static void bm_init_types_bmloopcol(void) int BPy_BMLoopColor_AssignPyObject(struct MLoopCol *mloopcol, PyObject *value) { - float tvec[3]; - if (mathutils_array_parse(tvec, 3, 3, value, "BMLoopCol") != -1) { + float tvec[4]; + if (mathutils_array_parse(tvec, 4, 4, value, "BMLoopCol") != -1) { mloopcol_from_float(mloopcol, tvec); return 0; } @@ -450,7 +450,7 @@ PyObject *BPy_BMLoopColor_CreatePyObject(struct MLoopCol *data) { PyObject *color_capsule; color_capsule = PyCapsule_New(data, NULL, NULL); - return Color_CreatePyObject_cb(color_capsule, mathutils_bmloopcol_cb_index, 0); + return Vector_CreatePyObject_cb(color_capsule, 4, mathutils_bmloopcol_cb_index, 0); } #undef MLOOPCOL_FROM_CAPSULE diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index 3e147d29c90..e0ca3634261 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -28,13 +28,14 @@ #include <Python.h> +#include "BLI_utildefines.h" + #include "RNA_types.h" #include "bpy_rna.h" #include "BKE_global.h" -#include "MEM_guardedalloc.h" -#include "BLI_utildefines.h" +#include "MEM_guardedalloc.h" #include "RNA_access.h" diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index c7b7b35474e..830f6a0bbf1 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -310,7 +310,7 @@ void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene bool RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode); bool RE_WriteRenderResult( struct ReportList *reports, RenderResult *rr, const char *filename, - struct ImageFormatData *imf, const char *view, const int layer); + struct ImageFormatData *imf, const char *view, int layer); struct RenderResult *RE_MultilayerConvert( void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 631503bdad5..88ccb9452ba 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -36,7 +36,6 @@ #include "MEM_guardedalloc.h" -#include "BKE_appdir.h" #include "BLI_utildefines.h" #include "BLI_listbase.h" #include "BLI_hash_md5.h" @@ -45,6 +44,7 @@ #include "BLI_string.h" #include "BLI_threads.h" +#include "BKE_appdir.h" #include "BKE_image.h" #include "BKE_global.h" #include "BKE_main.h" @@ -925,6 +925,17 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil } } + /* We only store RGBA passes as half float, for + * others precision loss can be problematic. */ + bool pass_half_float = half_float && + (STREQ(rp->chan_id, "RGB") || + STREQ(rp->chan_id, "RGBA") || + STREQ(rp->chan_id, "R") || + STREQ(rp->chan_id, "G") || + STREQ(rp->chan_id, "B") || + STREQ(rp->chan_id, "A")); + + for (int a = 0; a < rp->channels; a++) { /* Save Combined as RGBA if single layer save. */ char passname[EXR_PASS_MAXNAME]; @@ -940,10 +951,9 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil layname[0] = '\0'; } - /* Add channel. */ IMB_exr_add_channel(exrhandle, layname, passname, viewname, rp->channels, rp->channels * rr->rectx, rp->rect + a, - STREQ(rp->name, RE_PASSNAME_Z) ? false : half_float); + pass_half_float); } } } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 637ace9cd82..57f4219f23f 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -71,7 +71,6 @@ #include "DNA_windowmanager_types.h" #include "BKE_appdir.h" -#include "BKE_utildefines.h" #include "BKE_autoexec.h" #include "BKE_blender.h" #include "BKE_blendfile.h" @@ -327,12 +326,12 @@ static void wm_init_userdef(bContext *C, const bool read_userdef_from_memory) BKE_sound_init(bmain); /* needed so loading a file from the command line respects user-pref [#26156] */ - BKE_BIT_TEST_SET(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI); + SET_FLAG_FROM_TEST(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI); /* set the python auto-execute setting from user prefs */ /* enabled by default, unless explicitly enabled in the command line which overrides */ if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) { - BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC); + SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC); } /* avoid re-saving for every small change to our prefs, allow overrides */ @@ -675,7 +674,7 @@ int wm_homefile_read( BLI_assert((use_factory_settings && filepath_startup_override) == 0); if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) { - BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC); + SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC); } BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); @@ -714,8 +713,8 @@ int wm_homefile_read( if (!use_factory_settings && BLI_exists(filepath_userdef)) { UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL); if (userdef != NULL) { - BKE_blender_userdef_set_data(userdef); - MEM_freeN(userdef); + BKE_blender_userdef_data_set_and_free(userdef); + userdef = NULL; skip_flags |= BLO_READ_SKIP_USERDEF; printf("Read prefs: %s\n", filepath_userdef); @@ -825,9 +824,8 @@ int wm_homefile_read( read_userdef_from_memory = true; } if (userdef_template) { - BKE_blender_userdef_set_app_template(userdef_template); - BKE_blender_userdef_free_data(userdef_template); - MEM_freeN(userdef_template); + BKE_blender_userdef_app_template_data_set_and_free(userdef_template); + userdef_template = NULL; } } } @@ -1031,14 +1029,14 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, BlendThumbnail **t ibuf = ED_view3d_draw_offscreen_imbuf_simple( scene, scene->camera, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, - IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, 0, false, NULL, + IB_rect, OB_SOLID, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL, NULL, NULL, err_out); } else { ibuf = ED_view3d_draw_offscreen_imbuf( scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, - IB_rect, false, R_ALPHAPREMUL, 0, false, NULL, + IB_rect, V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL, NULL, NULL, err_out); } @@ -1167,8 +1165,8 @@ static int wm_file_write(bContext *C, const char *filepath, int fileflags, Repor G.save_over = 1; /* disable untitled.blend convention */ } - BKE_BIT_TEST_SET(G.fileflags, fileflags & G_FILE_COMPRESS, G_FILE_COMPRESS); - BKE_BIT_TEST_SET(G.fileflags, fileflags & G_FILE_AUTOPLAY, G_FILE_AUTOPLAY); + SET_FLAG_FROM_TEST(G.fileflags, fileflags & G_FILE_COMPRESS, G_FILE_COMPRESS); + SET_FLAG_FROM_TEST(G.fileflags, fileflags & G_FILE_AUTOPLAY, G_FILE_AUTOPLAY); /* prevent background mode scripts from clobbering history */ if (do_history) { @@ -1473,41 +1471,53 @@ static int wm_userpref_write_exec(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); char filepath[FILE_MAX]; const char *cfgdir; - bool ok = false; + bool ok = true; /* update keymaps in user preferences */ WM_keyconfig_update(wm); if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) { + bool ok_write; BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); printf("trying to save userpref at %s ", filepath); - if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) { + + if (U.app_template[0]) { + ok_write = BKE_blendfile_userdef_write_app_template(filepath, op->reports); + } + else { + ok_write = BKE_blendfile_userdef_write(filepath, op->reports); + } + + if (ok_write) { printf("ok\n"); - ok = true; } else { printf("fail\n"); + ok = false; } } else { BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path"); } - if (U.app_template[0] && (cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) { - /* Also save app-template prefs */ - BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); - printf("trying to save app-template userpref at %s ", filepath); - if (BKE_blendfile_userdef_write(filepath, op->reports) == 0) { - printf("fail\n"); - ok = true; + if (U.app_template[0]) { + if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) { + /* Also save app-template prefs */ + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + printf("trying to save app-template userpref at %s ", filepath); + if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) { + printf("ok\n"); + } + else { + printf("fail\n"); + ok = false; + } } else { - printf("ok\n"); + BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path"); + ok = false; } } - else if (U.app_template[0]) { - BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path"); - } return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } @@ -1555,7 +1565,7 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) /* This can be used when loading of a start-up file should only change * the scene content but keep the blender UI as it is. */ wm_open_init_load_ui(op, true); - BKE_BIT_TEST_SET(G.fileflags, !RNA_boolean_get(op->ptr, "load_ui"), G_FILE_NO_UI); + SET_FLAG_FROM_TEST(G.fileflags, !RNA_boolean_get(op->ptr, "load_ui"), G_FILE_NO_UI); if (RNA_property_is_set(op->ptr, prop)) { RNA_property_string_get(op->ptr, prop, filepath_buf); @@ -2038,20 +2048,24 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) fileflags = G.fileflags & ~G_FILE_USERPREFS; /* set compression flag */ - BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "compress"), - G_FILE_COMPRESS); - BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "relative_remap"), - G_FILE_RELATIVE_REMAP); - BKE_BIT_TEST_SET(fileflags, - (RNA_struct_property_is_set(op->ptr, "copy") && - RNA_boolean_get(op->ptr, "copy")), - G_FILE_SAVE_COPY); + SET_FLAG_FROM_TEST( + fileflags, RNA_boolean_get(op->ptr, "compress"), + G_FILE_COMPRESS); + SET_FLAG_FROM_TEST( + fileflags, RNA_boolean_get(op->ptr, "relative_remap"), + G_FILE_RELATIVE_REMAP); + SET_FLAG_FROM_TEST( + fileflags, + (RNA_struct_property_is_set(op->ptr, "copy") && + RNA_boolean_get(op->ptr, "copy")), + G_FILE_SAVE_COPY); #ifdef USE_BMESH_SAVE_AS_COMPAT - BKE_BIT_TEST_SET(fileflags, - (RNA_struct_find_property(op->ptr, "use_mesh_compat") && - RNA_boolean_get(op->ptr, "use_mesh_compat")), - G_FILE_MESH_COMPAT); + SET_FLAG_FROM_TEST( + fileflags, + (RNA_struct_find_property(op->ptr, "use_mesh_compat") && + RNA_boolean_get(op->ptr, "use_mesh_compat")), + G_FILE_MESH_COMPAT); #else # error "don't remove by accident" #endif diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index e73ec2b081a..7608b015f49 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -569,7 +569,7 @@ void WM_exit_ext(bContext *C, const bool do_python) ED_file_exit(); /* for fsmenu */ UI_exit(); - BKE_blender_userdef_free_data(&U); + BKE_blender_userdef_data_free(&U, false); RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index fbd6d89e7bc..4674df9983b 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3852,14 +3852,29 @@ void wm_window_keymap(wmKeyConfig *keyconf) gesture_straightline_modal_keymap(keyconf); } +/** + * Filter functions that can be used with rna_id_itemf() below. + * Should return false if 'id' should be excluded. + */ +static bool rna_id_enum_filter_single(ID *id, void *user_data) +{ + return (id != user_data); +} + /* Generic itemf's for operators that take library args */ -static const EnumPropertyItem *rna_id_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), bool *r_free, ID *id, bool local) +static const EnumPropertyItem *rna_id_itemf( + bContext *UNUSED(C), PointerRNA *UNUSED(ptr), + bool *r_free, ID *id, bool local, + bool (*filter_ids)(ID *id, void *user_data), void *user_data) { EnumPropertyItem item_tmp = {0}, *item = NULL; int totitem = 0; int i = 0; for (; id; id = id->next) { + if ((filter_ids != NULL) && filter_ids(user_data, id) == false) { + continue; + } if (local == false || !ID_IS_LINKED(id)) { item_tmp.identifier = item_tmp.name = id->name + 2; item_tmp.value = i++; @@ -3876,7 +3891,7 @@ static const EnumPropertyItem *rna_id_itemf(bContext *UNUSED(C), PointerRNA *UNU /* can add more as needed */ const EnumPropertyItem *RNA_action_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->action.first : NULL, false); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->action.first : NULL, false, NULL, NULL); } #if 0 /* UNUSED */ const EnumPropertyItem *RNA_action_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) @@ -3887,45 +3902,51 @@ const EnumPropertyItem *RNA_action_local_itemf(bContext *C, PointerRNA *ptr, Pro const EnumPropertyItem *RNA_group_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, false); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, false, NULL, NULL); } const EnumPropertyItem *RNA_group_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, true); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, true, NULL, NULL); } const EnumPropertyItem *RNA_image_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->image.first : NULL, false); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->image.first : NULL, false, NULL, NULL); } const EnumPropertyItem *RNA_image_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->image.first : NULL, true); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->image.first : NULL, true, NULL, NULL); } const EnumPropertyItem *RNA_scene_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, false); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, false, NULL, NULL); } const EnumPropertyItem *RNA_scene_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, true); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, true, NULL, NULL); +} +const EnumPropertyItem *RNA_scene_without_active_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) +{ + Scene *scene_active = C ? CTX_data_scene(C) : NULL; + return rna_id_itemf( + C, ptr, r_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, true, + rna_id_enum_filter_single, scene_active); } - const EnumPropertyItem *RNA_movieclip_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclip.first : NULL, false); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclip.first : NULL, false, NULL, NULL); } const EnumPropertyItem *RNA_movieclip_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclip.first : NULL, true); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->movieclip.first : NULL, true, NULL, NULL); } const EnumPropertyItem *RNA_mask_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, false); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, false, NULL, NULL); } const EnumPropertyItem *RNA_mask_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { - return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, true); + return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, true, NULL, NULL); } diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index d858097abef..64aab31ba22 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -488,7 +488,7 @@ int KX_SoundActuator::pyattr_set_3d_property(void *self, const struct KX_PYATTRI if (actuator->m_handle) AUD_Handle_setAttenuation(actuator->m_handle, prop_value); - } else if (!!strcmp(prop, "cone_angle_inner")) { + } else if (!strcmp(prop, "cone_angle_inner")) { actuator->m_3d.cone_inner_angle = prop_value; if (actuator->m_handle) AUD_Handle_setConeAngleInner(actuator->m_handle, prop_value); diff --git a/source/tools b/source/tools -Subproject b11375e89061303401376f7aeae42ac2fd64692 +Subproject e10a1b031b243482371c0673ee17aa3c0f53637 diff --git a/tests/gtests/blenlib/BLI_task_test.cc b/tests/gtests/blenlib/BLI_task_test.cc new file mode 100644 index 00000000000..e6464164ecb --- /dev/null +++ b/tests/gtests/blenlib/BLI_task_test.cc @@ -0,0 +1,76 @@ +/* Apache License, Version 2.0 */ + +#include "testing/testing.h" +#include <string.h> + +#include "atomic_ops.h" + +extern "C" { +#include "BLI_mempool.h" +#include "BLI_task.h" +#include "BLI_utildefines.h" +}; + +#define NUM_ITEMS 10000 + +static void task_mempool_iter_func(void *userdata, MempoolIterData *item) { + int *data = (int *)item; + int *count = (int *)userdata; + + EXPECT_TRUE(data != NULL); + + *data += 1; + atomic_sub_and_fetch_uint32((uint32_t *)count, 1); +} + +TEST(task, MempoolIter) +{ + int *data[NUM_ITEMS]; + BLI_mempool *mempool = BLI_mempool_create(sizeof(*data[0]), NUM_ITEMS, 32, BLI_MEMPOOL_ALLOW_ITER); + + int i; + + /* 'Randomly' add and remove some items from mempool, to create a non-homogenous one. */ + int num_items = 0; + for (i = 0; i < NUM_ITEMS; i++) { + data[i] = (int *)BLI_mempool_alloc(mempool); + *data[i] = i - 1; + num_items++; + } + + for (i = 0; i < NUM_ITEMS; i += 3) { + BLI_mempool_free(mempool, data[i]); + data[i] = NULL; + num_items--; + } + + for (i = 0; i < NUM_ITEMS; i += 7) { + if (data[i] == NULL) { + data[i] = (int *)BLI_mempool_alloc(mempool); + *data[i] = i - 1; + num_items++; + } + } + + for (i = 0; i < NUM_ITEMS - 5; i += 23) { + for (int j = 0; j < 5; j++) { + if (data[i + j] != NULL) { + BLI_mempool_free(mempool, data[i + j]); + data[i + j] = NULL; + num_items--; + } + } + } + + BLI_task_parallel_mempool(mempool, &num_items, task_mempool_iter_func, true); + + /* Those checks should ensure us all items of the mempool were processed once, and only once - as expected. */ + EXPECT_EQ(num_items, 0); + for (i = 0; i < NUM_ITEMS; i++) { + if (data[i] != NULL) { + EXPECT_EQ(*data[i], i); + } + } + + BLI_mempool_destroy(mempool); +} diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt index eff67f053e6..715b689387f 100644 --- a/tests/gtests/blenlib/CMakeLists.txt +++ b/tests/gtests/blenlib/CMakeLists.txt @@ -27,6 +27,7 @@ set(INC ../../../source/blender/blenlib ../../../source/blender/makesdna ../../../intern/guardedalloc + ../../../intern/atomic ) include_directories(${INC}) @@ -55,6 +56,7 @@ BLENDER_TEST(BLI_polyfill2d "bf_blenlib") BLENDER_TEST(BLI_stack "bf_blenlib") BLENDER_TEST(BLI_string "bf_blenlib") BLENDER_TEST(BLI_string_utf8 "bf_blenlib") +BLENDER_TEST(BLI_task "bf_blenlib") BLENDER_TEST_PERFORMANCE(BLI_ghash_performance "bf_blenlib") |