diff options
author | Jason Wilkins <Jason.A.Wilkins@gmail.com> | 2014-10-07 19:39:17 +0400 |
---|---|---|
committer | Jason Wilkins <Jason.A.Wilkins@gmail.com> | 2014-10-07 19:39:17 +0400 |
commit | 189c2e9277d4abd3b750a5a60ef42549dcfe359d (patch) | |
tree | 1430a845f4aab56b9133c3d8c6ffac09ee6dd92a | |
parent | 771bad9c6abaad4b742935e5d55067f281287650 (diff) | |
parent | 1519b6a23e0341e25bf5a5c714f9f3d119ab8781 (diff) |
Merge branch 'master' into soc-2014-viewport_contextsoc-2014-viewport_context
698 files changed, 21613 insertions, 11549 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 677150efd88..1fb406f650f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -252,6 +252,7 @@ option(WITH_LZMA "Enable best LZMA compression, (used for pointcache)" # Camera/motion tracking option(WITH_LIBMV "Enable libmv structure from motion library" ON) +option(WITH_LIBMV_SCHUR_SPECIALIZATIONS "Enable fixed-size schur specializations." ON) # Freestyle option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON) @@ -288,6 +289,10 @@ option(WITH_CYCLES_CUDA_BINARIES "Build cycles CUDA binaries" OFF) set(CYCLES_CUDA_BINARIES_ARCH sm_20 sm_21 sm_30 sm_35 sm_50 CACHE STRING "CUDA architectures to build binaries for") mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH) unset(PLATFORM_DEFAULT) +option(WITH_CYCLES_LOGGING "Build cycles with logging support" OFF) +option(WITH_CYCLES_DEBUG "Build cycles with with extra debug capabilties" OFF) +mark_as_advanced(WITH_CYCLES_LOGGING) +mark_as_advanced(WITH_CYCLES_DEBUG) # LLVM option(WITH_LLVM "Use LLVM" OFF) @@ -374,6 +379,8 @@ if(APPLE) execute_process(COMMAND uname -r OUTPUT_VARIABLE MAC_SYS) # check for actual system-version if(${MAC_SYS} MATCHES 14) set(OSX_SYSTEM 10.10) + # throw an error here, older cmake cannot handle 2 digit subversion! + cmake_minimum_required(VERSION 3.0.0) elseif(${MAC_SYS} MATCHES 13) set(OSX_SYSTEM 10.9) elseif(${MAC_SYS} MATCHES 12) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index c1b2fd96c97..a5acbe9b612 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -25,10 +25,12 @@ ARGS=$( \ getopt \ -o s:i:t:h \ ---long source:,install:,tmp:,threads:,help,no-sudo,with-all,with-opencollada,ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,\ +--long source:,install:,tmp:,info:,threads:,help,no-sudo,with-all,with-opencollada,\ +ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,\ force-all,force-python,force-numpy,force-boost,force-ocio,force-oiio,force-llvm,force-osl,force-opencollada,\ -force-ffmpeg,skip-python,skip-numpy,skip-boost,skip-ocio,skip-oiio,skip-llvm,skip-osl,skip-ffmpeg,\ -skip-opencollada,required-numpy: \ +force-ffmpeg,\ +skip-python,skip-numpy,skip-boost,skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-ffmpeg,skip-opencollada,\ +required-numpy: \ -- "$@" \ ) @@ -38,6 +40,7 @@ SRC="$HOME/src/blender-deps" INST="/opt/lib" TMP="/tmp" CWD=$PWD +INFO_PATH=$CWD # Do not install some optional, potentially conflicting libs by default... WITH_ALL=false @@ -74,6 +77,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: --tmp=<path> Use a specific temp path (defaults to '\$TMP'). + --info=<path> + Use a specific info path (to store BUILD_NOTES.txt, defaults to '\$INFO_PATH'). + -t n, --threads=n Use a specific number of threads when building the libraries (auto-detected as '\$THREADS'). @@ -320,6 +326,9 @@ while true; do --tmp) TMP="$2"; shift; shift; continue ;; + --info) + INFO_PATH="$2"; shift; shift; continue + ;; -t|--threads) THREADS="$2"; shift; shift; continue ;; @@ -3098,9 +3107,9 @@ else exit 1 fi -print_info | tee BUILD_NOTES.txt +print_info | tee $INFO_PATH/BUILD_NOTES.txt PRINT "" -PRINT "This information has been written to BUILD_NOTES.txt" +PRINT "This information has been written to $INFO_PATH/BUILD_NOTES.txt" PRINT "" # Switch back to user language. diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py index d7a1439e003..0971735f641 100644 --- a/build_files/buildbot/config/user-config-glibc211-i686.py +++ b/build_files/buildbot/config/user-config-glibc211-i686.py @@ -49,7 +49,7 @@ BF_CXX_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.7.1/libstdc++.a' WITH_BF_OPENAL = True WITH_BF_STATICOPENAL = True BF_OPENAL = '/opt/lib/openal' -BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a' +BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a /opt/lib/openal/lib/libcommon.a' WITH_BF_GETTEXT_STATIC = True diff --git a/build_files/buildbot/config/user-config-glibc211-x86_64.py b/build_files/buildbot/config/user-config-glibc211-x86_64.py index f07c447bf29..748d1004850 100644 --- a/build_files/buildbot/config/user-config-glibc211-x86_64.py +++ b/build_files/buildbot/config/user-config-glibc211-x86_64.py @@ -49,7 +49,7 @@ BF_CXX_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.7.1/libstdc++.a' WITH_BF_OPENAL = True WITH_BF_STATICOPENAL = True BF_OPENAL = '/opt/lib/openal' -BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a' +BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a /opt/lib/openal/lib/libcommon.a' WITH_BF_GETTEXT_STATIC = True diff --git a/build_files/buildbot/config/user-config-player-glibc211-i686.py b/build_files/buildbot/config/user-config-player-glibc211-i686.py index 641dbe082ad..384da4070eb 100644 --- a/build_files/buildbot/config/user-config-player-glibc211-i686.py +++ b/build_files/buildbot/config/user-config-player-glibc211-i686.py @@ -34,7 +34,7 @@ BF_CXX_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.7.1/libstdc++.a' WITH_BF_OPENAL = True WITH_BF_STATICOPENAL = True BF_OPENAL = '/opt/lib/openal' -BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a' +BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a /opt/lib/openal/lib/libcommon.a' WITH_BF_GETTEXT_STATIC = True diff --git a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py index 80503268b44..5176d59d5a0 100644 --- a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py +++ b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py @@ -34,7 +34,7 @@ BF_CXX_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.7.1/libstdc++.a' WITH_BF_OPENAL = True WITH_BF_STATICOPENAL = True BF_OPENAL = '/opt/lib/openal' -BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a' +BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a /opt/lib/openal/lib/libcommon.a' WITH_BF_GETTEXT_STATIC = True diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py index c2044fcc21d..2e0eeb1e067 100755 --- a/build_files/cmake/cmake_consistency_check.py +++ b/build_files/cmake/cmake_consistency_check.py @@ -174,7 +174,7 @@ def cmake_get_src(f): elif is_c(new_file): sources_c.append(new_file) global_refs.setdefault(new_file, []).append((f, i)) - elif l in ("PARENT_SCOPE", ): + elif l in {"PARENT_SCOPE", }: # cmake var, ignore pass elif new_file.endswith(".list"): diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index b7bd27dea03..12cbbb1618a 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -178,7 +178,7 @@ def validate_arguments(args, bc): 'WITH_BF_OIIO', 'WITH_BF_STATICOIIO', 'BF_OIIO', 'BF_OIIO_INC', 'BF_OIIO_LIB', 'BF_OIIO_LIB_STATIC', 'BF_OIIO_LIBPATH', 'WITH_BF_OCIO', 'WITH_BF_STATICOCIO', 'BF_OCIO', 'BF_OCIO_INC', 'BF_OCIO_LIB', 'BF_OCIO_LIB_STATIC', 'BF_OCIO_LIBPATH', 'WITH_BF_BOOST', 'WITH_BF_STATICBOOST', 'BF_BOOST', 'BF_BOOST_INC', 'BF_BOOST_LIB', 'BF_BOOST_LIB_INTERNATIONAL', 'BF_BOOST_LIB_STATIC', 'BF_BOOST_LIBPATH', - 'WITH_BF_LIBMV', + 'WITH_BF_LIBMV', 'WITH_BF_LIBMV_SCHUR_SPECIALIZATIONS', 'WITH_BF_CYCLES_OSL', 'WITH_BF_STATICOSL', 'BF_OSL', 'BF_OSL_INC', 'BF_OSL_LIB', 'BF_OSL_LIBPATH', 'BF_OSL_LIB_STATIC', 'BF_OSL_COMPILER', 'WITH_BF_LLVM', 'WITH_BF_STATICLLVM', 'BF_LLVM', 'BF_LLVM_LIB', 'BF_LLVM_LIBPATH', 'BF_LLVM_LIB_STATIC', 'BF_PROGRAM_LINKFLAGS' ] @@ -195,7 +195,8 @@ def validate_arguments(args, bc): 'BF_DEBUG_CFLAGS', 'BF_DEBUG_CCFLAGS', 'BF_DEBUG_CXXFLAGS', 'C_WARN', 'CC_WARN', 'CXX_WARN', 'LLIBS', 'PLATFORM_LINKFLAGS', 'MACOSX_ARCHITECTURE', 'MACOSX_SDK', 'XCODE_CUR_VER', 'C_COMPILER_ID', - 'BF_CYCLES_CUDA_BINARIES_ARCH', 'BF_PROGRAM_LINKFLAGS', 'MACOSX_DEPLOYMENT_TARGET' + 'BF_CYCLES_CUDA_BINARIES_ARCH', 'BF_PROGRAM_LINKFLAGS', 'MACOSX_DEPLOYMENT_TARGET', + 'WITH_BF_CYCLES_DEBUG' ] @@ -571,6 +572,7 @@ def read_opts(env, cfg, args): (BoolVariable('WITH_BF_LZMA', 'Enable best LZMA pointcache compression', True)), (BoolVariable('WITH_BF_LIBMV', 'Enable libmv structure from motion library', True)), + (BoolVariable('WITH_BF_LIBMV_SCHUR_SPECIALIZATIONS', 'Enable fixed-size schur specializations', True)), (BoolVariable('WITH_BF_COMPOSITOR', 'Enable the tile based nodal compositor', True)), ) # end of opts.AddOptions() @@ -600,6 +602,7 @@ def read_opts(env, cfg, args): ('BF_CYCLES_CUDA_NVCC', 'CUDA nvcc compiler path', ''), ('BF_CYCLES_CUDA_ENV', 'preset environement nvcc will execute in', ''), ('BF_CYCLES_CUDA_BINARIES_ARCH', 'CUDA architectures to compile binaries for', []), + (BoolVariable('WITH_BF_CYCLES_DEBUG', 'Build Cycles engine with extra debugging capabilities', False)), (BoolVariable('WITH_BF_OIIO', 'Build with OpenImageIO', False)), (BoolVariable('WITH_BF_STATICOIIO', 'Statically link to OpenImageIO', False)), diff --git a/build_files/utils/build_tgz.sh b/build_files/utils/build_tgz.sh index b0ff8ea2aa8..409c738e9f8 100755 --- a/build_files/utils/build_tgz.sh +++ b/build_files/utils/build_tgz.sh @@ -22,15 +22,18 @@ TARBALL="blender-$VERSION.tar.gz" cd "$blender_srcdir" +# not so nice, but works +FILTER_FILES_PY="import os, sys; [print(l[:-1]) for l in sys.stdin.readlines() if os.path.isfile(l[:-1])]" + # Build master list echo -n "Building manifest of files: \"$BASE_DIR/$MANIFEST\" ..." -git ls-files > $BASE_DIR/$MANIFEST +git ls-files | python3 -c "$FILTER_FILES_PY" > $BASE_DIR/$MANIFEST # Enumerate submodules -for lcv in $(git submodule | cut -f2 -d" "); do +for lcv in $(git submodule | awk '{print $2}'); do cd "$BASE_DIR" cd "$blender_srcdir/$lcv" - git ls-files | awk '$0="'"$lcv"/'"$0' >> $BASE_DIR/$MANIFEST + git ls-files | python3 -c "$FILTER_FILES_PY" | awk '$0="'"$lcv"/'"$0' >> $BASE_DIR/$MANIFEST cd "$BASE_DIR" done echo "OK" diff --git a/doc/python_api/examples/bpy.props.5.py b/doc/python_api/examples/bpy.props.5.py index d2ace54de27..4e9d61d5385 100644 --- a/doc/python_api/examples/bpy.props.5.py +++ b/doc/python_api/examples/bpy.props.5.py @@ -75,7 +75,7 @@ print(scene.test_float) scene.test_array = (True, False) print([x for x in scene.test_array]) -#scene.test_date = "blah" # this would fail, property is read-only +# scene.test_date = "blah" # this would fail, property is read-only print(scene.test_date) scene.test_enum = 'BLUE' diff --git a/doc/python_api/examples/bpy.types.Operator.5.py b/doc/python_api/examples/bpy.types.Operator.5.py index 4a0abcb62c3..78030c7d7c4 100644 --- a/doc/python_api/examples/bpy.types.Operator.5.py +++ b/doc/python_api/examples/bpy.types.Operator.5.py @@ -39,7 +39,7 @@ class ModalOperator(bpy.types.Operator): self.execute(context) elif event.type == 'LEFTMOUSE': # Confirm return {'FINISHED'} - elif event.type in ('RIGHTMOUSE', 'ESC'): # Cancel + elif event.type in {'RIGHTMOUSE', 'ESC'}: # Cancel context.object.location.x = self.init_loc_x return {'CANCELLED'} diff --git a/doc/python_api/examples/bpy.types.bpy_prop_collection.foreach_get.py b/doc/python_api/examples/bpy.types.bpy_prop_collection.foreach_get.py index 05163b332a9..a83b23e84f9 100644 --- a/doc/python_api/examples/bpy.types.bpy_prop_collection.foreach_get.py +++ b/doc/python_api/examples/bpy.types.bpy_prop_collection.foreach_get.py @@ -8,4 +8,3 @@ collection.foreach_get(attr, some_seq) # Python equivalent for i in range(len(seq)): some_seq[i] = getattr(collection[i], attr) - diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 98bf6bf2eed..0b9a4e6a37b 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -1,22 +1,22 @@ - # ***** 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. - # - # Contributor(s): Campbell Barton, Luca Bonavita - # - # #**** END GPL LICENSE BLOCK #**** +# ##### 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. +# +# Contributor(s): Campbell Barton +# +# ##### END GPL LICENSE BLOCK ##### # <pep8 compliant> @@ -274,6 +274,12 @@ else: "mathutils.kdtree", "mathutils.noise", "freestyle", + "freestyle.chainingiterators", + "freestyle.functions", + "freestyle.predicates", + "freestyle.shaders", + "freestyle.types", + "freestyle.utils", ] # ------ @@ -316,7 +322,13 @@ try: __import__("freestyle") except ImportError: BPY_LOGGER.debug("Warning: Built without 'freestyle' module, docs incomplete...") - EXCLUDE_MODULES = list(EXCLUDE_MODULES) + ["freestyle"] + EXCLUDE_MODULES = list(EXCLUDE_MODULES) + ["freestyle", + "freestyle.chainingiterators", + "freestyle.functions", + "freestyle.predicates", + "freestyle.shaders", + "freestyle.types", + "freestyle.utils"] # examples EXAMPLES_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "examples")) @@ -683,7 +695,7 @@ def py_descr2sphinx(ident, fw, descr, module_name, type_name, identifier): fw(ident + ".. data:: %s\n\n" % identifier) write_indented_lines(ident + " ", fw, doc, False) fw("\n") - elif type(descr) in (MethodDescriptorType, ClassMethodDescriptorType): + elif type(descr) in {MethodDescriptorType, ClassMethodDescriptorType}: write_indented_lines(ident, fw, doc, False) fw("\n") else: @@ -877,7 +889,7 @@ def pymodule2sphinx(basepath, module_name, module, title): for attribute, value, value_type in module_dir_value_type: if value_type == types.FunctionType: pyfunc2sphinx("", fw, module_name, None, attribute, value, is_class=False) - elif value_type in (types.BuiltinMethodType, types.BuiltinFunctionType): # both the same at the moment but to be future proof + elif value_type in {types.BuiltinMethodType, types.BuiltinFunctionType}: # both the same at the moment but to be future proof # note: can't get args from these, so dump the string as is # this means any module used like this must have fully formatted docstrings. py_c_func2sphinx("", fw, module_name, None, attribute, value, is_class=False) @@ -1780,8 +1792,14 @@ def write_rst_importable_modules(basepath): "mathutils.geometry" : "Geometry Utilities", "mathutils.kdtree" : "KDTree Utilities", "mathutils.noise" : "Noise Utilities", - "freestyle" : "Freestyle Data Types & Operators", - } + "freestyle" : "Freestyle Module", + "freestyle.types" : "Freestyle Types", + "freestyle.predicates" : "Freestyle Predicates", + "freestyle.functions" : "Freestyle Functions", + "freestyle.chainingiterators" : "Freestyle Chaining Iterators", + "freestyle.shaders" : "Freestyle Shaders", + "freestyle.utils" : "Freestyle Utilities", + } for mod_name, mod_descr in importable_modules.items(): if mod_name not in EXCLUDE_MODULES: module = __import__(mod_name, @@ -1852,8 +1870,8 @@ def rna2sphinx(basepath): # context if "bpy.context" not in EXCLUDE_MODULES: # one of a kind, context doc (uses ctypes to extract info!) - # doesn't work on mac - if PLATFORM != "darwin": + # doesn't work on mac and windows + if PLATFORM not in {"darwin", "windows"}: pycontext2sphinx(basepath) # internal modules diff --git a/doc/python_api/sphinx_doc_gen.sh b/doc/python_api/sphinx_doc_gen.sh index c8256a1c4cd..d7fc372a8d8 100755 --- a/doc/python_api/sphinx_doc_gen.sh +++ b/doc/python_api/sphinx_doc_gen.sh @@ -100,7 +100,7 @@ if $DO_UPLOAD ; then cp $SPHINXBASE/sphinx-out/contents.html $SPHINXBASE/sphinx-out/index.html ssh $SSH_USER@blender.org 'rm -rf '$SSH_UPLOAD_FULL'/*' - rsync --progress -avze "ssh -p 22" $SPHINXBASE/sphinx-out/* $SSH_HOST:$SSH_UPLOAD_FULL/ + rsync --progress -ave "ssh -p 22" $SPHINXBASE/sphinx-out/* $SSH_HOST:$SSH_UPLOAD_FULL/ ## symlink the dir to a static URL #ssh $SSH_USER@blender.org 'rm '$SSH_UPLOAD'/250PythonDoc && ln -s '$SSH_UPLOAD_FULL' '$SSH_UPLOAD'/250PythonDoc' @@ -115,11 +115,11 @@ if $DO_UPLOAD ; then if $DO_OUT_PDF ; then # rename so local PDF has matching name. - rsync --progress -avze "ssh -p 22" $SPHINXBASE/sphinx-out/blender_python_reference_$BLENDER_VERSION.pdf $SSH_HOST:$SSH_UPLOAD_FULL/blender_python_reference_$BLENDER_VERSION.pdf + rsync --progress -ave "ssh -p 22" $SPHINXBASE/sphinx-out/blender_python_reference_$BLENDER_VERSION.pdf $SSH_HOST:$SSH_UPLOAD_FULL/blender_python_reference_$BLENDER_VERSION.pdf fi if $DO_OUT_HTML_ZIP ; then - rsync --progress -avze "ssh -p 22" $SPHINXBASE/blender_python_reference_$BLENDER_VERSION.zip $SSH_HOST:$SSH_UPLOAD_FULL/blender_python_reference_$BLENDER_VERSION.zip + rsync --progress -ave "ssh -p 22" $SPHINXBASE/blender_python_reference_$BLENDER_VERSION.zip $SSH_HOST:$SSH_UPLOAD_FULL/blender_python_reference_$BLENDER_VERSION.zip fi fi diff --git a/doc/python_api/sphinx_doc_gen_monkeypatch.py b/doc/python_api/sphinx_doc_gen_monkeypatch.py index 1167ece05b7..9fdbf613d96 100644 --- a/doc/python_api/sphinx_doc_gen_monkeypatch.py +++ b/doc/python_api/sphinx_doc_gen_monkeypatch.py @@ -1,22 +1,22 @@ - # ***** 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. - # - # Contributor(s): Campbell Barton - # - # #**** END GPL LICENSE BLOCK #**** +# ##### 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. +# +# Contributor(s): Campbell Barton +# +# ##### END GPL LICENSE BLOCK ##### # <pep8 compliant> diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 9030ae9c1ed..09c36fc4383 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -35,12 +35,10 @@ set(INC_SYS set(SRC libmv-capi.h - libmv-capi_intern.h ) if(WITH_LIBMV) add_definitions( - -DWITH_LIBMV -DWITH_LIBMV_GUARDED_ALLOC -DGOOGLE_GLOG_DLL_DECL= -DLIBMV_NO_FAST_DETECTOR= @@ -66,15 +64,21 @@ if(WITH_LIBMV) ../../intern/guardedalloc ) - set(INC_SYS + list(APPEND INC_SYS ../Eigen3 ${PNG_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ) list(APPEND SRC - libmv-capi.cc - libmv-util.cc + intern/camera_intrinsics.cc + intern/detector.cc + intern/homography.cc + intern/image.cc + intern/logging.cc + intern/reconstruction.cc + intern/track_region.cc + intern/tracks.cc libmv/base/aligned_malloc.cc libmv/image/array_nd.cc libmv/image/convolve.cc @@ -109,7 +113,15 @@ if(WITH_LIBMV) libmv/tracking/track_region.cc libmv/tracking/trklt_region_tracker.cc - libmv-util.h + + intern/camera_intrinsics.h + intern/detector.h + intern/homography.h + intern/image.h + intern/logging.h + intern/reconstruction.h + intern/track_region.h + intern/tracks.h libmv/base/aligned_malloc.h libmv/base/id_generator.h libmv/base/scoped_ptr.h @@ -217,7 +229,7 @@ if(WITH_LIBMV) endif() else() list(APPEND SRC - libmv-capi_stub.cc + intern/stub.cc ) endif() @@ -228,7 +240,7 @@ if(WITH_LIBMV) endif() # make GLog a separate target, so it can be used for gtest as well. -if(WITH_LIBMV OR WITH_GTESTS) +if(WITH_LIBMV OR WITH_GTESTS OR WITH_CYCLES_LOGGING) # We compile GLog together with GFlag so we don't worry about # adding extra lib to linker. set(GLOG_SRC diff --git a/extern/libmv/SConscript b/extern/libmv/SConscript index 6156dd45146..162fb88df53 100644 --- a/extern/libmv/SConscript +++ b/extern/libmv/SConscript @@ -24,11 +24,11 @@ if env['WITH_BF_LIBMV']: defs.append('CERES_TR1_SHARED_PTR') defs.append('GOOGLE_GLOG_DLL_DECL=') - defs.append('WITH_LIBMV') defs.append('WITH_LIBMV_GUARDED_ALLOC') defs.append('LIBMV_NO_FAST_DETECTOR') - src = env.Glob('*.cc') + src = env.Glob('intern/*.cc') + src.remove('intern' + os.sep + 'stub.cc') src += env.Glob('libmv/base/*.cc') src += env.Glob('libmv/image/*.cc') src += env.Glob('libmv/multiview/*.cc') @@ -52,7 +52,7 @@ if env['WITH_BF_LIBMV']: src += env.Glob("third_party/glog/src/*.cc") incs += ' ./third_party/glog/src' else: - src = env.Glob("libmv-capi_stub.cc") + src = env.Glob("intern/stub.cc") src = [src for src in src if src.find('_test.cc') == -1] diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh index 0560ab0acd2..f352f77373b 100755 --- a/extern/libmv/bundle.sh +++ b/extern/libmv/bundle.sh @@ -7,7 +7,7 @@ else exit 1 fi -BRANCH="devel" +BRANCH="master" repo="git://git.blender.org/libmv.git" tmp=`mktemp -d` @@ -128,12 +128,10 @@ set(INC_SYS set(SRC libmv-capi.h - libmv-capi_intern.h ) if(WITH_LIBMV) add_definitions( - -DWITH_LIBMV -DWITH_LIBMV_GUARDED_ALLOC -DGOOGLE_GLOG_DLL_DECL= -DLIBMV_NO_FAST_DETECTOR= @@ -159,18 +157,32 @@ if(WITH_LIBMV) ../../intern/guardedalloc ) - set(INC_SYS + list(APPEND INC_SYS ../Eigen3 \${PNG_INCLUDE_DIR} \${ZLIB_INCLUDE_DIRS} ) list(APPEND SRC - libmv-capi.cc - libmv-util.cc + intern/camera_intrinsics.cc + intern/detector.cc + intern/homography.cc + intern/image.cc + intern/logging.cc + intern/reconstruction.cc + intern/track_region.cc + intern/tracks.cc ${sources} ${third_sources} - libmv-util.h + + intern/camera_intrinsics.h + intern/detector.h + intern/homography.h + intern/image.h + intern/logging.h + intern/reconstruction.h + intern/track_region.h + intern/tracks.h ${headers} ${third_headers} @@ -287,11 +299,11 @@ if env['WITH_BF_LIBMV']: defs.append('CERES_TR1_SHARED_PTR') defs.append('GOOGLE_GLOG_DLL_DECL=') - defs.append('WITH_LIBMV') defs.append('WITH_LIBMV_GUARDED_ALLOC') defs.append('LIBMV_NO_FAST_DETECTOR') - src = env.Glob('*.cc') + src = env.Glob('intern/*.cc') + src.remove('intern' + os.sep + 'stub.cc') $src incs += ' ../Eigen3 third_party/gflags third_party/glog/src third_party/ceres/include third_party/ceres/config ../../intern/guardedalloc' @@ -309,7 +321,7 @@ ${win_src} src += env.Glob("third_party/glog/src/*.cc") incs += ' ./third_party/glog/src' else: - src = env.Glob("libmv-capi_stub.cc") + src = env.Glob("intern/stub.cc") src = [src for src in src if src.find('_test.cc') == -1] diff --git a/extern/libmv/intern/camera_intrinsics.cc b/extern/libmv/intern/camera_intrinsics.cc new file mode 100644 index 00000000000..e8b99970ff7 --- /dev/null +++ b/extern/libmv/intern/camera_intrinsics.cc @@ -0,0 +1,354 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "intern/camera_intrinsics.h" +#include "intern/utildefines.h" +#include "libmv/simple_pipeline/camera_intrinsics.h" + +using libmv::CameraIntrinsics; +using libmv::DivisionCameraIntrinsics; +using libmv::PolynomialCameraIntrinsics; + +libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options) { + CameraIntrinsics *camera_intrinsics = + libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options); + return (libmv_CameraIntrinsics *) camera_intrinsics; +} + +libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy( + const libmv_CameraIntrinsics* libmv_intrinsics) { + const CameraIntrinsics *orig_intrinsics = + (const CameraIntrinsics *) libmv_intrinsics; + + CameraIntrinsics *new_intrinsics = NULL; + switch (orig_intrinsics->GetDistortionModelType()) { + case libmv::DISTORTION_MODEL_POLYNOMIAL: + { + const PolynomialCameraIntrinsics *polynomial_intrinsics = + static_cast<const PolynomialCameraIntrinsics*>(orig_intrinsics); + new_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics, + *polynomial_intrinsics); + break; + } + case libmv::DISTORTION_MODEL_DIVISION: + { + const DivisionCameraIntrinsics *division_intrinsics = + static_cast<const DivisionCameraIntrinsics*>(orig_intrinsics); + new_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics, + *division_intrinsics); + break; + } + default: + assert(!"Unknown distortion model"); + } + return (libmv_CameraIntrinsics *) new_intrinsics; +} + +void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics* libmv_intrinsics) { + LIBMV_OBJECT_DELETE(libmv_intrinsics, CameraIntrinsics); +} + +void libmv_cameraIntrinsicsUpdate( + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + libmv_CameraIntrinsics* libmv_intrinsics) { + CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics; + + double focal_length = libmv_camera_intrinsics_options->focal_length; + double principal_x = libmv_camera_intrinsics_options->principal_point_x; + double principal_y = libmv_camera_intrinsics_options->principal_point_y; + int image_width = libmv_camera_intrinsics_options->image_width; + int image_height = libmv_camera_intrinsics_options->image_height; + + /* Try avoid unnecessary updates, so pre-computed distortion grids + * are not freed. + */ + + if (camera_intrinsics->focal_length() != focal_length) { + camera_intrinsics->SetFocalLength(focal_length, focal_length); + } + + if (camera_intrinsics->principal_point_x() != principal_x || + camera_intrinsics->principal_point_y() != principal_y) { + camera_intrinsics->SetPrincipalPoint(principal_x, principal_y); + } + + if (camera_intrinsics->image_width() != image_width || + camera_intrinsics->image_height() != image_height) { + camera_intrinsics->SetImageSize(image_width, image_height); + } + + switch (libmv_camera_intrinsics_options->distortion_model) { + case LIBMV_DISTORTION_MODEL_POLYNOMIAL: + { + assert(camera_intrinsics->GetDistortionModelType() == + libmv::DISTORTION_MODEL_POLYNOMIAL); + + PolynomialCameraIntrinsics *polynomial_intrinsics = + (PolynomialCameraIntrinsics *) camera_intrinsics; + + double k1 = libmv_camera_intrinsics_options->polynomial_k1; + double k2 = libmv_camera_intrinsics_options->polynomial_k2; + double k3 = libmv_camera_intrinsics_options->polynomial_k3; + + if (polynomial_intrinsics->k1() != k1 || + polynomial_intrinsics->k2() != k2 || + polynomial_intrinsics->k3() != k3) { + polynomial_intrinsics->SetRadialDistortion(k1, k2, k3); + } + break; + } + + case LIBMV_DISTORTION_MODEL_DIVISION: + { + assert(camera_intrinsics->GetDistortionModelType() == + libmv::DISTORTION_MODEL_DIVISION); + + DivisionCameraIntrinsics *division_intrinsics = + (DivisionCameraIntrinsics *) camera_intrinsics; + + double k1 = libmv_camera_intrinsics_options->division_k1; + double k2 = libmv_camera_intrinsics_options->division_k2; + + if (division_intrinsics->k1() != k1 || + division_intrinsics->k2() != k2) { + division_intrinsics->SetDistortion(k1, k2); + } + + break; + } + + default: + assert(!"Unknown distortion model"); + } +} + +void libmv_cameraIntrinsicsSetThreads(libmv_CameraIntrinsics* libmv_intrinsics, + int threads) { + CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics; + camera_intrinsics->SetThreads(threads); +} + +void libmv_cameraIntrinsicsExtractOptions( + const libmv_CameraIntrinsics* libmv_intrinsics, + libmv_CameraIntrinsicsOptions* camera_intrinsics_options) { + const CameraIntrinsics *camera_intrinsics = + (const CameraIntrinsics *) libmv_intrinsics; + + // Fill in options which are common for all distortion models. + camera_intrinsics_options->focal_length = camera_intrinsics->focal_length(); + camera_intrinsics_options->principal_point_x = + camera_intrinsics->principal_point_x(); + camera_intrinsics_options->principal_point_y = + camera_intrinsics->principal_point_y(); + + camera_intrinsics_options->image_width = camera_intrinsics->image_width(); + camera_intrinsics_options->image_height = camera_intrinsics->image_height(); + + switch (camera_intrinsics->GetDistortionModelType()) { + case libmv::DISTORTION_MODEL_POLYNOMIAL: + { + const PolynomialCameraIntrinsics *polynomial_intrinsics = + static_cast<const PolynomialCameraIntrinsics *>(camera_intrinsics); + camera_intrinsics_options->distortion_model = + LIBMV_DISTORTION_MODEL_POLYNOMIAL; + camera_intrinsics_options->polynomial_k1 = polynomial_intrinsics->k1(); + camera_intrinsics_options->polynomial_k2 = polynomial_intrinsics->k2(); + camera_intrinsics_options->polynomial_k3 = polynomial_intrinsics->k3(); + camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p1(); + camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p2(); + break; + } + + case libmv::DISTORTION_MODEL_DIVISION: + { + const DivisionCameraIntrinsics *division_intrinsics = + static_cast<const DivisionCameraIntrinsics *>(camera_intrinsics); + camera_intrinsics_options->distortion_model = + LIBMV_DISTORTION_MODEL_DIVISION; + camera_intrinsics_options->division_k1 = division_intrinsics->k1(); + camera_intrinsics_options->division_k2 = division_intrinsics->k2(); + break; + } + + default: + assert(!"Uknown distortion model"); + } +} + +void libmv_cameraIntrinsicsUndistortByte( + const libmv_CameraIntrinsics* libmv_intrinsics, + const unsigned char *source_image, + int width, + int height, + float overscan, + int channels, + unsigned char* destination_image) { + CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics; + camera_intrinsics->UndistortBuffer(source_image, + width, height, + overscan, + channels, + destination_image); +} + +void libmv_cameraIntrinsicsUndistortFloat( + const libmv_CameraIntrinsics* libmv_intrinsics, + const float* source_image, + int width, + int height, + float overscan, + int channels, + float* destination_image) { + CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics; + intrinsics->UndistortBuffer(source_image, + width, height, + overscan, + channels, + destination_image); +} + +void libmv_cameraIntrinsicsDistortByte( + const struct libmv_CameraIntrinsics* libmv_intrinsics, + const unsigned char *source_image, + int width, + int height, + float overscan, + int channels, + unsigned char *destination_image) { + CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics; + intrinsics->DistortBuffer(source_image, + width, height, + overscan, + channels, + destination_image); +} + +void libmv_cameraIntrinsicsDistortFloat( + const libmv_CameraIntrinsics* libmv_intrinsics, + float* source_image, + int width, + int height, + float overscan, + int channels, + float* destination_image) { + CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmv_intrinsics; + intrinsics->DistortBuffer(source_image, + width, height, + overscan, + channels, + destination_image); +} + +void libmv_cameraIntrinsicsApply( + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + double x, + double y, + double* x1, + double* y1) { + /* Do a lens distortion if focal length is non-zero only. */ + if (libmv_camera_intrinsics_options->focal_length) { + CameraIntrinsics* camera_intrinsics = + libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options); + camera_intrinsics->ApplyIntrinsics(x, y, x1, y1); + LIBMV_OBJECT_DELETE(camera_intrinsics, CameraIntrinsics); + } +} + +void libmv_cameraIntrinsicsInvert( + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + double x, + double y, + double* x1, + double* y1) { + /* Do a lens un-distortion if focal length is non-zero only/ */ + if (libmv_camera_intrinsics_options->focal_length) { + CameraIntrinsics *camera_intrinsics = + libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options); + camera_intrinsics->InvertIntrinsics(x, y, x1, y1); + LIBMV_OBJECT_DELETE(camera_intrinsics, CameraIntrinsics); + } +} + +static void libmv_cameraIntrinsicsFillFromOptions( + const libmv_CameraIntrinsicsOptions* camera_intrinsics_options, + CameraIntrinsics* camera_intrinsics) { + camera_intrinsics->SetFocalLength(camera_intrinsics_options->focal_length, + camera_intrinsics_options->focal_length); + + camera_intrinsics->SetPrincipalPoint( + camera_intrinsics_options->principal_point_x, + camera_intrinsics_options->principal_point_y); + + camera_intrinsics->SetImageSize(camera_intrinsics_options->image_width, + camera_intrinsics_options->image_height); + + switch (camera_intrinsics_options->distortion_model) { + case LIBMV_DISTORTION_MODEL_POLYNOMIAL: + { + PolynomialCameraIntrinsics *polynomial_intrinsics = + static_cast<PolynomialCameraIntrinsics*>(camera_intrinsics); + + polynomial_intrinsics->SetRadialDistortion( + camera_intrinsics_options->polynomial_k1, + camera_intrinsics_options->polynomial_k2, + camera_intrinsics_options->polynomial_k3); + + break; + } + + case LIBMV_DISTORTION_MODEL_DIVISION: + { + DivisionCameraIntrinsics *division_intrinsics = + static_cast<DivisionCameraIntrinsics*>(camera_intrinsics); + + division_intrinsics->SetDistortion( + camera_intrinsics_options->division_k1, + camera_intrinsics_options->division_k2); + break; + } + + default: + assert(!"Unknown distortion model"); + } +} + +CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions( + const libmv_CameraIntrinsicsOptions* camera_intrinsics_options) { + CameraIntrinsics *camera_intrinsics = NULL; + switch (camera_intrinsics_options->distortion_model) { + case LIBMV_DISTORTION_MODEL_POLYNOMIAL: + camera_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics); + break; + case LIBMV_DISTORTION_MODEL_DIVISION: + camera_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics); + break; + default: + assert(!"Unknown distortion model"); + } + libmv_cameraIntrinsicsFillFromOptions(camera_intrinsics_options, camera_intrinsics); + return camera_intrinsics; +} diff --git a/extern/libmv/intern/camera_intrinsics.h b/extern/libmv/intern/camera_intrinsics.h new file mode 100644 index 00000000000..9910d16a108 --- /dev/null +++ b/extern/libmv/intern/camera_intrinsics.h @@ -0,0 +1,138 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef LIBMV_C_API_CAMERA_INTRINSICS_H_ +#define LIBMV_C_API_CAMERA_INTRINSICS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics; + +enum { + LIBMV_DISTORTION_MODEL_POLYNOMIAL = 0, + LIBMV_DISTORTION_MODEL_DIVISION = 1, +}; + +typedef struct libmv_CameraIntrinsicsOptions { + // Common settings of all distortion models. + int distortion_model; + int image_width, image_height; + double focal_length; + double principal_point_x, principal_point_y; + + // Radial distortion model. + double polynomial_k1, polynomial_k2, polynomial_k3; + double polynomial_p1, polynomial_p2; + + // Division distortion model. + double division_k1, division_k2; +} libmv_CameraIntrinsicsOptions; + +libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options); + +libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy( + const libmv_CameraIntrinsics* libmv_intrinsics); + +void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics* libmv_intrinsics); +void libmv_cameraIntrinsicsUpdate( + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + libmv_CameraIntrinsics* libmv_intrinsics); + +void libmv_cameraIntrinsicsSetThreads(libmv_CameraIntrinsics* libmv_intrinsics, + int threads); + +void libmv_cameraIntrinsicsExtractOptions( + const libmv_CameraIntrinsics* libmv_intrinsics, + libmv_CameraIntrinsicsOptions* camera_intrinsics_options); + +void libmv_cameraIntrinsicsUndistortByte( + const libmv_CameraIntrinsics* libmv_intrinsics, + const unsigned char *source_image, + int width, + int height, + float overscan, + int channels, + unsigned char* destination_image); + +void libmv_cameraIntrinsicsUndistortFloat( + const libmv_CameraIntrinsics* libmv_intrinsics, + const float* source_image, + int width, + int height, + float overscan, + int channels, + float* destination_image); + +void libmv_cameraIntrinsicsDistortByte( + const struct libmv_CameraIntrinsics* libmv_intrinsics, + const unsigned char *source_image, + int width, + int height, + float overscan, + int channels, + unsigned char *destination_image); + +void libmv_cameraIntrinsicsDistortFloat( + const libmv_CameraIntrinsics* libmv_intrinsics, + float* source_image, + int width, + int height, + float overscan, + int channels, + float* destination_image); + +void libmv_cameraIntrinsicsApply( + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + double x, + double y, + double* x1, + double* y1); + +void libmv_cameraIntrinsicsInvert( + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + double x, + double y, + double* x1, + double* y1); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + +namespace libmv { + class CameraIntrinsics; +} + +libmv::CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions( + const libmv_CameraIntrinsicsOptions* camera_intrinsics_options); +#endif + +#endif // LIBMV_C_API_CAMERA_INTRINSICS_H_ diff --git a/extern/libmv/intern/detector.cc b/extern/libmv/intern/detector.cc new file mode 100644 index 00000000000..8abc9014115 --- /dev/null +++ b/extern/libmv/intern/detector.cc @@ -0,0 +1,148 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "intern/detector.h" +#include "intern/image.h" +#include "intern/utildefines.h" +#include "libmv/simple_pipeline/detect.h" + +using libmv::Detect; +using libmv::DetectOptions; +using libmv::Feature; +using libmv::FloatImage; + +struct libmv_Features { + int count; + Feature* features; +}; + +namespace { + +libmv_Features *libmv_featuresFromVector( + const libmv::vector<Feature>& features) { + libmv_Features* libmv_features = LIBMV_STRUCT_NEW(libmv_Features, 1); + int count = features.size(); + if (count) { + libmv_features->features = LIBMV_STRUCT_NEW(Feature, count); + for (int i = 0; i < count; i++) { + libmv_features->features[i] = features.at(i); + } + } else { + libmv_features->features = NULL; + } + libmv_features->count = count; + return libmv_features; +} + +void libmv_convertDetectorOptions(libmv_DetectOptions *options, + DetectOptions *detector_options) { + switch (options->detector) { +#define LIBMV_CONVERT(the_detector) \ + case LIBMV_DETECTOR_ ## the_detector: \ + detector_options->type = DetectOptions::the_detector; \ + break; + LIBMV_CONVERT(FAST) + LIBMV_CONVERT(MORAVEC) + LIBMV_CONVERT(HARRIS) +#undef LIBMV_CONVERT + } + detector_options->margin = options->margin; + detector_options->min_distance = options->min_distance; + detector_options->fast_min_trackness = options->fast_min_trackness; + detector_options->moravec_max_count = options->moravec_max_count; + detector_options->moravec_pattern = options->moravec_pattern; + detector_options->harris_threshold = options->harris_threshold; +} + +} // namespace + +libmv_Features *libmv_detectFeaturesByte(const unsigned char* image_buffer, + int width, + int height, + int channels, + libmv_DetectOptions* options) { + // Prepare the image. + FloatImage image; + libmv_byteBufferToFloatImage(image_buffer, width, height, channels, &image); + + // Configure detector. + DetectOptions detector_options; + libmv_convertDetectorOptions(options, &detector_options); + + // Run the detector. + libmv::vector<Feature> detected_features; + Detect(image, detector_options, &detected_features); + + // Convert result to C-API. + libmv_Features* result = libmv_featuresFromVector(detected_features); + return result; +} + +libmv_Features* libmv_detectFeaturesFloat(const float* image_buffer, + int width, + int height, + int channels, + libmv_DetectOptions* options) { + // Prepare the image. + FloatImage image; + libmv_floatBufferToFloatImage(image_buffer, width, height, channels, &image); + + // Configure detector. + DetectOptions detector_options; + libmv_convertDetectorOptions(options, &detector_options); + + // Run the detector. + libmv::vector<Feature> detected_features; + Detect(image, detector_options, &detected_features); + + // Convert result to C-API. + libmv_Features* result = libmv_featuresFromVector(detected_features); + return result; +} + +void libmv_featuresDestroy(libmv_Features* libmv_features) { + if (libmv_features->features) { + LIBMV_STRUCT_DELETE(libmv_features->features); + } + LIBMV_STRUCT_DELETE(libmv_features); +} + +int libmv_countFeatures(const libmv_Features* libmv_features) { + return libmv_features->count; +} + +void libmv_getFeature(const libmv_Features* libmv_features, + int number, + double* x, + double* y, + double* score, + double* size) { + Feature &feature = libmv_features->features[number]; + *x = feature.x; + *y = feature.y; + *score = feature.score; + *size = feature.size; +} diff --git a/extern/libmv/intern/detector.h b/extern/libmv/intern/detector.h new file mode 100644 index 00000000000..f72b0dd8d6e --- /dev/null +++ b/extern/libmv/intern/detector.h @@ -0,0 +1,77 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef LIBMV_C_API_DETECTOR_H_ +#define LIBMV_C_API_DETECTOR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct libmv_Features libmv_Features; + +enum { + LIBMV_DETECTOR_FAST, + LIBMV_DETECTOR_MORAVEC, + LIBMV_DETECTOR_HARRIS, +}; + +typedef struct libmv_DetectOptions { + int detector; + int margin; + int min_distance; + int fast_min_trackness; + int moravec_max_count; + unsigned char *moravec_pattern; + double harris_threshold; +} libmv_DetectOptions; + +libmv_Features* libmv_detectFeaturesByte(const unsigned char* image_buffer, + int width, + int height, + int channels, + libmv_DetectOptions* options); + +libmv_Features* libmv_detectFeaturesFloat(const float* image_buffer, + int width, + int height, + int channels, + libmv_DetectOptions* options); + +void libmv_featuresDestroy(libmv_Features* libmv_features); +int libmv_countFeatures(const libmv_Features* libmv_features); +void libmv_getFeature(const libmv_Features* libmv_features, + int number, + double* x, + double* y, + double* score, + double* size); + +#ifdef __cplusplus +} +#endif + +#endif // LIBMV_C_API_DETECTOR_H_ diff --git a/extern/libmv/intern/homography.cc b/extern/libmv/intern/homography.cc new file mode 100644 index 00000000000..6b61bd9ab42 --- /dev/null +++ b/extern/libmv/intern/homography.cc @@ -0,0 +1,59 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "intern/homography.h" +#include "intern/utildefines.h" +#include "libmv/logging/logging.h" +#include "libmv/multiview/homography.h" + +void libmv_homography2DFromCorrespondencesEuc(/* const */ double (*x1)[2], + /* const */ double (*x2)[2], + int num_points, + double H[3][3]) { + libmv::Mat x1_mat, x2_mat; + libmv::Mat3 H_mat; + + x1_mat.resize(2, num_points); + x2_mat.resize(2, num_points); + + for (int i = 0; i < num_points; i++) { + x1_mat.col(i) = libmv::Vec2(x1[i][0], x1[i][1]); + x2_mat.col(i) = libmv::Vec2(x2[i][0], x2[i][1]); + } + + LG << "x1: " << x1_mat; + LG << "x2: " << x2_mat; + + libmv::EstimateHomographyOptions options; + libmv::EstimateHomography2DFromCorrespondences(x1_mat, + x2_mat, + options, + &H_mat); + + LG << "H: " << H_mat; + + memcpy(H, H_mat.data(), 9 * sizeof(double)); +} diff --git a/extern/libmv/intern/homography.h b/extern/libmv/intern/homography.h new file mode 100644 index 00000000000..175108e8171 --- /dev/null +++ b/extern/libmv/intern/homography.h @@ -0,0 +1,43 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef LIBMV_C_API_HOMOGRAPHY_H_ +#define LIBMV_C_API_HOMOGRAPHY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void libmv_homography2DFromCorrespondencesEuc(/* const */ double (*x1)[2], + /* const */ double (*x2)[2], + int num_points, + double H[3][3]); + +#ifdef __cplusplus +} +#endif + +#endif // LIBMV_C_API_HOMOGRAPHY_H_ diff --git a/extern/libmv/intern/image.cc b/extern/libmv/intern/image.cc new file mode 100644 index 00000000000..7e623bdbec7 --- /dev/null +++ b/extern/libmv/intern/image.cc @@ -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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "intern/image.h" +#include "intern/utildefines.h" +#include "libmv/tracking/track_region.h" + +#include <cassert> +#include <png.h> + +using libmv::FloatImage; +using libmv::SamplePlanarPatch; + +void libmv_floatImaheDestroy(libmv_FloatImage *image) { + delete [] image->buffer; +} + +/* Image <-> buffers conversion */ + +void libmv_byteBufferToFloatImage(const unsigned char* buffer, + int width, + int height, + int channels, + FloatImage* image) { + image->Resize(height, width, channels); + for (int y = 0, a = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + for (int k = 0; k < channels; k++) { + (*image)(y, x, k) = (float)buffer[a++] / 255.0f; + } + } + } +} + +void libmv_floatBufferToFloatImage(const float* buffer, + int width, + int height, + int channels, + FloatImage* image) { + image->Resize(height, width, channels); + for (int y = 0, a = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + for (int k = 0; k < channels; k++) { + (*image)(y, x, k) = buffer[a++]; + } + } + } +} + +void libmv_floatImageToFloatBuffer(const FloatImage &image, + float* buffer) { + for (int y = 0, a = 0; y < image.Height(); y++) { + for (int x = 0; x < image.Width(); x++) { + for (int k = 0; k < image.Depth(); k++) { + buffer[a++] = image(y, x, k); + } + } + } +} + +void libmv_floatImageToByteBuffer(const libmv::FloatImage &image, + unsigned char* buffer) { + for (int y = 0, a= 0; y < image.Height(); y++) { + for (int x = 0; x < image.Width(); x++) { + for (int k = 0; k < image.Depth(); k++) { + buffer[a++] = image(y, x, k) * 255.0f; + } + } + } +} + +static bool savePNGImage(png_bytep* row_pointers, + int width, + int height, + int depth, + int color_type, + const char* file_name) { + png_infop info_ptr; + png_structp png_ptr; + FILE *fp = fopen(file_name, "wb"); + + if (fp == NULL) { + return false; + } + + /* Initialize stuff */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + info_ptr = png_create_info_struct(png_ptr); + + if (setjmp(png_jmpbuf(png_ptr))) { + fclose(fp); + return false; + } + + png_init_io(png_ptr, fp); + + /* Write PNG header. */ + if (setjmp(png_jmpbuf(png_ptr))) { + fclose(fp); + return false; + } + + png_set_IHDR(png_ptr, + info_ptr, + width, + height, + depth, + color_type, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); + + png_write_info(png_ptr, info_ptr); + + /* Write bytes/ */ + if (setjmp(png_jmpbuf(png_ptr))) { + fclose(fp); + return false; + } + + png_write_image(png_ptr, row_pointers); + + /* End write/ */ + if (setjmp(png_jmpbuf(png_ptr))) { + fclose(fp); + return false; + } + + png_write_end(png_ptr, NULL); + fclose(fp); + + return true; +} + +bool libmv_saveImage(const FloatImage& image, + const char* prefix, + int x0, + int y0) { + int x, y; + png_bytep *row_pointers; + + assert(image.Depth() == 1); + + row_pointers = new png_bytep[image.Height()]; + + for (y = 0; y < image.Height(); y++) { + row_pointers[y] = new png_byte[4 * image.Width()]; + + for (x = 0; x < image.Width(); x++) { + if (x0 == x && image.Height() - y0 - 1 == y) { + row_pointers[y][x * 4 + 0] = 255; + row_pointers[y][x * 4 + 1] = 0; + row_pointers[y][x * 4 + 2] = 0; + row_pointers[y][x * 4 + 3] = 255; + } else { + float pixel = image(image.Height() - y - 1, x, 0); + row_pointers[y][x * 4 + 0] = pixel * 255; + row_pointers[y][x * 4 + 1] = pixel * 255; + row_pointers[y][x * 4 + 2] = pixel * 255; + row_pointers[y][x * 4 + 3] = 255; + } + } + } + + static int image_counter = 0; + char file_name[128]; + snprintf(file_name, sizeof(file_name), + "%s_%02d.png", + prefix, ++image_counter); + bool result = savePNGImage(row_pointers, + image.Width(), + image.Height(), + 8, + PNG_COLOR_TYPE_RGBA, + file_name); + + for (y = 0; y < image.Height(); y++) { + delete [] row_pointers[y]; + } + delete [] row_pointers; + + return result; +} + +void libmv_samplePlanarPatchFloat(const float* image, + int width, + int height, + int channels, + const double* xs, + const double* ys, + int num_samples_x, + int num_samples_y, + const float* mask, + float* patch, + double* warped_position_x, + double* warped_position_y) { + FloatImage libmv_image, libmv_patch, libmv_mask; + FloatImage *libmv_mask_for_sample = NULL; + + libmv_floatBufferToFloatImage(image, width, height, channels, &libmv_image); + + if (mask) { + libmv_floatBufferToFloatImage(mask, width, height, 1, &libmv_mask); + libmv_mask_for_sample = &libmv_mask; + } + + SamplePlanarPatch(libmv_image, + xs, ys, + num_samples_x, num_samples_y, + libmv_mask_for_sample, + &libmv_patch, + warped_position_x, + warped_position_y); + + libmv_floatImageToFloatBuffer(libmv_patch, patch); +} + + void libmv_samplePlanarPatchByte(const unsigned char* image, + int width, + int height, + int channels, + const double* xs, + const double* ys, + int num_samples_x, + int num_samples_y, + const float* mask, + unsigned char* patch, + double* warped_position_x, + double* warped_position_y) { + libmv::FloatImage libmv_image, libmv_patch, libmv_mask; + libmv::FloatImage *libmv_mask_for_sample = NULL; + + libmv_byteBufferToFloatImage(image, width, height, channels, &libmv_image); + + if (mask) { + libmv_floatBufferToFloatImage(mask, width, height, 1, &libmv_mask); + libmv_mask_for_sample = &libmv_mask; + } + + libmv::SamplePlanarPatch(libmv_image, + xs, ys, + num_samples_x, num_samples_y, + libmv_mask_for_sample, + &libmv_patch, + warped_position_x, + warped_position_y); + + libmv_floatImageToByteBuffer(libmv_patch, patch); +} diff --git a/extern/libmv/intern/image.h b/extern/libmv/intern/image.h new file mode 100644 index 00000000000..9936e748b9d --- /dev/null +++ b/extern/libmv/intern/image.h @@ -0,0 +1,99 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef LIBMV_IMAGE_H_ +#define LIBMV_IMAGE_H_ + +#ifdef __cplusplus +# include "libmv/image/image.h" +void libmv_byteBufferToFloatImage(const unsigned char* buffer, + int width, + int height, + int channels, + libmv::FloatImage* image); + +void libmv_floatBufferToFloatImage(const float* buffer, + int width, + int height, + int channels, + libmv::FloatImage* image); + +void libmv_floatImageToFloatBuffer(const libmv::FloatImage& image, + float *buffer); + +void libmv_floatImageToByteBuffer(const libmv::FloatImage& image, + unsigned char* buffer); + +bool libmv_saveImage(const libmv::FloatImage& image, + const char* prefix, + int x0, + int y0); +#endif // __cplusplus + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct libmv_FloatImage { + float *buffer; + int width; + int height; + int channels; +} libmv_FloatImage; + +void libmv_floatImaheDestroy(libmv_FloatImage *image); + +void libmv_samplePlanarPatchFloat(const float* image, + int width, + int height, + int channels, + const double* xs, + const double* ys, + int num_samples_x, + int num_samples_y, + const float* mask, + float* patch, + double* warped_position_x, + double* warped_position_y); + + void libmv_samplePlanarPatchByte(const unsigned char* image, + int width, + int height, + int channels, + const double* xs, + const double* ys, + int num_samples_x, + int num_samples_y, + const float* mask, + unsigned char* patch, + double* warped_position_x, + double* warped_position_y); + +#ifdef __cplusplus +} +#endif + +#endif // LIBMV_IMAGE_H_ diff --git a/extern/libmv/intern/logging.cc b/extern/libmv/intern/logging.cc new file mode 100644 index 00000000000..4ab2d91c8b4 --- /dev/null +++ b/extern/libmv/intern/logging.cc @@ -0,0 +1,55 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "intern/logging.h" +#include "intern/utildefines.h" +#include "libmv/logging/logging.h" + +void libmv_initLogging(const char* argv0) { + // Make it so FATAL messages are always print into console. + char severity_fatal[32]; + snprintf(severity_fatal, sizeof(severity_fatal), "%d", + google::GLOG_FATAL); + + google::InitGoogleLogging(argv0); + google::SetCommandLineOption("logtostderr", "1"); + google::SetCommandLineOption("v", "0"); + google::SetCommandLineOption("stderrthreshold", severity_fatal); + google::SetCommandLineOption("minloglevel", severity_fatal); +} + +void libmv_startDebugLogging(void) { + google::SetCommandLineOption("logtostderr", "1"); + google::SetCommandLineOption("v", "2"); + google::SetCommandLineOption("stderrthreshold", "1"); + google::SetCommandLineOption("minloglevel", "0"); +} + +void libmv_setLoggingVerbosity(int verbosity) { + char val[10]; + snprintf(val, sizeof(val), "%d", verbosity); + google::SetCommandLineOption("v", val); +} diff --git a/extern/libmv/intern/logging.h b/extern/libmv/intern/logging.h new file mode 100644 index 00000000000..479ed3d6288 --- /dev/null +++ b/extern/libmv/intern/logging.h @@ -0,0 +1,47 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef LIBMV_C_API_LOGGING_H_ +#define LIBMV_C_API_LOGGING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// Initialize GLog logging. +void libmv_initLogging(const char* argv0); + +// Switch Glog to debug logging level. +void libmv_startDebugLogging(void); + +// Set GLog logging verbosity level. +void libmv_setLoggingVerbosity(int verbosity); + +#ifdef __cplusplus +} +#endif + +#endif // LIBMV_C_API_LOGGING_H_ diff --git a/extern/libmv/intern/reconstruction.cc b/extern/libmv/intern/reconstruction.cc new file mode 100644 index 00000000000..eb3677fd206 --- /dev/null +++ b/extern/libmv/intern/reconstruction.cc @@ -0,0 +1,530 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "intern/reconstruction.h" +#include "intern/camera_intrinsics.h" +#include "intern/tracks.h" +#include "intern/utildefines.h" + +#include "libmv/logging/logging.h" +#include "libmv/simple_pipeline/bundle.h" +#include "libmv/simple_pipeline/keyframe_selection.h" +#include "libmv/simple_pipeline/initialize_reconstruction.h" +#include "libmv/simple_pipeline/modal_solver.h" +#include "libmv/simple_pipeline/pipeline.h" +#include "libmv/simple_pipeline/reconstruction_scale.h" +#include "libmv/simple_pipeline/tracks.h" + +using libmv::CameraIntrinsics; +using libmv::EuclideanCamera; +using libmv::EuclideanPoint; +using libmv::EuclideanReconstruction; +using libmv::EuclideanScaleToUnity; +using libmv::Marker; +using libmv::ProgressUpdateCallback; + +using libmv::PolynomialCameraIntrinsics; +using libmv::Tracks; +using libmv::EuclideanBundle; +using libmv::EuclideanCompleteReconstruction; +using libmv::EuclideanReconstructTwoFrames; +using libmv::EuclideanReprojectionError; + +struct libmv_Reconstruction { + EuclideanReconstruction reconstruction; + + /* Used for per-track average error calculation after reconstruction */ + Tracks tracks; + CameraIntrinsics *intrinsics; + + double error; +}; + +namespace { + +class ReconstructUpdateCallback : public ProgressUpdateCallback { + public: + ReconstructUpdateCallback( + reconstruct_progress_update_cb progress_update_callback, + void *callback_customdata) { + progress_update_callback_ = progress_update_callback; + callback_customdata_ = callback_customdata; + } + + void invoke(double progress, const char* message) { + if (progress_update_callback_) { + progress_update_callback_(callback_customdata_, progress, message); + } + } + protected: + reconstruct_progress_update_cb progress_update_callback_; + void* callback_customdata_; +}; + +void libmv_solveRefineIntrinsics( + const Tracks &tracks, + const int refine_intrinsics, + const int bundle_constraints, + reconstruct_progress_update_cb progress_update_callback, + void* callback_customdata, + EuclideanReconstruction* reconstruction, + CameraIntrinsics* intrinsics) { + /* only a few combinations are supported but trust the caller/ */ + int bundle_intrinsics = 0; + + if (refine_intrinsics & LIBMV_REFINE_FOCAL_LENGTH) { + bundle_intrinsics |= libmv::BUNDLE_FOCAL_LENGTH; + } + if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) { + bundle_intrinsics |= libmv::BUNDLE_PRINCIPAL_POINT; + } + if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) { + bundle_intrinsics |= libmv::BUNDLE_RADIAL_K1; + } + if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) { + bundle_intrinsics |= libmv::BUNDLE_RADIAL_K2; + } + + progress_update_callback(callback_customdata, 1.0, "Refining solution"); + + EuclideanBundleCommonIntrinsics(tracks, + bundle_intrinsics, + bundle_constraints, + reconstruction, + intrinsics); +} + +void finishReconstruction( + const Tracks &tracks, + const CameraIntrinsics &camera_intrinsics, + libmv_Reconstruction *libmv_reconstruction, + reconstruct_progress_update_cb progress_update_callback, + void *callback_customdata) { + EuclideanReconstruction &reconstruction = + libmv_reconstruction->reconstruction; + + /* Reprojection error calculation. */ + progress_update_callback(callback_customdata, 1.0, "Finishing solution"); + libmv_reconstruction->tracks = tracks; + libmv_reconstruction->error = EuclideanReprojectionError(tracks, + reconstruction, + camera_intrinsics); +} + +bool selectTwoKeyframesBasedOnGRICAndVariance( + Tracks& tracks, + Tracks& normalized_tracks, + CameraIntrinsics& camera_intrinsics, + int& keyframe1, + int& keyframe2) { + libmv::vector<int> keyframes; + + /* Get list of all keyframe candidates first. */ + SelectKeyframesBasedOnGRICAndVariance(normalized_tracks, + camera_intrinsics, + keyframes); + + if (keyframes.size() < 2) { + LG << "Not enough keyframes detected by GRIC"; + return false; + } else if (keyframes.size() == 2) { + keyframe1 = keyframes[0]; + keyframe2 = keyframes[1]; + return true; + } + + /* Now choose two keyframes with minimal reprojection error after initial + * reconstruction choose keyframes with the least reprojection error after + * solving from two candidate keyframes. + * + * In fact, currently libmv returns single pair only, so this code will + * not actually run. But in the future this could change, so let's stay + * prepared. + */ + int previous_keyframe = keyframes[0]; + double best_error = std::numeric_limits<double>::max(); + for (int i = 1; i < keyframes.size(); i++) { + EuclideanReconstruction reconstruction; + int current_keyframe = keyframes[i]; + libmv::vector<Marker> keyframe_markers = + normalized_tracks.MarkersForTracksInBothImages(previous_keyframe, + current_keyframe); + + Tracks keyframe_tracks(keyframe_markers); + + /* get a solution from two keyframes only */ + EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction); + EuclideanBundle(keyframe_tracks, &reconstruction); + EuclideanCompleteReconstruction(keyframe_tracks, + &reconstruction, + NULL); + + double current_error = EuclideanReprojectionError(tracks, + reconstruction, + camera_intrinsics); + + LG << "Error between " << previous_keyframe + << " and " << current_keyframe + << ": " << current_error; + + if (current_error < best_error) { + best_error = current_error; + keyframe1 = previous_keyframe; + keyframe2 = current_keyframe; + } + + previous_keyframe = current_keyframe; + } + + return true; +} + +Marker libmv_projectMarker(const EuclideanPoint& point, + const EuclideanCamera& camera, + const CameraIntrinsics& intrinsics) { + libmv::Vec3 projected = camera.R * point.X + camera.t; + projected /= projected(2); + + libmv::Marker reprojected_marker; + intrinsics.ApplyIntrinsics(projected(0), projected(1), + &reprojected_marker.x, + &reprojected_marker.y); + + reprojected_marker.image = camera.image; + reprojected_marker.track = point.track; + return reprojected_marker; +} + +void libmv_getNormalizedTracks(const Tracks &tracks, + const CameraIntrinsics &camera_intrinsics, + Tracks *normalized_tracks) +{ + libmv::vector<Marker> markers = tracks.AllMarkers(); + for (int i = 0; i < markers.size(); ++i) { + Marker &marker = markers[i]; + camera_intrinsics.InvertIntrinsics(marker.x, marker.y, + &marker.x, &marker.y); + normalized_tracks->Insert(marker.image, + marker.track, + marker.x, marker.y, + marker.weight); + } +} + +} // namespace + +libmv_Reconstruction *libmv_solveReconstruction( + const libmv_Tracks* libmv_tracks, + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + libmv_ReconstructionOptions* libmv_reconstruction_options, + reconstruct_progress_update_cb progress_update_callback, + void* callback_customdata) { + libmv_Reconstruction *libmv_reconstruction = + LIBMV_OBJECT_NEW(libmv_Reconstruction); + + Tracks &tracks = *((Tracks *) libmv_tracks); + EuclideanReconstruction &reconstruction = + libmv_reconstruction->reconstruction; + + ReconstructUpdateCallback update_callback = + ReconstructUpdateCallback(progress_update_callback, + callback_customdata); + + /* Retrieve reconstruction options from C-API to libmv API. */ + CameraIntrinsics *camera_intrinsics; + camera_intrinsics = libmv_reconstruction->intrinsics = + libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options); + + /* Invert the camera intrinsics/ */ + Tracks normalized_tracks; + libmv_getNormalizedTracks(tracks, *camera_intrinsics, &normalized_tracks); + + /* keyframe selection. */ + int keyframe1 = libmv_reconstruction_options->keyframe1, + keyframe2 = libmv_reconstruction_options->keyframe2; + + if (libmv_reconstruction_options->select_keyframes) { + LG << "Using automatic keyframe selection"; + + update_callback.invoke(0, "Selecting keyframes"); + + selectTwoKeyframesBasedOnGRICAndVariance(tracks, + normalized_tracks, + *camera_intrinsics, + keyframe1, + keyframe2); + + /* so keyframes in the interface would be updated */ + libmv_reconstruction_options->keyframe1 = keyframe1; + libmv_reconstruction_options->keyframe2 = keyframe2; + } + + /* Actual reconstruction. */ + LG << "frames to init from: " << keyframe1 << " " << keyframe2; + + libmv::vector<Marker> keyframe_markers = + normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2); + + LG << "number of markers for init: " << keyframe_markers.size(); + + update_callback.invoke(0, "Initial reconstruction"); + + EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction); + EuclideanBundle(normalized_tracks, &reconstruction); + EuclideanCompleteReconstruction(normalized_tracks, + &reconstruction, + &update_callback); + + /* Refinement/ */ + if (libmv_reconstruction_options->refine_intrinsics) { + libmv_solveRefineIntrinsics( + tracks, + libmv_reconstruction_options->refine_intrinsics, + libmv::BUNDLE_NO_CONSTRAINTS, + progress_update_callback, + callback_customdata, + &reconstruction, + camera_intrinsics); + } + + /* Set reconstruction scale to unity. */ + EuclideanScaleToUnity(&reconstruction); + + /* Finish reconstruction. */ + finishReconstruction(tracks, + *camera_intrinsics, + libmv_reconstruction, + progress_update_callback, + callback_customdata); + + return (libmv_Reconstruction *) libmv_reconstruction; +} + +libmv_Reconstruction *libmv_solveModal( + const libmv_Tracks *libmv_tracks, + const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, + const libmv_ReconstructionOptions *libmv_reconstruction_options, + reconstruct_progress_update_cb progress_update_callback, + void *callback_customdata) { + libmv_Reconstruction *libmv_reconstruction = + LIBMV_OBJECT_NEW(libmv_Reconstruction); + + Tracks &tracks = *((Tracks *) libmv_tracks); + EuclideanReconstruction &reconstruction = + libmv_reconstruction->reconstruction; + + ReconstructUpdateCallback update_callback = + ReconstructUpdateCallback(progress_update_callback, + callback_customdata); + + /* Retrieve reconstruction options from C-API to libmv API. */ + CameraIntrinsics *camera_intrinsics; + camera_intrinsics = libmv_reconstruction->intrinsics = + libmv_cameraIntrinsicsCreateFromOptions( + libmv_camera_intrinsics_options); + + /* Invert the camera intrinsics. */ + Tracks normalized_tracks; + libmv_getNormalizedTracks(tracks, *camera_intrinsics, &normalized_tracks); + + /* Actual reconstruction. */ + ModalSolver(normalized_tracks, &reconstruction, &update_callback); + + PolynomialCameraIntrinsics empty_intrinsics; + EuclideanBundleCommonIntrinsics(normalized_tracks, + libmv::BUNDLE_NO_INTRINSICS, + libmv::BUNDLE_NO_TRANSLATION, + &reconstruction, + &empty_intrinsics); + + /* Refinement. */ + if (libmv_reconstruction_options->refine_intrinsics) { + libmv_solveRefineIntrinsics( + tracks, + libmv_reconstruction_options->refine_intrinsics, + libmv::BUNDLE_NO_TRANSLATION, + progress_update_callback, callback_customdata, + &reconstruction, + camera_intrinsics); + } + + /* Finish reconstruction. */ + finishReconstruction(tracks, + *camera_intrinsics, + libmv_reconstruction, + progress_update_callback, + callback_customdata); + + return (libmv_Reconstruction *) libmv_reconstruction; +} + +void libmv_reconstructionDestroy(libmv_Reconstruction *libmv_reconstruction) { + LIBMV_OBJECT_DELETE(libmv_reconstruction->intrinsics, CameraIntrinsics); + LIBMV_OBJECT_DELETE(libmv_reconstruction, libmv_Reconstruction); +} + +int libmv_reprojectionPointForTrack( + const libmv_Reconstruction *libmv_reconstruction, + int track, + double pos[3]) { + const EuclideanReconstruction *reconstruction = + &libmv_reconstruction->reconstruction; + const EuclideanPoint *point = + reconstruction->PointForTrack(track); + if (point) { + pos[0] = point->X[0]; + pos[1] = point->X[2]; + pos[2] = point->X[1]; + return 1; + } + return 0; +} + +double libmv_reprojectionErrorForTrack( + const libmv_Reconstruction *libmv_reconstruction, + int track) { + const EuclideanReconstruction *reconstruction = + &libmv_reconstruction->reconstruction; + const CameraIntrinsics *intrinsics = libmv_reconstruction->intrinsics; + libmv::vector<Marker> markers = + libmv_reconstruction->tracks.MarkersForTrack(track); + + int num_reprojected = 0; + double total_error = 0.0; + + for (int i = 0; i < markers.size(); ++i) { + double weight = markers[i].weight; + const EuclideanCamera *camera = + reconstruction->CameraForImage(markers[i].image); + const EuclideanPoint *point = + reconstruction->PointForTrack(markers[i].track); + + if (!camera || !point || weight == 0.0) { + continue; + } + + num_reprojected++; + + Marker reprojected_marker = + libmv_projectMarker(*point, *camera, *intrinsics); + double ex = (reprojected_marker.x - markers[i].x) * weight; + double ey = (reprojected_marker.y - markers[i].y) * weight; + + total_error += sqrt(ex * ex + ey * ey); + } + + return total_error / num_reprojected; +} + +double libmv_reprojectionErrorForImage( + const libmv_Reconstruction *libmv_reconstruction, + int image) { + const EuclideanReconstruction *reconstruction = + &libmv_reconstruction->reconstruction; + const CameraIntrinsics *intrinsics = libmv_reconstruction->intrinsics; + libmv::vector<Marker> markers = + libmv_reconstruction->tracks.MarkersInImage(image); + const EuclideanCamera *camera = reconstruction->CameraForImage(image); + int num_reprojected = 0; + double total_error = 0.0; + + if (!camera) { + return 0.0; + } + + for (int i = 0; i < markers.size(); ++i) { + const EuclideanPoint *point = + reconstruction->PointForTrack(markers[i].track); + + if (!point) { + continue; + } + + num_reprojected++; + + Marker reprojected_marker = + libmv_projectMarker(*point, *camera, *intrinsics); + double ex = (reprojected_marker.x - markers[i].x) * markers[i].weight; + double ey = (reprojected_marker.y - markers[i].y) * markers[i].weight; + + total_error += sqrt(ex * ex + ey * ey); + } + + return total_error / num_reprojected; +} + +int libmv_reprojectionCameraForImage( + const libmv_Reconstruction *libmv_reconstruction, + int image, + double mat[4][4]) { + const EuclideanReconstruction *reconstruction = + &libmv_reconstruction->reconstruction; + const EuclideanCamera *camera = + reconstruction->CameraForImage(image); + + if (camera) { + for (int j = 0; j < 3; ++j) { + for (int k = 0; k < 3; ++k) { + int l = k; + + if (k == 1) { + l = 2; + } else if (k == 2) { + l = 1; + } + + if (j == 2) { + mat[j][l] = -camera->R(j, k); + } else { + mat[j][l] = camera->R(j, k); + } + } + mat[j][3] = 0.0; + } + + libmv::Vec3 optical_center = -camera->R.transpose() * camera->t; + + mat[3][0] = optical_center(0); + mat[3][1] = optical_center(2); + mat[3][2] = optical_center(1); + + mat[3][3] = 1.0; + + return 1; + } + + return 0; +} + +double libmv_reprojectionError( + const libmv_Reconstruction *libmv_reconstruction) { + return libmv_reconstruction->error; +} + +libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics( + libmv_Reconstruction *libmv_reconstruction) { + return (libmv_CameraIntrinsics *) libmv_reconstruction->intrinsics; +} diff --git a/extern/libmv/intern/reconstruction.h b/extern/libmv/intern/reconstruction.h new file mode 100644 index 00000000000..88e810b54aa --- /dev/null +++ b/extern/libmv/intern/reconstruction.h @@ -0,0 +1,100 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef LIBMV_C_API_RECONSTRUCTION_H_ +#define LIBMV_C_API_RECONSTRUCTION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct libmv_Tracks; +struct libmv_CameraIntrinsics; +struct libmv_CameraIntrinsicsOptions; + +typedef struct libmv_Reconstruction libmv_Reconstruction; + +enum { + LIBMV_REFINE_FOCAL_LENGTH = (1 << 0), + LIBMV_REFINE_PRINCIPAL_POINT = (1 << 1), + LIBMV_REFINE_RADIAL_DISTORTION_K1 = (1 << 2), + LIBMV_REFINE_RADIAL_DISTORTION_K2 = (1 << 4), +}; + +typedef struct libmv_ReconstructionOptions { + int select_keyframes; + int keyframe1, keyframe2; + int refine_intrinsics; +} libmv_ReconstructionOptions; + +typedef void (*reconstruct_progress_update_cb) (void* customdata, + double progress, + const char* message); + +libmv_Reconstruction* libmv_solveReconstruction( + const struct libmv_Tracks* libmv_tracks, + const struct libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + libmv_ReconstructionOptions* libmv_reconstruction_options, + reconstruct_progress_update_cb progress_update_callback, + void* callback_customdata); + +libmv_Reconstruction* libmv_solveModal( + const struct libmv_Tracks* libmv_tracks, + const struct libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + const libmv_ReconstructionOptions* libmv_reconstruction_options, + reconstruct_progress_update_cb progress_update_callback, + void* callback_customdata); + +void libmv_reconstructionDestroy(libmv_Reconstruction* libmv_reconstruction); + +int libmv_reprojectionPointForTrack( + const libmv_Reconstruction* libmv_reconstruction, + int track, + double pos[3]); + +double libmv_reprojectionErrorForTrack( + const libmv_Reconstruction* libmv_reconstruction, + int track); + +double libmv_reprojectionErrorForImage( + const libmv_Reconstruction* libmv_reconstruction, + int image); + +int libmv_reprojectionCameraForImage( + const libmv_Reconstruction* libmv_reconstruction, + int image, + double mat[4][4]); + +double libmv_reprojectionError(const libmv_Reconstruction* libmv_reconstruction); + +struct libmv_CameraIntrinsics* libmv_reconstructionExtractIntrinsics( + libmv_Reconstruction *libmv_Reconstruction); + +#ifdef __cplusplus +} +#endif + +#endif // LIBMV_C_API_RECONSTRUCTION_H_ diff --git a/extern/libmv/intern/region.h b/extern/libmv/intern/region.h new file mode 100644 index 00000000000..9f114bbad3b --- /dev/null +++ b/extern/libmv/intern/region.h @@ -0,0 +1,43 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef LIBMV_C_API_REGION_H_ +#define LIBMV_C_API_REGION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct libmv_Region { + float min[2]; + float max[2]; +} libmv_Region; + +#ifdef __cplusplus +} +#endif + +#endif // LIBMV_C_API_REGION_H_ diff --git a/extern/libmv/intern/stub.cc b/extern/libmv/intern/stub.cc new file mode 100644 index 00000000000..cd8bb8ab841 --- /dev/null +++ b/extern/libmv/intern/stub.cc @@ -0,0 +1,330 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "libmv-capi.h" + +#include <cstdlib> +#include <cstring> + +/* ************ Logging ************ */ + +void libmv_initLogging(const char * /*argv0*/) { +} + +void libmv_startDebugLogging(void) { +} + +void libmv_setLoggingVerbosity(int /*verbosity*/) { +} + +/* ************ Planar tracker ************ */ + +/* TrackRegion (new planar tracker) */ +int libmv_trackRegion(const libmv_TrackRegionOptions * /*options*/, + const float * /*image1*/, + int /*image1_width*/, + int /*image1_height*/, + const float * /*image2*/, + int /*image2_width*/, + int /*image2_height*/, + const double *x1, + const double *y1, + libmv_TrackRegionResult *result, + double *x2, + double *y2) { + /* Convert to doubles for the libmv api. The four corners and the center. */ + for (int i = 0; i < 5; ++i) { + x2[i] = x1[i]; + y2[i] = y1[i]; + } + + result->termination = -1; + result->termination_reason = "Built without libmv support"; + result->correlation = 0.0; + + return false; +} + +void libmv_samplePlanarPatchFloat(const float * /*image*/, + int /*width*/, + int /*height*/, + int /*channels*/, + const double * /*xs*/, + const double * /*ys*/, + int /*num_samples_x*/, + int /*num_samples_y*/, + const float * /*mask*/, + float * /*patch*/, + double * /*warped_position_x*/, + double * /*warped_position_y*/) { + /* TODO(sergey): implement */ +} + +void libmv_samplePlanarPatchByte(const unsigned char * /*image*/, + int /*width*/, + int /*height*/, + int /*channels*/, + const double * /*xs*/, + const double * /*ys*/, + int /*num_samples_x*/, int /*num_samples_y*/, + const float * /*mask*/, + unsigned char * /*patch*/, + double * /*warped_position_x*/, + double * /*warped_position_y*/) { + /* TODO(sergey): implement */ +} + +/* ************ Tracks ************ */ + +libmv_Tracks *libmv_tracksNew(void) { + return NULL; +} + +void libmv_tracksInsert(libmv_Tracks * /*libmv_tracks*/, + int /*image*/, + int /*track*/, + double /*x*/, + double /*y*/, + double /*weight*/) { +} + +void libmv_tracksDestroy(libmv_Tracks * /*libmv_tracks*/) { +} + +/* ************ Reconstruction solver ************ */ + +libmv_Reconstruction *libmv_solveReconstruction( + const libmv_Tracks * /*libmv_tracks*/, + const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/, + libmv_ReconstructionOptions * /*libmv_reconstruction_options*/, + reconstruct_progress_update_cb /*progress_update_callback*/, + void * /*callback_customdata*/) { + return NULL; +} + +libmv_Reconstruction *libmv_solveModal( + const libmv_Tracks * /*libmv_tracks*/, + const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/, + const libmv_ReconstructionOptions * /*libmv_reconstruction_options*/, + reconstruct_progress_update_cb /*progress_update_callback*/, + void * /*callback_customdata*/) { + return NULL; +} + +int libmv_reprojectionPointForTrack( + const libmv_Reconstruction * /*libmv_reconstruction*/, + int /*track*/, + double /*pos*/[3]) { + return 0; +} + +double libmv_reprojectionErrorForTrack( + const libmv_Reconstruction * /*libmv_reconstruction*/, + int /*track*/) { + return 0.0; +} + +double libmv_reprojectionErrorForImage( + const libmv_Reconstruction * /*libmv_reconstruction*/, + int /*image*/) { + return 0.0; +} + +int libmv_reprojectionCameraForImage( + const libmv_Reconstruction * /*libmv_reconstruction*/, + int /*image*/, + double /*mat*/[4][4]) { + return 0; +} + +double libmv_reprojectionError( + const libmv_Reconstruction * /*libmv_reconstruction*/) { + return 0.0; +} + +void libmv_reconstructionDestroy( + struct libmv_Reconstruction * /*libmv_reconstruction*/) { +} + +/* ************ Feature detector ************ */ + +libmv_Features *libmv_detectFeaturesByte(const unsigned char */*image_buffer*/, + int /*width*/, + int /*height*/, + int /*channels*/, + libmv_DetectOptions */*options*/) { + return NULL; +} + +struct libmv_Features *libmv_detectFeaturesFloat( + const float */*image_buffer*/, + int /*width*/, + int /*height*/, + int /*channels*/, + libmv_DetectOptions */*options*/) { + return NULL; +} + +int libmv_countFeatures(const libmv_Features * /*libmv_features*/) { + return 0; +} + +void libmv_getFeature(const libmv_Features * /*libmv_features*/, + int /*number*/, + double *x, + double *y, + double *score, + double *size) { + *x = 0.0; + *y = 0.0; + *score = 0.0; + *size = 0.0; +} + +void libmv_featuresDestroy(struct libmv_Features * /*libmv_features*/) { +} + +/* ************ Camera intrinsics ************ */ + +libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics( + libmv_Reconstruction * /*libmv_reconstruction*/) { + return NULL; +} + +libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( + const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/) { + return NULL; +} + +libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy( + const libmv_CameraIntrinsics * /*libmvIntrinsics*/) { + return NULL; +} + +void libmv_cameraIntrinsicsDestroy( + libmv_CameraIntrinsics * /*libmvIntrinsics*/) { +} + +void libmv_cameraIntrinsicsUpdate( + const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/, + libmv_CameraIntrinsics * /*libmv_intrinsics*/) { +} + +void libmv_cameraIntrinsicsSetThreads( + libmv_CameraIntrinsics * /*libmv_intrinsics*/, + int /*threads*/) { +} + +void libmv_cameraIntrinsicsExtractOptions( + const libmv_CameraIntrinsics */*libmv_intrinsics*/, + libmv_CameraIntrinsicsOptions *camera_intrinsics_options) { + memset(camera_intrinsics_options, 0, sizeof(libmv_CameraIntrinsicsOptions)); + camera_intrinsics_options->focal_length = 1.0; +} + +void libmv_cameraIntrinsicsUndistortByte( + const libmv_CameraIntrinsics * /*libmv_intrinsics*/, + const unsigned char *source_image, + int width, int height, + float overscan, int channels, + unsigned char *destination_image) { + memcpy(destination_image, source_image, + channels * width * height * sizeof(unsigned char)); +} + +void libmv_cameraIntrinsicsUndistortFloat( + const libmv_CameraIntrinsics* /*libmv_intrinsics*/, + const float* source_image, + int width, + int height, + float overscan, + int channels, + float* destination_image) { + memcpy(destination_image, source_image, + channels * width * height * sizeof(float)); +} + +void libmv_cameraIntrinsicsDistortByte( + const struct libmv_CameraIntrinsics* /*libmv_intrinsics*/, + const unsigned char *source_image, + int width, + int height, + float overscan, + int channels, + unsigned char *destination_image) { + memcpy(destination_image, source_image, + channels * width * height * sizeof(unsigned char)); +} + +void libmv_cameraIntrinsicsDistortFloat( + const libmv_CameraIntrinsics* /*libmv_intrinsics*/, + float* source_image, + int width, + int height, + float overscan, + int channels, + float* destination_image) { + memcpy(destination_image, source_image, + channels * width * height * sizeof(float)); +} + +/* ************ utils ************ */ + +void libmv_cameraIntrinsicsApply( + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + double x, + double y, + double* x1, + double* y1) { + double focal_length = libmv_camera_intrinsics_options->focal_length; + double principal_x = libmv_camera_intrinsics_options->principal_point_x; + double principal_y = libmv_camera_intrinsics_options->principal_point_y; + *x1 = x * focal_length + principal_x; + *y1 = y * focal_length + principal_y; +} + +void libmv_cameraIntrinsicsInvert( + const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options, + double x, + double y, + double* x1, + double* y1) { + double focal_length = libmv_camera_intrinsics_options->focal_length; + double principal_x = libmv_camera_intrinsics_options->principal_point_x; + double principal_y = libmv_camera_intrinsics_options->principal_point_y; + *x1 = (x - principal_x) / focal_length; + *y1 = (y - principal_y) / focal_length; +} + +void libmv_homography2DFromCorrespondencesEuc(/* const */ double (*x1)[2], + /* const */ double (*x2)[2], + int num_points, + double H[3][3]) { + memset(H, 0, sizeof(double[3][3])); + H[0][0] = 1.0f; + H[1][1] = 1.0f; + H[2][2] = 1.0f; +} diff --git a/extern/libmv/intern/track_region.cc b/extern/libmv/intern/track_region.cc new file mode 100644 index 00000000000..24fbc78c1a1 --- /dev/null +++ b/extern/libmv/intern/track_region.cc @@ -0,0 +1,177 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "intern/track_region.h" +#include "intern/image.h" +#include "intern/utildefines.h" +#include "libmv/image/image.h" +#include "libmv/tracking/track_region.h" + +/* define this to generate PNG images with content of search areas + tracking between which failed */ +#undef DUMP_FAILURE + +/* define this to generate PNG images with content of search areas + on every itteration of tracking */ +#undef DUMP_ALWAYS + +using libmv::FloatImage; +using libmv::TrackRegionOptions; +using libmv::TrackRegionResult; +using libmv::TrackRegion; + +void libmv_configureTrackRegionOptions( + const libmv_TrackRegionOptions& options, + TrackRegionOptions* track_region_options) { + switch (options.motion_model) { +#define LIBMV_CONVERT(the_model) \ + case TrackRegionOptions::the_model: \ + track_region_options->mode = TrackRegionOptions::the_model; \ + break; + LIBMV_CONVERT(TRANSLATION) + LIBMV_CONVERT(TRANSLATION_ROTATION) + LIBMV_CONVERT(TRANSLATION_SCALE) + LIBMV_CONVERT(TRANSLATION_ROTATION_SCALE) + LIBMV_CONVERT(AFFINE) + LIBMV_CONVERT(HOMOGRAPHY) +#undef LIBMV_CONVERT + } + + track_region_options->minimum_correlation = options.minimum_correlation; + track_region_options->max_iterations = options.num_iterations; + track_region_options->sigma = options.sigma; + track_region_options->num_extra_points = 1; + track_region_options->image1_mask = NULL; + track_region_options->use_brute_initialization = options.use_brute; + /* TODO(keir): This will make some cases better, but may be a regression until + * the motion model is in. Since this is on trunk, enable it for now. + * + * TODO(sergey): This gives much worse results on mango footage (see 04_2e) + * so disabling for now for until proper prediction model is landed. + * + * The thing is, currently blender sends input coordinates as the guess to + * region tracker and in case of fast motion such an early out ruins the track. + */ + track_region_options->attempt_refine_before_brute = false; + track_region_options->use_normalized_intensities = options.use_normalization; +} + +void libmv_regionTrackergetResult(const TrackRegionResult& track_region_result, + libmv_TrackRegionResult* result) { + result->termination = (int) track_region_result.termination; + result->termination_reason = ""; + result->correlation = track_region_result.correlation; +} + +int libmv_trackRegion(const libmv_TrackRegionOptions* options, + const float* image1, + int image1_width, + int image1_height, + const float* image2, + int image2_width, + int image2_height, + const double* x1, + const double* y1, + libmv_TrackRegionResult* result, + double* x2, + double* y2) { + double xx1[5], yy1[5]; + double xx2[5], yy2[5]; + bool tracking_result = false; + + // Convert to doubles for the libmv api. The four corners and the center. + for (int i = 0; i < 5; ++i) { + xx1[i] = x1[i]; + yy1[i] = y1[i]; + xx2[i] = x2[i]; + yy2[i] = y2[i]; + } + + TrackRegionOptions track_region_options; + FloatImage image1_mask; + + libmv_configureTrackRegionOptions(*options, &track_region_options); + if (options->image1_mask) { + libmv_floatBufferToFloatImage(options->image1_mask, + image1_width, + image1_height, + 1, + &image1_mask); + + track_region_options.image1_mask = &image1_mask; + } + + // Convert from raw float buffers to libmv's FloatImage. + FloatImage old_patch, new_patch; + libmv_floatBufferToFloatImage(image1, + image1_width, + image1_height, + 1, + &old_patch); + libmv_floatBufferToFloatImage(image2, + image2_width, + image2_height, + 1, + &new_patch); + + TrackRegionResult track_region_result; + TrackRegion(old_patch, new_patch, + xx1, yy1, + track_region_options, + xx2, yy2, + &track_region_result); + + // Convert to floats for the blender api. + for (int i = 0; i < 5; ++i) { + x2[i] = xx2[i]; + y2[i] = yy2[i]; + } + + // TODO(keir): Update the termination string with failure details. + if (track_region_result.termination == TrackRegionResult::CONVERGENCE || + track_region_result.termination == TrackRegionResult::NO_CONVERGENCE) { + tracking_result = true; + } + + // Debug dump of patches. +#if defined(DUMP_FAILURE) || defined(DUMP_ALWAYS) + bool need_dump = !tracking_result; + +# ifdef DUMP_ALWAYS + need_dump = true; +# endif + + if (need_dump) { + libmv_saveImage(old_patch, "old_patch", x1[4], y1[4]); + libmv_saveImage(new_patch, "new_patch", x2[4], y2[4]); + if (options->image1_mask) { + libmv_saveImage(image1_mask, "mask", x2[4], y2[4]); + } + } +#endif + + return tracking_result; +} diff --git a/extern/libmv/intern/track_region.h b/extern/libmv/intern/track_region.h new file mode 100644 index 00000000000..7ed3e443e40 --- /dev/null +++ b/extern/libmv/intern/track_region.h @@ -0,0 +1,81 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef LIBMV_C_API_TRACK_REGION_H_ +#define LIBMV_C_API_TRACK_REGION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct libmv_TrackRegionOptions { + int motion_model; + int num_iterations; + int use_brute; + int use_normalization; + double minimum_correlation; + double sigma; + float *image1_mask; +} libmv_TrackRegionOptions; + +typedef struct libmv_TrackRegionResult { + int termination; + const char* termination_reason; + double correlation; +} libmv_TrackRegionResult; + +#ifdef __cplusplus +namespace libmv { + struct TrackRegionOptions; + struct TrackRegionResult; +} +void libmv_configureTrackRegionOptions( + const libmv_TrackRegionOptions& options, + libmv::TrackRegionOptions* track_region_options); + +void libmv_regionTrackergetResult( + const libmv::TrackRegionResult& track_region_result, + libmv_TrackRegionResult* result); +#endif + +int libmv_trackRegion(const libmv_TrackRegionOptions* options, + const float* image1, + int image1_width, + int image1_height, + const float* image2, + int image2_width, + int image2_height, + const double* x1, + const double* y1, + libmv_TrackRegionResult* result, + double* x2, + double* y2); + +#ifdef __cplusplus +} +#endif + +#endif // LIBMV_C_API_PLANAR_TRACKER_H_ diff --git a/extern/libmv/intern/tracks.cc b/extern/libmv/intern/tracks.cc new file mode 100644 index 00000000000..9b032b0760a --- /dev/null +++ b/extern/libmv/intern/tracks.cc @@ -0,0 +1,52 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "intern/tracks.h" +#include "intern/utildefines.h" + +#include "libmv/simple_pipeline/tracks.h" + +using libmv::Marker; +using libmv::Tracks; + +libmv_Tracks* libmv_tracksNew(void) { + Tracks* tracks = LIBMV_OBJECT_NEW(Tracks); + + return (libmv_Tracks*) tracks; +} + +void libmv_tracksDestroy(libmv_Tracks* libmv_tracks) { + LIBMV_OBJECT_DELETE(libmv_tracks, Tracks); +} + +void libmv_tracksInsert(libmv_Tracks *libmv_tracks, + int image, + int track, + double x, + double y, + double weight) { + ((Tracks *) libmv_tracks)->Insert(image, track, x, y, weight); +} diff --git a/extern/libmv/intern/tracks.h b/extern/libmv/intern/tracks.h new file mode 100644 index 00000000000..79f6cc99579 --- /dev/null +++ b/extern/libmv/intern/tracks.h @@ -0,0 +1,51 @@ +/* + * ***** 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. + * + * The Original Code is Copyright (C) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef LIBMV_C_API_TRACKS_H_ +#define LIBMV_C_API_TRACKS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct libmv_Tracks libmv_Tracks; + +libmv_Tracks* libmv_tracksNew(void); + +void libmv_tracksDestroy(libmv_Tracks* libmv_tracks); + +void libmv_tracksInsert(libmv_Tracks* libmv_tracks, + int image, + int track, + double x, + double y, + double weight); + +#ifdef __cplusplus +} +#endif + +#endif // LIBMV_C_API_TRACKS_H_ diff --git a/extern/libmv/libmv-capi_intern.h b/extern/libmv/intern/utildefines.h index 90087c52a6c..7366b242cf7 100644 --- a/extern/libmv/libmv-capi_intern.h +++ b/extern/libmv/intern/utildefines.h @@ -23,8 +23,8 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifndef LIBMV_C_API_INTERN_H -#define LIBMV_C_API_INTERN_H +#ifndef LIBMV_C_API_UTILDEFINES_H_ +#define LIBMV_C_API_UTILDEFINES_H_ #if defined(_MSC_VER) # define __func__ __FUNCTION__ @@ -36,24 +36,27 @@ # define LIBMV_OBJECT_NEW OBJECT_GUARDED_NEW # define LIBMV_OBJECT_DELETE OBJECT_GUARDED_DELETE # define LIBMV_OBJECT_DELETE OBJECT_GUARDED_DELETE -# define LIBMV_STRUCT_NEW(type, count) (type*)MEM_mallocN(sizeof(type) * count, __func__) +# define LIBMV_STRUCT_NEW(type, count) \ + (type*)MEM_mallocN(sizeof(type) * count, __func__) # define LIBMV_STRUCT_DELETE(what) MEM_freeN(what) #else // Need this to keep libmv-capi potentially standalone. # if defined __GNUC__ || defined __sun # define LIBMV_OBJECT_NEW(type, args ...) \ - new(malloc(sizeof(type))) type(args) + new(malloc(sizeof(type))) type(args) # else # define LIBMV_OBJECT_NEW(type, ...) \ - new(malloc(sizeof(type))) type(__VA_ARGS__) + new(malloc(sizeof(type))) type(__VA_ARGS__) #endif # define LIBMV_OBJECT_DELETE(what, type) \ - { if(what) { \ - ((type*)(what))->~type(); \ - free(what); \ - } } (void)0 + { \ + if (what) { \ + ((type*)(what))->~type(); \ + free(what); \ + } \ + } (void)0 # define LIBMV_STRUCT_NEW(type, count) (type*)malloc(sizeof(type) * count) # define LIBMV_STRUCT_DELETE(what) { if (what) free(what); } (void)0 #endif -#endif // LIBMV_C_API_INTERN_H +#endif // LIBMV_C_API_UTILDEFINES_H_ diff --git a/extern/libmv/libmv-capi.cc b/extern/libmv/libmv-capi.cc deleted file mode 100644 index 82143d50fbf..00000000000 --- a/extern/libmv/libmv-capi.cc +++ /dev/null @@ -1,1185 +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. - * - * The Original Code is Copyright (C) 2011 Blender Foundation. - * All rights reserved. - * - * Contributor(s): Blender Foundation, - * Sergey Sharybin - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef WITH_LIBMV - -/* define this to generate PNG images with content of search areas - tracking between which failed */ -#undef DUMP_FAILURE - -/* define this to generate PNG images with content of search areas - on every itteration of tracking */ -#undef DUMP_ALWAYS - -#include "libmv-capi.h" -#include "libmv-util.h" - -#include <cassert> - -#include "libmv-capi_intern.h" -#include "libmv/logging/logging.h" -#include "libmv/multiview/homography.h" -#include "libmv/tracking/track_region.h" -#include "libmv/simple_pipeline/callbacks.h" -#include "libmv/simple_pipeline/tracks.h" -#include "libmv/simple_pipeline/initialize_reconstruction.h" -#include "libmv/simple_pipeline/bundle.h" -#include "libmv/simple_pipeline/detect.h" -#include "libmv/simple_pipeline/pipeline.h" -#include "libmv/simple_pipeline/camera_intrinsics.h" -#include "libmv/simple_pipeline/modal_solver.h" -#include "libmv/simple_pipeline/reconstruction_scale.h" -#include "libmv/simple_pipeline/keyframe_selection.h" - -#ifdef _MSC_VER -# define snprintf _snprintf -#endif - -using libmv::CameraIntrinsics; -using libmv::DetectOptions; -using libmv::DivisionCameraIntrinsics; -using libmv::EuclideanCamera; -using libmv::EuclideanPoint; -using libmv::EuclideanReconstruction; -using libmv::EuclideanScaleToUnity; -using libmv::Feature; -using libmv::FloatImage; -using libmv::Marker; -using libmv::PolynomialCameraIntrinsics; -using libmv::ProgressUpdateCallback; -using libmv::Tracks; -using libmv::TrackRegionOptions; -using libmv::TrackRegionResult; - -using libmv::Detect; -using libmv::EuclideanBundle; -using libmv::EuclideanCompleteReconstruction; -using libmv::EuclideanReconstructTwoFrames; -using libmv::EuclideanReprojectionError; -using libmv::TrackRegion; -using libmv::SamplePlanarPatch; - -typedef struct libmv_Tracks libmv_Tracks; -typedef struct libmv_Reconstruction libmv_Reconstruction; -typedef struct libmv_Features libmv_Features; -typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics; - -struct libmv_Reconstruction { - EuclideanReconstruction reconstruction; - - /* used for per-track average error calculation after reconstruction */ - Tracks tracks; - CameraIntrinsics *intrinsics; - - double error; -}; - -struct libmv_Features { - int count; - Feature *features; -}; - -/* ************ Logging ************ */ - -void libmv_initLogging(const char *argv0) -{ - /* Make it so FATAL messages are always print into console */ - char severity_fatal[32]; - snprintf(severity_fatal, sizeof(severity_fatal), "%d", - google::GLOG_FATAL); - - google::InitGoogleLogging(argv0); - google::SetCommandLineOption("logtostderr", "1"); - google::SetCommandLineOption("v", "0"); - google::SetCommandLineOption("stderrthreshold", severity_fatal); - google::SetCommandLineOption("minloglevel", severity_fatal); -} - -void libmv_startDebugLogging(void) -{ - google::SetCommandLineOption("logtostderr", "1"); - google::SetCommandLineOption("v", "2"); - google::SetCommandLineOption("stderrthreshold", "1"); - google::SetCommandLineOption("minloglevel", "0"); -} - -void libmv_setLoggingVerbosity(int verbosity) -{ - char val[10]; - snprintf(val, sizeof(val), "%d", verbosity); - - google::SetCommandLineOption("v", val); -} - -/* ************ Planar tracker ************ */ - -/* TrackRegion */ -int libmv_trackRegion(const libmv_TrackRegionOptions *options, - const float *image1, int image1_width, int image1_height, - const float *image2, int image2_width, int image2_height, - const double *x1, const double *y1, - libmv_TrackRegionResult *result, - double *x2, double *y2) -{ - double xx1[5], yy1[5]; - double xx2[5], yy2[5]; - bool tracking_result = false; - - /* Convert to doubles for the libmv api. The four corners and the center. */ - for (int i = 0; i < 5; ++i) { - xx1[i] = x1[i]; - yy1[i] = y1[i]; - xx2[i] = x2[i]; - yy2[i] = y2[i]; - } - - TrackRegionOptions track_region_options; - FloatImage image1_mask; - - switch (options->motion_model) { -#define LIBMV_CONVERT(the_model) \ - case TrackRegionOptions::the_model: \ - track_region_options.mode = TrackRegionOptions::the_model; \ - break; - LIBMV_CONVERT(TRANSLATION) - LIBMV_CONVERT(TRANSLATION_ROTATION) - LIBMV_CONVERT(TRANSLATION_SCALE) - LIBMV_CONVERT(TRANSLATION_ROTATION_SCALE) - LIBMV_CONVERT(AFFINE) - LIBMV_CONVERT(HOMOGRAPHY) -#undef LIBMV_CONVERT - } - - track_region_options.minimum_correlation = options->minimum_correlation; - track_region_options.max_iterations = options->num_iterations; - track_region_options.sigma = options->sigma; - track_region_options.num_extra_points = 1; - track_region_options.image1_mask = NULL; - track_region_options.use_brute_initialization = options->use_brute; - /* TODO(keir): This will make some cases better, but may be a regression until - * the motion model is in. Since this is on trunk, enable it for now. - * - * TODO(sergey): This gives much worse results on mango footage (see 04_2e) - * so disabling for now for until proper prediction model is landed. - * - * The thing is, currently blender sends input coordinates as the guess to - * region tracker and in case of fast motion such an early out ruins the track. - */ - track_region_options.attempt_refine_before_brute = false; - track_region_options.use_normalized_intensities = options->use_normalization; - - if (options->image1_mask) { - libmv_floatBufferToImage(options->image1_mask, - image1_width, image1_height, 1, - &image1_mask); - - track_region_options.image1_mask = &image1_mask; - } - - /* Convert from raw float buffers to libmv's FloatImage. */ - FloatImage old_patch, new_patch; - libmv_floatBufferToImage(image1, - image1_width, image1_height, 1, - &old_patch); - libmv_floatBufferToImage(image2, - image2_width, image2_height, 1, - &new_patch); - - TrackRegionResult track_region_result; - TrackRegion(old_patch, new_patch, - xx1, yy1, - track_region_options, - xx2, yy2, - &track_region_result); - - /* Convert to floats for the blender api. */ - for (int i = 0; i < 5; ++i) { - x2[i] = xx2[i]; - y2[i] = yy2[i]; - } - - /* TODO(keir): Update the termination string with failure details. */ - if (track_region_result.termination == TrackRegionResult::CONVERGENCE || - track_region_result.termination == TrackRegionResult::NO_CONVERGENCE) - { - tracking_result = true; - } - - /* Debug dump of patches. */ -#if defined(DUMP_FAILURE) || defined(DUMP_ALWAYS) - { - bool need_dump = !tracking_result; - -# ifdef DUMP_ALWAYS - need_dump = true; -# endif - - if (need_dump) { - libmv_saveImage(old_patch, "old_patch", x1[4], y1[4]); - libmv_saveImage(new_patch, "new_patch", x2[4], y2[4]); - - if (options->image1_mask) { - libmv_saveImage(image1_mask, "mask", x2[4], y2[4]); - } - } - } -#endif - - return tracking_result; -} - -void libmv_samplePlanarPatch(const float *image, - int width, int height, int channels, - const double *xs, const double *ys, - int num_samples_x, int num_samples_y, - const float *mask, - float *patch, - double *warped_position_x, - double *warped_position_y) -{ - FloatImage libmv_image, libmv_patch, libmv_mask; - FloatImage *libmv_mask_for_sample = NULL; - - libmv_floatBufferToImage(image, width, height, channels, &libmv_image); - - if (mask) { - libmv_floatBufferToImage(mask, width, height, 1, &libmv_mask); - - libmv_mask_for_sample = &libmv_mask; - } - - SamplePlanarPatch(libmv_image, - xs, ys, - num_samples_x, num_samples_y, - libmv_mask_for_sample, - &libmv_patch, - warped_position_x, - warped_position_y); - - libmv_imageToFloatBuffer(libmv_patch, patch); -} - - void libmv_samplePlanarPatchByte(const unsigned char *image, - int width, int height, int channels, - const double *xs, const double *ys, - int num_samples_x, int num_samples_y, - const float *mask, - unsigned char *patch, - double *warped_position_x, double *warped_position_y) -{ - libmv::FloatImage libmv_image, libmv_patch, libmv_mask; - libmv::FloatImage *libmv_mask_for_sample = NULL; - - libmv_byteBufferToImage(image, width, height, channels, &libmv_image); - - if (mask) { - libmv_floatBufferToImage(mask, width, height, 1, &libmv_mask); - - libmv_mask_for_sample = &libmv_mask; - } - - libmv::SamplePlanarPatch(libmv_image, xs, ys, - num_samples_x, num_samples_y, - libmv_mask_for_sample, - &libmv_patch, - warped_position_x, - warped_position_y); - - libmv_imageToByteBuffer(libmv_patch, patch); -} - -/* ************ Tracks ************ */ - -libmv_Tracks *libmv_tracksNew(void) -{ - Tracks *libmv_tracks = LIBMV_OBJECT_NEW(Tracks); - - return (libmv_Tracks *) libmv_tracks; -} - -void libmv_tracksDestroy(libmv_Tracks *libmv_tracks) -{ - LIBMV_OBJECT_DELETE(libmv_tracks, Tracks); -} - -void libmv_tracksInsert(libmv_Tracks *libmv_tracks, - int image, int track, - double x, double y, - double weight) -{ - ((Tracks *) libmv_tracks)->Insert(image, track, x, y, weight); -} - -/* ************ Reconstruction ************ */ - -namespace { - -class ReconstructUpdateCallback : public ProgressUpdateCallback { -public: - ReconstructUpdateCallback( - reconstruct_progress_update_cb progress_update_callback, - void *callback_customdata) - { - progress_update_callback_ = progress_update_callback; - callback_customdata_ = callback_customdata; - } - - void invoke(double progress, const char *message) - { - if (progress_update_callback_) { - progress_update_callback_(callback_customdata_, progress, message); - } - } -protected: - reconstruct_progress_update_cb progress_update_callback_; - void *callback_customdata_; -}; - -void libmv_solveRefineIntrinsics( - const Tracks &tracks, - const int refine_intrinsics, - const int bundle_constraints, - reconstruct_progress_update_cb progress_update_callback, - void *callback_customdata, - EuclideanReconstruction *reconstruction, - CameraIntrinsics *intrinsics) -{ - /* only a few combinations are supported but trust the caller */ - int bundle_intrinsics = 0; - - if (refine_intrinsics & LIBMV_REFINE_FOCAL_LENGTH) { - bundle_intrinsics |= libmv::BUNDLE_FOCAL_LENGTH; - } - if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) { - bundle_intrinsics |= libmv::BUNDLE_PRINCIPAL_POINT; - } - if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) { - bundle_intrinsics |= libmv::BUNDLE_RADIAL_K1; - } - if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) { - bundle_intrinsics |= libmv::BUNDLE_RADIAL_K2; - } - - progress_update_callback(callback_customdata, 1.0, "Refining solution"); - - EuclideanBundleCommonIntrinsics(tracks, - bundle_intrinsics, - bundle_constraints, - reconstruction, - intrinsics); -} - -void finishReconstruction( - const Tracks &tracks, - const CameraIntrinsics &camera_intrinsics, - libmv_Reconstruction *libmv_reconstruction, - reconstruct_progress_update_cb progress_update_callback, - void *callback_customdata) -{ - EuclideanReconstruction &reconstruction = - libmv_reconstruction->reconstruction; - - /* reprojection error calculation */ - progress_update_callback(callback_customdata, 1.0, "Finishing solution"); - libmv_reconstruction->tracks = tracks; - libmv_reconstruction->error = EuclideanReprojectionError(tracks, - reconstruction, - camera_intrinsics); -} - -bool selectTwoKeyframesBasedOnGRICAndVariance( - Tracks &tracks, - Tracks &normalized_tracks, - CameraIntrinsics &camera_intrinsics, - int &keyframe1, - int &keyframe2) -{ - libmv::vector<int> keyframes; - - /* Get list of all keyframe candidates first. */ - SelectKeyframesBasedOnGRICAndVariance(normalized_tracks, - camera_intrinsics, - keyframes); - - if (keyframes.size() < 2) { - LG << "Not enough keyframes detected by GRIC"; - return false; - } - else if (keyframes.size() == 2) { - keyframe1 = keyframes[0]; - keyframe2 = keyframes[1]; - return true; - } - - /* Now choose two keyframes with minimal reprojection error after initial - * reconstruction choose keyframes with the least reprojection error after - * solving from two candidate keyframes. - * - * In fact, currently libmv returns single pair only, so this code will - * not actually run. But in the future this could change, so let's stay - * prepared. - */ - int previous_keyframe = keyframes[0]; - double best_error = std::numeric_limits<double>::max(); - for (int i = 1; i < keyframes.size(); i++) { - EuclideanReconstruction reconstruction; - int current_keyframe = keyframes[i]; - - libmv::vector<Marker> keyframe_markers = - normalized_tracks.MarkersForTracksInBothImages(previous_keyframe, - current_keyframe); - - Tracks keyframe_tracks(keyframe_markers); - - /* get a solution from two keyframes only */ - EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction); - EuclideanBundle(keyframe_tracks, &reconstruction); - EuclideanCompleteReconstruction(keyframe_tracks, - &reconstruction, - NULL); - - double current_error = EuclideanReprojectionError(tracks, - reconstruction, - camera_intrinsics); - - LG << "Error between " << previous_keyframe - << " and " << current_keyframe - << ": " << current_error; - - if (current_error < best_error) { - best_error = current_error; - keyframe1 = previous_keyframe; - keyframe2 = current_keyframe; - } - - previous_keyframe = current_keyframe; - } - - return true; -} - -} // namespace - -libmv_Reconstruction *libmv_solveReconstruction( - const libmv_Tracks *libmv_tracks, - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - libmv_ReconstructionOptions *libmv_reconstruction_options, - reconstruct_progress_update_cb progress_update_callback, - void *callback_customdata) -{ - libmv_Reconstruction *libmv_reconstruction = - LIBMV_OBJECT_NEW(libmv_Reconstruction); - - Tracks &tracks = *((Tracks *) libmv_tracks); - EuclideanReconstruction &reconstruction = - libmv_reconstruction->reconstruction; - - ReconstructUpdateCallback update_callback = - ReconstructUpdateCallback(progress_update_callback, - callback_customdata); - - /* Retrieve reconstruction options from C-API to libmv API */ - CameraIntrinsics *camera_intrinsics; - camera_intrinsics = libmv_reconstruction->intrinsics = - libmv_cameraIntrinsicsCreateFromOptions( - libmv_camera_intrinsics_options); - - /* Invert the camera intrinsics */ - Tracks normalized_tracks; - libmv_getNormalizedTracks(tracks, *camera_intrinsics, &normalized_tracks); - - /* keyframe selection */ - int keyframe1 = libmv_reconstruction_options->keyframe1, - keyframe2 = libmv_reconstruction_options->keyframe2; - - if (libmv_reconstruction_options->select_keyframes) { - LG << "Using automatic keyframe selection"; - - update_callback.invoke(0, "Selecting keyframes"); - - selectTwoKeyframesBasedOnGRICAndVariance(tracks, - normalized_tracks, - *camera_intrinsics, - keyframe1, - keyframe2); - - /* so keyframes in the interface would be updated */ - libmv_reconstruction_options->keyframe1 = keyframe1; - libmv_reconstruction_options->keyframe2 = keyframe2; - } - - /* actual reconstruction */ - LG << "frames to init from: " << keyframe1 << " " << keyframe2; - - libmv::vector<Marker> keyframe_markers = - normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2); - - LG << "number of markers for init: " << keyframe_markers.size(); - - update_callback.invoke(0, "Initial reconstruction"); - - EuclideanReconstructTwoFrames(keyframe_markers, &reconstruction); - EuclideanBundle(normalized_tracks, &reconstruction); - EuclideanCompleteReconstruction(normalized_tracks, - &reconstruction, - &update_callback); - - /* refinement */ - if (libmv_reconstruction_options->refine_intrinsics) { - libmv_solveRefineIntrinsics( - tracks, - libmv_reconstruction_options->refine_intrinsics, - libmv::BUNDLE_NO_CONSTRAINTS, - progress_update_callback, - callback_customdata, - &reconstruction, - camera_intrinsics); - } - - /* set reconstruction scale to unity */ - EuclideanScaleToUnity(&reconstruction); - - /* finish reconstruction */ - finishReconstruction(tracks, - *camera_intrinsics, - libmv_reconstruction, - progress_update_callback, - callback_customdata); - - return (libmv_Reconstruction *) libmv_reconstruction; -} - -libmv_Reconstruction *libmv_solveModal( - const libmv_Tracks *libmv_tracks, - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - const libmv_ReconstructionOptions *libmv_reconstruction_options, - reconstruct_progress_update_cb progress_update_callback, - void *callback_customdata) -{ - libmv_Reconstruction *libmv_reconstruction = - LIBMV_OBJECT_NEW(libmv_Reconstruction); - - Tracks &tracks = *((Tracks *) libmv_tracks); - EuclideanReconstruction &reconstruction = - libmv_reconstruction->reconstruction; - - ReconstructUpdateCallback update_callback = - ReconstructUpdateCallback(progress_update_callback, - callback_customdata); - - /* Retrieve reconstruction options from C-API to libmv API */ - CameraIntrinsics *camera_intrinsics; - camera_intrinsics = libmv_reconstruction->intrinsics = - libmv_cameraIntrinsicsCreateFromOptions( - libmv_camera_intrinsics_options); - - /* Invert the camera intrinsics. */ - Tracks normalized_tracks; - libmv_getNormalizedTracks(tracks, *camera_intrinsics, &normalized_tracks); - - /* Actual reconstruction. */ - ModalSolver(normalized_tracks, &reconstruction, &update_callback); - - PolynomialCameraIntrinsics empty_intrinsics; - EuclideanBundleCommonIntrinsics(normalized_tracks, - libmv::BUNDLE_NO_INTRINSICS, - libmv::BUNDLE_NO_TRANSLATION, - &reconstruction, - &empty_intrinsics); - - /* Refinement. */ - if (libmv_reconstruction_options->refine_intrinsics) { - libmv_solveRefineIntrinsics( - tracks, - libmv_reconstruction_options->refine_intrinsics, - libmv::BUNDLE_NO_TRANSLATION, - progress_update_callback, callback_customdata, - &reconstruction, - camera_intrinsics); - } - - /* Finish reconstruction. */ - finishReconstruction(tracks, - *camera_intrinsics, - libmv_reconstruction, - progress_update_callback, - callback_customdata); - - return (libmv_Reconstruction *) libmv_reconstruction; -} - -void libmv_reconstructionDestroy(libmv_Reconstruction *libmv_reconstruction) -{ - LIBMV_OBJECT_DELETE(libmv_reconstruction->intrinsics, CameraIntrinsics); - LIBMV_OBJECT_DELETE(libmv_reconstruction, libmv_Reconstruction); -} - -int libmv_reprojectionPointForTrack( - const libmv_Reconstruction *libmv_reconstruction, - int track, - double pos[3]) -{ - const EuclideanReconstruction *reconstruction = - &libmv_reconstruction->reconstruction; - const EuclideanPoint *point = - reconstruction->PointForTrack(track); - - if (point) { - pos[0] = point->X[0]; - pos[1] = point->X[2]; - pos[2] = point->X[1]; - - return 1; - } - - return 0; -} - -double libmv_reprojectionErrorForTrack( - const libmv_Reconstruction *libmv_reconstruction, - int track) -{ - const EuclideanReconstruction *reconstruction = - &libmv_reconstruction->reconstruction; - const CameraIntrinsics *intrinsics = libmv_reconstruction->intrinsics; - libmv::vector<Marker> markers = - libmv_reconstruction->tracks.MarkersForTrack(track); - - int num_reprojected = 0; - double total_error = 0.0; - - for (int i = 0; i < markers.size(); ++i) { - double weight = markers[i].weight; - const EuclideanCamera *camera = - reconstruction->CameraForImage(markers[i].image); - const EuclideanPoint *point = - reconstruction->PointForTrack(markers[i].track); - - if (!camera || !point || weight == 0.0) { - continue; - } - - num_reprojected++; - - Marker reprojected_marker = - libmv_projectMarker(*point, *camera, *intrinsics); - double ex = (reprojected_marker.x - markers[i].x) * weight; - double ey = (reprojected_marker.y - markers[i].y) * weight; - - total_error += sqrt(ex * ex + ey * ey); - } - - return total_error / num_reprojected; -} - -double libmv_reprojectionErrorForImage( - const libmv_Reconstruction *libmv_reconstruction, - int image) -{ - const EuclideanReconstruction *reconstruction = - &libmv_reconstruction->reconstruction; - const CameraIntrinsics *intrinsics = libmv_reconstruction->intrinsics; - libmv::vector<Marker> markers = - libmv_reconstruction->tracks.MarkersInImage(image); - const EuclideanCamera *camera = reconstruction->CameraForImage(image); - int num_reprojected = 0; - double total_error = 0.0; - - if (!camera) { - return 0.0; - } - - for (int i = 0; i < markers.size(); ++i) { - const EuclideanPoint *point = - reconstruction->PointForTrack(markers[i].track); - - if (!point) { - continue; - } - - num_reprojected++; - - Marker reprojected_marker = - libmv_projectMarker(*point, *camera, *intrinsics); - double ex = (reprojected_marker.x - markers[i].x) * markers[i].weight; - double ey = (reprojected_marker.y - markers[i].y) * markers[i].weight; - - total_error += sqrt(ex * ex + ey * ey); - } - - return total_error / num_reprojected; -} - -int libmv_reprojectionCameraForImage( - const libmv_Reconstruction *libmv_reconstruction, - int image, double mat[4][4]) -{ - const EuclideanReconstruction *reconstruction = - &libmv_reconstruction->reconstruction; - const EuclideanCamera *camera = - reconstruction->CameraForImage(image); - - if (camera) { - for (int j = 0; j < 3; ++j) { - for (int k = 0; k < 3; ++k) { - int l = k; - - if (k == 1) l = 2; - else if (k == 2) l = 1; - - if (j == 2) mat[j][l] = -camera->R(j,k); - else mat[j][l] = camera->R(j,k); - } - mat[j][3] = 0.0; - } - - libmv::Vec3 optical_center = -camera->R.transpose() * camera->t; - - mat[3][0] = optical_center(0); - mat[3][1] = optical_center(2); - mat[3][2] = optical_center(1); - - mat[3][3] = 1.0; - - return 1; - } - - return 0; -} - -double libmv_reprojectionError( - const libmv_Reconstruction *libmv_reconstruction) -{ - return libmv_reconstruction->error; -} - -libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics( - libmv_Reconstruction *libmv_reconstruction) -{ - return (libmv_CameraIntrinsics *) libmv_reconstruction->intrinsics; -} - -/* ************ Feature detector ************ */ - -static libmv_Features *libmv_featuresFromVector( - const libmv::vector<Feature> &features) -{ - libmv_Features *libmv_features = LIBMV_STRUCT_NEW(libmv_Features, 1); - int count = features.size(); - if (count) { - libmv_features->features = LIBMV_STRUCT_NEW(Feature, count); - - for (int i = 0; i < count; i++) { - libmv_features->features[i] = features.at(i); - } - } - else { - libmv_features->features = NULL; - } - - libmv_features->count = count; - - return libmv_features; -} - -static void libmv_convertDetectorOptions(libmv_DetectOptions *options, - DetectOptions *detector_options) -{ - switch (options->detector) { -#define LIBMV_CONVERT(the_detector) \ - case LIBMV_DETECTOR_ ## the_detector: \ - detector_options->type = DetectOptions::the_detector; \ - break; - LIBMV_CONVERT(FAST) - LIBMV_CONVERT(MORAVEC) - LIBMV_CONVERT(HARRIS) -#undef LIBMV_CONVERT - } - detector_options->margin = options->margin; - detector_options->min_distance = options->min_distance; - detector_options->fast_min_trackness = options->fast_min_trackness; - detector_options->moravec_max_count = options->moravec_max_count; - detector_options->moravec_pattern = options->moravec_pattern; - detector_options->harris_threshold = options->harris_threshold; -} - -libmv_Features *libmv_detectFeaturesByte( - const unsigned char *image_buffer, - int width, int height, - int channels, - libmv_DetectOptions *options) -{ - // Prepare the image. - FloatImage image; - libmv_byteBufferToImage(image_buffer, width, height, channels, &image); - - // Configure detector. - DetectOptions detector_options; - libmv_convertDetectorOptions(options, &detector_options); - - // Run the detector. - libmv::vector<Feature> detected_features; - Detect(image, detector_options, &detected_features); - - // Convert result to C-API. - libmv_Features *result = libmv_featuresFromVector(detected_features); - return result; -} - -libmv_Features *libmv_detectFeaturesFloat(const float *image_buffer, - int width, int height, - int channels, - libmv_DetectOptions *options) -{ - // Prepare the image. - FloatImage image; - libmv_floatBufferToImage(image_buffer, width, height, channels, &image); - - // Configure detector. - DetectOptions detector_options; - libmv_convertDetectorOptions(options, &detector_options); - - // Run the detector. - libmv::vector<Feature> detected_features; - Detect(image, detector_options, &detected_features); - - // Convert result to C-API. - libmv_Features *result = libmv_featuresFromVector(detected_features); - return result; -} - -void libmv_featuresDestroy(libmv_Features *libmv_features) -{ - if (libmv_features->features) { - LIBMV_STRUCT_DELETE(libmv_features->features); - } - - LIBMV_STRUCT_DELETE(libmv_features); -} - -int libmv_countFeatures(const libmv_Features *libmv_features) -{ - return libmv_features->count; -} - -void libmv_getFeature(const libmv_Features *libmv_features, - int number, - double *x, double *y, double *score, double *size) -{ - Feature &feature = libmv_features->features[number]; - - *x = feature.x; - *y = feature.y; - *score = feature.score; - *size = feature.size; -} - -/* ************ Camera intrinsics ************ */ - -libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options) -{ - CameraIntrinsics *camera_intrinsics = - libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options); - - return (libmv_CameraIntrinsics *) camera_intrinsics; -} - -libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy( - const libmv_CameraIntrinsics *libmvIntrinsics) -{ - const CameraIntrinsics *orig_intrinsics = - (const CameraIntrinsics *) libmvIntrinsics; - - CameraIntrinsics *new_intrinsics = NULL; - - switch (orig_intrinsics->GetDistortionModelType()) { - case libmv::DISTORTION_MODEL_POLYNOMIAL: - { - const PolynomialCameraIntrinsics *polynomial_intrinsics = - static_cast<const PolynomialCameraIntrinsics*>(orig_intrinsics); - new_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics, - *polynomial_intrinsics); - break; - } - case libmv::DISTORTION_MODEL_DIVISION: - { - const DivisionCameraIntrinsics *division_intrinsics = - static_cast<const DivisionCameraIntrinsics*>(orig_intrinsics); - new_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics, - *division_intrinsics); - break; - } - default: - assert(!"Unknown distortion model"); - } - - return (libmv_CameraIntrinsics *) new_intrinsics; -} - -void libmv_cameraIntrinsicsDestroy(libmv_CameraIntrinsics *libmvIntrinsics) -{ - LIBMV_OBJECT_DELETE(libmvIntrinsics, CameraIntrinsics); -} - -void libmv_cameraIntrinsicsUpdate( - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - libmv_CameraIntrinsics *libmv_intrinsics) -{ - CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics; - - double focal_length = libmv_camera_intrinsics_options->focal_length; - double principal_x = libmv_camera_intrinsics_options->principal_point_x; - double principal_y = libmv_camera_intrinsics_options->principal_point_y; - int image_width = libmv_camera_intrinsics_options->image_width; - int image_height = libmv_camera_intrinsics_options->image_height; - - /* Try avoid unnecessary updates, - * so pre-computed distortion grids are not freed. - */ - - if (camera_intrinsics->focal_length() != focal_length) - camera_intrinsics->SetFocalLength(focal_length, focal_length); - - if (camera_intrinsics->principal_point_x() != principal_x || - camera_intrinsics->principal_point_y() != principal_y) - { - camera_intrinsics->SetPrincipalPoint(principal_x, principal_y); - } - - if (camera_intrinsics->image_width() != image_width || - camera_intrinsics->image_height() != image_height) - { - camera_intrinsics->SetImageSize(image_width, image_height); - } - - switch (libmv_camera_intrinsics_options->distortion_model) { - case LIBMV_DISTORTION_MODEL_POLYNOMIAL: - { - assert(camera_intrinsics->GetDistortionModelType() == - libmv::DISTORTION_MODEL_POLYNOMIAL); - - PolynomialCameraIntrinsics *polynomial_intrinsics = - (PolynomialCameraIntrinsics *) camera_intrinsics; - - double k1 = libmv_camera_intrinsics_options->polynomial_k1; - double k2 = libmv_camera_intrinsics_options->polynomial_k2; - double k3 = libmv_camera_intrinsics_options->polynomial_k3; - - if (polynomial_intrinsics->k1() != k1 || - polynomial_intrinsics->k2() != k2 || - polynomial_intrinsics->k3() != k3) - { - polynomial_intrinsics->SetRadialDistortion(k1, k2, k3); - } - - break; - } - - case LIBMV_DISTORTION_MODEL_DIVISION: - { - assert(camera_intrinsics->GetDistortionModelType() == - libmv::DISTORTION_MODEL_DIVISION); - - DivisionCameraIntrinsics *division_intrinsics = - (DivisionCameraIntrinsics *) camera_intrinsics; - - double k1 = libmv_camera_intrinsics_options->division_k1; - double k2 = libmv_camera_intrinsics_options->division_k2; - - if (division_intrinsics->k1() != k1 || - division_intrinsics->k2() != k2) - { - division_intrinsics->SetDistortion(k1, k2); - } - - break; - } - - default: - assert(!"Unknown distortion model"); - } -} - -void libmv_cameraIntrinsicsSetThreads( - libmv_CameraIntrinsics *libmv_intrinsics, int threads) -{ - CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics; - - camera_intrinsics->SetThreads(threads); -} - -void libmv_cameraIntrinsicsExtractOptions( - const libmv_CameraIntrinsics *libmv_intrinsics, - libmv_CameraIntrinsicsOptions *camera_intrinsics_options) -{ - const CameraIntrinsics *camera_intrinsics = - (const CameraIntrinsics *) libmv_intrinsics; - - // Fill in options which are common for all distortion models. - camera_intrinsics_options->focal_length = camera_intrinsics->focal_length(); - camera_intrinsics_options->principal_point_x = - camera_intrinsics->principal_point_x(); - camera_intrinsics_options->principal_point_y = - camera_intrinsics->principal_point_y(); - - camera_intrinsics_options->image_width = camera_intrinsics->image_width(); - camera_intrinsics_options->image_height = camera_intrinsics->image_height(); - - switch (camera_intrinsics->GetDistortionModelType()) { - case libmv::DISTORTION_MODEL_POLYNOMIAL: - { - const PolynomialCameraIntrinsics *polynomial_intrinsics = - static_cast<const PolynomialCameraIntrinsics *>(camera_intrinsics); - camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_POLYNOMIAL; - camera_intrinsics_options->polynomial_k1 = polynomial_intrinsics->k1(); - camera_intrinsics_options->polynomial_k2 = polynomial_intrinsics->k2(); - camera_intrinsics_options->polynomial_k3 = polynomial_intrinsics->k3(); - camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p1(); - camera_intrinsics_options->polynomial_p1 = polynomial_intrinsics->p2(); - break; - } - - case libmv::DISTORTION_MODEL_DIVISION: - { - const DivisionCameraIntrinsics *division_intrinsics = - static_cast<const DivisionCameraIntrinsics *>(camera_intrinsics); - camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_DIVISION; - camera_intrinsics_options->division_k1 = division_intrinsics->k1(); - camera_intrinsics_options->division_k2 = division_intrinsics->k2(); - break; - } - - default: - assert(!"Uknown distortion model"); - } -} - -void libmv_cameraIntrinsicsUndistortByte( - const libmv_CameraIntrinsics *libmv_intrinsics, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels) -{ - CameraIntrinsics *camera_intrinsics = (CameraIntrinsics *) libmv_intrinsics; - camera_intrinsics->UndistortBuffer(src, - width, height, overscan, channels, - dst); -} - -void libmv_cameraIntrinsicsUndistortFloat( - const libmv_CameraIntrinsics *libmvIntrinsics, - float *src, float *dst, int width, int height, - float overscan, int channels) -{ - CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmvIntrinsics; - intrinsics->UndistortBuffer(src, - width, height, overscan, channels, - dst); -} - -void libmv_cameraIntrinsicsDistortByte( - const libmv_CameraIntrinsics *libmvIntrinsics, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels) -{ - CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmvIntrinsics; - intrinsics->DistortBuffer(src, - width, height, overscan, channels, - dst); -} - -void libmv_cameraIntrinsicsDistortFloat( - const libmv_CameraIntrinsics *libmvIntrinsics, - float *src, float *dst, int width, int height, - float overscan, int channels) -{ - CameraIntrinsics *intrinsics = (CameraIntrinsics *) libmvIntrinsics; - intrinsics->DistortBuffer(src, - width, height, overscan, channels, - dst); -} - -void libmv_cameraIntrinsicsApply( - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - double x, double y, double *x1, double *y1) -{ - /* do a lens undistortion if focal length is non-zero only */ - if (libmv_camera_intrinsics_options->focal_length) { - CameraIntrinsics *camera_intrinsics = - libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options); - - camera_intrinsics->ApplyIntrinsics(x, y, x1, y1); - - LIBMV_OBJECT_DELETE(camera_intrinsics, CameraIntrinsics); - } -} - -void libmv_cameraIntrinsicsInvert( - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - double x, double y, double *x1, double *y1) -{ - /* do a lens distortion if focal length is non-zero only */ - if (libmv_camera_intrinsics_options->focal_length) { - CameraIntrinsics *camera_intrinsics = - libmv_cameraIntrinsicsCreateFromOptions(libmv_camera_intrinsics_options); - - camera_intrinsics->InvertIntrinsics(x, y, x1, y1); - - LIBMV_OBJECT_DELETE(camera_intrinsics, CameraIntrinsics); - } -} - -void libmv_homography2DFromCorrespondencesEuc(double (*x1)[2], - double (*x2)[2], - int num_points, - double H[3][3]) -{ - libmv::Mat x1_mat, x2_mat; - libmv::Mat3 H_mat; - - x1_mat.resize(2, num_points); - x2_mat.resize(2, num_points); - - for (int i = 0; i < num_points; i++) { - x1_mat.col(i) = libmv::Vec2(x1[i][0], x1[i][1]); - x2_mat.col(i) = libmv::Vec2(x2[i][0], x2[i][1]); - } - - LG << "x1: " << x1_mat; - LG << "x2: " << x2_mat; - - libmv::EstimateHomographyOptions options; - libmv::EstimateHomography2DFromCorrespondences(x1_mat, - x2_mat, - options, - &H_mat); - - LG << "H: " << H_mat; - - memcpy(H, H_mat.data(), 9 * sizeof(double)); -} - -#endif diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index 5cd9936723b..524f1822bc7 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -27,180 +27,13 @@ #ifndef LIBMV_C_API_H #define LIBMV_C_API_H -#ifdef __cplusplus -extern "C" { -#endif - -struct libmv_Tracks; -struct libmv_Reconstruction; -struct libmv_Features; -struct libmv_CameraIntrinsics; - -/* Logging */ -void libmv_initLogging(const char *argv0); -void libmv_startDebugLogging(void); -void libmv_setLoggingVerbosity(int verbosity); - -/* Planar tracker */ -typedef struct libmv_TrackRegionOptions { - int motion_model; - int num_iterations; - int use_brute; - int use_normalization; - double minimum_correlation; - double sigma; - float *image1_mask; -} libmv_TrackRegionOptions; - -typedef struct libmv_TrackRegionResult { - int termination; - const char *termination_reason; - double correlation; -} libmv_TrackRegionResult; - -int libmv_trackRegion(const libmv_TrackRegionOptions *options, - const float *image1, int image1_width, int image1_height, - const float *image2, int image2_width, int image2_height, - const double *x1, const double *y1, - libmv_TrackRegionResult *result, - double *x2, double *y2); -void libmv_samplePlanarPatch(const float *image, - int width, int height, - int channels, - const double *xs, const double *ys, - int num_samples_x, int num_samples_y, - const float *mask, - float *patch, - double *warped_position_x, double *warped_position_y); -void libmv_samplePlanarPatchByte(const unsigned char *image, - int width, int height, - int channels, - const double *xs, const double *ys, - int num_samples_x, int num_samples_y, - const float *mask, - unsigned char *patch, - double *warped_position_x, double *warped_position_y); - -/* Tracks */ -struct libmv_Tracks *libmv_tracksNew(void); -void libmv_tracksDestroy(struct libmv_Tracks *libmv_tracks); -void libmv_tracksInsert(struct libmv_Tracks *libmv_tracks, int image, int track, double x, double y, double weight); - -/* Reconstruction */ -#define LIBMV_REFINE_FOCAL_LENGTH (1 << 0) -#define LIBMV_REFINE_PRINCIPAL_POINT (1 << 1) -#define LIBMV_REFINE_RADIAL_DISTORTION_K1 (1 << 2) -#define LIBMV_REFINE_RADIAL_DISTORTION_K2 (1 << 4) - -enum { - LIBMV_DISTORTION_MODEL_POLYNOMIAL = 0, - LIBMV_DISTORTION_MODEL_DIVISION = 1, -}; - -typedef struct libmv_CameraIntrinsicsOptions { - /* Common settings of all distortion models. */ - int distortion_model; - int image_width, image_height; - double focal_length; - double principal_point_x, principal_point_y; - - /* Radial distortion model. */ - double polynomial_k1, polynomial_k2, polynomial_k3; - double polynomial_p1, polynomial_p2; - - /* Division distortion model. */ - double division_k1, division_k2; -} libmv_CameraIntrinsicsOptions; - -typedef struct libmv_ReconstructionOptions { - int select_keyframes; - int keyframe1, keyframe2; - - int refine_intrinsics; -} libmv_ReconstructionOptions; - -typedef void (*reconstruct_progress_update_cb) (void *customdata, double progress, const char *message); - -struct libmv_Reconstruction *libmv_solveReconstruction(const struct libmv_Tracks *libmv_tracks, - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - libmv_ReconstructionOptions *libmv_reconstruction_options, - reconstruct_progress_update_cb progress_update_callback, - void *callback_customdata); -struct libmv_Reconstruction *libmv_solveModal(const struct libmv_Tracks *libmv_tracks, - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - const libmv_ReconstructionOptions *libmv_reconstruction_options, - reconstruct_progress_update_cb progress_update_callback, - void *callback_customdata); -void libmv_reconstructionDestroy(struct libmv_Reconstruction *libmv_reconstruction); -int libmv_reprojectionPointForTrack(const struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]); -double libmv_reprojectionErrorForTrack(const struct libmv_Reconstruction *libmv_reconstruction, int track); -double libmv_reprojectionErrorForImage(const struct libmv_Reconstruction *libmv_reconstruction, int image); -int libmv_reprojectionCameraForImage(const struct libmv_Reconstruction *libmv_reconstruction, - int image, double mat[4][4]); -double libmv_reprojectionError(const struct libmv_Reconstruction *libmv_reconstruction); -struct libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics(struct libmv_Reconstruction *libmv_Reconstruction); - -/* Feature detector */ -enum { - LIBMV_DETECTOR_FAST, - LIBMV_DETECTOR_MORAVEC, - LIBMV_DETECTOR_HARRIS, -}; - -typedef struct libmv_DetectOptions { - int detector; - int margin; - int min_distance; - int fast_min_trackness; - int moravec_max_count; - unsigned char *moravec_pattern; - double harris_threshold; -} libmv_DetectOptions; - -struct libmv_Features *libmv_detectFeaturesByte(const unsigned char *image_buffer, - int width, int height, int channels, - libmv_DetectOptions *options); -struct libmv_Features *libmv_detectFeaturesFloat(const float *image_buffer, - int width, int height, int channels, - libmv_DetectOptions *options); - -void libmv_featuresDestroy(struct libmv_Features *libmv_features); -int libmv_countFeatures(const struct libmv_Features *libmv_features); -void libmv_getFeature(const struct libmv_Features *libmv_features, int number, double *x, double *y, double *score, - double *size); - -/* Camera intrinsics */ -struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( - const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options); -struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(const struct libmv_CameraIntrinsics *libmv_intrinsics); -void libmv_cameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmv_intrinsics); -void libmv_cameraIntrinsicsUpdate(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - struct libmv_CameraIntrinsics *libmv_intrinsics); -void libmv_cameraIntrinsicsSetThreads(struct libmv_CameraIntrinsics *libmv_intrinsics, int threads); -void libmv_cameraIntrinsicsExtractOptions( - const struct libmv_CameraIntrinsics *libmv_intrinsics, - struct libmv_CameraIntrinsicsOptions *camera_intrinsics_options); -void libmv_cameraIntrinsicsUndistortByte(const struct libmv_CameraIntrinsics *libmv_intrinsics, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels); -void libmv_cameraIntrinsicsUndistortFloat(const struct libmv_CameraIntrinsics *libmv_intrinsics, - float *src, float *dst, int width, int height, - float overscan, int channels); -void libmv_cameraIntrinsicsDistortByte(const struct libmv_CameraIntrinsics *libmv_intrinsics, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels); -void libmv_cameraIntrinsicsDistortFloat(const struct libmv_CameraIntrinsics *libmv_intrinsics, - float *src, float *dst, int width, int height, - float overscan, int channels); -void libmv_cameraIntrinsicsApply(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - double x, double y, double *x1, double *y1); -void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - double x, double y, double *x1, double *y1); - -void libmv_homography2DFromCorrespondencesEuc(double (*x1)[2], double (*x2)[2], int num_points, double H[3][3]); - -#ifdef __cplusplus -} -#endif - -#endif // LIBMV_C_API_H +#include "intern/camera_intrinsics.h" +#include "intern/detector.h" +#include "intern/homography.h" +#include "intern/image.h" +#include "intern/logging.h" +#include "intern/reconstruction.h" +#include "intern/track_region.h" +#include "intern/tracks.h" + +#endif // LIBMV_C_API_H diff --git a/extern/libmv/libmv-capi_stub.cc b/extern/libmv/libmv-capi_stub.cc deleted file mode 100644 index 36a3bc7ddee..00000000000 --- a/extern/libmv/libmv-capi_stub.cc +++ /dev/null @@ -1,293 +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. - * - * The Original Code is Copyright (C) 2013 Blender Foundation. - * All rights reserved. - * - * Contributor(s): Blender Foundation, - * Sergey Sharybin - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef WITH_LIBMV - -#include "libmv-capi.h" - -#include <cstdlib> -#include <cstring> - -/* ************ Logging ************ */ - -void libmv_initLogging(const char * /*argv0*/) -{ -} - -void libmv_startDebugLogging(void) -{ -} - -void libmv_setLoggingVerbosity(int /*verbosity*/) -{ -} - -/* ************ Planar tracker ************ */ - -/* TrackRegion (new planar tracker) */ -int libmv_trackRegion(const libmv_TrackRegionOptions * /*options*/, - const float * /*image1*/, int /*image1_width*/, int /*image1_height*/, - const float * /*image2*/, int /*image2_width*/, int /*image2_height*/, - const double *x1, const double *y1, - libmv_TrackRegionResult *result, - double *x2, double *y2) -{ - /* Convert to doubles for the libmv api. The four corners and the center. */ - for (int i = 0; i < 5; ++i) { - x2[i] = x1[i]; - y2[i] = y1[i]; - } - - result->termination = -1; - result->termination_reason = "Built without libmv support"; - result->correlation = 0.0; - - return false; -} - -void libmv_samplePlanarPatch(const float * /*image*/, - int /*width*/, int /*height*/, int /*channels*/, - const double * /*xs*/, const double * /*ys*/, - int /*num_samples_x*/, int /*num_samples_y*/, - const float * /*mask*/, - float * /*patch*/, - double * /*warped_position_x*/, double * /*warped_position_y*/) -{ - /* TODO(sergey): implement */ -} - -void libmv_samplePlanarPatchByte(const unsigned char * /*image*/, - int /*width*/, int /*height*/, int /*channels*/, - const double * /*xs*/, const double * /*ys*/, - int /*num_samples_x*/, int /*num_samples_y*/, - const float * /*mask*/, - unsigned char * /*patch*/, - double * /*warped_position_x*/, double * /*warped_position_y*/) -{ - /* TODO(sergey): implement */ -} - -/* ************ Tracks ************ */ - -struct libmv_Tracks *libmv_tracksNew(void) -{ - return NULL; -} - -void libmv_tracksInsert(struct libmv_Tracks * /*libmv_tracks*/, int /*image*/, - int /*track*/, double /*x*/, double /*y*/, double /*weight*/) -{ -} - -void libmv_tracksDestroy(struct libmv_Tracks * /*libmv_tracks*/) -{ -} - -/* ************ Reconstruction solver ************ */ - -struct libmv_Reconstruction *libmv_solveReconstruction(const struct libmv_Tracks * /*libmv_tracks*/, - const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/, - libmv_ReconstructionOptions * /*libmv_reconstruction_options*/, - reconstruct_progress_update_cb /*progress_update_callback*/, - void * /*callback_customdata*/) -{ - return NULL; -} - -struct libmv_Reconstruction *libmv_solveModal(const struct libmv_Tracks * /*libmv_tracks*/, - const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/, - const libmv_ReconstructionOptions * /*libmv_reconstruction_options*/, - reconstruct_progress_update_cb /*progress_update_callback*/, - void * /*callback_customdata*/) -{ - return NULL; -} - -int libmv_reprojectionPointForTrack(const struct libmv_Reconstruction * /*libmv_reconstruction*/, - int /*track*/, double /*pos*/[3]) -{ - return 0; -} - -double libmv_reprojectionErrorForTrack(const struct libmv_Reconstruction * /*libmv_reconstruction*/, int /*track*/) -{ - return 0.0; -} - -double libmv_reprojectionErrorForImage(const struct libmv_Reconstruction * /*libmv_reconstruction*/, int /*image*/) -{ - return 0.0; -} - -int libmv_reprojectionCameraForImage(const struct libmv_Reconstruction * /*libmv_reconstruction*/, int /*image*/, - double /*mat*/[4][4]) -{ - return 0; -} - -double libmv_reprojectionError(const struct libmv_Reconstruction * /*libmv_reconstruction*/) -{ - return 0.0; -} - -void libmv_reconstructionDestroy(struct libmv_Reconstruction * /*libmv_reconstruction*/) -{ -} - -/* ************ feature detector ************ */ - -struct libmv_Features *libmv_detectFeaturesByte(const unsigned char */*image_buffer*/, - int /*width*/, int /*height*/, int /*channels*/, - libmv_DetectOptions */*options*/) -{ - return NULL; -} - -struct libmv_Features *libmv_detectFeaturesFloat(const float */*image_buffer*/, - int /*width*/, int /*height*/, int /*channels*/, - libmv_DetectOptions */*options*/) -{ - return NULL; -} - -int libmv_countFeatures(const struct libmv_Features * /*libmv_features*/) -{ - return 0; -} - -void libmv_getFeature(const struct libmv_Features * /*libmv_features*/, int /*number*/, - double *x, double *y, double *score, double *size) -{ - *x = 0.0; - *y = 0.0; - *score = 0.0; - *size = 0.0; -} - -void libmv_featuresDestroy(struct libmv_Features * /*libmv_features*/) -{ -} - -/* ************ camera intrinsics ************ */ - -struct libmv_CameraIntrinsics *libmv_reconstructionExtractIntrinsics( - struct libmv_Reconstruction * /*libmv_reconstruction*/) -{ - return NULL; -} - -struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew( - const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/) -{ - return NULL; -} - -struct libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(const libmv_CameraIntrinsics * /*libmvIntrinsics*/) -{ - return NULL; -} - -void libmv_cameraIntrinsicsDestroy(struct libmv_CameraIntrinsics * /*libmvIntrinsics*/) -{ -} - -void libmv_cameraIntrinsicsUpdate(const libmv_CameraIntrinsicsOptions * /*libmv_camera_intrinsics_options*/, - struct libmv_CameraIntrinsics * /*libmv_intrinsics*/) -{ -} - -void libmv_cameraIntrinsicsSetThreads(struct libmv_CameraIntrinsics * /*libmv_intrinsics*/, int /*threads*/) -{ -} - -void libmv_cameraIntrinsicsExtractOptions( - const libmv_CameraIntrinsics */*libmv_intrinsics*/, - libmv_CameraIntrinsicsOptions *camera_intrinsics_options) -{ - memset(camera_intrinsics_options, 0, sizeof(libmv_CameraIntrinsicsOptions)); - camera_intrinsics_options->focal_length = 1.0; -} - -void libmv_cameraIntrinsicsUndistortByte(const struct libmv_CameraIntrinsics * /*libmv_intrinsics*/, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels) -{ - memcpy(dst, src, channels * width * height * sizeof(unsigned char)); -} - -void libmv_cameraIntrinsicsUndistortFloat(const struct libmv_CameraIntrinsics * /*libmvIntrinsics*/, - float *src, float *dst, int width, int height, float overscan, int channels) -{ - memcpy(dst, src, channels * width * height * sizeof(float)); -} - -void libmv_cameraIntrinsicsDistortByte(const struct libmv_CameraIntrinsics *libmvIntrinsics, - unsigned char *src, unsigned char *dst, int width, int height, - float overscan, int channels) -{ - memcpy(dst, src, channels * width * height * sizeof(unsigned char)); -} - -void libmv_cameraIntrinsicsDistortFloat(const struct libmv_CameraIntrinsics *libmvIntrinsics, - float *src, float *dst, int width, int height, float overscan, int channels) -{ - memcpy(dst, src, channels * width * height * sizeof(float)); -} - -/* ************ utils ************ */ - -void libmv_cameraIntrinsicsApply(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - double x, double y, double *x1, double *y1) -{ - double focal_length = libmv_camera_intrinsics_options->focal_length; - double principal_x = libmv_camera_intrinsics_options->principal_point_x; - double principal_y = libmv_camera_intrinsics_options->principal_point_y; - - *x1 = x * focal_length + principal_x; - *y1 = y * focal_length + principal_y; -} - -void libmv_cameraIntrinsicsInvert(const libmv_CameraIntrinsicsOptions *libmv_camera_intrinsics_options, - double x, double y, double *x1, double *y1) -{ - double focal_length = libmv_camera_intrinsics_options->focal_length; - double principal_x = libmv_camera_intrinsics_options->principal_point_x; - double principal_y = libmv_camera_intrinsics_options->principal_point_y; - - *x1 = (x - principal_x) / focal_length; - *y1 = (y - principal_y) / focal_length; -} - -void libmv_homography2DFromCorrespondencesEuc(double (* /* x1 */)[2], double (* /* x2 */)[2], int /* num_points */, - double H[3][3]) -{ - memset(H, 0, sizeof(double[3][3])); - H[0][0] = 1.0f; - H[1][1] = 1.0f; - H[2][2] = 1.0f; -} - -#endif // ifndef WITH_LIBMV diff --git a/extern/libmv/libmv-util.cc b/extern/libmv/libmv-util.cc deleted file mode 100644 index f969417d6c1..00000000000 --- a/extern/libmv/libmv-util.cc +++ /dev/null @@ -1,309 +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. - * - * The Original Code is Copyright (C) 2014 Blender Foundation. - * All rights reserved. - * - * Contributor(s): Blender Foundation, - * Sergey Sharybin - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include "libmv-util.h" -#include "libmv-capi_intern.h" - -#include <cassert> -#include <png.h> - -using libmv::CameraIntrinsics; -using libmv::DivisionCameraIntrinsics; -using libmv::EuclideanCamera; -using libmv::EuclideanPoint; -using libmv::FloatImage; -using libmv::Marker; -using libmv::PolynomialCameraIntrinsics; -using libmv::Tracks; - -/* Image <-> buffers conversion */ - -void libmv_byteBufferToImage(const unsigned char *buf, - int width, int height, int channels, - FloatImage *image) -{ - int x, y, k, a = 0; - - image->Resize(height, width, channels); - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - for (k = 0; k < channels; k++) { - (*image)(y, x, k) = (float)buf[a++] / 255.0f; - } - } - } -} - -void libmv_floatBufferToImage(const float *buf, - int width, int height, int channels, - FloatImage *image) -{ - image->Resize(height, width, channels); - - for (int y = 0, a = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - for (int k = 0; k < channels; k++) { - (*image)(y, x, k) = buf[a++]; - } - } - } -} - -void libmv_imageToFloatBuffer(const FloatImage &image, - float *buf) -{ - for (int y = 0, a = 0; y < image.Height(); y++) { - for (int x = 0; x < image.Width(); x++) { - for (int k = 0; k < image.Depth(); k++) { - buf[a++] = image(y, x, k); - } - } - } -} - -void libmv_imageToByteBuffer(const libmv::FloatImage &image, - unsigned char *buf) -{ - for (int y = 0, a= 0; y < image.Height(); y++) { - for (int x = 0; x < image.Width(); x++) { - for (int k = 0; k < image.Depth(); k++) { - buf[a++] = image(y, x, k) * 255.0f; - } - } - } -} - -/* Debugging */ - -static void savePNGImage(png_bytep *row_pointers, - int width, int height, int depth, int color_type, - const char *file_name) -{ - png_infop info_ptr; - png_structp png_ptr; - FILE *fp = fopen(file_name, "wb"); - - if (!fp) { - return; - } - - /* Initialize stuff */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - info_ptr = png_create_info_struct(png_ptr); - - if (setjmp(png_jmpbuf(png_ptr))) { - fclose(fp); - return; - } - - png_init_io(png_ptr, fp); - - /* write header */ - if (setjmp(png_jmpbuf(png_ptr))) { - fclose(fp); - return; - } - - png_set_IHDR(png_ptr, info_ptr, - width, height, depth, color_type, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, - PNG_FILTER_TYPE_BASE); - - png_write_info(png_ptr, info_ptr); - - /* write bytes */ - if (setjmp(png_jmpbuf(png_ptr))) { - fclose(fp); - return; - } - - png_write_image(png_ptr, row_pointers); - - /* end write */ - if (setjmp(png_jmpbuf(png_ptr))) { - fclose(fp); - return; - } - - png_write_end(png_ptr, NULL); - - fclose(fp); -} - -void libmv_saveImage(const FloatImage &image, - const char *prefix, - int x0, int y0) -{ - int x, y; - png_bytep *row_pointers; - - assert(image.Depth() == 1); - - row_pointers = new png_bytep[image.Height()]; - - for (y = 0; y < image.Height(); y++) { - row_pointers[y] = new png_byte[4 * image.Width()]; - - for (x = 0; x < image.Width(); x++) { - if (x0 == x && image.Height() - y0 - 1 == y) { - row_pointers[y][x * 4 + 0] = 255; - row_pointers[y][x * 4 + 1] = 0; - row_pointers[y][x * 4 + 2] = 0; - row_pointers[y][x * 4 + 3] = 255; - } - else { - float pixel = image(image.Height() - y - 1, x, 0); - row_pointers[y][x * 4 + 0] = pixel * 255; - row_pointers[y][x * 4 + 1] = pixel * 255; - row_pointers[y][x * 4 + 2] = pixel * 255; - row_pointers[y][x * 4 + 3] = 255; - } - } - } - - { - static int a = 0; - char buf[128]; - snprintf(buf, sizeof(buf), "%s_%02d.png", prefix, ++a); - savePNGImage(row_pointers, - image.Width(), image.Height(), 8, - PNG_COLOR_TYPE_RGBA, - buf); - } - - for (y = 0; y < image.Height(); y++) { - delete [] row_pointers[y]; - } - delete [] row_pointers; -} - -/* Camera intrinsics utility functions */ - -void libmv_cameraIntrinsicsFillFromOptions( - const libmv_CameraIntrinsicsOptions *camera_intrinsics_options, - CameraIntrinsics *camera_intrinsics) -{ - camera_intrinsics->SetFocalLength(camera_intrinsics_options->focal_length, - camera_intrinsics_options->focal_length); - - camera_intrinsics->SetPrincipalPoint( - camera_intrinsics_options->principal_point_x, - camera_intrinsics_options->principal_point_y); - - camera_intrinsics->SetImageSize(camera_intrinsics_options->image_width, - camera_intrinsics_options->image_height); - - switch (camera_intrinsics_options->distortion_model) { - case LIBMV_DISTORTION_MODEL_POLYNOMIAL: - { - PolynomialCameraIntrinsics *polynomial_intrinsics = - static_cast<PolynomialCameraIntrinsics*>(camera_intrinsics); - - polynomial_intrinsics->SetRadialDistortion( - camera_intrinsics_options->polynomial_k1, - camera_intrinsics_options->polynomial_k2, - camera_intrinsics_options->polynomial_k3); - - break; - } - - case LIBMV_DISTORTION_MODEL_DIVISION: - { - DivisionCameraIntrinsics *division_intrinsics = - static_cast<DivisionCameraIntrinsics*>(camera_intrinsics); - - division_intrinsics->SetDistortion( - camera_intrinsics_options->division_k1, - camera_intrinsics_options->division_k2); - - break; - } - - default: - assert(!"Unknown distortion model"); - } -} - -CameraIntrinsics *libmv_cameraIntrinsicsCreateFromOptions( - const libmv_CameraIntrinsicsOptions *camera_intrinsics_options) -{ - CameraIntrinsics *camera_intrinsics = NULL; - - switch (camera_intrinsics_options->distortion_model) { - case LIBMV_DISTORTION_MODEL_POLYNOMIAL: - camera_intrinsics = LIBMV_OBJECT_NEW(PolynomialCameraIntrinsics); - break; - - case LIBMV_DISTORTION_MODEL_DIVISION: - camera_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics); - break; - - default: - assert(!"Unknown distortion model"); - } - - libmv_cameraIntrinsicsFillFromOptions(camera_intrinsics_options, camera_intrinsics); - - return camera_intrinsics; -} - -/* Reconstruction utilities */ - -void libmv_getNormalizedTracks(const Tracks &tracks, - const CameraIntrinsics &camera_intrinsics, - Tracks *normalized_tracks) -{ - libmv::vector<Marker> markers = tracks.AllMarkers(); - - for (int i = 0; i < markers.size(); ++i) { - Marker &marker = markers[i]; - camera_intrinsics.InvertIntrinsics(marker.x, marker.y, - &marker.x, &marker.y); - normalized_tracks->Insert(marker.image, marker.track, - marker.x, marker.y, - marker.weight); - } -} - -Marker libmv_projectMarker(const EuclideanPoint &point, - const EuclideanCamera &camera, - const CameraIntrinsics &intrinsics) -{ - libmv::Vec3 projected = camera.R * point.X + camera.t; - projected /= projected(2); - - libmv::Marker reprojected_marker; - intrinsics.ApplyIntrinsics(projected(0), projected(1), - &reprojected_marker.x, - &reprojected_marker.y); - - reprojected_marker.image = camera.image; - reprojected_marker.track = point.track; - - return reprojected_marker; -} diff --git a/extern/libmv/libmv-util.h b/extern/libmv/libmv-util.h deleted file mode 100644 index d755f98d06d..00000000000 --- a/extern/libmv/libmv-util.h +++ /dev/null @@ -1,69 +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. - * - * The Original Code is Copyright (C) 2014 Blender Foundation. - * All rights reserved. - * - * Contributor(s): Blender Foundation, - * Sergey Sharybin - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef LIBMV_UTIL_H -#define LIBMV_UTIL_H - -#include "libmv-capi.h" -#include "libmv/image/image.h" -#include "libmv/simple_pipeline/camera_intrinsics.h" -#include "libmv/simple_pipeline/tracks.h" -#include "libmv/simple_pipeline/reconstruction.h" - -void libmv_byteBufferToImage(const unsigned char *buf, - int width, int height, int channels, - libmv::FloatImage *image); - -void libmv_floatBufferToImage(const float *buf, - int width, int height, int channels, - libmv::FloatImage *image); - -void libmv_imageToFloatBuffer(const libmv::FloatImage &image, - float *buf); - -void libmv_imageToByteBuffer(const libmv::FloatImage &image, - unsigned char *buf); - -void libmv_saveImage(const libmv::FloatImage &image, - const char *prefix, - int x0, int y0); - -void libmv_cameraIntrinsicsFillFromOptions( - const libmv_CameraIntrinsicsOptions *camera_intrinsics_options, - libmv::CameraIntrinsics *camera_intrinsics); - -libmv::CameraIntrinsics *libmv_cameraIntrinsicsCreateFromOptions( - const libmv_CameraIntrinsicsOptions *camera_intrinsics_options); - -void libmv_getNormalizedTracks(const libmv::Tracks &tracks, - const libmv::CameraIntrinsics &camera_intrinsics, - libmv::Tracks *normalized_tracks); - -libmv::Marker libmv_projectMarker(const libmv::EuclideanPoint &point, - const libmv::EuclideanCamera &camera, - const libmv::CameraIntrinsics &intrinsics); - -#endif diff --git a/extern/libmv/libmv/simple_pipeline/bundle.cc b/extern/libmv/libmv/simple_pipeline/bundle.cc index 09b55f34eef..e61650fb371 100644 --- a/extern/libmv/libmv/simple_pipeline/bundle.cc +++ b/extern/libmv/libmv/simple_pipeline/bundle.cc @@ -424,6 +424,7 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model, options.use_nonmonotonic_steps = true; options.preconditioner_type = ceres::SCHUR_JACOBI; options.linear_solver_type = ceres::ITERATIVE_SCHUR; + options.use_explicit_schur_complement = true; options.use_inner_iterations = true; options.max_num_iterations = 100; @@ -593,6 +594,7 @@ void EuclideanBundleCommonIntrinsics( options.use_nonmonotonic_steps = true; options.preconditioner_type = ceres::SCHUR_JACOBI; options.linear_solver_type = ceres::ITERATIVE_SCHUR; + options.use_explicit_schur_complement = true; options.use_inner_iterations = true; options.max_num_iterations = 100; diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt index 770803868cc..0ca888f6393 100644 --- a/extern/libmv/third_party/ceres/CMakeLists.txt +++ b/extern/libmv/third_party/ceres/CMakeLists.txt @@ -51,6 +51,7 @@ set(SRC internal/ceres/block_random_access_sparse_matrix.cc internal/ceres/block_sparse_matrix.cc internal/ceres/block_structure.cc + internal/ceres/callbacks.cc internal/ceres/canonical_views_clustering.cc internal/ceres/c_api.cc internal/ceres/cgnr_solver.cc @@ -76,6 +77,8 @@ set(SRC internal/ceres/generated/partitioned_matrix_view_d_d_d.cc internal/ceres/generated/schur_eliminator_d_d_d.cc internal/ceres/gradient_checking_cost_function.cc + internal/ceres/gradient_problem.cc + internal/ceres/gradient_problem_solver.cc internal/ceres/implicit_schur_complement.cc internal/ceres/incomplete_lq_factorization.cc internal/ceres/iterative_schur_complement_solver.cc @@ -87,6 +90,7 @@ set(SRC internal/ceres/line_search.cc internal/ceres/line_search_direction.cc internal/ceres/line_search_minimizer.cc + internal/ceres/line_search_preprocessor.cc internal/ceres/local_parameterization.cc internal/ceres/loss_function.cc internal/ceres/low_rank_inverse_hessian.cc @@ -96,9 +100,11 @@ set(SRC internal/ceres/partitioned_matrix_view.cc internal/ceres/polynomial.cc internal/ceres/preconditioner.cc + internal/ceres/preprocessor.cc internal/ceres/problem.cc internal/ceres/problem_impl.cc internal/ceres/program.cc + internal/ceres/reorder_program.cc internal/ceres/residual_block.cc internal/ceres/residual_block_utils.cc internal/ceres/schur_complement_solver.cc @@ -107,7 +113,7 @@ set(SRC internal/ceres/scratch_evaluate_preparer.cc internal/ceres/single_linkage_clustering.cc internal/ceres/solver.cc - internal/ceres/solver_impl.cc + internal/ceres/solver_utils.cc internal/ceres/sparse_matrix.cc internal/ceres/sparse_normal_cholesky_solver.cc internal/ceres/split.cc @@ -115,6 +121,7 @@ set(SRC internal/ceres/suitesparse.cc internal/ceres/triplet_sparse_matrix.cc internal/ceres/trust_region_minimizer.cc + internal/ceres/trust_region_preprocessor.cc internal/ceres/trust_region_strategy.cc internal/ceres/types.cc internal/ceres/visibility_based_preconditioner.cc @@ -134,13 +141,17 @@ set(SRC include/ceres/dynamic_numeric_diff_cost_function.h include/ceres/fpclassify.h include/ceres/gradient_checker.h + include/ceres/gradient_problem.h + include/ceres/gradient_problem_solver.h include/ceres/internal/autodiff.h + include/ceres/internal/disable_warnings.h include/ceres/internal/eigen.h include/ceres/internal/fixed_array.h include/ceres/internal/macros.h include/ceres/internal/manual_constructor.h include/ceres/internal/numeric_diff.h include/ceres/internal/port.h + include/ceres/internal/reenable_warnings.h include/ceres/internal/scoped_ptr.h include/ceres/internal/variadic_evaluate.h include/ceres/iteration_callback.h @@ -149,13 +160,13 @@ set(SRC include/ceres/loss_function.h include/ceres/normal_prior.h include/ceres/numeric_diff_cost_function.h - include/ceres/numeric_diff_functor.h include/ceres/ordered_groups.h include/ceres/problem.h include/ceres/rotation.h include/ceres/sized_cost_function.h include/ceres/solver.h include/ceres/types.h + include/ceres/version.h internal/ceres/array_utils.h internal/ceres/blas.h internal/ceres/block_evaluate_preparer.h @@ -167,6 +178,7 @@ set(SRC internal/ceres/block_random_access_sparse_matrix.h internal/ceres/block_sparse_matrix.h internal/ceres/block_structure.h + internal/ceres/callbacks.h internal/ceres/canonical_views_clustering.h internal/ceres/casts.h internal/ceres/cgnr_linear_operator.h @@ -193,6 +205,7 @@ set(SRC internal/ceres/execution_summary.h internal/ceres/file.h internal/ceres/gradient_checking_cost_function.h + internal/ceres/gradient_problem_evaluator.h internal/ceres/graph_algorithms.h internal/ceres/graph.h internal/ceres/implicit_schur_complement.h @@ -207,6 +220,7 @@ set(SRC internal/ceres/line_search_direction.h internal/ceres/line_search.h internal/ceres/line_search_minimizer.h + internal/ceres/line_search_preprocessor.h internal/ceres/low_rank_inverse_hessian.h internal/ceres/map_util.h internal/ceres/minimizer.h @@ -217,10 +231,12 @@ set(SRC internal/ceres/partitioned_matrix_view_impl.h internal/ceres/polynomial.h internal/ceres/preconditioner.h + internal/ceres/preprocessor.h internal/ceres/problem_impl.h internal/ceres/program_evaluator.h internal/ceres/program.h internal/ceres/random.h + internal/ceres/reorder_program.h internal/ceres/residual_block.h internal/ceres/residual_block_utils.h internal/ceres/schur_complement_solver.h @@ -230,7 +246,7 @@ set(SRC internal/ceres/scratch_evaluate_preparer.h internal/ceres/single_linkage_clustering.h internal/ceres/small_blas.h - internal/ceres/solver_impl.h + internal/ceres/solver_utils.h internal/ceres/sparse_matrix.h internal/ceres/sparse_normal_cholesky_solver.h internal/ceres/split.h @@ -239,52 +255,55 @@ set(SRC internal/ceres/suitesparse.h internal/ceres/triplet_sparse_matrix.h internal/ceres/trust_region_minimizer.h + internal/ceres/trust_region_preprocessor.h internal/ceres/trust_region_strategy.h internal/ceres/visibility_based_preconditioner.h internal/ceres/visibility.h internal/ceres/wall_time.h ) -#if(FALSE) -# list(APPEND SRC -# internal/ceres/generated/partitioned_matrix_view_2_2_2.cc -# internal/ceres/generated/partitioned_matrix_view_2_2_3.cc -# internal/ceres/generated/partitioned_matrix_view_2_2_4.cc -# internal/ceres/generated/partitioned_matrix_view_2_2_d.cc -# internal/ceres/generated/partitioned_matrix_view_2_3_3.cc -# internal/ceres/generated/partitioned_matrix_view_2_3_4.cc -# internal/ceres/generated/partitioned_matrix_view_2_3_9.cc -# internal/ceres/generated/partitioned_matrix_view_2_3_d.cc -# internal/ceres/generated/partitioned_matrix_view_2_4_3.cc -# internal/ceres/generated/partitioned_matrix_view_2_4_4.cc -# internal/ceres/generated/partitioned_matrix_view_2_4_8.cc -# internal/ceres/generated/partitioned_matrix_view_2_4_9.cc -# internal/ceres/generated/partitioned_matrix_view_2_4_d.cc -# internal/ceres/generated/partitioned_matrix_view_2_d_d.cc -# internal/ceres/generated/partitioned_matrix_view_4_4_2.cc -# internal/ceres/generated/partitioned_matrix_view_4_4_3.cc -# internal/ceres/generated/partitioned_matrix_view_4_4_4.cc -# internal/ceres/generated/partitioned_matrix_view_4_4_d.cc -# internal/ceres/generated/schur_eliminator_2_2_2.cc -# internal/ceres/generated/schur_eliminator_2_2_3.cc -# internal/ceres/generated/schur_eliminator_2_2_4.cc -# internal/ceres/generated/schur_eliminator_2_2_d.cc -# internal/ceres/generated/schur_eliminator_2_3_3.cc -# internal/ceres/generated/schur_eliminator_2_3_4.cc -# internal/ceres/generated/schur_eliminator_2_3_9.cc -# internal/ceres/generated/schur_eliminator_2_3_d.cc -# internal/ceres/generated/schur_eliminator_2_4_3.cc -# internal/ceres/generated/schur_eliminator_2_4_4.cc -# internal/ceres/generated/schur_eliminator_2_4_8.cc -# internal/ceres/generated/schur_eliminator_2_4_9.cc -# internal/ceres/generated/schur_eliminator_2_4_d.cc -# internal/ceres/generated/schur_eliminator_2_d_d.cc -# internal/ceres/generated/schur_eliminator_4_4_2.cc -# internal/ceres/generated/schur_eliminator_4_4_3.cc -# internal/ceres/generated/schur_eliminator_4_4_4.cc -# internal/ceres/generated/schur_eliminator_4_4_d.cc -# ) -#endif() +if(WITH_LIBMV_SCHUR_SPECIALIZATIONS) + list(APPEND SRC + internal/ceres/generated/partitioned_matrix_view_2_2_2.cc + internal/ceres/generated/partitioned_matrix_view_2_2_3.cc + internal/ceres/generated/partitioned_matrix_view_2_2_4.cc + internal/ceres/generated/partitioned_matrix_view_2_2_d.cc + internal/ceres/generated/partitioned_matrix_view_2_3_3.cc + internal/ceres/generated/partitioned_matrix_view_2_3_4.cc + internal/ceres/generated/partitioned_matrix_view_2_3_9.cc + internal/ceres/generated/partitioned_matrix_view_2_3_d.cc + internal/ceres/generated/partitioned_matrix_view_2_4_3.cc + internal/ceres/generated/partitioned_matrix_view_2_4_4.cc + internal/ceres/generated/partitioned_matrix_view_2_4_8.cc + internal/ceres/generated/partitioned_matrix_view_2_4_9.cc + internal/ceres/generated/partitioned_matrix_view_2_4_d.cc + internal/ceres/generated/partitioned_matrix_view_2_d_d.cc + internal/ceres/generated/partitioned_matrix_view_4_4_2.cc + internal/ceres/generated/partitioned_matrix_view_4_4_3.cc + internal/ceres/generated/partitioned_matrix_view_4_4_4.cc + internal/ceres/generated/partitioned_matrix_view_4_4_d.cc + internal/ceres/generated/schur_eliminator_2_2_2.cc + internal/ceres/generated/schur_eliminator_2_2_3.cc + internal/ceres/generated/schur_eliminator_2_2_4.cc + internal/ceres/generated/schur_eliminator_2_2_d.cc + internal/ceres/generated/schur_eliminator_2_3_3.cc + internal/ceres/generated/schur_eliminator_2_3_4.cc + internal/ceres/generated/schur_eliminator_2_3_9.cc + internal/ceres/generated/schur_eliminator_2_3_d.cc + internal/ceres/generated/schur_eliminator_2_4_3.cc + internal/ceres/generated/schur_eliminator_2_4_4.cc + internal/ceres/generated/schur_eliminator_2_4_8.cc + internal/ceres/generated/schur_eliminator_2_4_9.cc + internal/ceres/generated/schur_eliminator_2_4_d.cc + internal/ceres/generated/schur_eliminator_2_d_d.cc + internal/ceres/generated/schur_eliminator_4_4_2.cc + internal/ceres/generated/schur_eliminator_4_4_3.cc + internal/ceres/generated/schur_eliminator_4_4_4.cc + internal/ceres/generated/schur_eliminator_4_4_d.cc + ) +else() + add_definitions(-DCERES_RESTRICT_SCHUR_SPECIALIZATION) +endif() if(WIN32) list(APPEND INC @@ -307,7 +326,6 @@ add_definitions( -DCERES_NO_SUITESPARSE -DCERES_NO_CXSPARSE -DCERES_NO_LAPACK - -DCERES_RESTRICT_SCHUR_SPECIALIZATION -DCERES_HAVE_RWLOCK ) diff --git a/extern/libmv/third_party/ceres/ChangeLog b/extern/libmv/third_party/ceres/ChangeLog index c9f5b3426bc..6f921542019 100644 --- a/extern/libmv/third_party/ceres/ChangeLog +++ b/extern/libmv/third_party/ceres/ChangeLog @@ -1,646 +1,671 @@ -commit 8c62487e437b91d3d354cd1ae8957e43fe540732 +commit 9e11cd16d09403b9270e621e839d5948b6a74b8d Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Fri May 16 09:44:18 2014 -0700 +Date: Mon Sep 29 14:27:58 2014 -0700 - Preparations for 1.9.0 release. + Faster BlockRandomAccessSparseMatrix::SymmetricRightMultiply. - Version bump. - minor docs update. + Trade a small amount of memory to improve the cache coherency of + the SymmetricRightMultiply operation. - Change-Id: I2fbe20ba4af6b2e186fe244c96ce6d6464fe0469 + The resulting code leads to a 10-20% speedup in the linear solver + end to end. + + Change-Id: I8ab2fe152099e849b211b5b19e4ef9f03d8e7f1c -commit 0831275a78ab65e4c95979598cb35c54d03d3185 +commit 46b8461fd010c1e7ffce6bb2bdf8a84b659d5e09 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Fri May 16 08:17:54 2014 -0700 +Date: Mon Sep 29 15:10:58 2014 -0700 - Documentation update. - - 1. Update iOS build instructions. - 2. Update version history. + Various minor fixes from William Rucklidge. - Change-Id: I49d62e86ecff39190b50c050cb12eef4e2773357 + Change-Id: Ibe731d5db374ad8ee148d62a9fdd8d726b607a3f -commit c7c7458625996a20203f1366d11bd701e5fb621b -Author: Jack Feng <jackfengji@gmail.com> -Date: Mon May 12 10:23:56 2014 +0800 +commit b44cfdef25f6bf0917a23b3fd65cce38aa6a3362 +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Mon Sep 29 07:53:54 2014 -0700 - add support for building for ios + Let ITERATIVE_SCHUR use an explicit Schur Complement matrix. - use ios-cmake to build for ios + Up till now ITERATIVE_SCHUR evaluates matrix-vector products + between the Schur complement and a vector implicitly by exploiting + the algebraic expression for the Schur complement. - Change-Id: I6b17c33339f3121322a4004d79629b22a62f7a94 - -commit 36c2ce87d13b9b7123bd0473b8b45fb3b6ae4271 -Author: Sergey Sharybin <sergey.vfx@gmail.com> -Date: Mon Jan 13 21:18:08 2014 +0600 - - Libmv 2D homography estimation example application + This cost of this evaluation scales with the number of non-zeros + in the Jacobian. + + For small to medium sized problems there is a sweet spot where + computing the Schur complement is cheap enough that it is much + more efficient to explicitly compute it and use it for evaluating + the matrix-vector products. + + This changes implements support for an explicit Schur complement + in ITERATIVE_SCHUR in combination with the SCHUR_JACOBI preconditioner. + + API wise a new bool Solver::Options::use_explicit_schur_complement + has been added. + + The implementation extends the SparseSchurComplementSolver to use + Conjugate Gradients. + + Example speedup: + + use_explicit_schur_complement = false + + Time (in seconds): + Preprocessor 0.585 - Add an example application of homography matrix estimation - from a 2D euclidean correspondences which is done in two - steps: + Residual evaluation 0.319 + Jacobian evaluation 1.590 + Linear solver 25.685 + Minimizer 27.990 - - Coarse algebraic estimation - - Fine refinement using Ceres minimizer + Postprocessor 0.010 + Total 28.585 - Nothing terribly exciting apart from an example of how to - use user callbacks. + use_explicit_schur_complement = true - User callback is used here to stop minimizer when average - of symmetric geometric distance becomes good enough. - This might be arguable whether it's the best way to go - (in some cases you would want to stop minimizer when - maximal symmetric distance is lower than a threshold) but - for a callback usage example it's good enough to stick - to current logic. + Time (in seconds): + Preprocessor 0.638 - Change-Id: I60c8559cb10b001a0eb64ab71920c08bd68455b8 + Residual evaluation 0.318 + Jacobian evaluation 1.507 + Linear solver 5.930 + Minimizer 8.144 + + Postprocessor 0.010 + Total 8.791 + + Which indicates an end-to-end speedup of more than 3x, with the linear + solver being sped up by > 4x. + + The idea to explore this optimization was inspired by the recent paper: + + Mining structure fragments for smart bundle adjustment + L. Carlone, P. Alcantarilla, H. Chiu, K. Zsolt, F. Dellaert + British Machine Vision Conference, 2014 + + which uses a more complicated algorithm to compute parts of the + Schur complement to speed up the matrix-vector product. + + Change-Id: I95324af0ab351faa1600f5204039a1d2a64ae61d -commit d99a3a961e4a6ff7218d0ab749da57cf1a1677bd -Author: Björn Piltz <bjornpiltz@gmail.com> -Date: Wed May 7 14:59:12 2014 +0200 +commit 4ad91490827f2ebebcc70d17e63ef653bf06fd0d +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Wed Sep 24 23:54:18 2014 -0700 - Separate PUBLIC and PRIVATE library dependencies - Do not propagate 3d party libs through - IMPORTED_LINK_INTERFACE_LIBRARIES_[DEBUG/RELEASE] mechanism - when building shared libraries. SuiteSparse, lapack & co - are considered private. Glog still gets propagated since - it is part of the public interface. See documentation of - TARGET_LINK_LIBRARIES(). + Simplify the Block Jacobi and Schur Jacobi preconditioners. + + 1. Extend the implementation of BlockRandomAccessDiagonalMatrix + by adding Invert and RightMultiply methods. - Change-Id: If0563b0c705b102876f5190e9a86694d10f79283 + 2. Simplify the implementation of the Schur Jacobi preconditioner + using these new methods. + + 3. Replace the custom storage used inside Block Jacobi preconditioner + with BlockRandomAccessDiagonalMatrix and simplify its implementation + too. + + Change-Id: I9d4888b35f0f228c08244abbdda5298b3ce9c466 -commit 1c089e8453583876f417b214f76a5863d7694986 +commit 8f7be1036b853addc33224d97b92412b5a1281b6 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Tue May 13 16:58:25 2014 -0700 +Date: Mon Sep 29 08:13:35 2014 -0700 - Notational fix in modeling.rst by William Rucklidge. + Fix a formatting error TrustRegionMinimizer logging. - Change-Id: Iffa127541380fcc32da13fe4ac474692e1e3d0ec + Change-Id: Iad1873c51eece46c3fdee1356d154367cfd7925e -commit 082d9e2a1b43b26a81157a6c711de0ff34c40ba4 +commit c99872d48e322662ea19efb9010a62b7432687ae Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Mon May 12 20:41:27 2014 -0700 +Date: Wed Sep 24 21:30:02 2014 -0700 - Add iOS.cmake from the ios-cmake project. - - URL: https://github.com/cristeab/ios-cmake - Commit: 86dc085f0d5ed955cd58e2657cc3efc7c1aabbc8 + Add BlockRandomAccessSparseMatrix::SymmetricRightMultiply. - Change-Id: I8fe6023d4cb6655b5a724e8b695fdae87ce3b685 + Change-Id: Ib06a22a209b4c985ba218162dfb6bf46bd93169e -commit a97056c9752fe7223c8560da58862ecb1fd241ad +commit d3ecd18625ba260e0d00912a305a448b566acc59 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Tue May 13 16:45:36 2014 -0700 +Date: Tue Sep 23 10:12:42 2014 -0700 - Various documentation fixes from William Rucklidge. + Add an explicit include for local_parameterization.h - Change-Id: I102e98f41f4b5fe2a84d1224d5ed7517fdfdb022 + Thanks to cooordz for reporting this. + + Change-Id: I7d345404e362a94ff1eb433ad6b9dcc4960ba76d -commit 2f8fb218f0a08102231ace07ef02b34b4aad7336 +commit 5dd76869cf45122c79579423f09e0de08cf04092 Author: Alex Stewart <alexs.mac@gmail.com> -Date: Tue May 13 20:57:39 2014 +0100 +Date: Fri Sep 19 16:08:25 2014 +0100 - Adding function to update CMake cache variables and preserve help. + Fix unused-function warning with Eigen < 3.2.2. - - Previously we were replicating the same two lines to update a cache - variable whilst preserving its help string. - - This commit adds a function which wraps up this common operation into - a single line. + - CreateBlockJacobian() is only ever used when Eigen >= 3.2.2 is + detected, but was previously defined whenever CERES_USE_EIGEN_SPARSE + was defined with no check on the Eigen version. + - This resulted in an unused-function compile warning that became an + error due to -Werror, preventing compilation when using Eigen < 3.2.2. - Change-Id: Ic78a5adf5d59262bbbcec1e353ded7620391e862 + Change-Id: I24628ff329f14b087ece66bf2626bdc0de4ba224 -commit 8f4dcb25f1be74a8c12c0f9eeb67b6b0755563f5 +commit 820cb7b14831aa03eca1e8186000cebfdf0a42f3 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Tue Apr 29 21:40:57 2014 -0700 +Date: Wed Sep 17 09:46:08 2014 -0700 - Documentation update. - - Update modeling.rst and solving.rst to reflect - changes to the API. + Add solver_utils.cc to Android.mk - Change-Id: Id1a8adfed1486f08e5fd67c5af2d29708a26490c + Change-Id: I358522971711280f4362a1fa39b1568160e21e63 -commit d48e7050225730f61eaef851def5b43bc439e991 -Author: Alex Stewart <alexs.mac@gmail.com> -Date: Sat May 10 08:58:58 2014 +0100 +commit 092b94970a073f8b47179d96160226fc19095898 +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Fri Sep 5 11:56:29 2014 -0700 - Configure config.h and include it from the build directory. + Add GradientProblem and GradientProblemSolver. + + The line search minimizer in Ceres does not require that the + problems that is solving is a sum of squares. Over the past + year there have been multiple requests to expose this algorithm + on its own so that it can be used to solve unconstrained + non-linear minimization problems on its own. + + With this change, a new optimization problem called + GradientProblem is introduced which is basically a thin + wrapper around a user defined functor that evaluates cost + and gradients (FirstOrderFunction) and an optional LocalParameterization. - - Previously we overwrote the default (empty) config.h in the source - tree with a configured config.h, generated using the current compile - options. - - This was undesirable as it could lead to inadvertant commits of the - generated config.h. + Corresponding to it, a GradientProblemSolver and its associated + options and summary structs are introduced too. - - This patch moves the default config.h to <src>/config/ceres/internal, - separate from the other headers, thus if Ceres is compiled without - CMake this directory will now also have to be included. This - directory is _not_ added to the CMake include directories for Ceres - (thus the default config.h is never used when compiling with CMake). - - When using CMake, the generated config.h is now placed in - <build>/config/ceres/internal, which is in turn added to the include - directories for Ceres when it is compiled, and the resulting config.h - is copied to ceres/internal when installed. + An example that uses the new API to find the minimum of Rosenbrock's + function is also added. - Change-Id: Ib1ba45e66e383ade2ebb08603af9165c1df616f2 + Change-Id: I42bf687540da25de991e9bdb00e321239244e8b4 -commit 11c496164ffe9809306945c2b81276efcd51533d +commit 6c45d6b891aac01489b478a021f99081c61792cb Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Fri May 9 16:27:03 2014 -0700 +Date: Thu Sep 11 07:48:30 2014 -0700 - Fix 80cols violation in local_parameterization.h + Add more inspection methods to Problem. - Change-Id: I07f59baa9e4aba7c5ae028f0c144ea9ad153d49a + Problem::GetCostFunctionForResidualBlock + Problem::GetLossFunctionForResidualBlock + + are added, so that users do not have to maintain this mapping + outside the Problem. + + Change-Id: I38356dfa094b2c7eec90651dafeaf3a33c5f5f56 -commit af3154422b63b7792ecd23b00ca1a0c003764dae +commit 6ad9b8e2ae66c9009441d0f9304486ec8dfa9a6a Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Fri May 9 05:45:03 2014 -0700 +Date: Tue Sep 9 14:29:28 2014 -0700 - Add Alex Stewart as a maintainer. + Ignore row/column blocks structure when using dynamic sparsity + + The row/column blocks can be huge when using dynamic sparsity. This + can result in very large memory usage when augmenting the jacobian + with the LM diagonal. - Update contributing.rst to mention Alex - as one of the people who can be added - as a reviewer. + Thanks to Mingsong Dou for reporting this. - Change-Id: I30ff3e635e8c419e11e8f20394aaea5f284a10d5 + Change-Id: I6aa140ceefa98389ae17958f89ca76e0c76f95b8 -commit ea765850685f1ff0431da5212656378fc20d3673 -Author: Alex Stewart <alexs.mac@gmail.com> -Date: Wed May 7 20:46:17 2014 +0100 - - Adding autogenerated Ceres config.h to #define Ceres compile options. - - - Previously we passed all compile options to Ceres via add_definitions - in CMake. This was fine for private definitions (used only by Ceres) - but required additional work for public definitions to ensure they - were correctly propagated to clients via CMake using - target_compile_definitions() (>= 2.8.11) or add_definitions(). - - A drawback to these approaches is that they did not work for chained - dependencies on Ceres, as in if in the users project B <- A <- Ceres, - then although the required Ceres public compile definitions would - be used when compiling A, they would not be propagated to B. - - - This patch replaces the addition of compile definitions via - add_definitions() with an autogenerated config.h header which - is installed with Ceres and defines all of the enabled Ceres compile - options. - - This removes the need for the user to propagate any compile - definitions in their projects, and additionally allows post-install - inspect of the options with which Ceres was compiled. - - Change-Id: Idbdb6abdad0eb31e7540370e301afe87a07f2260 - -commit cbf955474acf8f275b272da6ff5acd3a629cc806 -Author: Björn Piltz <bjornpiltz@gmail.com> -Date: Wed May 7 17:10:15 2014 +0200 +commit 7e43460d42e20be1ba13121655dbbfd0d1c751ae +Author: Martin Baeuml <baeuml@gmail.com> +Date: Mon Sep 8 16:49:06 2014 +0200 - Fixes swapped verboselevel and condition. + Fix a few typos in the documentation. - Change-Id: I296d86e6bbf415be4bfd19d6a0fe0963e3d36d74 + Change-Id: I541db56b2b81ae758e233ce850d78c3cbb4b6fa3 -commit 3209b045744ea31f38d74bd9e9c8f88e605e7f76 -Author: Björn Piltz <bjornpiltz@gmail.com> -Date: Wed May 7 17:02:27 2014 +0200 +commit 1aef66eeae7042902655a11b0d6a1a32900abb7b +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Sun Sep 7 21:18:44 2014 -0700 - Fixed warning : 'va_copy' : macro redefinition - MSVC 2013 has got va_copy - Compare - http://msdn.microsoft.com/en-us/library/kb57fad8(v=vs.110).aspx - and - http://msdn.microsoft.com/en-us/library/kb57fad8.aspx. + Remove errant space. - Change-Id: If0937c76e8d250cde4b343844f3d35c980bf0921 + Change-Id: Iedc06960417a9b938d57f623b4beb87a98e3d081 -commit 1df2f0f5d704f0cc458cf707e2602d495979e3c6 -Author: Björn Piltz <bjornpiltz@gmail.com> -Date: Wed May 7 11:10:30 2014 +0200 +commit 89080ab153a33008782759187fa8e9af7d2f83f1 +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Sat Sep 6 21:13:48 2014 -0700 - Removed MSVC warnings - These are warnings which show up when using Ceres. + Add LocalParameterization::MultiplyByJacobian. - Change-Id: Id1f382f46b8a60743f0b12535b5b3cdf46f988e0 + This is needed to efficiently support LocalParameterization objects + in GradientProblemSolver. + + Change-Id: Ic7b715b8be694b099dc95d6707a67474297533e6 -commit eca7e1c635581834c858794e09c1e876323b7775 +commit d76da16f49d419ae3664ca1bdc2286c1ea78ebed Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Tue May 6 10:16:19 2014 -0700 +Date: Sun Sep 7 18:42:49 2014 -0700 - Remove BlockRandomAccessCRSMatrix. + Move some routines to solver_utils.h/cc - It is not used anywhere. + This moves a couple of routines from solver.cc into solver_utils.h/cc + so that they can also be used by the upcoming GradientProblemSolver. - Change-Id: I2a8ebbdacf788582f21266825ead3f76646da29e + Change-Id: I627b32ad3dc639422aacde78a8e391459d947e99 -commit 7088a08f5d9e04e75a5a4c3823ef7927e13ff0e4 +commit cbf03ac292a0c0e9e6b7fcc1b08b67e95965922f Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Mon May 5 09:02:05 2014 -0700 +Date: Sat Sep 6 21:07:08 2014 -0700 - Fix some 80col violations and reflow the comments in cmake.in file. + Make LineSearchMinimizer consistent with TrustRegionMinimizer. + + Change the logic for how IterationSummary objects are added to + Summary::iterations to match the one in TrustRegionMinimizer. - Change-Id: I4c65c89b794845aeef69159a03350c727e2ee812 + Change-Id: I57851ad8294e58f83b9115cca9c24695d86ee92a -commit 95cce0834d5a2d72568e6d2be968a51c244c2787 +commit f04c32319751e1efd610acd3699bca0a6dd6c6d1 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Mon May 5 08:54:50 2014 -0700 +Date: Sat Sep 6 21:05:41 2014 -0700 - Remove some errant tabs. + Fix some obsolete documentation in CostFunction::Evaluate - Change-Id: Ie1f7051e99bcb15ad068711b68a9d8f317b12ed7 + Change-Id: I1d7ee5c596fbf6a4d886dce5b989c8eb18af2dce -commit a536ae76dfa2dbe2bc487900b98cf6c15276c649 -Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Sun May 4 21:18:42 2014 -0700 +commit 9263547c02a1807532b159c217e7acd124d3db10 +Author: Johannes Schönberger <hannesschoenberger@gmail.com> +Date: Sat Sep 6 17:26:15 2014 -0400 - Lazily initialize the bounds arrays in ParameterBlock. + Fix CG solver options for ITERATIVE_SCHUR, which did not copy min_num_iterations - Problems that do not use bounds do not have to pay the - price of storing bounds constraints. + Change-Id: If31bc53b49ec20426fd438b79b8fa1f69d11e861 + +commit b41f048256d1a8184cbe874b5a96dffa7fa4630d +Author: Martin Baeuml <baeuml@gmail.com> +Date: Fri Sep 5 15:03:32 2014 +0200 + + Remove obsolete include of numeric_diff_functor.h. - Also replace the raw pointer access to the upper and - lower bounds arrays with accessors which hides the - lazy initialization from the user. + numeric_diff_functor.h was removed and does not exist anymore. - Change-Id: I0325a35de9c29f853559f891e32e7c777686e537 + Change-Id: I07bf04bf81142551e867b95b83a0653e11cad54c -commit 633b50b7af9841607c07133f585e131fba7de177 +commit b7fb6056a717cc3c372cfb7115c527ee8bc05ddb Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Fri May 2 22:46:20 2014 -0700 +Date: Wed Sep 3 11:19:02 2014 -0700 - Add the (2,4,8) template specialization. + Remove NumericDiffFunctor. + + Its API was broken, and its implementation was an unnecessary + layer of abstraction over CostFunctionToFunctor. - Change-Id: I058bcebdd1725031d573404133b184d6f27dc005 + Change-Id: I18fc261fc6a3620b51a9eeb4dde0af03d753af69 -commit 5ffe06019a6c741ee7edc940ffeeceaaeabfa05d -Author: Alex Stewart <alexs.mac@gmail.com> -Date: Thu May 1 12:06:46 2014 +0100 +commit 175fa8ff09049110a8509409f60cee5fd52cdbe6 +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Tue Sep 2 06:49:08 2014 -0700 - Export Ceres compile definitions to targets compiled against Ceres. + CostFunctionToFunctor allows dynamic number of residuals. - - Previously all Ceres compile definitions were private to Ceres, that - is they were not exported to users via the CMake export mechanism. - - Now that we use compile definitions in public (installed) Ceres - headers, we need to export the Ceres compile definitions. - - If we did not do this, then the client's code 'see's' a different - version of the Ceres headers to those which were in fact compiled, - or in the case of shared_ptr, may not find the required header. + The code itself was perfectly capable of handling residuals, but there + was an overly strict runtime check that had to be removed. - - This patch makes use of the new, in CMake 2.8.11, function: - target_compile_definitions() to export all of the Ceres compile - definitions using CMake's export functionality. - - For CMake versions < 2.8.11, we have to use the blunter instrument of - calling add_definitions() in CeresConfig.cmake (invoked by a call to - find_package(Ceres)). This is messy because it ends up adding the - Ceres compile definitions to any target declared in the user's code - after the call to find_package(Ceres). Although this should do no - harm as all of our defines are prefaced with CERES_, so any - unintentional name clashes are unlikely. + Thanks to Domink Reitzle for reporting this. - Change-Id: I5dea80949190eaf4fb08ea4ac568ce28c32dd4e0 + Change-Id: I6a6d000a7c5203dd5945a61b4caeda1b8aeb09c9 -commit 0e811b0881f1f21df0ae04fd745ae4ba5189cac1 -Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Thu May 1 07:54:12 2014 -0700 +commit 70ace0d5a5601901288974fcf27919754260cf0e +Author: Johannes Schönberger <hannesschoenberger@gmail.com> +Date: Sat Aug 30 15:52:34 2014 -0400 - Fix a bug in Minimizer::RunCallbacks. - - Solver::Summary::message was not being updated when the solver - terminated because of a user's iteration callback indicating - success or failure. - - Thanks to Sergey Sharybin for reporting this. + Fix max. linear solver iterations in ConjugateGradientsSolver - Change-Id: I27e6e5eed086920ddf765461b0159417ac79d7b3 + Change-Id: Ice0cef46441dbc1c121eeb42113667a46c96936f -commit 31b503792611d2119bb1acb3528fc8d58c5bd029 +commit c5d8d0680250f5eb554577d30d28fc805b03fab9 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Wed Apr 30 15:02:38 2014 -0700 +Date: Fri Aug 29 20:31:19 2014 -0700 - Lint cleanup from William Rucklidge. + Fix a unused function error with Eigen version 3.2.1 or less. + + Thanks to Johannes Schoenberger for reporting this. - Change-Id: If545f114c1a2b07edd660a3c71ecfc16ffa25e43 + Change-Id: Ie17d28f2a68734a978a8c95007724bc4055de43a -commit 15c1210a8bdf3e936b4ef600d75f0fbb70878fb5 +commit 0e1cc2a55488e4cf381833baaa3531c02ce9d69e Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Tue Apr 29 08:12:19 2014 -0700 +Date: Fri Aug 29 09:16:56 2014 -0700 - Lint cleanup from Jim Roseborough. + Fix the build on Eigen version 3.2.1 and older. - Change-Id: I53f4e0d020602443b397387b8c5908f25649403d + Change-Id: I18f5cb5d42113737d7b8f78a67acee28bd5b3e08 -commit b1668067f1c97520d5d28eecf2c11d2afc1b01b3 +commit 5f96c62b56222f27e606f2246a8a16b6942af8d1 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Tue Apr 29 08:12:19 2014 -0700 +Date: Thu Aug 28 23:06:17 2014 -0700 - Variety of changes to documentation and example code. + Add Block AMD ordering for SPARSE_SCHUR + EIGEN_SPARSE. + + Ordering routines for the Schur complement when using EIGEN_SPARSE. + Also integration into SchurComplementSolver. - 1. Update version history. - 2. Minor changes to the tutorial to reflect the bounds constrained - problem. - 3. Added static factory methods to the SnavelyReprojectionError. - 4. Removed relative gradient tolerance from types.h as it is - not true anymore. + Part of this CL is also a refactoring of the block jacobian matrix + construction. - Change-Id: I8de386e5278a008c84ef2d3290d2c4351417a9f1 + Change-Id: I11d665cc7d4867c64190e6fed1118f4d2e13d59b -commit 658407dacc351a999206980fbb3265099e50e7a3 +commit 7344626c04d19ca1dc4871c377c4422c744b1bca Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Mon Apr 28 13:25:17 2014 -0700 +Date: Thu Aug 28 22:03:09 2014 -0700 - Add missing template specializations to the NDK build. + Let EIGEN_SPARSE + SPARSE_NORMAL_CHOLESKY use block AMD. - Change-Id: I42bb6c3bd47648050298472af80333aa900e79bf - -commit 5d7eed87b47871bc882af765188fa4fbca976855 -Author: Björn Piltz <bjornpiltz@gmail.com> -Date: Wed Apr 23 22:13:37 2014 +0200 - - Suppport for MSVC DLLs. + Modify SparseNormalCholeskySolver to use a pre-ordered Jacobian + matrix. - Change-Id: Ibbcc4ba4e59f5bbf1cb91fe81c7d3b9042d03493 + Change-Id: Ib4d725d7a2d7bb94ea76dbb3a9b172784dbc8ea0 -commit c830820a5c2be0d0cecb0822f2cff8b4ffe88f36 +commit 9f7032369ea4e432f0fb507cb6d2209741ee6946 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Mon Apr 28 10:28:24 2014 -0700 +Date: Thu Aug 28 21:46:43 2014 -0700 - Add missing files to Android.mk + Block AMD for SparseNormalCholesky + EIGEN_SPARSE. - Change-Id: Ibdf577c592bcde0fe5c2ce343ed8e9028b82af8f + This is just the reordering routine. The integration with + SparseNormalCholesky shall happen in a subsequent CL. + + Change-Id: I39ddc32aa66b11c368faf75404850fa0ae0d2b3a -commit ceb7a3beaad140762b499f9a306fd7230715941a -Author: Sergey Sharybin <sergey.vfx@gmail.com> -Date: Mon Apr 28 13:50:09 2014 +0600 +commit b9331cd4077100d645be22a912d5743eeda72878 +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Thu Aug 28 14:42:27 2014 -0700 - Fix compilation error when using G++ compiler + Cleanup reorder_program.cc - This compiler defines shared_ptr in std::tr1 namespace, but - for this <tr1/memory> is to be included. Further, this compiler - also does have <memory> header which confused previous shared - pointer check. + Program::SetParameterOffsetsAndIndex() was being called willy nilly. + Now the invariant is that any function that actually reorders the + program, updates the offsets and indices. - Simplified logic around defines now, so currently we've got: - - CERES_TR1_MEMORY_HEADER defined if <tr1/memory> is to be - used for shared_ptr, otherwise <memory> is to be used. - - CERES_TR1_SHARED_PTR defined if shared_ptr is defined in - std::tr1 namespace, otherwise it's defined in std namespace. + Also the logic around handling EIGEN_SPARSE has been simplified in + anticipation of the block AMD code that is forthcoming. - All the shared_ptr checks are now moved to own file FindSharedPtr - which simplifies main CMakeLists. + Last but not the least, num_eliminate_blocks, which is a rather + cryptic name to begin with has been replaced by the more meaningful + size_of_first_elimination_group. - Change-Id: I558a74793baaa0bd088801910a356be4ef17c31b + Change-Id: I77e684f699a93b53e76aa406d64f40f8704df813 -commit 02db9414fb6739857a37e268500083a0546cd0a3 +commit 79491a3f4a3939a3cce4644da7a998b7782b963a Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Mon Apr 28 08:32:51 2014 -0700 +Date: Thu Aug 28 13:57:50 2014 -0700 - Fix the documentation for RandNormal. + Solver::FullReport now reports build config. + + The header of Summary::FullReport now looks like - As pointed out by Jim Roseborough, this is the Marsaglia Polar - method and not the Box-Muller method. + Solver Summary (v 1.10.0-suitesparse-cxsparse-lapack-no_openmp) - Change-Id: Id5332bcd4b4c23a3885cc296729b44eaa5edd0a8 + Original Reduced + Parameter blocks 22122 22122 + Parameters 66462 66462 + Residual blocks 83718 83718 + Residual 167436 167436 + + Change-Id: Id1b81bbf90ba412d19e2dd3687eeb9d372b72c1b -commit 32530788d08c53f8d2c8a5f9bd61aa60a23d6e03 -Author: Richard Stebbing <richie.stebbing@gmail.com> -Date: Sat Apr 26 07:42:23 2014 +0100 +commit 48068c753e91d77f6c96ef2d529a27ef8ee3947c +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Thu Aug 28 13:03:40 2014 -0700 - Add dynamic_sparsity option. - - The standard sparse normal Cholesky solver assumes a fixed - sparsity pattern which is useful for a large number of problems - presented to Ceres. However, some problems are symbolically dense - but numerically sparse i.e. each residual is a function of a - large number of parameters but at any given state the residual - only depends on a sparse subset of them. For these class of - problems it is faster to re-analyse the sparsity pattern of the - jacobian at each iteration of the non-linear optimisation instead - of including all of the zero entries in the step computation. + Lint cleanup from William Rucklidge. - The proposed solution adds the dynamic_sparsity option which can - be used with SPARSE_NORMAL_CHOLESKY. A - DynamicCompressedRowSparseMatrix type (which extends - CompressedRowSparseMatrix) has been introduced which allows - dynamic addition and removal of elements. A Finalize method is - provided which then consolidates the matrix so that it can be - used in place of a regular CompressedRowSparseMatrix. An - associated jacobian writer has also been provided. + Change-Id: Ie0e0aa58440be7a4f67dcd633dbb6f1bb0c051a8 + +commit 6a51b135e6298e8ba44a58cc2b54a170ab61a82f +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Thu Aug 28 10:48:29 2014 -0700 + + Fix solver_test.cc - Changes that were required to make this extension were adding the - SetMaxNumNonZeros method to CompressedRowSparseMatrix and adding - a JacobianFinalizer template parameter to the ProgramEvaluator. + When Eigen is not installed, Solver::IsValid was not detecting + it correctly. - Change-Id: Ia5a8a9523fdae8d5b027bc35e70b4611ec2a8d01 + Change-Id: Id285a84d829a9e20bc5de663adfca66ac31e08f3 -commit 2569076ff0bf8ffb3938da8b5df7edc4883aa053 +commit 62a8d64453ee41dae56710a4eead3fadf2fe1a4e Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Fri Apr 25 23:54:48 2014 -0700 +Date: Wed Aug 27 22:54:00 2014 -0700 - More NDK fixes. + Expand check for lack of a sparse linear algebra library. - Fix variable names in port.h and fix fpclassify when - using gnustl. This was tested by switching to gnustl - in the JNI build. + The LinearSolver factory was creating a NULL linear solver + if only Eigen's sparse linear algebra backend was available. - Thanks to Carlos Hernandez for suggesting the gnustl fixes. + Thanks to Michael Samples and Domink Reitzle for reporting this. - Change-Id: I690b73caf495ccc79061f45288e416da1604cc72 + Change-Id: I35e3a6c0fd0da2a31934adb5dfe4cad29577cc73 -commit e55596f8860a09b12b5e1f949237f15357c1ac59 +commit 12eb389b4ec4113a2260c1a192a1d3f8d1b6a2d3 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Fri Apr 25 16:17:19 2014 -0700 +Date: Wed Aug 27 22:18:33 2014 -0700 - Change the defaults for shared_ptr. + Fix Eigen Row/ColMajor bug in NumericDiffCostFunction. - By default shared_ptr is now assumed to be - in the standard <memory> header and in the - std namespace. + If the parameter block size is 1, asking Eigen to create + a row-major matrix triggers a compile time error. Previously + we were handling the case where the number of rows in the + jacobian block was known statically, but the problem is present + when the nummber of rows is dynamic. - Previously the way the ifdefs were structured if the appropriate - variable was not defined, it would default to <t1/memory>. + This CL fixes this problem. - The new defaults are more future proof. + Thanks to Dominik Reitzle for reporting this. - Change-Id: If457806191196be2b6425b8289ea7a3488a27445 + Change-Id: I99c3eec3558e66ebf4efa51c4dee8ce292ffe0c1 -commit bb05be341b8436f611e4b69954a529edcca5b577 -Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Sun Apr 13 14:22:19 2014 -0700 +commit 6c25185bb1643d8d0f3d8e1a7b82a058156aa869 +Author: Alex Stewart <alexs.mac@gmail.com> +Date: Thu Aug 28 16:07:51 2014 +0100 - Solver::Options uses shared_ptr to handle ownership. + Fix crash in Covariance if # threads > 1 requested without OpenMP. - Solver::Options::linear_solver_ordering and - Solver::Options::inner_iteration_ordering - were bare pointers even though Solver::Options took ownership of these - objects. + - Previously if options.num_threads > 1 was given to Covariance compiled + without OpenMP, a CHECK() would be triggered in program_evalutor. - This lead to buggy user code and the inability to copy Solver::Options - objects around. - - With this change, these naked pointers have been replaced by a - shared_ptr object which will managed the lifetime of these objects. This - also leads to simplification of the lifetime handling of these objects - inside the solver. + Change-Id: Iaade4f5ed5326b0c59a7014c750c41ee026e1124 + +commit 6f89d850fb4ace0104abccf467c4fe37ad378b79 +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Wed Aug 27 11:51:50 2014 -0700 + + Further build breakage fixes. - The Android.mk and Application.mk files have also been updated - to use a newer NDK revision which ships with LLVM's libc++. + 1. Allow the minimum number of linear solver iterations to be zero. + 2. Fix conjugate gradients solver's iteration loop to be sane again. - Change-Id: I25161fb3ddf737be0b3e5dfd8e7a0039b22548cd + Change-Id: I8594815fec940c2b30e28eb58ec5d8baacf13dae -commit 8e0991381ea3a2baddea017cd07b333f0c5de595 -Author: Joydeep Biswas <joydeep.biswas@gmail.com> -Date: Tue Apr 22 10:40:47 2014 -0400 +commit dd596d0f0d6d08951efc2c11a639b546db2080c6 +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Wed Aug 27 11:26:50 2014 -0700 - Added a simplified robotics example for DynamicAutoDiffCostFunction. + Fix the broken build. - Change-Id: I9520e0a9a8d9743285c5114523fbafa6ffa5b0bd + Change-Id: I083cf1cca1bf4cca956193022d450364e73f833a -commit cc9d3bba1008066e51502cabd956985c6bdedfe8 +commit d906afae22b05b9b9a9a2657924f4c0bf1a9b5ea Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Fri Apr 18 22:58:09 2014 -0700 +Date: Mon Aug 25 22:32:38 2014 -0700 - Remove a comment from conf.py + A number of bug fixes. + + 1. Fix a build breakage in graph_test. + 2. Respect Solver::Options::min_num_linear_solver_iterations in + conjugate_gradients_solver.cc - Change-Id: I675f7e8fc5dd2143eab74901bc7241e02e37285f + Thanks to Johannes Schönberger for reporting these. + + Change-Id: Ib32e3929bf5d92dd576ae5b53d4d88797095136e -commit c4cd29dd7c80ade5b3ac7a1f6ee7df22c8869ab5 +commit dab955928c6d0942d6acc5b5f1c4c11260d0767d Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Wed Apr 16 23:40:12 2014 -0700 +Date: Sun Aug 17 13:14:50 2014 -0700 - Merge landing page with introduction. + Add an unweighted graph. - The existing introduction was a bit redundant and also - was not really an introduction. Also updated the build - instructions to reflect the new reality on Mac OSX. + Rename Graph -> WeightedGraph. + Add a new Graph class, which is cheaper to construct and + work with if the weights are not needed. - Also updated the beginning of the tutorial to be a bit - gentler and updated the history to be more consistent + This cuts down the cost of building the Hessian graph + significantly. - Change-Id: Ife38c1949252cf9f4c6301856957f2d38365f313 + Change-Id: Id0cfc81dd2c0bb5ff8f63a1b55aa133c53c0c869 -commit 46ccfb376ac52ac159f9187e0f7384ef68c1cbdd +commit a0c282adbd268c2ad82551fab31fe1cf8d0c4282 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Sat Apr 12 21:56:51 2014 -0700 +Date: Sun Aug 24 22:19:03 2014 -0700 - Cleanup block_structure.h/cc + Add EIGEN_STRONG_INLINE annotation to jet.h - 1. Remove obsolete Proto conversion functions. - 2. Fix a strict weak ordering bug. + This improves performance when using MSVC on Windows. On GCC + there will be no effect. - Change-Id: I1ce6d4b06e29cf475df1d5bd37c79f66f20f8d93 + Change-Id: I555a81ff6823c2855d64773073f75af50c48d716 -commit 7d489fdb073937ac05c0693c1902fbcb9eeb7dfc -Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Mon Apr 7 11:14:51 2014 -0700 +commit 20de0a7793c574e964350a623446136889f74632 +Author: Björn Piltz <bjornpiltz@gmail.com> +Date: Mon Aug 25 17:05:54 2014 +0200 - Refactor the landing page to be a bit more compact. + Fixed Malformed regex - Also minor changes to the introduction. + I got the following error with MSVC: + Syntax error at index 9 in simple regular expression "NumGroups()": '(' is unsupported. - Change-Id: Iaa71f576b95c869f075d6837dbb60ba4bb608ee7 + Change-Id: Id1952831d81d3eb5d73bbed8c311914c4c8ab51f -commit 406ac7816730c15425db20d994ac0d60d932ab6c -Author: Keir Mierle <mierle@gmail.com> -Date: Mon Apr 7 08:36:07 2014 +0000 +commit ccf8aea988269841d84d746e52164d5056c67a10 +Author: Björn Piltz <bjornpiltz@gmail.com> +Date: Mon Aug 25 16:16:01 2014 +0200 - Rework Ceres documentation as new website + Fixed MSVC error C2124: divide or mod by zero - This reworks the Ceres Sphinx documentation such that it can - function as the main Ceres website, now hosted at - ceres-solver.org. This also changes to the theme sphinx_rtd_theme - used by Read The Docs; this theme has strong mobile support and is - well enough designed. + Alternatively, if quiet_NaN is not available on all platforms a workaround would be: + volatile double zero = 0.0; + double x = 1.0/zero; + The 'volatile' is needed to shut up "warning C4723: potential divide by 0". - Change-Id: I63232d985859a6dac94ff58f08bf81eb2b9e7f99 + Change-Id: If2bbdab8540595aa2e0079e1eb6b6fed6d4a6ef7 -commit 3e60a998ac970da659d590bac2ff892ee619aa1b -Author: Richard Bowen <rsbowen@google.com> -Date: Tue Apr 1 16:22:49 2014 -0700 +commit 8de27be218d42b282d7f15867733ad07058b0887 +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Tue Aug 19 08:22:40 2014 -0700 - Added support and tests: row and column blocks for sparse matrix - transpose. + Fix a bug in TrustRegionPreprocessor + + TrustRegionPreprocessor was not setting Minimizer::Options::is_constrained. + This meant that the line search for bounds constraints was not being + invoked for bounds constrained problems. - Change-Id: Ife641b08a9e86826478521a405f21ba60667f0e8 + And some minor lint cleanup. + + Change-Id: I18852cfaf1b33fd90b7d8c196f2063c128126658 -commit 5ecb1c3f1dfde6e8ed4b493eafef7b43dad19e72 +commit 1745dd615b3897a3ef9896acfdba67eee1739bf4 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Tue Apr 1 09:20:35 2014 -0700 +Date: Thu Jun 5 21:30:13 2014 -0700 - Add Problem::IsParameterBlockPresent. + Refactor SolverImpl. + + Replace SolverImpl with + + a. A minimizer specific preprocessor class. + b. A generic Solve function inside solver.cc + c. Presummarize and Postsummarize functions to handle + updates to the summary object. - This allows the user to query the Problem to see if a - parameter block is already present or not. + The existing SolverImpl class was a mixture of the above three + things and was increasingly complicated code to follow. This change, + breaks it into its three separate constituents, with the aims of + better separation of concerns and thus better testability and + reliability. - Change-Id: If786f6c008cc644f3398597901d718d12a6d865d + The call to Solver::Solve() now consists of + + 1. Presummarize - summarize the given state of the problem and solver + options. + 2. Preprocess - Setup everything that is needed to call the minimizer. + This includes, removing redundant parameter and residual blocks, + setting up the reordering for the linear solver, creating the + linear solver, evaluator, inner iteration minimizer etc. + 3. Minimize. + 4. Post summarize - summarize the result of the preprocessing and the + solve. + + Change-Id: I80f35cfc9f2cbf78f1df4aceace27075779d8a3a -commit 75e2232b29ff2ea42c8406c9d45b138a7e7a0048 +commit bd90384226a7f8629467f72fc410a9e8086a2dff Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Fri Mar 28 11:21:02 2014 -0700 +Date: Mon Aug 18 11:27:06 2014 -0700 - Fix spacing in building.rst + Lint comments from William Rucklidge. + + Also some minor refactoring of the trust_region_preprocessor_test.cc - Change-Id: I4c68d732c80d7ff2bdbc812bf0b7c7fb98c43957 + Change-Id: Ica28002254c95722faf93a7ef35bf3deab557f0b -commit b555b489b8447434294a8a6676272289140d6a1d -Author: Richard Bowen <rsbowen@google.com> -Date: Thu Mar 27 15:51:28 2014 -0700 +commit 3150321db4a0cb1bb4894961a030d95dacae3591 +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Tue Aug 12 22:46:51 2014 -0700 - Changes documentation to reflect changes in output format. + Preprocessor for the LineSearchMinimizer. - Change-Id: Ic0ba234283e791edcad29aec067905dcb2130813 + Change-Id: Ieb5dfe1c0b96ef323c1130edd0c3a8a8b2c644cc -commit 1cfb600bfc3be8342f85f155b2b219a595ee58da +commit f7da411ef0d0067e269629887d64cdb769368800 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Wed Mar 26 12:55:11 2014 -0700 +Date: Thu Aug 7 14:30:33 2014 -0700 - Add the (2,4,9) template specialization for PartitionedMatrixView - and SchurEliminator. + Preprocessor for the TrustRegionMinimizer. - Also update the comment inside generate_partitioned_matrix_view_specializations.py + 1. Base class for preprocessors. + 2. A preprocessor for problems that will be solved using + the trust region minimizer. + 3. Added sanity tests to the program reordering options + for Schur type linear solvers. + 4. Tests for the TrustRegionPreprocessor. - Change-Id: I99a7ab4256091b1da48553da3076e5996a5757ed + Change-Id: I88cd926f0053bbbf2bd6b11e03ec55b8bf473cf1 -commit 195e49351b386ffc23020d406883eaa6511e29b3 +commit 54893ba523106e38ab06eb72fb5d8748685c7797 Author: Alex Stewart <alexs.mac@gmail.com> -Date: Wed Mar 26 11:36:11 2014 +0000 +Date: Mon Aug 11 19:04:18 2014 +0100 - Check validity of residual block before removal in RemoveResidualBlock. - - - Breaking change: Problem::Options::enable_fast_parameter_block_removal - is now Problem::Options::enable_fast_removal, as it now controls - the behaviour for both parameter and residual blocks. - - - Previously we did not check that the specified residual block to - remove in RemoveResidualBlock actually represented a valid residual - for the problem. - - This meant that Ceres would die unexpectedly if the user passed an - uninitialised residual_block, or more likely attempted to remove a - residual block that had already been removed automatically after - the user removed a parameter block upon on which it was dependent. - - RemoveResidualBlock now verifies the validity of the given - residual_block to remove. Either by checking against a hash set of - all residuals maintained in ProblemImpl iff enable_fast_removal - is enabled. Or by a full scan of the residual blocks if not. + Add missing #include of <limits> for loss functions. - Change-Id: I9ab178e2f68a74135f0a8e20905b16405c77a62b + Change-Id: Id632451429e03031a1533a9be795270debc70706 -commit 74762b60332d4a1c08ec5aef75ec718da9d305a2 -Author: Alex Stewart <alexs.mac@gmail.com> -Date: Thu Mar 20 14:50:25 2014 +0000 +commit 4a2a888905fd1ce7203e45df15762d52740bb240 +Author: Sameer Agarwal <sameeragarwal@google.com> +Date: Thu Aug 7 11:48:03 2014 -0700 - Allow construction of an AutoDiffLocalParameterization with a functor. + Change ownership of pointers in Minimizer::Options. + + This is a intermediate change to clean things up + in preparation for a broader refactoring of the SolverImpl. - - Previously AutoDiffLocalParameterization would internally instantiate - a functor instance whenever one was required. This prohibits the - user passing arguments to the constructor of the functor. - - Now AutoDiffLocalParameterization can take over ownership of an - allocated functor which the user created. This mimics the behaviour - of AutoDiffCostFunction. + Essentially we are replacing raw pointers in Minimizer::Options + with shared_ptr objects. For now this only makes things a bit + more complicated looking inside solver_impl.cc, but going + forward this will lead to considerable simplifications in + tracking ownership of various pointers. - Change-Id: I264e1face44ca5d5e71cc20c77cc7654d3f74cc0 + Change-Id: I21db8fc6763c29b0d15e834d7c968a0f514042a0 -commit 4f603fb0d82317a53fa9d96abe6a97b2e69bff36 +commit 0d4e3bd664d442b700fee2895c7a8ac37717dc08 Author: Sameer Agarwal <sameeragarwal@google.com> -Date: Wed Mar 19 17:16:43 2014 -0700 +Date: Thu Aug 7 12:19:10 2014 -0700 - Grammer fixes from William Rucklidge. + GradientCheckingProblem's parameter blocks are initialized correctly. + + Ensure that when a new problem object is constructed for validing + gradients, the parameter blocks have their data pointers point to + the user's parameter blocks. + + We used to do this inside solver_impl.cc, but doing this at + construction is the right thing to do. - Change-Id: Ia40df7a1d141eb2552694510453d1431bb0c8dce + Change-Id: I3bfdc89bb0027c8d67cde937e8f2fa385d89c30c diff --git a/extern/libmv/third_party/ceres/SConscript b/extern/libmv/third_party/ceres/SConscript index 573157cb770..f53d54ba94b 100644 --- a/extern/libmv/third_party/ceres/SConscript +++ b/extern/libmv/third_party/ceres/SConscript @@ -13,15 +13,17 @@ src = [] defs = [] src += env.Glob('internal/ceres/*.cc') -src += env.Glob('internal/ceres/generated/schur_eliminator_d_d_d.cc') -src += env.Glob('internal/ceres/generated/partitioned_matrix_view_d_d_d.cc') -#src += env.Glob('internal/ceres/generated/*.cc') +if env['WITH_BF_LIBMV_SCHUR_SPECIALIZATIONS']: + src += env.Glob('internal/ceres/generated/*.cc') +else: + src += env.Glob('internal/ceres/generated/schur_eliminator_d_d_d.cc') + src += env.Glob('internal/ceres/generated/partitioned_matrix_view_d_d_d.cc') + defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION') defs.append('CERES_HAVE_PTHREAD') defs.append('CERES_NO_SUITESPARSE') defs.append('CERES_NO_CXSPARSE') defs.append('CERES_NO_LAPACK') -defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION') defs.append('CERES_HAVE_RWLOCK') if env['WITH_BF_OPENMP']: @@ -50,11 +52,6 @@ if env['SHARED_PTR_NAMESPACE'] == 'std::tr1': incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags ./config' -# work around broken hashtable in 10.5 SDK -if env['OURPLATFORM'] == 'darwin' and env['WITH_BF_BOOST']: - incs += ' ' + env['BF_BOOST_INC'] - defs.append('CERES_HASH_BOOST') - if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): incs += ' ../msinttypes' diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh index e7239d9a823..51a463a18ad 100755 --- a/extern/libmv/third_party/ceres/bundle.sh +++ b/extern/libmv/third_party/ceres/bundle.sh @@ -46,7 +46,7 @@ rm -rf $tmp sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | \ grep -v -E 'schur_eliminator_[0-9]_[0-9d]_[0-9d].cc' | \ grep -v -E 'partitioned_matrix_view_[0-9]_[0-9d]_[0-9d].cc' | sort -d` -generated_sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//#\t\t/' | \ +generated_sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t\t/' | \ grep -E 'schur_eliminator_[0-9]_[0-9d]_[0-9d].cc|partitioned_matrix_view_[0-9]_[0-9d]_[0-9d].cc' | sort -d` headers=`find ./include ./internal -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d` @@ -138,11 +138,13 @@ ${sources} ${headers} ) -#if(FALSE) -# list(APPEND SRC +if(WITH_LIBMV_SCHUR_SPECIALIZATIONS) + list(APPEND SRC ${generated_sources} -# ) -#endif() + ) +else() + add_definitions-DCERES_RESTRICT_SCHUR_SPECIALIZATION) +endif() if(WIN32) list(APPEND INC @@ -165,7 +167,6 @@ add_definitions( -DCERES_NO_SUITESPARSE -DCERES_NO_CXSPARSE -DCERES_NO_LAPACK - -DCERES_RESTRICT_SCHUR_SPECIALIZATION -DCERES_HAVE_RWLOCK ) @@ -215,15 +216,17 @@ src = [] defs = [] $src -src += env.Glob('internal/ceres/generated/schur_eliminator_d_d_d.cc') -src += env.Glob('internal/ceres/generated/partitioned_matrix_view_d_d_d.cc') -#src += env.Glob('internal/ceres/generated/*.cc') +if env['WITH_BF_LIBMV_SCHUR_SPECIALIZATIONS']: + src += env.Glob('internal/ceres/generated/*.cc') +else: + src += env.Glob('internal/ceres/generated/schur_eliminator_d_d_d.cc') + src += env.Glob('internal/ceres/generated/partitioned_matrix_view_d_d_d.cc') + defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION') defs.append('CERES_HAVE_PTHREAD') defs.append('CERES_NO_SUITESPARSE') defs.append('CERES_NO_CXSPARSE') defs.append('CERES_NO_LAPACK') -defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION') defs.append('CERES_HAVE_RWLOCK') if env['WITH_BF_OPENMP']: @@ -252,11 +255,6 @@ if env['SHARED_PTR_NAMESPACE'] == 'std::tr1': incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags ./config' -# work around broken hashtable in 10.5 SDK -if env['OURPLATFORM'] == 'darwin' and env['WITH_BF_BOOST']: - incs += ' ' + env['BF_BOOST_INC'] - defs.append('CERES_HASH_BOOST') - if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): incs += ' ../msinttypes' diff --git a/extern/libmv/third_party/ceres/files.txt b/extern/libmv/third_party/ceres/files.txt index 164681d4d34..d1bd69672c8 100644 --- a/extern/libmv/third_party/ceres/files.txt +++ b/extern/libmv/third_party/ceres/files.txt @@ -11,13 +11,17 @@ include/ceres/dynamic_autodiff_cost_function.h include/ceres/dynamic_numeric_diff_cost_function.h include/ceres/fpclassify.h include/ceres/gradient_checker.h +include/ceres/gradient_problem.h +include/ceres/gradient_problem_solver.h include/ceres/internal/autodiff.h +include/ceres/internal/disable_warnings.h include/ceres/internal/eigen.h include/ceres/internal/fixed_array.h include/ceres/internal/macros.h include/ceres/internal/manual_constructor.h include/ceres/internal/numeric_diff.h include/ceres/internal/port.h +include/ceres/internal/reenable_warnings.h include/ceres/internal/scoped_ptr.h include/ceres/internal/variadic_evaluate.h include/ceres/iteration_callback.h @@ -26,13 +30,13 @@ include/ceres/local_parameterization.h include/ceres/loss_function.h include/ceres/normal_prior.h include/ceres/numeric_diff_cost_function.h -include/ceres/numeric_diff_functor.h include/ceres/ordered_groups.h include/ceres/problem.h include/ceres/rotation.h include/ceres/sized_cost_function.h include/ceres/solver.h include/ceres/types.h +include/ceres/version.h internal/ceres/array_utils.cc internal/ceres/array_utils.h internal/ceres/blas.cc @@ -55,6 +59,8 @@ internal/ceres/block_sparse_matrix.cc internal/ceres/block_sparse_matrix.h internal/ceres/block_structure.cc internal/ceres/block_structure.h +internal/ceres/callbacks.cc +internal/ceres/callbacks.h internal/ceres/canonical_views_clustering.cc internal/ceres/canonical_views_clustering.h internal/ceres/c_api.cc @@ -62,7 +68,6 @@ internal/ceres/casts.h internal/ceres/cgnr_linear_operator.h internal/ceres/cgnr_solver.cc internal/ceres/cgnr_solver.h -internal/ceres/CMakeLists.txt internal/ceres/collections_port.h internal/ceres/compressed_col_sparse_matrix_utils.cc internal/ceres/compressed_col_sparse_matrix_utils.h @@ -145,6 +150,9 @@ internal/ceres/generate_eliminator_specialization.py internal/ceres/generate_partitioned_matrix_view_specializations.py internal/ceres/gradient_checking_cost_function.cc internal/ceres/gradient_checking_cost_function.h +internal/ceres/gradient_problem.cc +internal/ceres/gradient_problem_evaluator.h +internal/ceres/gradient_problem_solver.cc internal/ceres/graph_algorithms.h internal/ceres/graph.h internal/ceres/implicit_schur_complement.cc @@ -170,6 +178,8 @@ internal/ceres/line_search_direction.h internal/ceres/line_search.h internal/ceres/line_search_minimizer.cc internal/ceres/line_search_minimizer.h +internal/ceres/line_search_preprocessor.cc +internal/ceres/line_search_preprocessor.h internal/ceres/local_parameterization.cc internal/ceres/loss_function.cc internal/ceres/low_rank_inverse_hessian.cc @@ -189,6 +199,8 @@ internal/ceres/polynomial.cc internal/ceres/polynomial.h internal/ceres/preconditioner.cc internal/ceres/preconditioner.h +internal/ceres/preprocessor.cc +internal/ceres/preprocessor.h internal/ceres/problem.cc internal/ceres/problem_impl.cc internal/ceres/problem_impl.h @@ -196,6 +208,8 @@ internal/ceres/program.cc internal/ceres/program_evaluator.h internal/ceres/program.h internal/ceres/random.h +internal/ceres/reorder_program.cc +internal/ceres/reorder_program.h internal/ceres/residual_block.cc internal/ceres/residual_block.h internal/ceres/residual_block_utils.cc @@ -213,8 +227,8 @@ internal/ceres/single_linkage_clustering.cc internal/ceres/single_linkage_clustering.h internal/ceres/small_blas.h internal/ceres/solver.cc -internal/ceres/solver_impl.cc -internal/ceres/solver_impl.h +internal/ceres/solver_utils.cc +internal/ceres/solver_utils.h internal/ceres/sparse_matrix.cc internal/ceres/sparse_matrix.h internal/ceres/sparse_normal_cholesky_solver.cc @@ -230,6 +244,8 @@ internal/ceres/triplet_sparse_matrix.cc internal/ceres/triplet_sparse_matrix.h internal/ceres/trust_region_minimizer.cc internal/ceres/trust_region_minimizer.h +internal/ceres/trust_region_preprocessor.cc +internal/ceres/trust_region_preprocessor.h internal/ceres/trust_region_strategy.cc internal/ceres/trust_region_strategy.h internal/ceres/types.cc diff --git a/extern/libmv/third_party/ceres/include/ceres/c_api.h b/extern/libmv/third_party/ceres/include/ceres/c_api.h index 632542e9bdd..71f41fd226b 100644 --- a/extern/libmv/third_party/ceres/include/ceres/c_api.h +++ b/extern/libmv/third_party/ceres/include/ceres/c_api.h @@ -39,6 +39,7 @@ #define CERES_PUBLIC_C_API_H_ #include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" #ifdef __cplusplus extern "C" { @@ -140,4 +141,6 @@ CERES_EXPORT void ceres_solve(ceres_problem_t* problem); } #endif +#include "ceres/internal/reenable_warnings.h" + #endif /* CERES_PUBLIC_C_API_H_ */ diff --git a/extern/libmv/third_party/ceres/include/ceres/ceres.h b/extern/libmv/third_party/ceres/include/ceres/ceres.h index acb402c542d..7c8981e2994 100644 --- a/extern/libmv/third_party/ceres/include/ceres/ceres.h +++ b/extern/libmv/third_party/ceres/include/ceres/ceres.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// Copyright 2014 Google Inc. All rights reserved. // http://code.google.com/p/ceres-solver/ // // Redistribution and use in source and binary forms, with or without @@ -34,9 +34,6 @@ #ifndef CERES_PUBLIC_CERES_H_ #define CERES_PUBLIC_CERES_H_ -#define CERES_VERSION 1.9.0 -#define CERES_ABI_VERSION 1.9.0 - #include "ceres/autodiff_cost_function.h" #include "ceres/autodiff_local_parameterization.h" #include "ceres/cost_function.h" @@ -45,16 +42,18 @@ #include "ceres/crs_matrix.h" #include "ceres/dynamic_autodiff_cost_function.h" #include "ceres/dynamic_numeric_diff_cost_function.h" +#include "ceres/gradient_problem.h" +#include "ceres/gradient_problem_solver.h" #include "ceres/iteration_callback.h" #include "ceres/jet.h" #include "ceres/local_parameterization.h" #include "ceres/loss_function.h" #include "ceres/numeric_diff_cost_function.h" -#include "ceres/numeric_diff_functor.h" #include "ceres/ordered_groups.h" #include "ceres/problem.h" #include "ceres/sized_cost_function.h" #include "ceres/solver.h" #include "ceres/types.h" +#include "ceres/version.h" #endif // CERES_PUBLIC_CERES_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h index 2a12ba6fe37..3f0087c7815 100644 --- a/extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h +++ b/extern/libmv/third_party/ceres/include/ceres/conditioned_cost_function.h @@ -39,6 +39,7 @@ #include "ceres/cost_function.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -93,5 +94,6 @@ class CERES_EXPORT ConditionedCostFunction : public CostFunction { } // namespace ceres +#include "ceres/internal/reenable_warnings.h" #endif // CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/cost_function.h b/extern/libmv/third_party/ceres/include/ceres/cost_function.h index fee3e73c111..fe8fc07d2ce 100644 --- a/extern/libmv/third_party/ceres/include/ceres/cost_function.h +++ b/extern/libmv/third_party/ceres/include/ceres/cost_function.h @@ -48,6 +48,7 @@ #include "ceres/internal/macros.h" #include "ceres/internal/port.h" #include "ceres/types.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -105,8 +106,7 @@ class CERES_EXPORT CostFunction { // the constraints, then returning false whenever the constraints // are not satisfied will prevent the solver from moving into the // infeasible region. This is not a very sophisticated mechanism for - // enforcing constraints, but is often good enough for things like - // non-negativity constraints. + // enforcing constraints, but is often good enough. // // Note that it is important that the initial values of the // parameter block must be feasible, otherwise the solver will @@ -142,4 +142,6 @@ class CERES_EXPORT CostFunction { } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_PUBLIC_COST_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/cost_function_to_functor.h b/extern/libmv/third_party/ceres/include/ceres/cost_function_to_functor.h index 0d01f772a3b..b4a516e0ab1 100644 --- a/extern/libmv/third_party/ceres/include/ceres/cost_function_to_functor.h +++ b/extern/libmv/third_party/ceres/include/ceres/cost_function_to_functor.h @@ -107,9 +107,7 @@ class CostFunctionToFunctor { explicit CostFunctionToFunctor(CostFunction* cost_function) : cost_function_(cost_function) { CHECK_NOTNULL(cost_function); - - CHECK_GE(kNumResiduals, 0); - CHECK_EQ(cost_function->num_residuals(), kNumResiduals); + CHECK(kNumResiduals > 0 || kNumResiduals == DYNAMIC); // This block breaks the 80 column rule to keep it somewhat readable. CHECK((!N1 && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) || diff --git a/extern/libmv/third_party/ceres/include/ceres/covariance.h b/extern/libmv/third_party/ceres/include/ceres/covariance.h index b6e9a6ae392..35fde4de05d 100644 --- a/extern/libmv/third_party/ceres/include/ceres/covariance.h +++ b/extern/libmv/third_party/ceres/include/ceres/covariance.h @@ -36,6 +36,7 @@ #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -201,9 +202,9 @@ class CERES_EXPORT Covariance { struct CERES_EXPORT Options { Options() #ifndef CERES_NO_SUITESPARSE - : algorithm_type(SPARSE_QR), + : algorithm_type(SUITE_SPARSE_QR), #else - : algorithm_type(DENSE_SVD), + : algorithm_type(EIGEN_SPARSE_QR), #endif min_reciprocal_condition_number(1e-14), null_space_rank(0), @@ -228,47 +229,22 @@ class CERES_EXPORT Covariance { // for small to moderate sized problems. It can handle // full-rank as well as rank deficient Jacobians. // - // 2. SPARSE_CHOLESKY uses the CHOLMOD sparse Cholesky - // factorization library to compute the decomposition : - // - // R'R = J'J - // - // and then - // - // [J'J]^-1 = [R'R]^-1 - // - // It a fast algorithm for sparse matrices that should be used - // when the Jacobian matrix J is well conditioned. For - // ill-conditioned matrices, this algorithm can fail - // unpredictabily. This is because Cholesky factorization is - // not a rank-revealing factorization, i.e., it cannot reliably - // detect when the matrix being factorized is not of full - // rank. SuiteSparse/CHOLMOD supplies a heuristic for checking - // if the matrix is rank deficient (cholmod_rcond), but it is - // only a heuristic and can have both false positive and false - // negatives. - // - // Recent versions of SuiteSparse (>= 4.2.0) provide a much - // more efficient method for solving for rows of the covariance - // matrix. Therefore, if you are doing SPARSE_CHOLESKY, we - // strongly recommend using a recent version of SuiteSparse. - // - // 3. SPARSE_QR uses the SuiteSparseQR sparse QR factorization - // library to compute the decomposition + // 2. EIGEN_SPARSE_QR uses the sparse QR factorization algorithm + // in Eigen to compute the decomposition // // Q * R = J // // [J'J]^-1 = [R*R']^-1 // - // It is a moderately fast algorithm for sparse matrices, which - // at the price of more time and memory than the - // SPARSE_CHOLESKY algorithm is numerically better behaved and - // is rank revealing, i.e., it can reliably detect when the - // Jacobian matrix is rank deficient. + // It is a moderately fast algorithm for sparse matrices. // - // Neither SPARSE_CHOLESKY or SPARSE_QR are capable of computing - // the covariance if the Jacobian is rank deficient. - + // 3. SUITE_SPARSE_QR uses the SuiteSparseQR sparse QR + // factorization algorithm. It uses dense linear algebra and is + // multi threaded, so for large sparse sparse matrices it is + // significantly faster than EIGEN_SPARSE_QR. + // + // Neither EIGEN_SPARSE_QR not SUITE_SPARSE_QR are capable of + // computing the covariance if the Jacobian is rank deficient. CovarianceAlgorithmType algorithm_type; // If the Jacobian matrix is near singular, then inverting J'J @@ -294,29 +270,13 @@ class CERES_EXPORT Covariance { // where min_sigma and max_sigma are the minimum and maxiumum // singular values of J respectively. // - // 2. SPARSE_CHOLESKY - // - // cholmod_rcond < min_reciprocal_conditioner_number - // - // Here cholmod_rcond is a crude estimate of the reciprocal - // condition number of J'J by using the maximum and minimum - // diagonal entries of the Cholesky factor R. There are no - // theoretical guarantees associated with this test. It can - // give false positives and negatives. Use at your own - // risk. The default value of min_reciprocal_condition_number - // has been set to a conservative value, and sometimes the - // Covariance::Compute may return false even if it is possible - // to estimate the covariance reliably. In such cases, the user - // should exercise their judgement before lowering the value of - // min_reciprocal_condition_number. - // - // 3. SPARSE_QR + // 2. SUITE_SPARSE_QR and EIGEN_SPARSE_QR // // rank(J) < num_col(J) // // Here rank(J) is the estimate of the rank of J returned by the - // SuiteSparseQR algorithm. It is a fairly reliable indication - // of rank deficiency. + // sparse QR factorization algorithm. It is a fairly reliable + // indication of rank deficiency. // double min_reciprocal_condition_number; @@ -351,8 +311,8 @@ class CERES_EXPORT Covariance { // // lambda_i / lambda_max < min_reciprocal_condition_number. // - // This option has no effect on the SPARSE_CHOLESKY or SPARSE_QR - // algorithms. + // This option has no effect on the SUITE_SPARSE_QR and + // EIGEN_SPARSE_QR algorithms. int null_space_rank; int num_threads; @@ -419,4 +379,6 @@ class CERES_EXPORT Covariance { } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_PUBLIC_COVARIANCE_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h b/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h index 687c9586dfd..d2d62894194 100644 --- a/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h +++ b/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h @@ -33,6 +33,7 @@ #include <vector> #include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -80,4 +81,6 @@ struct CERES_EXPORT CRSMatrix { } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_PUBLIC_CRS_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/gradient_problem.h b/extern/libmv/third_party/ceres/include/ceres/gradient_problem.h new file mode 100644 index 00000000000..55a8be1df09 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/gradient_problem.h @@ -0,0 +1,127 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_PUBLIC_GRADIENT_PROBLEM_H_ +#define CERES_PUBLIC_GRADIENT_PROBLEM_H_ + +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/local_parameterization.h" + +namespace ceres { + +class FirstOrderFunction; + +// Instances of GradientProblem represent general non-linear +// optimization problems that must be solved using just the value of +// the objective function and its gradient. Unlike the Problem class, +// which can only be used to model non-linear least squares problems, +// instances of GradientProblem not restricted in the form of the +// objective function. +// +// Structurally GradientProblem is a composition of a +// FirstOrderFunction and optionally a LocalParameterization. +// +// The FirstOrderFunction is responsible for evaluating the cost and +// gradient of the objective function. +// +// The LocalParameterization is responsible for going back and forth +// between the ambient space and the local tangent space. (See +// local_parameterization.h for more details). When a +// LocalParameterization is not provided, then the tangent space is +// assumed to coincide with the ambient Euclidean space that the +// gradient vector lives in. +// +// Example usage: +// +// The following demonstrate the problem construction for Rosenbrock's function +// +// f(x,y) = (1-x)^2 + 100(y - x^2)^2; +// +// class Rosenbrock : public ceres::FirstOrderFunction { +// public: +// virtual ~Rosenbrock() {} +// +// virtual bool Evaluate(const double* parameters, +// double* cost, +// double* gradient) const { +// const double x = parameters[0]; +// const double y = parameters[1]; +// +// cost[0] = (1.0 - x) * (1.0 - x) + 100.0 * (y - x * x) * (y - x * x); +// if (gradient != NULL) { +// gradient[0] = -2.0 * (1.0 - x) - 200.0 * (y - x * x) * 2.0 * x; +// gradient[1] = 200.0 * (y - x * x); +// } +// return true; +// }; +// +// virtual int NumParameters() const { return 2; }; +// }; +// +// ceres::GradientProblem problem(new Rosenbrock()); +class CERES_EXPORT GradientProblem { + public: + // Takes ownership of the function. + explicit GradientProblem(FirstOrderFunction* function); + + // Takes ownership of the function and the parameterization. + GradientProblem(FirstOrderFunction* function, + LocalParameterization* parameterization); + + int NumParameters() const; + int NumLocalParameters() const; + + // This call is not thread safe. + bool Evaluate(const double* parameters, double* cost, double* gradient) const; + bool Plus(const double* x, const double* delta, double* x_plus_delta) const; + + private: + internal::scoped_ptr<FirstOrderFunction> function_; + internal::scoped_ptr<LocalParameterization> parameterization_; + internal::scoped_array<double> scratch_; +}; + +// A FirstOrderFunction object implements the evaluation of a function +// and its gradient. +class CERES_EXPORT FirstOrderFunction { + public: + virtual ~FirstOrderFunction() {} + // cost is never NULL. gradient may be null. + virtual bool Evaluate(const double* const parameters, + double* cost, + double* gradient) const = 0; + virtual int NumParameters() const = 0; +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_GRADIENT_PROBLEM_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/gradient_problem_solver.h b/extern/libmv/third_party/ceres/include/ceres/gradient_problem_solver.h new file mode 100644 index 00000000000..484d88ece82 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/gradient_problem_solver.h @@ -0,0 +1,365 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_PUBLIC_GRADIENT_PROBLEM_SOLVER_H_ +#define CERES_PUBLIC_GRADIENT_PROBLEM_SOLVER_H_ + +#include <cmath> +#include <string> +#include <vector> +#include "ceres/internal/macros.h" +#include "ceres/internal/port.h" +#include "ceres/iteration_callback.h" +#include "ceres/types.h" +#include "ceres/internal/disable_warnings.h" + +namespace ceres { + +class GradientProblem; + +class CERES_EXPORT GradientProblemSolver { + public: + virtual ~GradientProblemSolver(); + + // The options structure contains, not surprisingly, options that control how + // the solver operates. The defaults should be suitable for a wide range of + // problems; however, better performance is often obtainable with tweaking. + // + // The constants are defined inside types.h + struct CERES_EXPORT Options { + // Default constructor that sets up a generic sparse problem. + Options() { + line_search_direction_type = LBFGS; + line_search_type = WOLFE; + nonlinear_conjugate_gradient_type = FLETCHER_REEVES; + max_lbfgs_rank = 20; + use_approximate_eigenvalue_bfgs_scaling = false; + line_search_interpolation_type = CUBIC; + min_line_search_step_size = 1e-9; + line_search_sufficient_function_decrease = 1e-4; + max_line_search_step_contraction = 1e-3; + min_line_search_step_contraction = 0.6; + max_num_line_search_step_size_iterations = 20; + max_num_line_search_direction_restarts = 5; + line_search_sufficient_curvature_decrease = 0.9; + max_line_search_step_expansion = 10.0; + max_num_iterations = 50; + max_solver_time_in_seconds = 1e9; + num_threads = 1; + function_tolerance = 1e-6; + gradient_tolerance = 1e-10; + logging_type = PER_MINIMIZER_ITERATION; + minimizer_progress_to_stdout = false; + } + + // Returns true if the options struct has a valid + // configuration. Returns false otherwise, and fills in *error + // with a message describing the problem. + bool IsValid(string* error) const; + + // Minimizer options ---------------------------------------- + LineSearchDirectionType line_search_direction_type; + LineSearchType line_search_type; + NonlinearConjugateGradientType nonlinear_conjugate_gradient_type; + + // The LBFGS hessian approximation is a low rank approximation to + // the inverse of the Hessian matrix. The rank of the + // approximation determines (linearly) the space and time + // complexity of using the approximation. Higher the rank, the + // better is the quality of the approximation. The increase in + // quality is however is bounded for a number of reasons. + // + // 1. The method only uses secant information and not actual + // derivatives. + // + // 2. The Hessian approximation is constrained to be positive + // definite. + // + // So increasing this rank to a large number will cost time and + // space complexity without the corresponding increase in solution + // quality. There are no hard and fast rules for choosing the + // maximum rank. The best choice usually requires some problem + // specific experimentation. + // + // For more theoretical and implementation details of the LBFGS + // method, please see: + // + // Nocedal, J. (1980). "Updating Quasi-Newton Matrices with + // Limited Storage". Mathematics of Computation 35 (151): 773–782. + int max_lbfgs_rank; + + // As part of the (L)BFGS update step (BFGS) / right-multiply step (L-BFGS), + // the initial inverse Hessian approximation is taken to be the Identity. + // However, Oren showed that using instead I * \gamma, where \gamma is + // chosen to approximate an eigenvalue of the true inverse Hessian can + // result in improved convergence in a wide variety of cases. Setting + // use_approximate_eigenvalue_bfgs_scaling to true enables this scaling. + // + // It is important to note that approximate eigenvalue scaling does not + // always improve convergence, and that it can in fact significantly degrade + // performance for certain classes of problem, which is why it is disabled + // by default. In particular it can degrade performance when the + // sensitivity of the problem to different parameters varies significantly, + // as in this case a single scalar factor fails to capture this variation + // and detrimentally downscales parts of the jacobian approximation which + // correspond to low-sensitivity parameters. It can also reduce the + // robustness of the solution to errors in the jacobians. + // + // Oren S.S., Self-scaling variable metric (SSVM) algorithms + // Part II: Implementation and experiments, Management Science, + // 20(5), 863-874, 1974. + bool use_approximate_eigenvalue_bfgs_scaling; + + // Degree of the polynomial used to approximate the objective + // function. Valid values are BISECTION, QUADRATIC and CUBIC. + // + // BISECTION corresponds to pure backtracking search with no + // interpolation. + LineSearchInterpolationType line_search_interpolation_type; + + // If during the line search, the step_size falls below this + // value, it is truncated to zero. + double min_line_search_step_size; + + // Line search parameters. + + // Solving the line search problem exactly is computationally + // prohibitive. Fortunately, line search based optimization + // algorithms can still guarantee convergence if instead of an + // exact solution, the line search algorithm returns a solution + // which decreases the value of the objective function + // sufficiently. More precisely, we are looking for a step_size + // s.t. + // + // f(step_size) <= f(0) + sufficient_decrease * f'(0) * step_size + // + double line_search_sufficient_function_decrease; + + // In each iteration of the line search, + // + // new_step_size >= max_line_search_step_contraction * step_size + // + // Note that by definition, for contraction: + // + // 0 < max_step_contraction < min_step_contraction < 1 + // + double max_line_search_step_contraction; + + // In each iteration of the line search, + // + // new_step_size <= min_line_search_step_contraction * step_size + // + // Note that by definition, for contraction: + // + // 0 < max_step_contraction < min_step_contraction < 1 + // + double min_line_search_step_contraction; + + // Maximum number of trial step size iterations during each line search, + // if a step size satisfying the search conditions cannot be found within + // this number of trials, the line search will terminate. + int max_num_line_search_step_size_iterations; + + // Maximum number of restarts of the line search direction algorithm before + // terminating the optimization. Restarts of the line search direction + // algorithm occur when the current algorithm fails to produce a new descent + // direction. This typically indicates a numerical failure, or a breakdown + // in the validity of the approximations used. + int max_num_line_search_direction_restarts; + + // The strong Wolfe conditions consist of the Armijo sufficient + // decrease condition, and an additional requirement that the + // step-size be chosen s.t. the _magnitude_ ('strong' Wolfe + // conditions) of the gradient along the search direction + // decreases sufficiently. Precisely, this second condition + // is that we seek a step_size s.t. + // + // |f'(step_size)| <= sufficient_curvature_decrease * |f'(0)| + // + // Where f() is the line search objective and f'() is the derivative + // of f w.r.t step_size (d f / d step_size). + double line_search_sufficient_curvature_decrease; + + // During the bracketing phase of the Wolfe search, the step size is + // increased until either a point satisfying the Wolfe conditions is + // found, or an upper bound for a bracket containing a point satisfying + // the conditions is found. Precisely, at each iteration of the + // expansion: + // + // new_step_size <= max_step_expansion * step_size. + // + // By definition for expansion, max_step_expansion > 1.0. + double max_line_search_step_expansion; + + // Maximum number of iterations for the minimizer to run for. + int max_num_iterations; + + // Maximum time for which the minimizer should run for. + double max_solver_time_in_seconds; + + // Number of threads used by Ceres for evaluating the cost and + // jacobians. + int num_threads; + + // Minimizer terminates when + // + // (new_cost - old_cost) < function_tolerance * old_cost; + // + double function_tolerance; + + // Minimizer terminates when + // + // max_i |x - Project(Plus(x, -g(x))| < gradient_tolerance + // + // This value should typically be 1e-4 * function_tolerance. + double gradient_tolerance; + + // Logging options --------------------------------------------------------- + + LoggingType logging_type; + + // By default the Minimizer progress is logged to VLOG(1), which + // is sent to STDERR depending on the vlog level. If this flag is + // set to true, and logging_type is not SILENT, the logging output + // is sent to STDOUT. + bool minimizer_progress_to_stdout; + + // If true, the user's parameter blocks are updated at the end of + // every Minimizer iteration, otherwise they are updated when the + // Minimizer terminates. This is useful if, for example, the user + // wishes to visualize the state of the optimization every + // iteration. + bool update_state_every_iteration; + + // Callbacks that are executed at the end of each iteration of the + // Minimizer. An iteration may terminate midway, either due to + // numerical failures or because one of the convergence tests has + // been satisfied. In this case none of the callbacks are + // executed. + + // Callbacks are executed in the order that they are specified in + // this vector. By default, parameter blocks are updated only at + // the end of the optimization, i.e when the Minimizer + // terminates. This behaviour is controlled by + // update_state_every_variable. If the user wishes to have access + // to the update parameter blocks when his/her callbacks are + // executed, then set update_state_every_iteration to true. + // + // The solver does NOT take ownership of these pointers. + vector<IterationCallback*> callbacks; + }; + + struct CERES_EXPORT Summary { + Summary(); + + // A brief one line description of the state of the solver after + // termination. + string BriefReport() const; + + // A full multiline description of the state of the solver after + // termination. + string FullReport() const; + + bool IsSolutionUsable() const; + + // Minimizer summary ------------------------------------------------- + TerminationType termination_type; + + // Reason why the solver terminated. + string message; + + // Cost of the problem (value of the objective function) before + // the optimization. + double initial_cost; + + // Cost of the problem (value of the objective function) after the + // optimization. + double final_cost; + + // IterationSummary for each minimizer iteration in order. + vector<IterationSummary> iterations; + + // Sum total of all time spent inside Ceres when Solve is called. + double total_time_in_seconds; + + // Time (in seconds) spent evaluating the residual vector. + double cost_evaluation_time_in_seconds; + + // Time (in seconds) spent evaluating the jacobian matrix. + double gradient_evaluation_time_in_seconds; + + // Number of parameters in the probem. + int num_parameters; + + // Dimension of the tangent space of the problem. + int num_local_parameters; + + // Type of line search direction used. + LineSearchDirectionType line_search_direction_type; + + // Type of the line search algorithm used. + LineSearchType line_search_type; + + // When performing line search, the degree of the polynomial used + // to approximate the objective function. + LineSearchInterpolationType line_search_interpolation_type; + + // If the line search direction is NONLINEAR_CONJUGATE_GRADIENT, + // then this indicates the particular variant of non-linear + // conjugate gradient used. + NonlinearConjugateGradientType nonlinear_conjugate_gradient_type; + + // If the type of the line search direction is LBFGS, then this + // indicates the rank of the Hessian approximation. + int max_lbfgs_rank; + }; + + // Once a least squares problem has been built, this function takes + // the problem and optimizes it based on the values of the options + // parameters. Upon return, a detailed summary of the work performed + // by the preprocessor, the non-linear minmizer and the linear + // solver are reported in the summary object. + virtual void Solve(const GradientProblemSolver::Options& options, + const GradientProblem& problem, + double* parameters, + GradientProblemSolver::Summary* summary); +}; + +// Helper function which avoids going through the interface. +CERES_EXPORT void Solve(const GradientProblemSolver::Options& options, + const GradientProblem& problem, + double* parameters, + GradientProblemSolver::Summary* summary); + +} // namespace ceres + +#include "ceres/internal/reenable_warnings.h" + +#endif // CERES_PUBLIC_GRADIENT_PROBLEM_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/disable_warnings.h b/extern/libmv/third_party/ceres/include/ceres/internal/disable_warnings.h new file mode 100644 index 00000000000..78924de1346 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/disable_warnings.h @@ -0,0 +1,44 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// This file has the sole purpose to silence warnings when including Ceres. + +// This is not your usual header guard. The macro CERES_WARNINGS_DISABLED +// shows up again in reenable_warnings.h. +#ifndef CERES_WARNINGS_DISABLED +#define CERES_WARNINGS_DISABLED + +#ifdef _MSC_VER +#pragma warning( push ) +// Disable the warning C4251 which is trigerred by stl classes in +// Ceres' public interface. To quote MSDN: "C4251 can be ignored " +// "if you are deriving from a type in the Standard C++ Library" +#pragma warning( disable : 4251 ) +#endif + +#endif // CERES_WARNINGS_DISABLED diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h b/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h index 5048348564a..3b264b45af3 100644 --- a/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h +++ b/extern/libmv/third_party/ceres/include/ceres/internal/numeric_diff.h @@ -103,14 +103,17 @@ struct NumericDiff { typedef Matrix<double, kNumResiduals, 1> ResidualVector; typedef Matrix<double, kParameterBlockSize, 1> ParameterVector; + + // The convoluted reasoning for choosing the Row/Column major + // ordering of the matrix is an artifact of the restrictions in + // Eigen that prevent it from creating RowMajor matrices with a + // single column. In these cases, we ask for a ColMajor matrix. typedef Matrix<double, kNumResiduals, kParameterBlockSize, - (kParameterBlockSize == 1 && - kNumResiduals > 1) ? ColMajor : RowMajor> + (kParameterBlockSize == 1) ? ColMajor : RowMajor> JacobianMatrix; - Map<JacobianMatrix> parameter_jacobian(jacobian, NUM_RESIDUALS, kParameterBlockSize); diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/reenable_warnings.h b/extern/libmv/third_party/ceres/include/ceres/internal/reenable_warnings.h new file mode 100644 index 00000000000..1f477d8d2ac --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/internal/reenable_warnings.h @@ -0,0 +1,38 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// + +// This is not your usual header guard. See disable_warnings.h +#ifdef CERES_WARNINGS_DISABLED +#undef CERES_WARNINGS_DISABLED + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif // CERES_WARNINGS_DISABLED diff --git a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h index 5eca392da36..237ada6e0c9 100644 --- a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h +++ b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h @@ -36,6 +36,7 @@ #define CERES_PUBLIC_ITERATION_CALLBACK_H_ #include "ceres/types.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -219,4 +220,6 @@ class CERES_EXPORT IterationCallback { } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_PUBLIC_ITERATION_CALLBACK_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/jet.h b/extern/libmv/third_party/ceres/include/ceres/jet.h index 81f96c70f73..74ce1e9dd53 100644 --- a/extern/libmv/third_party/ceres/include/ceres/jet.h +++ b/extern/libmv/third_party/ceres/include/ceres/jet.h @@ -159,6 +159,7 @@ #include <cmath> #include <iosfwd> #include <iostream> // NOLINT +#include <limits> #include <string> #include "Eigen/Core" @@ -197,10 +198,8 @@ struct Jet { // to be passed in without being fully evaluated until // they are assigned to v template<typename Derived> - Jet(const T& value, const Eigen::DenseBase<Derived> &vIn) - : a(value), - v(vIn) - { + EIGEN_STRONG_INLINE Jet(const T& a, const Eigen::DenseBase<Derived> &v) + : a(a), v(v) { } // Compound operators @@ -649,7 +648,9 @@ struct NumTraits<ceres::Jet<T, N> > { return ceres::Jet<T, N>(1e-12); } - static inline Real epsilon() { return Real(std::numeric_limits<T>::epsilon()); } + static inline Real epsilon() { + return Real(std::numeric_limits<T>::epsilon()); + } enum { IsComplex = 0, diff --git a/extern/libmv/third_party/ceres/include/ceres/local_parameterization.h b/extern/libmv/third_party/ceres/include/ceres/local_parameterization.h index ecac5ba3ce0..656c4d46662 100644 --- a/extern/libmv/third_party/ceres/include/ceres/local_parameterization.h +++ b/extern/libmv/third_party/ceres/include/ceres/local_parameterization.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// Copyright 2014 Google Inc. All rights reserved. // http://code.google.com/p/ceres-solver/ // // Redistribution and use in source and binary forms, with or without @@ -34,6 +34,7 @@ #include <vector> #include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -109,7 +110,7 @@ namespace ceres { // Jacobian which is needed to compute the Jacobian of f w.r.t delta. class CERES_EXPORT LocalParameterization { public: - virtual ~LocalParameterization() {} + virtual ~LocalParameterization(); // Generalization of the addition operation, // @@ -121,8 +122,23 @@ class CERES_EXPORT LocalParameterization { double* x_plus_delta) const = 0; // The jacobian of Plus(x, delta) w.r.t delta at delta = 0. + // + // jacobian is a row-major GlobalSize() x LocalSize() matrix. virtual bool ComputeJacobian(const double* x, double* jacobian) const = 0; + // local_matrix = global_matrix * jacobian + // + // global_matrix is a num_rows x GlobalSize row major matrix. + // local_matrix is a num_rows x LocalSize row major matrix. + // jacobian(x) is the matrix returned by ComputeJacobian at x. + // + // This is only used by GradientProblem. For most normal uses, it is + // okay to use the default implementation. + virtual bool MultiplyByJacobian(const double* x, + const int num_rows, + const double* global_matrix, + double* local_matrix) const; + // Size of x. virtual int GlobalSize() const = 0; @@ -142,6 +158,10 @@ class CERES_EXPORT IdentityParameterization : public LocalParameterization { double* x_plus_delta) const; virtual bool ComputeJacobian(const double* x, double* jacobian) const; + virtual bool MultiplyByJacobian(const double* x, + const int num_cols, + const double* global_matrix, + double* local_matrix) const; virtual int GlobalSize() const { return size_; } virtual int LocalSize() const { return size_; } @@ -160,6 +180,10 @@ class CERES_EXPORT SubsetParameterization : public LocalParameterization { double* x_plus_delta) const; virtual bool ComputeJacobian(const double* x, double* jacobian) const; + virtual bool MultiplyByJacobian(const double* x, + const int num_cols, + const double* global_matrix, + double* local_matrix) const; virtual int GlobalSize() const { return static_cast<int>(constancy_mask_.size()); } @@ -188,4 +212,6 @@ class CERES_EXPORT QuaternionParameterization : public LocalParameterization { } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/loss_function.h b/extern/libmv/third_party/ceres/include/ceres/loss_function.h index 5b6bf68e700..2c585009990 100644 --- a/extern/libmv/third_party/ceres/include/ceres/loss_function.h +++ b/extern/libmv/third_party/ceres/include/ceres/loss_function.h @@ -75,10 +75,11 @@ #ifndef CERES_PUBLIC_LOSS_FUNCTION_H_ #define CERES_PUBLIC_LOSS_FUNCTION_H_ +#include "glog/logging.h" #include "ceres/internal/macros.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" -#include "glog/logging.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -395,4 +396,6 @@ class CERES_EXPORT LossFunctionWrapper : public LossFunction { } // namespace ceres +#include "ceres/internal/disable_warnings.h" + #endif // CERES_PUBLIC_LOSS_FUNCTION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/normal_prior.h b/extern/libmv/third_party/ceres/include/ceres/normal_prior.h index 530e65253bb..df665054530 100644 --- a/extern/libmv/third_party/ceres/include/ceres/normal_prior.h +++ b/extern/libmv/third_party/ceres/include/ceres/normal_prior.h @@ -36,6 +36,7 @@ #include "ceres/cost_function.h" #include "ceres/internal/eigen.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -72,4 +73,6 @@ class CERES_EXPORT NormalPrior: public CostFunction { } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_PUBLIC_NORMAL_PRIOR_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h deleted file mode 100644 index a29eb97fa6e..00000000000 --- a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_functor.h +++ /dev/null @@ -1,351 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2013 Google Inc. All rights reserved. -// http://code.google.com/p/ceres-solver/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Author: sameeragarwal@google.com (Sameer Agarwal) -// -// A wrapper class that takes a variadic functor evaluating a -// function, numerically differentiates it and makes it available as a -// templated functor so that it can be easily used as part of Ceres' -// automatic differentiation framework. -// -// For example: -// -// For example, let us assume that -// -// struct IntrinsicProjection -// IntrinsicProjection(const double* observations); -// bool operator()(const double* calibration, -// const double* point, -// double* residuals); -// }; -// -// is a functor that implements the projection of a point in its local -// coordinate system onto its image plane and subtracts it from the -// observed point projection. -// -// Now we would like to compose the action of this functor with the -// action of camera extrinsics, i.e., rotation and translation, which -// is given by the following templated function -// -// template<typename T> -// void RotateAndTranslatePoint(const T* rotation, -// const T* translation, -// const T* point, -// T* result); -// -// To compose the extrinsics and intrinsics, we can construct a -// CameraProjection functor as follows. -// -// struct CameraProjection { -// typedef NumericDiffFunctor<IntrinsicProjection, CENTRAL, 2, 5, 3> -// IntrinsicProjectionFunctor; -// -// CameraProjection(double* observation) { -// intrinsic_projection_.reset( -// new IntrinsicProjectionFunctor(observation)) { -// } -// -// template <typename T> -// bool operator()(const T* rotation, -// const T* translation, -// const T* intrinsics, -// const T* point, -// T* residuals) const { -// T transformed_point[3]; -// RotateAndTranslatePoint(rotation, translation, point, transformed_point); -// return (*intrinsic_projection_)(intrinsics, transformed_point, residual); -// } -// -// private: -// scoped_ptr<IntrinsicProjectionFunctor> intrinsic_projection_; -// }; -// -// Here, we made the choice of using CENTRAL differences to compute -// the jacobian of IntrinsicProjection. -// -// Now, we are ready to construct an automatically differentiated cost -// function as -// -// CostFunction* cost_function = -// new AutoDiffCostFunction<CameraProjection, 2, 3, 3, 5>( -// new CameraProjection(observations)); -// -// cost_function now seamlessly integrates automatic differentiation -// of RotateAndTranslatePoint with a numerically differentiated -// version of IntrinsicProjection. - -#ifndef CERES_PUBLIC_NUMERIC_DIFF_FUNCTOR_H_ -#define CERES_PUBLIC_NUMERIC_DIFF_FUNCTOR_H_ - -#include "ceres/numeric_diff_cost_function.h" -#include "ceres/types.h" -#include "ceres/cost_function_to_functor.h" - -namespace ceres { - -template<typename Functor, - NumericDiffMethod kMethod = CENTRAL, - int kNumResiduals = 0, - int N0 = 0, int N1 = 0 , int N2 = 0, int N3 = 0, int N4 = 0, - int N5 = 0, int N6 = 0 , int N7 = 0, int N8 = 0, int N9 = 0> -class NumericDiffFunctor { - public: - // relative_step_size controls the step size used by the numeric - // differentiation process. - explicit NumericDiffFunctor(double relative_step_size = 1e-6) - : functor_( - new NumericDiffCostFunction<Functor, - kMethod, - kNumResiduals, - N0, N1, N2, N3, N4, - N5, N6, N7, N8, N9>(new Functor, - TAKE_OWNERSHIP, - kNumResiduals, - relative_step_size)) { - } - - NumericDiffFunctor(Functor* functor, double relative_step_size = 1e-6) - : functor_(new NumericDiffCostFunction<Functor, - kMethod, - kNumResiduals, - N0, N1, N2, N3, N4, - N5, N6, N7, N8, N9>( - functor, - TAKE_OWNERSHIP, - kNumResiduals, - relative_step_size)) { - } - - bool operator()(const double* x0, double* residuals) const { - return functor_(x0, residuals); - } - - bool operator()(const double* x0, - const double* x1, - double* residuals) const { - return functor_(x0, x1, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - double* residuals) const { - return functor_(x0, x1, x2, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - double* residuals) const { - return functor_(x0, x1, x2, x3, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - const double* x5, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - const double* x5, - const double* x6, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - const double* x5, - const double* x6, - const double* x7, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - const double* x5, - const double* x6, - const double* x7, - const double* x8, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, residuals); - } - - bool operator()(const double* x0, - const double* x1, - const double* x2, - const double* x3, - const double* x4, - const double* x5, - const double* x6, - const double* x7, - const double* x8, - const double* x9, - double* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, residuals); - } - - template <typename T> - bool operator()(const T* x0, T* residuals) const { - return functor_(x0, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - T* residuals) const { - return functor_(x0, x1, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - T* residuals) const { - return functor_(x0, x1, x2, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - T* residuals) const { - return functor_(x0, x1, x2, x3, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - const T* x5, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - const T* x5, - const T* x6, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - const T* x5, - const T* x6, - const T* x7, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - const T* x5, - const T* x6, - const T* x7, - const T* x8, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, residuals); - } - - template <typename T> - bool operator()(const T* x0, - const T* x1, - const T* x2, - const T* x3, - const T* x4, - const T* x5, - const T* x6, - const T* x7, - const T* x8, - const T* x9, - T* residuals) const { - return functor_(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, residuals); - } - - - private: - CostFunctionToFunctor<kNumResiduals, - N0, N1, N2, N3, N4, - N5, N6, N7, N8, N9> functor_; -}; - -} // namespace ceres - -#endif // CERES_PUBLIC_NUMERIC_DIFF_FUNCTOR_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h b/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h index dff859d7b82..c316d712e97 100644 --- a/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h +++ b/extern/libmv/third_party/ceres/include/ceres/ordered_groups.h @@ -33,7 +33,9 @@ #include <map> #include <set> +#include <vector> #include "ceres/internal/port.h" +#include "glog/logging.h" namespace ceres { @@ -103,6 +105,20 @@ class OrderedGroups { return true; } + // Bulk remove elements. The return value indicates the number of + // elements successfully removed. + int Remove(const vector<T>& elements) { + if (NumElements() == 0 || elements.size() == 0) { + return 0; + } + + int num_removed = 0; + for (int i = 0; i < elements.size(); ++i) { + num_removed += Remove(elements[i]); + } + return num_removed; + } + // Reverse the order of the groups in place. void Reverse() { typename map<int, set<T> >::reverse_iterator it = @@ -156,10 +172,22 @@ class OrderedGroups { return group_to_elements_.size(); } + // The first group with one or more elements. Calling this when + // there are no groups with non-zero elements will result in a + // crash. + int MinNonZeroGroup() const { + CHECK_NE(NumGroups(), 0); + return group_to_elements_.begin()->first; + } + const map<int, set<T> >& group_to_elements() const { return group_to_elements_; } + const map<T, int>& element_to_group() const { + return element_to_group_; + } + private: map<int, set<T> > group_to_elements_; map<T, int> element_to_group_; diff --git a/extern/libmv/third_party/ceres/include/ceres/problem.h b/extern/libmv/third_party/ceres/include/ceres/problem.h index 5881677a815..f75ede3a5c6 100644 --- a/extern/libmv/third_party/ceres/include/ceres/problem.h +++ b/extern/libmv/third_party/ceres/include/ceres/problem.h @@ -39,11 +39,12 @@ #include <set> #include <vector> +#include "glog/logging.h" #include "ceres/internal/macros.h" #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" -#include "glog/logging.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -367,6 +368,15 @@ class CERES_EXPORT Problem { const ResidualBlockId residual_block, vector<double*>* parameter_blocks) const; + // Get the CostFunction for the given residual block. + const CostFunction* GetCostFunctionForResidualBlock( + const ResidualBlockId residual_block) const; + + // Get the LossFunction for the given residual block. Returns NULL + // if no loss function is associated with this residual block. + const LossFunction* GetLossFunctionForResidualBlock( + const ResidualBlockId residual_block) const; + // Get all the residual blocks that depend on the given parameter block. // // If Problem::Options::enable_fast_removal is true, then @@ -466,4 +476,6 @@ class CERES_EXPORT Problem { } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_PUBLIC_PROBLEM_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/solver.h b/extern/libmv/third_party/ceres/include/ceres/solver.h index fc70073ec89..a5efa2a3915 100644 --- a/extern/libmv/third_party/ceres/include/ceres/solver.h +++ b/extern/libmv/third_party/ceres/include/ceres/solver.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// Copyright 2014 Google Inc. All rights reserved. // http://code.google.com/p/ceres-solver/ // // Redistribution and use in source and binary forms, with or without @@ -40,6 +40,7 @@ #include "ceres/iteration_callback.h" #include "ceres/ordered_groups.h" #include "ceres/types.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -91,7 +92,7 @@ class CERES_EXPORT Solver { gradient_tolerance = 1e-10; parameter_tolerance = 1e-8; -#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) +#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) && !defined(CERES_ENABLE_LGPL_CODE) linear_solver_type = DENSE_QR; #else linear_solver_type = SPARSE_NORMAL_CHOLESKY; @@ -100,16 +101,27 @@ class CERES_EXPORT Solver { preconditioner_type = JACOBI; visibility_clustering_type = CANONICAL_VIEWS; dense_linear_algebra_library_type = EIGEN; + + // Choose a default sparse linear algebra library in the order: + // + // SUITE_SPARSE > CX_SPARSE > EIGEN_SPARSE +#if !defined(CERES_NO_SUITESPARSE) sparse_linear_algebra_library_type = SUITE_SPARSE; -#if defined(CERES_NO_SUITESPARSE) && !defined(CERES_NO_CXSPARSE) +#else + #if !defined(CERES_NO_CXSPARSE) sparse_linear_algebra_library_type = CX_SPARSE; + #else + #if defined(CERES_USE_EIGEN_SPARSE) + sparse_linear_algebra_library_type = EIGEN_SPARSE; + #endif + #endif #endif - num_linear_solver_threads = 1; + use_explicit_schur_complement = false; use_postordering = false; dynamic_sparsity = false; - min_linear_solver_iterations = 1; + min_linear_solver_iterations = 0; max_linear_solver_iterations = 500; eta = 1e-1; jacobi_scaling = true; @@ -125,6 +137,11 @@ class CERES_EXPORT Solver { update_state_every_iteration = false; } + // Returns true if the options struct has a valid + // configuration. Returns false otherwise, and fills in *error + // with a message describing the problem. + bool IsValid(string* error) const; + // Minimizer options ---------------------------------------- // Ceres supports the two major families of optimization strategies - @@ -480,6 +497,29 @@ class CERES_EXPORT Solver { // smaller than the group containing cameras. shared_ptr<ParameterBlockOrdering> linear_solver_ordering; + // Use an explicitly computed Schur complement matrix with + // ITERATIVE_SCHUR. + // + // By default this option is disabled and ITERATIVE_SCHUR + // evaluates evaluates matrix-vector products between the Schur + // complement and a vector implicitly by exploiting the algebraic + // expression for the Schur complement. + // + // The cost of this evaluation scales with the number of non-zeros + // in the Jacobian. + // + // For small to medium sized problems there is a sweet spot where + // computing the Schur complement is cheap enough that it is much + // more efficient to explicitly compute it and use it for evaluating + // the matrix-vector products. + // + // Enabling this option tells ITERATIVE_SCHUR to use an explicitly + // computed Schur complement. + // + // NOTE: This option can only be used with the SCHUR_JACOBI + // preconditioner. + bool use_explicit_schur_complement; + // Sparse Cholesky factorization algorithms use a fill-reducing // ordering to permute the columns of the Jacobian matrix. There // are two ways of doing this. @@ -707,10 +747,6 @@ class CERES_EXPORT Solver { // // The solver does NOT take ownership of these pointers. vector<IterationCallback*> callbacks; - - // If non-empty, a summary of the execution of the solver is - // recorded to this file. - string solver_log; }; struct CERES_EXPORT Summary { @@ -898,9 +934,15 @@ class CERES_EXPORT Solver { // parameter blocks. vector<int> inner_iteration_ordering_used; - // Type of preconditioner used for solving the trust region - // step. Only meaningful when an iterative linear solver is used. - PreconditionerType preconditioner_type; + // Type of the preconditioner requested by the user. + PreconditionerType preconditioner_type_given; + + // Type of the preconditioner actually used. This may be different + // from linear_solver_type_given if Ceres determines that the + // problem structure is not compatible with the linear solver + // requested or if the linear solver requested by the user is not + // available. + PreconditionerType preconditioner_type_used; // Type of clustering algorithm used for visibility based // preconditioning. Only meaningful when the preconditioner_type @@ -957,4 +999,6 @@ CERES_EXPORT void Solve(const Solver::Options& options, } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_PUBLIC_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/types.h b/extern/libmv/third_party/ceres/include/ceres/types.h index ff31d4530db..a07c8933e64 100644 --- a/extern/libmv/third_party/ceres/include/ceres/types.h +++ b/extern/libmv/third_party/ceres/include/ceres/types.h @@ -40,6 +40,7 @@ #include <string> #include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" namespace ceres { @@ -149,8 +150,14 @@ enum SparseLinearAlgebraLibraryType { // minimum degree ordering. SUITE_SPARSE, - // A lightweight replacment for SuiteSparse. - CX_SPARSE + // A lightweight replacment for SuiteSparse, which does not require + // a LAPACK/BLAS implementation. Consequently, its performance is + // also a bit lower than SuiteSparse. + CX_SPARSE, + + // Eigen's sparse linear algebra routines. In particular Ceres uses + // the Simplicial LDLT routines. + EIGEN_SPARSE }; enum DenseLinearAlgebraLibraryType { @@ -246,7 +253,7 @@ enum LineSearchDirectionType { // details see Numerical Optimization by Nocedal & Wright. enum NonlinearConjugateGradientType { FLETCHER_REEVES, - POLAK_RIBIRERE, + POLAK_RIBIERE, HESTENES_STIEFEL, }; @@ -398,8 +405,8 @@ enum LineSearchInterpolationType { enum CovarianceAlgorithmType { DENSE_SVD, - SPARSE_CHOLESKY, - SPARSE_QR + SUITE_SPARSE_QR, + EIGEN_SPARSE_QR }; CERES_EXPORT const char* LinearSolverTypeToString( @@ -475,4 +482,6 @@ CERES_EXPORT bool IsDenseLinearAlgebraLibraryTypeAvailable( } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_PUBLIC_TYPES_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/version.h b/extern/libmv/third_party/ceres/include/ceres/version.h new file mode 100644 index 00000000000..370b08af73e --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/version.h @@ -0,0 +1,49 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: mierle@gmail.com (Keir Mierle) + +#ifndef CERES_PUBLIC_VERSION_H_ +#define CERES_PUBLIC_VERSION_H_ + +#define CERES_VERSION_MAJOR 1 +#define CERES_VERSION_MINOR 10 +#define CERES_VERSION_REVISION 0 +#define CERES_VERSION_ABI 1 + +// Classic CPP stringifcation; the extra level of indirection allows the +// preprocessor to expand the macro before being converted to a string. +#define CERES_TO_STRING_HELPER(x) #x +#define CERES_TO_STRING(x) CERES_TO_STRING_HELPER(x) + +// The Ceres version as a string; for example "1.9.0". +#define CERES_VERSION_STRING CERES_TO_STRING(CERES_VERSION_MAJOR) "." \ + CERES_TO_STRING(CERES_VERSION_MINOR) "." \ + CERES_TO_STRING(CERES_VERSION_REVISION) + +#endif // CERES_PUBLIC_VERSION_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/internal/ceres/CMakeLists.txt deleted file mode 100644 index 1dd40900031..00000000000 --- a/extern/libmv/third_party/ceres/internal/ceres/CMakeLists.txt +++ /dev/null @@ -1,287 +0,0 @@ -# Ceres Solver - A fast non-linear least squares minimizer -# Copyright 2010, 2011, 2012 Google Inc. All rights reserved. -# http://code.google.com/p/ceres-solver/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# * Neither the name of Google Inc. nor the names of its contributors may be -# used to endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -# Author: keir@google.com (Keir Mierle) - -SET(CERES_INTERNAL_SRC - array_utils.cc - blas.cc - block_evaluate_preparer.cc - block_jacobi_preconditioner.cc - block_jacobian_writer.cc - block_random_access_dense_matrix.cc - block_random_access_diagonal_matrix.cc - block_random_access_matrix.cc - block_random_access_sparse_matrix.cc - block_sparse_matrix.cc - block_structure.cc - c_api.cc - canonical_views_clustering.cc - cgnr_solver.cc - compressed_col_sparse_matrix_utils.cc - compressed_row_jacobian_writer.cc - compressed_row_sparse_matrix.cc - conditioned_cost_function.cc - conjugate_gradients_solver.cc - coordinate_descent_minimizer.cc - corrector.cc - covariance.cc - covariance_impl.cc - cxsparse.cc - dense_normal_cholesky_solver.cc - dense_qr_solver.cc - dense_sparse_matrix.cc - detect_structure.cc - dogleg_strategy.cc - dynamic_compressed_row_jacobian_writer.cc - dynamic_compressed_row_sparse_matrix.cc - evaluator.cc - file.cc - gradient_checking_cost_function.cc - implicit_schur_complement.cc - incomplete_lq_factorization.cc - iterative_schur_complement_solver.cc - levenberg_marquardt_strategy.cc - lapack.cc - line_search.cc - line_search_direction.cc - line_search_minimizer.cc - linear_least_squares_problems.cc - linear_operator.cc - linear_solver.cc - local_parameterization.cc - loss_function.cc - low_rank_inverse_hessian.cc - minimizer.cc - normal_prior.cc - parameter_block_ordering.cc - partitioned_matrix_view.cc - polynomial.cc - preconditioner.cc - problem.cc - problem_impl.cc - program.cc - residual_block.cc - residual_block_utils.cc - schur_complement_solver.cc - schur_eliminator.cc - schur_jacobi_preconditioner.cc - scratch_evaluate_preparer.cc - single_linkage_clustering.cc - solver.cc - solver_impl.cc - sparse_matrix.cc - sparse_normal_cholesky_solver.cc - split.cc - stringprintf.cc - suitesparse.cc - triplet_sparse_matrix.cc - trust_region_minimizer.cc - trust_region_strategy.cc - types.cc - visibility.cc - visibility_based_preconditioner.cc - wall_time.cc -) - -# Heuristic for determining LIB_SUFFIX. FHS recommends that 64-bit systems -# install native libraries to lib64 rather than lib. Most distros seem to -# follow this convention with a couple notable exceptions (Debian-based and -# Arch-based distros) which we try to detect here. -IF (CMAKE_SYSTEM_NAME MATCHES "Linux" AND - NOT DEFINED LIB_SUFFIX AND - NOT CMAKE_CROSSCOMPILING AND - CMAKE_SIZEOF_VOID_P EQUAL "8" AND - NOT EXISTS "/etc/debian_version" AND - NOT EXISTS "/etc/arch-release") - SET(LIB_SUFFIX "64") -ENDIF () - -# Also depend on the header files so that they appear in IDEs. -FILE(GLOB CERES_INTERNAL_HDRS *.h) - -# Include the specialized schur solvers. -IF (SCHUR_SPECIALIZATIONS) - FILE(GLOB CERES_INTERNAL_SCHUR_FILES generated/*.cc) -ELSE (SCHUR_SPECIALIZATIONS) - # Only the fully dynamic solver. The build is much faster this way. - FILE(GLOB CERES_INTERNAL_SCHUR_FILES generated/*_d_d_d.cc) -ENDIF (SCHUR_SPECIALIZATIONS) - -# Primarily for Android, but optionally for others, use the minimal internal -# Glog implementation. -IF (MINIGLOG) - ADD_LIBRARY(miniglog STATIC miniglog/glog/logging.cc) - INSTALL(TARGETS miniglog - EXPORT CeresExport - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) -ENDIF (MINIGLOG) - -SET(CERES_LIBRARY_PUBLIC_DEPENDENCIES ${GLOG_LIBRARIES}) - -IF (SUITESPARSE AND SUITESPARSE_FOUND) - LIST(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES ${SUITESPARSE_LIBRARIES}) -ENDIF (SUITESPARSE AND SUITESPARSE_FOUND) - -IF (CXSPARSE AND CXSPARSE_FOUND) - LIST(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES ${CXSPARSE_LIBRARIES}) -ENDIF (CXSPARSE AND CXSPARSE_FOUND) - -IF (BLAS_FOUND AND LAPACK_FOUND) - LIST(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES ${LAPACK_LIBRARIES}) - LIST(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES ${BLAS_LIBRARIES}) -ENDIF (BLAS_FOUND AND LAPACK_FOUND) - -IF (OPENMP_FOUND) - IF (NOT MSVC) - LIST(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES gomp) - LIST(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES ${CMAKE_THREAD_LIBS_INIT}) - ENDIF (NOT MSVC) -ENDIF (OPENMP_FOUND) - -SET(CERES_LIBRARY_SOURCE - ${CERES_INTERNAL_SRC} - ${CERES_INTERNAL_HDRS} - ${CERES_INTERNAL_SCHUR_FILES}) - -ADD_LIBRARY(ceres ${CERES_LIBRARY_SOURCE}) -SET_TARGET_PROPERTIES(ceres PROPERTIES - VERSION ${CERES_VERSION} - SOVERSION ${CERES_VERSION_MAJOR} -) - -IF (BUILD_SHARED_LIBS) - # When building a shared library, mark all external libraries as - # PRIVATE so they don't show up as a dependency. - TARGET_LINK_LIBRARIES(ceres - LINK_PUBLIC ${CERES_LIBRARY_PUBLIC_DEPENDENCIES} - LINK_PRIVATE ${CERES_LIBRARY_PRIVATE_DEPENDENCIES}) -ELSE (BUILD_SHARED_LIBS) - # When building a static library, all external libraries are - # PUBLIC(default) since the user needs to link to them. - # They will be listed in CeresTargets.cmake. - SET(CERES_LIBRARY_DEPENDENCIES - ${CERES_LIBRARY_PUBLIC_DEPENDENCIES} - ${CERES_LIBRARY_PRIVATE_DEPENDENCIES}) - TARGET_LINK_LIBRARIES(ceres ${CERES_LIBRARY_DEPENDENCIES}) -ENDIF (BUILD_SHARED_LIBS) - -INSTALL(TARGETS ceres - EXPORT CeresExport - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib${LIB_SUFFIX} - ARCHIVE DESTINATION lib${LIB_SUFFIX}) - -IF (BUILD_TESTING AND GFLAGS) - ADD_LIBRARY(gtest gmock_gtest_all.cc gmock_main.cc) - ADD_LIBRARY(test_util - evaluator_test_utils.cc - numeric_diff_test_utils.cc - test_util.cc) - - TARGET_LINK_LIBRARIES(gtest ${GFLAGS_LIBRARIES} ${GLOG_LIBRARIES}) - TARGET_LINK_LIBRARIES(test_util ceres gtest ${GLOG_LIBRARIES}) - - MACRO (CERES_TEST NAME) - ADD_EXECUTABLE(${NAME}_test ${NAME}_test.cc) - TARGET_LINK_LIBRARIES(${NAME}_test test_util ceres gtest) - ADD_TEST(NAME ${NAME}_test - COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${NAME}_test - --test_srcdir - ${CMAKE_SOURCE_DIR}/data) - ENDMACRO (CERES_TEST) - - CERES_TEST(array_utils) - CERES_TEST(autodiff) - CERES_TEST(autodiff_cost_function) - CERES_TEST(autodiff_local_parameterization) - CERES_TEST(block_random_access_dense_matrix) - CERES_TEST(block_random_access_diagonal_matrix) - CERES_TEST(block_random_access_sparse_matrix) - CERES_TEST(block_sparse_matrix) - CERES_TEST(c_api) - CERES_TEST(canonical_views_clustering) - CERES_TEST(compressed_row_sparse_matrix) - CERES_TEST(conditioned_cost_function) - CERES_TEST(corrector) - CERES_TEST(cost_function_to_functor) - CERES_TEST(covariance) - CERES_TEST(dense_sparse_matrix) - CERES_TEST(dynamic_autodiff_cost_function) - CERES_TEST(dynamic_compressed_row_sparse_matrix) - CERES_TEST(dynamic_numeric_diff_cost_function) - CERES_TEST(evaluator) - CERES_TEST(gradient_checker) - CERES_TEST(gradient_checking_cost_function) - CERES_TEST(graph) - CERES_TEST(graph_algorithms) - CERES_TEST(implicit_schur_complement) - CERES_TEST(incomplete_lq_factorization) - CERES_TEST(iterative_schur_complement_solver) - CERES_TEST(jet) - CERES_TEST(levenberg_marquardt_strategy) - CERES_TEST(dogleg_strategy) - CERES_TEST(local_parameterization) - CERES_TEST(loss_function) - CERES_TEST(minimizer) - CERES_TEST(normal_prior) - CERES_TEST(numeric_diff_cost_function) - CERES_TEST(numeric_diff_functor) - CERES_TEST(ordered_groups) - CERES_TEST(parameter_block) - CERES_TEST(parameter_block_ordering) - CERES_TEST(partitioned_matrix_view) - CERES_TEST(polynomial) - CERES_TEST(problem) - CERES_TEST(residual_block) - CERES_TEST(residual_block_utils) - CERES_TEST(rotation) - CERES_TEST(schur_complement_solver) - CERES_TEST(schur_eliminator) - CERES_TEST(single_linkage_clustering) - CERES_TEST(small_blas) - CERES_TEST(solver_impl) - - # TODO(sameeragarwal): This test should ultimately be made - # independent of SuiteSparse. - IF (SUITESPARSE AND SUITESPARSE_FOUND) - CERES_TEST(compressed_col_sparse_matrix_utils) - ENDIF (SUITESPARSE AND SUITESPARSE_FOUND) - - CERES_TEST(symmetric_linear_solver) - CERES_TEST(triplet_sparse_matrix) - CERES_TEST(trust_region_minimizer) - CERES_TEST(unsymmetric_linear_solver) - CERES_TEST(visibility) - CERES_TEST(visibility_based_preconditioner) - - # Put the large end to end test last. - CERES_TEST(system) -ENDIF (BUILD_TESTING AND GFLAGS) diff --git a/extern/libmv/third_party/ceres/internal/ceres/array_utils.cc b/extern/libmv/third_party/ceres/internal/ceres/array_utils.cc index 3eea042d511..205ddaf27c9 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/array_utils.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/array_utils.cc @@ -30,10 +30,11 @@ #include "ceres/array_utils.h" +#include <algorithm> #include <cmath> #include <cstddef> #include <string> - +#include <vector> #include "ceres/fpclassify.h" #include "ceres/stringprintf.h" @@ -94,5 +95,19 @@ void AppendArrayToString(const int size, const double* x, string* result) { } } +void MapValuesToContiguousRange(const int size, int* array) { + std::vector<int> unique_values(array, array + size); + std::sort(unique_values.begin(), unique_values.end()); + unique_values.erase(std::unique(unique_values.begin(), + unique_values.end()), + unique_values.end()); + + for (int i = 0; i < size; ++i) { + array[i] = std::lower_bound(unique_values.begin(), + unique_values.end(), + array[i]) - unique_values.begin(); + } +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/array_utils.h b/extern/libmv/third_party/ceres/internal/ceres/array_utils.h index 34fda6fd475..7f56947066b 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/array_utils.h +++ b/extern/libmv/third_party/ceres/internal/ceres/array_utils.h @@ -67,6 +67,21 @@ void AppendArrayToString(const int size, const double* x, string* result); extern const double kImpossibleValue; +// This routine takes an array of integer values, sorts and uniques +// them and then maps each value in the array to its position in the +// sorted+uniqued array. By doing this, if there are are k unique +// values in the array, each value is replaced by an integer in the +// range [0, k-1], while preserving their relative order. +// +// For example +// +// [1 0 3 5 0 1 5] +// +// gets mapped to +// +// [1 0 2 3 0 1 3] +void MapValuesToContiguousRange(int size, int* array); + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc index 19b749bfc39..7f79a4f993d 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc @@ -30,9 +30,9 @@ #include "ceres/block_jacobi_preconditioner.h" -#include "Eigen/Cholesky" #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" +#include "ceres/block_random_access_diagonal_matrix.h" #include "ceres/casts.h" #include "ceres/integral_types.h" #include "ceres/internal/eigen.h" @@ -41,27 +41,14 @@ namespace ceres { namespace internal { BlockJacobiPreconditioner::BlockJacobiPreconditioner( - const BlockSparseMatrix& A) - : num_rows_(A.num_rows()), - block_structure_(*A.block_structure()) { - // Calculate the amount of storage needed. - int storage_needed = 0; - for (int c = 0; c < block_structure_.cols.size(); ++c) { - int size = block_structure_.cols[c].size; - storage_needed += size * size; + const BlockSparseMatrix& A) { + const CompressedRowBlockStructure* bs = A.block_structure(); + vector<int> blocks(bs->cols.size()); + for (int i = 0; i < blocks.size(); ++i) { + blocks[i] = bs->cols[i].size; } - // Size the offsets and storage. - blocks_.resize(block_structure_.cols.size()); - block_storage_.resize(storage_needed); - - // Put pointers to the storage in the offsets. - double* block_cursor = &block_storage_[0]; - for (int c = 0; c < block_structure_.cols.size(); ++c) { - int size = block_structure_.cols[c].size; - blocks_[c] = block_cursor; - block_cursor += size * size; - } + m_.reset(new BlockRandomAccessDiagonalMatrix(blocks)); } BlockJacobiPreconditioner::~BlockJacobiPreconditioner() {} @@ -69,70 +56,50 @@ BlockJacobiPreconditioner::~BlockJacobiPreconditioner() {} bool BlockJacobiPreconditioner::UpdateImpl(const BlockSparseMatrix& A, const double* D) { const CompressedRowBlockStructure* bs = A.block_structure(); - - // Compute the diagonal blocks by block inner products. - std::fill(block_storage_.begin(), block_storage_.end(), 0.0); const double* values = A.values(); - for (int r = 0; r < bs->rows.size(); ++r) { - const int row_block_size = bs->rows[r].block.size; - const vector<Cell>& cells = bs->rows[r].cells; - for (int c = 0; c < cells.size(); ++c) { - const int col_block_size = bs->cols[cells[c].block_id].size; - ConstMatrixRef m(values + cells[c].position, + m_->SetZero(); + for (int i = 0; i < bs->rows.size(); ++i) { + const int row_block_size = bs->rows[i].block.size; + const vector<Cell>& cells = bs->rows[i].cells; + for (int j = 0; j < cells.size(); ++j) { + const int block_id = cells[j].block_id; + const int col_block_size = bs->cols[block_id].size; + + int r, c, row_stride, col_stride; + CellInfo* cell_info = m_->GetCell(block_id, block_id, + &r, &c, + &row_stride, &col_stride); + MatrixRef m(cell_info->values, row_stride, col_stride); + ConstMatrixRef b(values + cells[j].position, row_block_size, col_block_size); - - MatrixRef(blocks_[cells[c].block_id], - col_block_size, - col_block_size).noalias() += m.transpose() * m; - - // TODO(keir): Figure out when the below expression is actually faster - // than doing the full rank update. The issue is that for smaller sizes, - // the rankUpdate() function is slower than the full product done above. - // - // On the typical bundling problems, the above product is ~5% faster. - // - // MatrixRef(blocks_[cells[c].block_id], - // col_block_size, - // col_block_size) - // .selfadjointView<Eigen::Upper>() - // .rankUpdate(m); - // + m.block(r, c, col_block_size, col_block_size) += b.transpose() * b; } } - // Add the diagonal and invert each block. - for (int c = 0; c < bs->cols.size(); ++c) { - const int size = block_structure_.cols[c].size; - const int position = block_structure_.cols[c].position; - MatrixRef block(blocks_[c], size, size); - - if (D != NULL) { - block.diagonal() += - ConstVectorRef(D + position, size).array().square().matrix(); + if (D != NULL) { + // Add the diagonal. + int position = 0; + for (int i = 0; i < bs->cols.size(); ++i) { + const int block_size = bs->cols[i].size; + int r, c, row_stride, col_stride; + CellInfo* cell_info = m_->GetCell(i, i, + &r, &c, + &row_stride, &col_stride); + MatrixRef m(cell_info->values, row_stride, col_stride); + m.block(r, c, block_size, block_size).diagonal() += + ConstVectorRef(D + position, block_size).array().square().matrix(); + position += block_size; } - - block = block.selfadjointView<Eigen::Upper>() - .llt() - .solve(Matrix::Identity(size, size)); } + + m_->Invert(); return true; } void BlockJacobiPreconditioner::RightMultiply(const double* x, double* y) const { - for (int c = 0; c < block_structure_.cols.size(); ++c) { - const int size = block_structure_.cols[c].size; - const int position = block_structure_.cols[c].position; - ConstMatrixRef D(blocks_[c], size, size); - ConstVectorRef x_block(x + position, size); - VectorRef y_block(y + position, size); - y_block += D * x_block; - } -} - -void BlockJacobiPreconditioner::LeftMultiply(const double* x, double* y) const { - RightMultiply(x, y); + m_->RightMultiply(x, y); } } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h index 3505a01248b..e23e0e2d24c 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2012 Google Inc. All rights reserved. +// Copyright 2014 Google Inc. All rights reserved. // http://code.google.com/p/ceres-solver/ // // Redistribution and use in source and binary forms, with or without @@ -32,6 +32,8 @@ #define CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_ #include <vector> +#include "ceres/block_random_access_diagonal_matrix.h" +#include "ceres/internal/scoped_ptr.h" #include "ceres/preconditioner.h" namespace ceres { @@ -39,7 +41,6 @@ namespace internal { class BlockSparseMatrix; struct CompressedRowBlockStructure; -class LinearOperator; // A block Jacobi preconditioner. This is intended for use with // conjugate gradients, or other iterative symmetric solvers. To use @@ -59,19 +60,14 @@ class BlockJacobiPreconditioner : public BlockSparseMatrixPreconditioner { // Preconditioner interface virtual void RightMultiply(const double* x, double* y) const; - virtual void LeftMultiply(const double* x, double* y) const; - virtual int num_rows() const { return num_rows_; } - virtual int num_cols() const { return num_rows_; } + virtual int num_rows() const { return m_->num_rows(); } + virtual int num_cols() const { return m_->num_rows(); } + const BlockRandomAccessDiagonalMatrix& matrix() const { return *m_; } private: virtual bool UpdateImpl(const BlockSparseMatrix& A, const double* D); - std::vector<double*> blocks_; - std::vector<double> block_storage_; - int num_rows_; - - // The block structure of the matrix this preconditioner is for (e.g. J). - const CompressedRowBlockStructure& block_structure_; + scoped_ptr<BlockRandomAccessDiagonalMatrix> m_; }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.cc index d8bf4ef0cb5..b7ff33184cb 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.cc @@ -34,16 +34,19 @@ #include <set> #include <utility> #include <vector> +#include "Eigen/Dense" #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" +#include "ceres/stl_util.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" -#include "ceres/stl_util.h" #include "glog/logging.h" namespace ceres { namespace internal { +// TODO(sameeragarwal): Drop the dependence on TripletSparseMatrix. + BlockRandomAccessDiagonalMatrix::BlockRandomAccessDiagonalMatrix( const vector<int>& blocks) : blocks_(blocks) { @@ -51,9 +54,9 @@ BlockRandomAccessDiagonalMatrix::BlockRandomAccessDiagonalMatrix( // rows/columns. int num_cols = 0; int num_nonzeros = 0; - vector<int> col_layout; + vector<int> block_positions; for (int i = 0; i < blocks_.size(); ++i) { - col_layout.push_back(num_cols); + block_positions.push_back(num_cols); num_cols += blocks_[i]; num_nonzeros += blocks_[i] * blocks_[i]; } @@ -72,7 +75,7 @@ BlockRandomAccessDiagonalMatrix::BlockRandomAccessDiagonalMatrix( for (int i = 0; i < blocks_.size(); ++i) { const int block_size = blocks_[i]; layout_.push_back(new CellInfo(values + pos)); - const int block_begin = col_layout[i]; + const int block_begin = block_positions[i]; for (int r = 0; r < block_size; ++r) { for (int c = 0; c < block_size; ++c, ++pos) { rows[pos] = block_begin + r; @@ -116,5 +119,34 @@ void BlockRandomAccessDiagonalMatrix::SetZero() { } } +void BlockRandomAccessDiagonalMatrix::Invert() { + double* values = tsm_->mutable_values(); + for (int i = 0; i < blocks_.size(); ++i) { + const int block_size = blocks_[i]; + MatrixRef block(values, block_size, block_size); + block = + block + .selfadjointView<Eigen::Upper>() + .llt() + .solve(Matrix::Identity(block_size, block_size)); + values += block_size * block_size; + } +} + +void BlockRandomAccessDiagonalMatrix::RightMultiply(const double* x, + double* y) const { + CHECK_NOTNULL(x); + CHECK_NOTNULL(y); + const double* values = tsm_->values(); + for (int i = 0; i < blocks_.size(); ++i) { + const int block_size = blocks_[i]; + ConstMatrixRef block(values, block_size, block_size); + VectorRef(y, block_size).noalias() += block * ConstVectorRef(x, block_size); + x += block_size; + y += block_size; + values += block_size * block_size; + } +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.h index 6b3cff2338f..ea9967817db 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_diagonal_matrix.h @@ -52,7 +52,7 @@ namespace internal { class BlockRandomAccessDiagonalMatrix : public BlockRandomAccessMatrix { public: // blocks is an array of block sizes. - BlockRandomAccessDiagonalMatrix(const vector<int>& blocks); + explicit BlockRandomAccessDiagonalMatrix(const vector<int>& blocks); // The destructor is not thread safe. It assumes that no one is // modifying any cells when the matrix is being destroyed. @@ -70,11 +70,16 @@ class BlockRandomAccessDiagonalMatrix : public BlockRandomAccessMatrix { // locked. virtual void SetZero(); + // Invert the matrix assuming that each block is positive definite. + void Invert(); + + // y += S * x + void RightMultiply(const double* x, double* y) const; + // Since the matrix is square, num_rows() == num_cols(). virtual int num_rows() const { return tsm_->num_rows(); } virtual int num_cols() const { return tsm_->num_cols(); } - // Access to the underlying matrix object. const TripletSparseMatrix* matrix() const { return tsm_.get(); } TripletSparseMatrix* mutable_matrix() { return tsm_.get(); } diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc index f789436364a..c43a9b78feb 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc @@ -54,9 +54,9 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( // Build the row/column layout vector and count the number of scalar // rows/columns. int num_cols = 0; - vector<int> col_layout; + block_positions_.reserve(blocks_.size()); for (int i = 0; i < blocks_.size(); ++i) { - col_layout.push_back(num_cols); + block_positions_.push_back(num_cols); num_cols += blocks_[i]; } @@ -88,6 +88,8 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( ++it) { const int row_block_size = blocks_[it->first]; const int col_block_size = blocks_[it->second]; + cell_values_.push_back(make_pair(make_pair(it->first, it->second), + values + pos)); layout_[IntPairToLong(it->first, it->second)] = new CellInfo(values + pos); pos += row_block_size * col_block_size; @@ -105,8 +107,8 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( layout_[IntPairToLong(row_block_id, col_block_id)]->values - values; for (int r = 0; r < row_block_size; ++r) { for (int c = 0; c < col_block_size; ++c, ++pos) { - rows[pos] = col_layout[row_block_id] + r; - cols[pos] = col_layout[col_block_id] + c; + rows[pos] = block_positions_[row_block_id] + r; + cols[pos] = block_positions_[col_block_id] + c; values[pos] = 1.0; DCHECK_LT(rows[pos], tsm_->num_rows()); DCHECK_LT(cols[pos], tsm_->num_rows()); @@ -154,5 +156,36 @@ void BlockRandomAccessSparseMatrix::SetZero() { } } +void BlockRandomAccessSparseMatrix::SymmetricRightMultiply(const double* x, + double* y) const { + vector< pair<pair<int, int>, double*> >::const_iterator it = + cell_values_.begin(); + for (; it != cell_values_.end(); ++it) { + const int row = it->first.first; + const int row_block_size = blocks_[row]; + const int row_block_pos = block_positions_[row]; + + const int col = it->first.second; + const int col_block_size = blocks_[col]; + const int col_block_pos = block_positions_[col]; + + MatrixVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>( + it->second, row_block_size, col_block_size, + x + col_block_pos, + y + row_block_pos); + + // Since the matrix is symmetric, but only the upper triangular + // part is stored, if the block being accessed is not a diagonal + // block, then use the same block to do the corresponding lower + // triangular multiply also. + if (row != col) { + MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>( + it->second, row_block_size, col_block_size, + x + row_block_pos, + y + col_block_pos); + } + } +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h index 27b10296d6c..51b5d20cfe0 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h @@ -43,6 +43,7 @@ #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" +#include "ceres/small_blas.h" namespace ceres { namespace internal { @@ -75,6 +76,12 @@ class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix { // locked. virtual void SetZero(); + // Assume that the matrix is symmetric and only one half of the + // matrix is stored. + // + // y += S * x + void SymmetricRightMultiply(const double* x, double* y) const; + // Since the matrix is square, num_rows() == num_cols(). virtual int num_rows() const { return tsm_->num_rows(); } virtual int num_cols() const { return tsm_->num_cols(); } @@ -84,19 +91,30 @@ class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix { TripletSparseMatrix* mutable_matrix() { return tsm_.get(); } private: - int64 IntPairToLong(int a, int b) { - return a * kMaxRowBlocks + b; + int64 IntPairToLong(int row, int col) const { + return row * kMaxRowBlocks + col; + } + + void LongToIntPair(int64 index, int* row, int* col) const { + *row = index / kMaxRowBlocks; + *col = index % kMaxRowBlocks; } const int64 kMaxRowBlocks; + // row/column block sizes. const vector<int> blocks_; + vector<int> block_positions_; // A mapping from <row_block_id, col_block_id> to the position in // the values array of tsm_ where the block is stored. typedef HashMap<long int, CellInfo* > LayoutType; LayoutType layout_; + // In order traversal of contents of the matrix. This allows us to + // implement a matrix-vector which is 20% faster than using the + // iterator in the Layout object instead. + vector<pair<pair<int, int>, double*> > cell_values_; // The underlying matrix object which actually stores the cells. scoped_ptr<TripletSparseMatrix> tsm_; diff --git a/extern/libmv/third_party/ceres/internal/ceres/callbacks.cc b/extern/libmv/third_party/ceres/internal/ceres/callbacks.cc new file mode 100644 index 00000000000..7d5ce2548e4 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/callbacks.cc @@ -0,0 +1,109 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include <iostream> // NO LINT +#include "ceres/callbacks.h" +#include "ceres/program.h" +#include "ceres/stringprintf.h" +#include "glog/logging.h" + +namespace ceres { +namespace internal { + +StateUpdatingCallback::StateUpdatingCallback(Program* program, + double* parameters) + : program_(program), parameters_(parameters) {} + +StateUpdatingCallback::~StateUpdatingCallback() {} + +CallbackReturnType StateUpdatingCallback::operator()( + const IterationSummary& summary) { + if (summary.step_is_successful) { + program_->StateVectorToParameterBlocks(parameters_); + program_->CopyParameterBlockStateToUserState(); + } + return SOLVER_CONTINUE; +} + +LoggingCallback::LoggingCallback(const MinimizerType minimizer_type, + const bool log_to_stdout) + : minimizer_type(minimizer_type), + log_to_stdout_(log_to_stdout) {} + +LoggingCallback::~LoggingCallback() {} + +CallbackReturnType LoggingCallback::operator()( + const IterationSummary& summary) { + string output; + if (minimizer_type == LINE_SEARCH) { + const char* kReportRowFormat = + "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e " + "s:% 3.2e e:% 3d it:% 3.2e tt:% 3.2e"; + output = StringPrintf(kReportRowFormat, + summary.iteration, + summary.cost, + summary.cost_change, + summary.gradient_max_norm, + summary.step_norm, + summary.step_size, + summary.line_search_function_evaluations, + summary.iteration_time_in_seconds, + summary.cumulative_time_in_seconds); + } else if (minimizer_type == TRUST_REGION) { + if (summary.iteration == 0) { + output = "iter cost cost_change |gradient| |step| tr_ratio tr_radius ls_iter iter_time total_time\n"; + } + const char* kReportRowFormat = + "% 4d % 8e % 3.2e % 3.2e % 3.2e % 3.2e % 3.2e % 4d % 3.2e % 3.2e"; + output += StringPrintf(kReportRowFormat, + summary.iteration, + summary.cost, + summary.cost_change, + summary.gradient_max_norm, + summary.step_norm, + summary.relative_decrease, + summary.trust_region_radius, + summary.linear_solver_iterations, + summary.iteration_time_in_seconds, + summary.cumulative_time_in_seconds); + } else { + LOG(FATAL) << "Unknown minimizer type."; + } + + if (log_to_stdout_) { + cout << output << endl; + } else { + VLOG(1) << output; + } + return SOLVER_CONTINUE; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/callbacks.h b/extern/libmv/third_party/ceres/internal/ceres/callbacks.h new file mode 100644 index 00000000000..93704dfd6d1 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/callbacks.h @@ -0,0 +1,71 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_CALLBACKS_H_ +#define CERES_INTERNAL_CALLBACKS_H_ + +#include <string> +#include "ceres/iteration_callback.h" +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +class Program; + +// Callback for updating the externally visible state of parameter +// blocks. +class StateUpdatingCallback : public IterationCallback { + public: + StateUpdatingCallback(Program* program, double* parameters); + virtual ~StateUpdatingCallback(); + virtual CallbackReturnType operator()(const IterationSummary& summary); + private: + Program* program_; + double* parameters_; +}; + +// Callback for logging the state of the minimizer to STDERR or +// STDOUT depending on the user's preferences and logging level. +class LoggingCallback : public IterationCallback { + public: + LoggingCallback(MinimizerType minimizer_type, bool log_to_stdout); + virtual ~LoggingCallback(); + virtual CallbackReturnType operator()(const IterationSummary& summary); + + private: + const MinimizerType minimizer_type; + const bool log_to_stdout_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_CALLBACKS_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc index 2f032e6580a..9bbab4b2377 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc @@ -61,7 +61,7 @@ class CanonicalViewsClustering { // vertices may not be assigned to any cluster. In this case they // are assigned to a cluster with id = kInvalidClusterId. void ComputeClustering(const CanonicalViewsClusteringOptions& options, - const Graph<int>& graph, + const WeightedGraph<int>& graph, vector<int>* centers, IntMap* membership); @@ -74,7 +74,7 @@ class CanonicalViewsClustering { IntMap* membership) const; CanonicalViewsClusteringOptions options_; - const Graph<int>* graph_; + const WeightedGraph<int>* graph_; // Maps a view to its representative canonical view (its cluster // center). IntMap view_to_canonical_view_; @@ -85,7 +85,7 @@ class CanonicalViewsClustering { void ComputeCanonicalViewsClustering( const CanonicalViewsClusteringOptions& options, - const Graph<int>& graph, + const WeightedGraph<int>& graph, vector<int>* centers, IntMap* membership) { time_t start_time = time(NULL); @@ -98,7 +98,7 @@ void ComputeCanonicalViewsClustering( // Implementation of CanonicalViewsClustering void CanonicalViewsClustering::ComputeClustering( const CanonicalViewsClusteringOptions& options, - const Graph<int>& graph, + const WeightedGraph<int>& graph, vector<int>* centers, IntMap* membership) { options_ = options; @@ -150,7 +150,7 @@ void CanonicalViewsClustering::FindValidViews( for (IntSet::const_iterator view = views.begin(); view != views.end(); ++view) { - if (graph_->VertexWeight(*view) != Graph<int>::InvalidWeight()) { + if (graph_->VertexWeight(*view) != WeightedGraph<int>::InvalidWeight()) { valid_views->insert(*view); } } diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h index 1b4c4ee059f..d3fa5725831 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h +++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.h @@ -101,7 +101,7 @@ struct CanonicalViewsClusteringOptions; // cluster. In this case they are assigned to a cluster with id = -1; void ComputeCanonicalViewsClustering( const CanonicalViewsClusteringOptions& options, - const Graph<int>& graph, + const WeightedGraph<int>& graph, vector<int>* centers, HashMap<int, int>* membership); diff --git a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc index 524cb8ad988..3071a0918e4 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc @@ -101,7 +101,7 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve( A->RightMultiply(x, tmp.data()); r = bref - tmp; double norm_r = r.norm(); - if (norm_r <= tol_r) { + if (options_.min_num_iterations == 0 && norm_r <= tol_r) { summary.termination_type = LINEAR_SOLVER_SUCCESS; summary.message = StringPrintf("Convergence. |r| = %e <= %e.", norm_r, tol_r); @@ -113,9 +113,8 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve( // Initial value of the quadratic model Q = x'Ax - 2 * b'x. double Q0 = -1.0 * xref.dot(bref + r); - for (summary.num_iterations = 1; - summary.num_iterations < options_.max_num_iterations; - ++summary.num_iterations) { + for (summary.num_iterations = 1;; ++summary.num_iterations) { + // Apply preconditioner if (per_solve_options.preconditioner != NULL) { z.setZero(); @@ -207,7 +206,8 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve( // 124(1-2), 45-59, 2000. // const double zeta = summary.num_iterations * (Q1 - Q0) / Q1; - if (zeta < per_solve_options.q_tolerance) { + if (zeta < per_solve_options.q_tolerance && + summary.num_iterations >= options_.min_num_iterations) { summary.termination_type = LINEAR_SOLVER_SUCCESS; summary.message = StringPrintf("Convergence: zeta = %e < %e", @@ -219,12 +219,17 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve( // Residual based termination. norm_r = r. norm(); - if (norm_r <= tol_r) { + if (norm_r <= tol_r && + summary.num_iterations >= options_.min_num_iterations) { summary.termination_type = LINEAR_SOLVER_SUCCESS; summary.message = StringPrintf("Convergence. |r| = %e <= %e.", norm_r, tol_r); break; } + + if (summary.num_iterations >= options_.max_num_iterations) { + break; + } } return summary; diff --git a/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc index bfe93c49826..1d55458bb69 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.cc @@ -40,15 +40,15 @@ #include "ceres/evaluator.h" #include "ceres/linear_solver.h" #include "ceres/minimizer.h" -#include "ceres/ordered_groups.h" #include "ceres/parameter_block.h" +#include "ceres/parameter_block_ordering.h" #include "ceres/problem_impl.h" #include "ceres/program.h" #include "ceres/residual_block.h" #include "ceres/solver.h" -#include "ceres/solver_impl.h" #include "ceres/trust_region_minimizer.h" #include "ceres/trust_region_strategy.h" +#include "ceres/parameter_block_ordering.h" namespace ceres { namespace internal { @@ -210,28 +210,54 @@ void CoordinateDescentMinimizer::Solve(Program* program, summary->final_cost = 0.0; string error; - scoped_ptr<Evaluator> evaluator( - Evaluator::Create(evaluator_options_, program, &error)); - CHECK_NOTNULL(evaluator.get()); - - scoped_ptr<SparseMatrix> jacobian(evaluator->CreateJacobian()); - CHECK_NOTNULL(jacobian.get()); + Minimizer::Options minimizer_options; + minimizer_options.evaluator.reset( + CHECK_NOTNULL(Evaluator::Create(evaluator_options_, program, &error))); + minimizer_options.jacobian.reset( + CHECK_NOTNULL(minimizer_options.evaluator->CreateJacobian())); TrustRegionStrategy::Options trs_options; trs_options.linear_solver = linear_solver; - - scoped_ptr<TrustRegionStrategy>trust_region_strategy( + minimizer_options.trust_region_strategy.reset( CHECK_NOTNULL(TrustRegionStrategy::Create(trs_options))); - - Minimizer::Options minimizer_options; - minimizer_options.evaluator = evaluator.get(); - minimizer_options.jacobian = jacobian.get(); - minimizer_options.trust_region_strategy = trust_region_strategy.get(); minimizer_options.is_silent = true; TrustRegionMinimizer minimizer; minimizer.Minimize(minimizer_options, parameter, summary); } +bool CoordinateDescentMinimizer::IsOrderingValid( + const Program& program, + const ParameterBlockOrdering& ordering, + string* message) { + const map<int, set<double*> >& group_to_elements = + ordering.group_to_elements(); + + // Verify that each group is an independent set + map<int, set<double*> >::const_iterator it = group_to_elements.begin(); + for ( ; it != group_to_elements.end(); ++it) { + if (!program.IsParameterBlockSetIndependent(it->second)) { + *message = + StringPrintf("The user-provided " + "parameter_blocks_for_inner_iterations does not " + "form an independent set. Group Id: %d", it->first); + return false; + } + } + return true; +} + +// Find a recursive decomposition of the Hessian matrix as a set +// of independent sets of decreasing size and invert it. This +// seems to work better in practice, i.e., Cameras before +// points. +ParameterBlockOrdering* CoordinateDescentMinimizer::CreateOrdering( + const Program& program) { + scoped_ptr<ParameterBlockOrdering> ordering(new ParameterBlockOrdering); + ComputeRecursiveIndependentSetOrdering(program, ordering.get()); + ordering->Reverse(); + return ordering.release(); +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.h index 424acda94ae..c1f8ffcd02a 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.h +++ b/extern/libmv/third_party/ceres/internal/ceres/coordinate_descent_minimizer.h @@ -37,12 +37,14 @@ #include "ceres/evaluator.h" #include "ceres/minimizer.h" #include "ceres/problem_impl.h" -#include "ceres/program.h" #include "ceres/solver.h" namespace ceres { namespace internal { +class Program; +class LinearSolver; + // Given a Program, and a ParameterBlockOrdering which partitions // (non-exhaustively) the Hessian matrix into independent sets, // perform coordinate descent on the parameter blocks in the @@ -66,6 +68,17 @@ class CoordinateDescentMinimizer : public Minimizer { double* parameters, Solver::Summary* summary); + // Verify that each group in the ordering forms an independent set. + static bool IsOrderingValid(const Program& program, + const ParameterBlockOrdering& ordering, + string* message); + + // Find a recursive decomposition of the Hessian matrix as a set + // of independent sets of decreasing size and invert it. This + // seems to work better in practice, i.e., Cameras before + // points. + static ParameterBlockOrdering* CreateOrdering(const Program& program); + private: void Solve(Program* program, LinearSolver* linear_solver, diff --git a/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc index 75c80bf5687..cfbfb445343 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc @@ -38,6 +38,25 @@ #include <cstdlib> #include <utility> #include <vector> +#include "Eigen/SparseCore" + +// Suppress unused local variable warning from Eigen Ordering.h #included by +// SparseQR in Eigen 3.2.0. This was fixed in Eigen 3.2.1, but 3.2.0 is still +// widely used (Ubuntu 14.04), and Ceres won't compile otherwise due to -Werror. +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4189 ) +#else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" +#endif +#include "Eigen/SparseQR" +#if defined(_MSC_VER) +#pragma warning( pop ) +#else +#pragma GCC diagnostic pop +#endif + #include "Eigen/SVD" #include "ceres/compressed_col_sparse_matrix_utils.h" #include "ceres/compressed_row_sparse_matrix.h" @@ -53,40 +72,6 @@ namespace ceres { namespace internal { -namespace { - -// Per thread storage for SuiteSparse. -#ifndef CERES_NO_SUITESPARSE - -struct PerThreadContext { - explicit PerThreadContext(int num_rows) - : solution(NULL), - solution_set(NULL), - y_workspace(NULL), - e_workspace(NULL), - rhs(NULL) { - rhs = ss.CreateDenseVector(NULL, num_rows, num_rows); - } - - ~PerThreadContext() { - ss.Free(solution); - ss.Free(solution_set); - ss.Free(y_workspace); - ss.Free(e_workspace); - ss.Free(rhs); - } - - cholmod_dense* solution; - cholmod_sparse* solution_set; - cholmod_dense* y_workspace; - cholmod_dense* e_workspace; - cholmod_dense* rhs; - SuiteSparse ss; -}; - -#endif - -} // namespace typedef vector<pair<const double*, const double*> > CovarianceBlocks; @@ -94,8 +79,17 @@ CovarianceImpl::CovarianceImpl(const Covariance::Options& options) : options_(options), is_computed_(false), is_valid_(false) { - evaluate_options_.num_threads = options.num_threads; - evaluate_options_.apply_loss_function = options.apply_loss_function; +#ifndef CERES_USE_OPENMP + if (options_.num_threads > 1) { + LOG(WARNING) + << "OpenMP support is not compiled into this binary; " + << "only options.num_threads = 1 is supported. Switching " + << "to single threaded mode."; + options_.num_threads = 1; + } +#endif + evaluate_options_.num_threads = options_.num_threads; + evaluate_options_.apply_loss_function = options_.apply_loss_function; } CovarianceImpl::~CovarianceImpl() { @@ -396,11 +390,15 @@ bool CovarianceImpl::ComputeCovarianceValues() { case DENSE_SVD: return ComputeCovarianceValuesUsingDenseSVD(); #ifndef CERES_NO_SUITESPARSE - case SPARSE_CHOLESKY: - return ComputeCovarianceValuesUsingSparseCholesky(); - case SPARSE_QR: - return ComputeCovarianceValuesUsingSparseQR(); + case SUITE_SPARSE_QR: + return ComputeCovarianceValuesUsingSuiteSparseQR(); +#else + LOG(ERROR) << "SuiteSparse is required to use the " + << "SUITE_SPARSE_QR algorithm."; + return false; #endif + case EIGEN_SPARSE_QR: + return ComputeCovarianceValuesUsingEigenSparseQR(); default: LOG(ERROR) << "Unsupported covariance estimation algorithm type: " << CovarianceAlgorithmTypeToString(options_.algorithm_type); @@ -409,197 +407,7 @@ bool CovarianceImpl::ComputeCovarianceValues() { return false; } -bool CovarianceImpl::ComputeCovarianceValuesUsingSparseCholesky() { - EventLogger event_logger( - "CovarianceImpl::ComputeCovarianceValuesUsingSparseCholesky"); -#ifndef CERES_NO_SUITESPARSE - if (covariance_matrix_.get() == NULL) { - // Nothing to do, all zeros covariance matrix. - return true; - } - - SuiteSparse ss; - - CRSMatrix jacobian; - problem_->Evaluate(evaluate_options_, NULL, NULL, NULL, &jacobian); - - event_logger.AddEvent("Evaluate"); - // m is a transposed view of the Jacobian. - cholmod_sparse cholmod_jacobian_view; - cholmod_jacobian_view.nrow = jacobian.num_cols; - cholmod_jacobian_view.ncol = jacobian.num_rows; - cholmod_jacobian_view.nzmax = jacobian.values.size(); - cholmod_jacobian_view.nz = NULL; - cholmod_jacobian_view.p = reinterpret_cast<void*>(&jacobian.rows[0]); - cholmod_jacobian_view.i = reinterpret_cast<void*>(&jacobian.cols[0]); - cholmod_jacobian_view.x = reinterpret_cast<void*>(&jacobian.values[0]); - cholmod_jacobian_view.z = NULL; - cholmod_jacobian_view.stype = 0; // Matrix is not symmetric. - cholmod_jacobian_view.itype = CHOLMOD_INT; - cholmod_jacobian_view.xtype = CHOLMOD_REAL; - cholmod_jacobian_view.dtype = CHOLMOD_DOUBLE; - cholmod_jacobian_view.sorted = 1; - cholmod_jacobian_view.packed = 1; - - string message; - cholmod_factor* factor = ss.AnalyzeCholesky(&cholmod_jacobian_view, &message); - event_logger.AddEvent("Symbolic Factorization"); - if (factor == NULL) { - LOG(ERROR) << "Covariance estimation failed. " - << "CHOLMOD symbolic cholesky factorization returned with: " - << message; - return false; - } - - LinearSolverTerminationType termination_type = - ss.Cholesky(&cholmod_jacobian_view, factor, &message); - event_logger.AddEvent("Numeric Factorization"); - if (termination_type != LINEAR_SOLVER_SUCCESS) { - LOG(ERROR) << "Covariance estimation failed. " - << "CHOLMOD numeric cholesky factorization returned with: " - << message; - ss.Free(factor); - return false; - } - - const double reciprocal_condition_number = - cholmod_rcond(factor, ss.mutable_cc()); - - if (reciprocal_condition_number < - options_.min_reciprocal_condition_number) { - LOG(ERROR) << "Cholesky factorization of J'J is not reliable. " - << "Reciprocal condition number: " - << reciprocal_condition_number << " " - << "min_reciprocal_condition_number: " - << options_.min_reciprocal_condition_number; - ss.Free(factor); - return false; - } - - const int num_rows = covariance_matrix_->num_rows(); - const int* rows = covariance_matrix_->rows(); - const int* cols = covariance_matrix_->cols(); - double* values = covariance_matrix_->mutable_values(); - - // The following loop exploits the fact that the i^th column of A^{-1} - // is given by the solution to the linear system - // - // A x = e_i - // - // where e_i is a vector with e(i) = 1 and all other entries zero. - // - // Since the covariance matrix is symmetric, the i^th row and column - // are equal. - // - // The ifdef separates two different version of SuiteSparse. Newer - // versions of SuiteSparse have the cholmod_solve2 function which - // re-uses memory across calls. -#if (SUITESPARSE_VERSION < 4002) - cholmod_dense* rhs = ss.CreateDenseVector(NULL, num_rows, num_rows); - double* rhs_x = reinterpret_cast<double*>(rhs->x); - - for (int r = 0; r < num_rows; ++r) { - int row_begin = rows[r]; - int row_end = rows[r + 1]; - if (row_end == row_begin) { - continue; - } - - rhs_x[r] = 1.0; - cholmod_dense* solution = ss.Solve(factor, rhs, &message); - double* solution_x = reinterpret_cast<double*>(solution->x); - for (int idx = row_begin; idx < row_end; ++idx) { - const int c = cols[idx]; - values[idx] = solution_x[c]; - } - ss.Free(solution); - rhs_x[r] = 0.0; - } - - ss.Free(rhs); -#else // SUITESPARSE_VERSION < 4002 - - const int num_threads = options_.num_threads; - vector<PerThreadContext*> contexts(num_threads); - for (int i = 0; i < num_threads; ++i) { - contexts[i] = new PerThreadContext(num_rows); - } - - // The first call to cholmod_solve2 is not thread safe, since it - // changes the factorization from supernodal to simplicial etc. - { - PerThreadContext* context = contexts[0]; - double* context_rhs_x = reinterpret_cast<double*>(context->rhs->x); - context_rhs_x[0] = 1.0; - cholmod_solve2(CHOLMOD_A, - factor, - context->rhs, - NULL, - &context->solution, - &context->solution_set, - &context->y_workspace, - &context->e_workspace, - context->ss.mutable_cc()); - context_rhs_x[0] = 0.0; - } - -#pragma omp parallel for num_threads(num_threads) schedule(dynamic) - for (int r = 0; r < num_rows; ++r) { - int row_begin = rows[r]; - int row_end = rows[r + 1]; - if (row_end == row_begin) { - continue; - } - -# ifdef CERES_USE_OPENMP - int thread_id = omp_get_thread_num(); -# else - int thread_id = 0; -# endif - - PerThreadContext* context = contexts[thread_id]; - double* context_rhs_x = reinterpret_cast<double*>(context->rhs->x); - context_rhs_x[r] = 1.0; - - // TODO(sameeragarwal) There should be a more efficient way - // involving the use of Bset but I am unable to make it work right - // now. - cholmod_solve2(CHOLMOD_A, - factor, - context->rhs, - NULL, - &context->solution, - &context->solution_set, - &context->y_workspace, - &context->e_workspace, - context->ss.mutable_cc()); - - double* solution_x = reinterpret_cast<double*>(context->solution->x); - for (int idx = row_begin; idx < row_end; ++idx) { - const int c = cols[idx]; - values[idx] = solution_x[c]; - } - context_rhs_x[r] = 0.0; - } - - for (int i = 0; i < num_threads; ++i) { - delete contexts[i]; - } - -#endif // SUITESPARSE_VERSION < 4002 - - ss.Free(factor); - event_logger.AddEvent("Inversion"); - return true; - -#else // CERES_NO_SUITESPARSE - - return false; - -#endif // CERES_NO_SUITESPARSE -}; - -bool CovarianceImpl::ComputeCovarianceValuesUsingSparseQR() { +bool CovarianceImpl::ComputeCovarianceValuesUsingSuiteSparseQR() { EventLogger event_logger( "CovarianceImpl::ComputeCovarianceValuesUsingSparseQR"); @@ -851,7 +659,102 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingDenseSVD() { } event_logger.AddEvent("CopyToCovarianceMatrix"); return true; -}; +} + +bool CovarianceImpl::ComputeCovarianceValuesUsingEigenSparseQR() { + EventLogger event_logger( + "CovarianceImpl::ComputeCovarianceValuesUsingEigenSparseQR"); + if (covariance_matrix_.get() == NULL) { + // Nothing to do, all zeros covariance matrix. + return true; + } + + CRSMatrix jacobian; + problem_->Evaluate(evaluate_options_, NULL, NULL, NULL, &jacobian); + event_logger.AddEvent("Evaluate"); + + typedef Eigen::SparseMatrix<double, Eigen::ColMajor> EigenSparseMatrix; + + // Convert the matrix to column major order as required by SparseQR. + EigenSparseMatrix sparse_jacobian = + Eigen::MappedSparseMatrix<double, Eigen::RowMajor>( + jacobian.num_rows, jacobian.num_cols, + static_cast<int>(jacobian.values.size()), + jacobian.rows.data(), jacobian.cols.data(), jacobian.values.data()); + event_logger.AddEvent("ConvertToSparseMatrix"); + + Eigen::SparseQR<EigenSparseMatrix, Eigen::COLAMDOrdering<int> > + qr_solver(sparse_jacobian); + event_logger.AddEvent("QRDecomposition"); + + if(qr_solver.info() != Eigen::Success) { + LOG(ERROR) << "Eigen::SparseQR decomposition failed."; + return false; + } + + if (qr_solver.rank() < jacobian.num_cols) { + LOG(ERROR) << "Jacobian matrix is rank deficient. " + << "Number of columns: " << jacobian.num_cols + << " rank: " << qr_solver.rank(); + return false; + } + + const int* rows = covariance_matrix_->rows(); + const int* cols = covariance_matrix_->cols(); + double* values = covariance_matrix_->mutable_values(); + + // Compute the inverse column permutation used by QR factorization. + Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic> inverse_permutation = + qr_solver.colsPermutation().inverse(); + + // The following loop exploits the fact that the i^th column of A^{-1} + // is given by the solution to the linear system + // + // A x = e_i + // + // where e_i is a vector with e(i) = 1 and all other entries zero. + // + // Since the covariance matrix is symmetric, the i^th row and column + // are equal. + const int num_cols = jacobian.num_cols; + const int num_threads = options_.num_threads; + scoped_array<double> workspace(new double[num_threads * num_cols]); + +#pragma omp parallel for num_threads(num_threads) schedule(dynamic) + for (int r = 0; r < num_cols; ++r) { + const int row_begin = rows[r]; + const int row_end = rows[r + 1]; + if (row_end == row_begin) { + continue; + } + +# ifdef CERES_USE_OPENMP + int thread_id = omp_get_thread_num(); +# else + int thread_id = 0; +# endif + + double* solution = workspace.get() + thread_id * num_cols; + SolveRTRWithSparseRHS<int>( + num_cols, + qr_solver.matrixR().innerIndexPtr(), + qr_solver.matrixR().outerIndexPtr(), + &qr_solver.matrixR().data().value(0), + inverse_permutation.indices().coeff(r), + solution); + + // Assign the values of the computed covariance using the + // inverse permutation used in the QR factorization. + for (int idx = row_begin; idx < row_end; ++idx) { + const int c = cols[idx]; + values[idx] = solution[inverse_permutation.indices().coeff(c)]; + } + } + + event_logger.AddEvent("Inverse"); + + return true; +} } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.h b/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.h index 0e7e2173079..135f4a1d624 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.h +++ b/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.h @@ -64,9 +64,9 @@ class CovarianceImpl { ProblemImpl* problem); bool ComputeCovarianceValues(); - bool ComputeCovarianceValuesUsingSparseCholesky(); - bool ComputeCovarianceValuesUsingSparseQR(); bool ComputeCovarianceValuesUsingDenseSVD(); + bool ComputeCovarianceValuesUsingSuiteSparseQR(); + bool ComputeCovarianceValuesUsingEigenSparseQR(); const CompressedRowSparseMatrix* covariance_matrix() const { return covariance_matrix_.get(); diff --git a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h index 1fed82f7866..5868401b961 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h +++ b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h @@ -38,7 +38,6 @@ #include <vector> #include "cs.h" -#include "ceres/internal/port.h" namespace ceres { namespace internal { @@ -130,9 +129,13 @@ class CXSparse { #else // CERES_NO_CXSPARSE -class CXSparse {}; typedef void cs_dis; +class CXSparse { + public: + void Free(void*) {}; + +}; #endif // CERES_NO_CXSPARSE #endif // CERES_INTERNAL_CXSPARSE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.cc b/extern/libmv/third_party/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.cc index 2f01617749d..b46cb797ff2 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.cc @@ -54,8 +54,15 @@ SparseMatrix* DynamicCompressedRowJacobianWriter::CreateJacobian() const { num_effective_parameters, 0); - CompressedRowJacobianWriter::PopulateJacobianRowAndColumnBlockVectors( - program_, jacobian); + vector<int>* row_blocks = jacobian->mutable_row_blocks(); + for (int i = 0; i < jacobian->num_rows(); ++i) { + row_blocks->push_back(1); + } + + vector<int>* col_blocks = jacobian->mutable_col_blocks(); + for (int i = 0; i < jacobian->num_cols(); ++i) { + col_blocks->push_back(1); + } return jacobian; } diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc index bca22e6de03..3272848a499 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc @@ -310,6 +310,17 @@ ProblemImpl* CreateGradientCheckingProblemImpl(ProblemImpl* problem_impl, parameter_blocks); } + // Normally, when a problem is given to the solver, we guarantee + // that the state pointers for each parameter block point to the + // user provided data. Since we are creating this new problem from a + // problem given to us at an arbitrary stage of the solve, we cannot + // depend on this being the case, so we explicitly call + // SetParameterBlockStatePtrsToUserStatePtrs to ensure that this is + // the case. + gradient_checking_problem_impl + ->mutable_program() + ->SetParameterBlockStatePtrsToUserStatePtrs(); + return gradient_checking_problem_impl; } diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_problem.cc b/extern/libmv/third_party/ceres/internal/ceres/gradient_problem.cc new file mode 100644 index 00000000000..8f9a842bd89 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_problem.cc @@ -0,0 +1,81 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/gradient_problem.h" +#include "ceres/local_parameterization.h" +#include "glog/logging.h" + +namespace ceres { + +GradientProblem::GradientProblem(FirstOrderFunction* function) + : function_(function), + parameterization_( + new IdentityParameterization(function_->NumParameters())), + scratch_(new double[function_->NumParameters()]) { +} + +GradientProblem::GradientProblem(FirstOrderFunction* function, + LocalParameterization* parameterization) + : function_(function), + parameterization_(parameterization), + scratch_(new double[function_->NumParameters()]) { + CHECK_EQ(function_->NumParameters(), parameterization_->GlobalSize()); +} + +int GradientProblem::NumParameters() const { + return function_->NumParameters(); +} + +int GradientProblem::NumLocalParameters() const { + return parameterization_->LocalSize(); +} + + +bool GradientProblem::Evaluate(const double* parameters, + double* cost, + double* gradient) const { + if (gradient == NULL) { + return function_->Evaluate(parameters, cost, NULL); + } + + return (function_->Evaluate(parameters, cost, scratch_.get()) && + parameterization_->MultiplyByJacobian(parameters, + 1, + scratch_.get(), + gradient)); +} + +bool GradientProblem::Plus(const double* x, + const double* delta, + double* x_plus_delta) const { + return parameterization_->Plus(x, delta, x_plus_delta); +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_problem_evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/gradient_problem_evaluator.h new file mode 100644 index 00000000000..20053de2af6 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_problem_evaluator.h @@ -0,0 +1,98 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2013 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_GRADIENT_PROBLEM_EVALUATOR_H_ +#define CERES_INTERNAL_GRADIENT_PROBLEM_EVALUATOR_H_ + +#include <map> +#include <string> + +#include "ceres/evaluator.h" +#include "ceres/execution_summary.h" +#include "ceres/gradient_problem.h" +#include "ceres/internal/port.h" +#include "ceres/wall_time.h" + +namespace ceres { +namespace internal { + +class GradientProblemEvaluator : public Evaluator { + public: + explicit GradientProblemEvaluator(const GradientProblem& problem) + : problem_(problem) {} + virtual ~GradientProblemEvaluator() {} + virtual SparseMatrix* CreateJacobian() const { return NULL; } + virtual bool Evaluate(const EvaluateOptions& evaluate_options, + const double* state, + double* cost, + double* residuals, + double* gradient, + SparseMatrix* jacobian) { + CHECK(jacobian == NULL); + ScopedExecutionTimer total_timer("Evaluator::Total", &execution_summary_); + ScopedExecutionTimer call_type_timer( + gradient == NULL ? "Evaluator::Cost" : "Evaluator::Gradient", + &execution_summary_); + return problem_.Evaluate(state, cost, gradient); + } + + virtual bool Plus(const double* state, + const double* delta, + double* state_plus_delta) const { + return problem_.Plus(state, delta, state_plus_delta); + } + + virtual int NumParameters() const { + return problem_.NumParameters(); + } + + virtual int NumEffectiveParameters() const { + return problem_.NumLocalParameters(); + } + + virtual int NumResiduals() const { return 1; } + + virtual map<string, int> CallStatistics() const { + return execution_summary_.calls(); + } + + virtual map<string, double> TimeStatistics() const { + return execution_summary_.times(); + } + + private: + const GradientProblem& problem_; + ::ceres::internal::ExecutionSummary execution_summary_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_GRADIENT_PROBLEM_EVALUATOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_problem_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/gradient_problem_solver.cc new file mode 100644 index 00000000000..4024f4cc4e6 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_problem_solver.cc @@ -0,0 +1,270 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/gradient_problem_solver.h" + +#include "ceres/callbacks.h" +#include "ceres/gradient_problem.h" +#include "ceres/gradient_problem_evaluator.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" +#include "ceres/map_util.h" +#include "ceres/minimizer.h" +#include "ceres/solver.h" +#include "ceres/solver_utils.h" +#include "ceres/stringprintf.h" +#include "ceres/types.h" +#include "ceres/wall_time.h" + +namespace ceres { +using internal::StringPrintf; +using internal::StringAppendF; + +namespace { + +Solver::Options GradientProblemSolverOptionsToSolverOptions( + const GradientProblemSolver::Options& options) { +#define COPY_OPTION(x) solver_options.x = options.x + + Solver::Options solver_options; + solver_options.minimizer_type = LINE_SEARCH; + COPY_OPTION(line_search_direction_type); + COPY_OPTION(line_search_type); + COPY_OPTION(nonlinear_conjugate_gradient_type); + COPY_OPTION(max_lbfgs_rank); + COPY_OPTION(use_approximate_eigenvalue_bfgs_scaling); + COPY_OPTION(line_search_interpolation_type); + COPY_OPTION(min_line_search_step_size); + COPY_OPTION(line_search_sufficient_function_decrease); + COPY_OPTION(max_line_search_step_contraction); + COPY_OPTION(min_line_search_step_contraction); + COPY_OPTION(max_num_line_search_step_size_iterations); + COPY_OPTION(max_num_line_search_direction_restarts); + COPY_OPTION(line_search_sufficient_curvature_decrease); + COPY_OPTION(max_line_search_step_expansion); + COPY_OPTION(max_num_iterations); + COPY_OPTION(max_solver_time_in_seconds); + COPY_OPTION(function_tolerance); + COPY_OPTION(gradient_tolerance); + COPY_OPTION(logging_type); + COPY_OPTION(minimizer_progress_to_stdout); + COPY_OPTION(callbacks); + return solver_options; +#undef COPY_OPTION +} + + +} // namespace + +GradientProblemSolver::~GradientProblemSolver() { +} + +void GradientProblemSolver::Solve(const GradientProblemSolver::Options& options, + const GradientProblem& problem, + double* parameters_ptr, + GradientProblemSolver::Summary* summary) { + using internal::scoped_ptr; + using internal::WallTimeInSeconds; + using internal::Minimizer; + using internal::GradientProblemEvaluator; + using internal::LoggingCallback; + using internal::SetSummaryFinalCost; + + double start_time = WallTimeInSeconds(); + Solver::Options solver_options = + GradientProblemSolverOptionsToSolverOptions(options); + + *CHECK_NOTNULL(summary) = Summary(); + summary->num_parameters = problem.NumParameters(); + summary->num_local_parameters = problem.NumLocalParameters(); + summary->line_search_direction_type = options.line_search_direction_type; // NOLINT + summary->line_search_interpolation_type = options.line_search_interpolation_type; // NOLINT + summary->line_search_type = options.line_search_type; + summary->max_lbfgs_rank = options.max_lbfgs_rank; + summary->nonlinear_conjugate_gradient_type = options.nonlinear_conjugate_gradient_type; // NOLINT + + // Check validity + if (!solver_options.IsValid(&summary->message)) { + LOG(ERROR) << "Terminating: " << summary->message; + return; + } + + // Assuming that the parameter blocks in the program have been + Minimizer::Options minimizer_options; + minimizer_options = Minimizer::Options(solver_options); + minimizer_options.evaluator.reset(new GradientProblemEvaluator(problem)); + + scoped_ptr<IterationCallback> logging_callback; + if (options.logging_type != SILENT) { + logging_callback.reset( + new LoggingCallback(LINE_SEARCH, options.minimizer_progress_to_stdout)); + minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), + logging_callback.get()); + } + + scoped_ptr<Minimizer> minimizer(Minimizer::Create(LINE_SEARCH)); + Vector solution(problem.NumParameters()); + VectorRef parameters(parameters_ptr, problem.NumParameters()); + solution = parameters; + + Solver::Summary solver_summary; + solver_summary.fixed_cost = 0.0; + solver_summary.preprocessor_time_in_seconds = 0.0; + solver_summary.postprocessor_time_in_seconds = 0.0; + + minimizer->Minimize(minimizer_options, solution.data(), &solver_summary); + + summary->termination_type = solver_summary.termination_type; + summary->message = solver_summary.message; + summary->initial_cost = solver_summary.initial_cost; + summary->final_cost = solver_summary.final_cost; + summary->iterations = solver_summary.iterations; + + if (summary->IsSolutionUsable()) { + parameters = solution; + SetSummaryFinalCost(summary); + } + + const map<string, double>& evaluator_time_statistics = + minimizer_options.evaluator->TimeStatistics(); + summary->cost_evaluation_time_in_seconds = + FindWithDefault(evaluator_time_statistics, "Evaluator::Residual", 0.0); + summary->gradient_evaluation_time_in_seconds = + FindWithDefault(evaluator_time_statistics, "Evaluator::Jacobian", 0.0); + + summary->total_time_in_seconds = WallTimeInSeconds() - start_time; +} + +// Invalid values for most fields, to ensure that we are not +// accidentally reporting default values. +GradientProblemSolver::Summary::Summary() + : termination_type(FAILURE), + message("ceres::GradientProblemSolve was not called."), + initial_cost(-1.0), + final_cost(-1.0), + total_time_in_seconds(-1.0), + cost_evaluation_time_in_seconds(-1.0), + gradient_evaluation_time_in_seconds(-1.0), + num_parameters(-1), + num_local_parameters(-1), + line_search_direction_type(LBFGS), + line_search_type(ARMIJO), + line_search_interpolation_type(BISECTION), + nonlinear_conjugate_gradient_type(FLETCHER_REEVES), + max_lbfgs_rank(-1) { +} + +bool GradientProblemSolver::Summary::IsSolutionUsable() const { + return internal::IsSolutionUsable(*this); +} + +string GradientProblemSolver::Summary::BriefReport() const { + return StringPrintf("Ceres GradientProblemSolver Report: " + "Iterations: %d, " + "Initial cost: %e, " + "Final cost: %e, " + "Termination: %s", + static_cast<int>(iterations.size()), + initial_cost, + final_cost, + TerminationTypeToString(termination_type)); +}; + +string GradientProblemSolver::Summary::FullReport() const { + using internal::VersionString; + + string report = string("\nSolver Summary (v " + VersionString() + ")\n\n"); + + StringAppendF(&report, "Parameters % 25d\n", num_parameters); + if (num_local_parameters != num_parameters) { + StringAppendF(&report, "Local parameters % 25d\n", + num_local_parameters); + } + + string line_search_direction_string; + if (line_search_direction_type == LBFGS) { + line_search_direction_string = StringPrintf("LBFGS (%d)", max_lbfgs_rank); + } else if (line_search_direction_type == NONLINEAR_CONJUGATE_GRADIENT) { + line_search_direction_string = + NonlinearConjugateGradientTypeToString( + nonlinear_conjugate_gradient_type); + } else { + line_search_direction_string = + LineSearchDirectionTypeToString(line_search_direction_type); + } + + StringAppendF(&report, "Line search direction %19s\n", + line_search_direction_string.c_str()); + + const string line_search_type_string = + StringPrintf("%s %s", + LineSearchInterpolationTypeToString( + line_search_interpolation_type), + LineSearchTypeToString(line_search_type)); + StringAppendF(&report, "Line search type %19s\n", + line_search_type_string.c_str()); + StringAppendF(&report, "\n"); + + StringAppendF(&report, "\nCost:\n"); + StringAppendF(&report, "Initial % 30e\n", initial_cost); + if (termination_type != FAILURE && + termination_type != USER_FAILURE) { + StringAppendF(&report, "Final % 30e\n", final_cost); + StringAppendF(&report, "Change % 30e\n", + initial_cost - final_cost); + } + + StringAppendF(&report, "\nMinimizer iterations % 16d\n", + static_cast<int>(iterations.size())); + + StringAppendF(&report, "\nTime (in seconds):\n"); + + StringAppendF(&report, "\n Cost evaluation %23.3f\n", + cost_evaluation_time_in_seconds); + StringAppendF(&report, " Gradient evaluation %23.3f\n", + gradient_evaluation_time_in_seconds); + + StringAppendF(&report, "Total %25.3f\n\n", + total_time_in_seconds); + + StringAppendF(&report, "Termination: %25s (%s)\n", + TerminationTypeToString(termination_type), message.c_str()); + return report; +}; + +void Solve(const GradientProblemSolver::Options& options, + const GradientProblem& problem, + double* parameters, + GradientProblemSolver::Summary* summary) { + GradientProblemSolver solver; + solver.Solve(options, problem, parameters, summary); +} + +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/graph.h b/extern/libmv/third_party/ceres/internal/ceres/graph.h index 5f92d4d4df2..f639d15323d 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/graph.h +++ b/extern/libmv/third_party/ceres/internal/ceres/graph.h @@ -43,13 +43,75 @@ namespace ceres { namespace internal { -// A weighted undirected graph templated over the vertex ids. Vertex -// should be hashable and comparable. +// A unweighted undirected graph templated over the vertex ids. Vertex +// should be hashable. template <typename Vertex> class Graph { public: Graph() {} + // Add a vertex. + void AddVertex(const Vertex& vertex) { + if (vertices_.insert(vertex).second) { + edges_[vertex] = HashSet<Vertex>(); + } + } + + bool RemoveVertex(const Vertex& vertex) { + if (vertices_.find(vertex) == vertices_.end()) { + return false; + } + + vertices_.erase(vertex); + const HashSet<Vertex>& sinks = edges_[vertex]; + for (typename HashSet<Vertex>::const_iterator it = sinks.begin(); + it != sinks.end(); ++it) { + edges_[*it].erase(vertex); + } + + edges_.erase(vertex); + return true; + } + + // Add an edge between the vertex1 and vertex2. Calling AddEdge on a + // pair of vertices which do not exist in the graph yet will result + // in undefined behavior. + // + // It is legal to call this method repeatedly for the same set of + // vertices. + void AddEdge(const Vertex& vertex1, const Vertex& vertex2) { + DCHECK(vertices_.find(vertex1) != vertices_.end()); + DCHECK(vertices_.find(vertex2) != vertices_.end()); + + if (edges_[vertex1].insert(vertex2).second) { + edges_[vertex2].insert(vertex1); + } + } + + // Calling Neighbors on a vertex not in the graph will result in + // undefined behaviour. + const HashSet<Vertex>& Neighbors(const Vertex& vertex) const { + return FindOrDie(edges_, vertex); + } + + const HashSet<Vertex>& vertices() const { + return vertices_; + } + + private: + HashSet<Vertex> vertices_; + HashMap<Vertex, HashSet<Vertex> > edges_; + + CERES_DISALLOW_COPY_AND_ASSIGN(Graph); +}; + +// A weighted undirected graph templated over the vertex ids. Vertex +// should be hashable and comparable. +template <typename Vertex> +class WeightedGraph { + public: + WeightedGraph() {} + // Add a weighted vertex. If the vertex already exists in the graph, // its weight is set to the new weight. void AddVertex(const Vertex& vertex, double weight) { @@ -152,7 +214,7 @@ class Graph { HashMap<Vertex, HashSet<Vertex> > edges_; HashMap<pair<Vertex, Vertex>, double> edge_weights_; - CERES_DISALLOW_COPY_AND_ASSIGN(Graph); + CERES_DISALLOW_COPY_AND_ASSIGN(WeightedGraph); }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h b/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h index ca3a2fe1a88..fb75e2f45f2 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h +++ b/extern/libmv/third_party/ceres/internal/ceres/graph_algorithms.h @@ -38,6 +38,7 @@ #include <utility> #include "ceres/collections_port.h" #include "ceres/graph.h" +#include "ceres/wall_time.h" #include "glog/logging.h" namespace ceres { @@ -270,11 +271,11 @@ Vertex FindConnectedComponent(const Vertex& vertex, // spanning forest, or a collection of linear paths that span the // graph G. template <typename Vertex> -Graph<Vertex>* -Degree2MaximumSpanningForest(const Graph<Vertex>& graph) { +WeightedGraph<Vertex>* +Degree2MaximumSpanningForest(const WeightedGraph<Vertex>& graph) { // Array of edges sorted in decreasing order of their weights. vector<pair<double, pair<Vertex, Vertex> > > weighted_edges; - Graph<Vertex>* forest = new Graph<Vertex>(); + WeightedGraph<Vertex>* forest = new WeightedGraph<Vertex>(); // Disjoint-set to keep track of the connected components in the // maximum spanning tree. diff --git a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc index 6de410bf80f..0cf08fef5f7 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc @@ -101,6 +101,7 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl( // complement matrix with the block diagonal of the matrix F'F as // the preconditioner. LinearSolver::Options cg_options; + cg_options.min_num_iterations = options_.min_num_iterations; cg_options.max_num_iterations = options_.max_num_iterations; ConjugateGradientsSolver cg_solver(cg_options); LinearSolver::PerSolveOptions cg_per_solve_options; diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc b/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc index e04c65b63be..dddcecdb196 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_direction.cc @@ -65,7 +65,7 @@ class NonlinearConjugateGradient : public LineSearchDirection { case FLETCHER_REEVES: beta = current.gradient_squared_norm / previous.gradient_squared_norm; break; - case POLAK_RIBIRERE: + case POLAK_RIBIERE: gradient_change = current.gradient - previous.gradient; beta = (current.gradient.dot(gradient_change) / previous.gradient_squared_norm); diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc index ae77a73805c..ad28ffb137d 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc @@ -103,7 +103,7 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options, double start_time = WallTimeInSeconds(); double iteration_start_time = start_time; - Evaluator* evaluator = CHECK_NOTNULL(options.evaluator); + Evaluator* evaluator = CHECK_NOTNULL(options.evaluator.get()); const int num_parameters = evaluator->NumParameters(); const int num_effective_parameters = evaluator->NumEffectiveParameters(); @@ -375,7 +375,6 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options, WallTimeInSeconds() - start_time + summary->preprocessor_time_in_seconds; - summary->iterations.push_back(iteration_summary); ++summary->num_successful_steps; if (iteration_summary.gradient_max_norm <= options.gradient_tolerance) { @@ -401,6 +400,8 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options, VLOG_IF(1, is_not_silent) << "Terminating: " << summary->message; break; } + + summary->iterations.push_back(iteration_summary); } } diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search_preprocessor.cc b/extern/libmv/third_party/ceres/internal/ceres/line_search_preprocessor.cc new file mode 100644 index 00000000000..bf17dee351d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_preprocessor.cc @@ -0,0 +1,106 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/line_search_preprocessor.h" + +#include <numeric> +#include <string> +#include "ceres/evaluator.h" +#include "ceres/minimizer.h" +#include "ceres/problem_impl.h" +#include "ceres/program.h" +#include "ceres/wall_time.h" + +namespace ceres { +namespace internal { +namespace { + +bool IsProgramValid(const Program& program, string* error) { + if (program.IsBoundsConstrained()) { + *error = "LINE_SEARCH Minimizer does not support bounds."; + return false; + } + return program.ParameterBlocksAreFinite(error); +} + +bool SetupEvaluator(PreprocessedProblem* pp) { + pp->evaluator_options = Evaluator::Options(); + // This ensures that we get a Block Jacobian Evaluator without any + // requirement on orderings. + pp->evaluator_options.linear_solver_type = CGNR; + pp->evaluator_options.num_eliminate_blocks = 0; + pp->evaluator_options.num_threads = pp->options.num_threads; + pp->evaluator.reset(Evaluator::Create(pp->evaluator_options, + pp->reduced_program.get(), + &pp->error)); + return (pp->evaluator.get() != NULL); +} + +} // namespace + +LineSearchPreprocessor::~LineSearchPreprocessor() { +} + +bool LineSearchPreprocessor::Preprocess(const Solver::Options& options, + ProblemImpl* problem, + PreprocessedProblem* pp) { + CHECK_NOTNULL(pp); + pp->options = options; + ChangeNumThreadsIfNeeded(&pp->options); + + pp->problem = problem; + Program* program = problem->mutable_program(); + if (!IsProgramValid(*program, &pp->error)) { + return false; + } + + pp->reduced_program.reset( + program->CreateReducedProgram(&pp->removed_parameter_blocks, + &pp->fixed_cost, + &pp->error)); + + if (pp->reduced_program.get() == NULL) { + return false; + } + + if (pp->reduced_program->NumParameterBlocks() == 0) { + return true; + } + + if (!SetupEvaluator(pp)) { + return false; + } + + SetupCommonMinimizerOptions(pp); + return true; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search_preprocessor.h b/extern/libmv/third_party/ceres/internal/ceres/line_search_preprocessor.h new file mode 100644 index 00000000000..54b968bc29e --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_preprocessor.h @@ -0,0 +1,50 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_LINE_SEARCH_PREPROCESSOR_H_ +#define CERES_INTERNAL_LINE_SEARCH_PREPROCESSOR_H_ + +#include "ceres/preprocessor.h" + +namespace ceres { +namespace internal { + +class LineSearchPreprocessor : public Preprocessor { + public: + virtual ~LineSearchPreprocessor(); + virtual bool Preprocess(const Solver::Options& options, + ProblemImpl* problem, + PreprocessedProblem* preprocessed_problem); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_LINE_SEARCH_PREPROCESSOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc index 08c3ba110d0..e479b751363 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc @@ -45,26 +45,48 @@ namespace internal { LinearSolver::~LinearSolver() { } +LinearSolverType LinearSolver::LinearSolverForZeroEBlocks( + LinearSolverType linear_solver_type) { + if (!IsSchurType(linear_solver_type)) { + return linear_solver_type; + } + + if (linear_solver_type == SPARSE_SCHUR) { + return SPARSE_NORMAL_CHOLESKY; + } + + if (linear_solver_type == DENSE_SCHUR) { + // TODO(sameeragarwal): This is probably not a great choice. + // Ideally, we should have a DENSE_NORMAL_CHOLESKY, that can take + // a BlockSparseMatrix as input. + return DENSE_QR; + } + + if (linear_solver_type == ITERATIVE_SCHUR) { + return CGNR; + } + + return linear_solver_type; +} + LinearSolver* LinearSolver::Create(const LinearSolver::Options& options) { switch (options.type) { case CGNR: return new CgnrSolver(options); case SPARSE_NORMAL_CHOLESKY: -#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) - LOG(WARNING) << "SPARSE_NORMAL_CHOLESKY is not available. Please " - << "build Ceres with SuiteSparse or CXSparse. " - << "Returning NULL."; +#if defined(CERES_NO_SUITESPARSE) && \ + defined(CERES_NO_CXSPARSE) && \ + !defined(CERES_USE_EIGEN_SPARSE) return NULL; #else return new SparseNormalCholeskySolver(options); #endif case SPARSE_SCHUR: -#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) - LOG(WARNING) << "SPARSE_SCHUR is not available. Please " - << "build Ceres with SuiteSparse or CXSparse. " - << "Returning NULL."; +#if defined(CERES_NO_SUITESPARSE) && \ + defined(CERES_NO_CXSPARSE) && \ + !defined(CERES_USE_EIGEN_SPARSE) return NULL; #else return new SparseSchurComplementSolver(options); @@ -74,7 +96,11 @@ LinearSolver* LinearSolver::Create(const LinearSolver::Options& options) { return new DenseSchurComplementSolver(options); case ITERATIVE_SCHUR: - return new IterativeSchurComplementSolver(options); + if (options.use_explicit_schur_complement) { + return new SparseSchurComplementSolver(options); + } else { + return new IterativeSchurComplementSolver(options); + } case DENSE_QR: return new DenseQRSolver(options); diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h index f091bc5b187..5f59765f074 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h @@ -99,6 +99,7 @@ class LinearSolver { sparse_linear_algebra_library_type(SUITE_SPARSE), use_postordering(false), dynamic_sparsity(false), + use_explicit_schur_complement(false), min_num_iterations(1), max_num_iterations(1), num_threads(1), @@ -114,9 +115,10 @@ class LinearSolver { DenseLinearAlgebraLibraryType dense_linear_algebra_library_type; SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type; - // See solver.h for information about this flag. + // See solver.h for information about these flags. bool use_postordering; bool dynamic_sparsity; + bool use_explicit_schur_complement; // Number of internal iterations that the solver uses. This // parameter only makes sense for iterative solvers like CG. @@ -274,6 +276,14 @@ class LinearSolver { string message; }; + // If the optimization problem is such that there are no remaining + // e-blocks, a Schur type linear solver cannot be used. If the + // linear solver is of Schur type, this function implements a policy + // to select an alternate nearest linear solver to the one selected + // by the user. The input linear_solver_type is returned otherwise. + static LinearSolverType LinearSolverForZeroEBlocks( + LinearSolverType linear_solver_type); + virtual ~LinearSolver(); // Solve Ax = b. diff --git a/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc b/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc index 26e7f4908a4..a4832c57443 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// Copyright 2014 Google Inc. All rights reserved. // http://code.google.com/p/ceres-solver/ // // Redistribution and use in source and binary forms, with or without @@ -36,6 +36,23 @@ namespace ceres { +LocalParameterization::~LocalParameterization() { +} + +bool LocalParameterization::MultiplyByJacobian(const double* x, + const int num_rows, + const double* global_matrix, + double* local_matrix) const { + Matrix jacobian(GlobalSize(), LocalSize()); + if (!ComputeJacobian(x, jacobian.data())) { + return false; + } + + MatrixRef(local_matrix, num_rows, LocalSize()) = + ConstMatrixRef(global_matrix, num_rows, GlobalSize()) * jacobian; + return true; +} + IdentityParameterization::IdentityParameterization(const int size) : size_(size) { CHECK_GT(size, 0); @@ -55,6 +72,16 @@ bool IdentityParameterization::ComputeJacobian(const double* x, return true; } +bool IdentityParameterization::MultiplyByJacobian(const double* x, + const int num_cols, + const double* global_matrix, + double* local_matrix) const { + std::copy(global_matrix, + global_matrix + num_cols * GlobalSize(), + local_matrix); + return true; +} + SubsetParameterization::SubsetParameterization( int size, const vector<int>& constant_parameters) @@ -108,6 +135,21 @@ bool SubsetParameterization::ComputeJacobian(const double* x, return true; } +bool SubsetParameterization::MultiplyByJacobian(const double* x, + const int num_rows, + const double* global_matrix, + double* local_matrix) const { + for (int row = 0; row < num_rows; ++row) { + for (int col = 0, j = 0; col < constancy_mask_.size(); ++col) { + if (!constancy_mask_[col]) { + local_matrix[row * LocalSize() + j++] = + global_matrix[row * GlobalSize() + col]; + } + } + } + return true; +} + bool QuaternionParameterization::Plus(const double* x, const double* delta, double* x_plus_delta) const { diff --git a/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc b/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc index b948f289f21..62b545be12f 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc @@ -34,13 +34,14 @@ #include <cmath> #include <cstddef> +#include <limits> namespace ceres { void TrivialLoss::Evaluate(double s, double rho[3]) const { rho[0] = s; - rho[1] = 1; - rho[2] = 0; + rho[1] = 1.0; + rho[2] = 0.0; } void HuberLoss::Evaluate(double s, double rho[3]) const { @@ -48,32 +49,32 @@ void HuberLoss::Evaluate(double s, double rho[3]) const { // Outlier region. // 'r' is always positive. const double r = sqrt(s); - rho[0] = 2 * a_ * r - b_; - rho[1] = a_ / r; - rho[2] = - rho[1] / (2 * s); + rho[0] = 2.0 * a_ * r - b_; + rho[1] = std::max(std::numeric_limits<double>::min(), a_ / r); + rho[2] = - rho[1] / (2.0 * s); } else { // Inlier region. rho[0] = s; - rho[1] = 1; - rho[2] = 0; + rho[1] = 1.0; + rho[2] = 0.0; } } void SoftLOneLoss::Evaluate(double s, double rho[3]) const { - const double sum = 1 + s * c_; + const double sum = 1.0 + s * c_; const double tmp = sqrt(sum); // 'sum' and 'tmp' are always positive, assuming that 's' is. - rho[0] = 2 * b_ * (tmp - 1); - rho[1] = 1 / tmp; - rho[2] = - (c_ * rho[1]) / (2 * sum); + rho[0] = 2.0 * b_ * (tmp - 1.0); + rho[1] = std::max(std::numeric_limits<double>::min(), 1.0 / tmp); + rho[2] = - (c_ * rho[1]) / (2.0 * sum); } void CauchyLoss::Evaluate(double s, double rho[3]) const { - const double sum = 1 + s * c_; - const double inv = 1 / sum; + const double sum = 1.0 + s * c_; + const double inv = 1.0 / sum; // 'sum' and 'inv' are always positive, assuming that 's' is. rho[0] = b_ * log(sum); - rho[1] = inv; + rho[1] = std::max(std::numeric_limits<double>::min(), inv); rho[2] = - c_ * (inv * inv); } @@ -82,8 +83,8 @@ void ArctanLoss::Evaluate(double s, double rho[3]) const { const double inv = 1 / sum; // 'sum' and 'inv' are always positive. rho[0] = a_ * atan2(s, a_); - rho[1] = inv; - rho[2] = -2 * s * b_ * (inv * inv); + rho[1] = std::max(std::numeric_limits<double>::min(), inv); + rho[2] = -2.0 * s * b_ * (inv * inv); } TolerantLoss::TolerantLoss(double a, double b) @@ -108,7 +109,7 @@ void TolerantLoss::Evaluate(double s, double rho[3]) const { } else { const double e_x = exp(x); rho[0] = b_ * log(1.0 + e_x) - c_; - rho[1] = e_x / (1.0 + e_x); + rho[1] = std::max(std::numeric_limits<double>::min(), e_x / (1.0 + e_x)); rho[2] = 0.5 / (b_ * (1.0 + cosh(x))); } } diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc index 6c3b68dbbc2..558921b8441 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc @@ -28,13 +28,29 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) +#include "ceres/line_search_minimizer.h" #include "ceres/minimizer.h" +#include "ceres/trust_region_minimizer.h" #include "ceres/types.h" #include "glog/logging.h" namespace ceres { namespace internal { +Minimizer* Minimizer::Create(MinimizerType minimizer_type) { + if (minimizer_type == TRUST_REGION) { + return new TrustRegionMinimizer; + } + + if (minimizer_type == LINE_SEARCH) { + return new LineSearchMinimizer; + } + + LOG(FATAL) << "Unknown minimizer_type: " << minimizer_type; + return NULL; +} + + Minimizer::~Minimizer() {} bool Minimizer::RunCallbacks(const Minimizer::Options& options, diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h index f1da3f704fa..dabf07e583a 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h +++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h @@ -41,9 +41,10 @@ namespace ceres { namespace internal { class Evaluator; -class LinearSolver; class SparseMatrix; class TrustRegionStrategy; +class CoordinateDescentMinimizer; +class LinearSolver; // Interface for non-linear least squares solvers. class Minimizer { @@ -107,14 +108,10 @@ class Minimizer { options.line_search_sufficient_curvature_decrease; max_line_search_step_expansion = options.max_line_search_step_expansion; - is_silent = (options.logging_type == SILENT); - evaluator = NULL; - trust_region_strategy = NULL; - jacobian = NULL; - callbacks = options.callbacks; - inner_iteration_minimizer = NULL; inner_iteration_tolerance = options.inner_iteration_tolerance; + is_silent = (options.logging_type == SILENT); is_constrained = false; + callbacks = options.callbacks; } int max_num_iterations; @@ -154,10 +151,14 @@ class Minimizer { int max_num_line_search_direction_restarts; double line_search_sufficient_curvature_decrease; double max_line_search_step_expansion; + double inner_iteration_tolerance; // If true, then all logging is disabled. bool is_silent; + // Use a bounds constrained optimization algorithm. + bool is_constrained; + // List of callbacks that are executed by the Minimizer at the end // of each iteration. // @@ -165,27 +166,23 @@ class Minimizer { vector<IterationCallback*> callbacks; // Object responsible for evaluating the cost, residuals and - // Jacobian matrix. The Options struct does not own this pointer. - Evaluator* evaluator; + // Jacobian matrix. + shared_ptr<Evaluator> evaluator; // Object responsible for actually computing the trust region - // step, and sizing the trust region radius. The Options struct - // does not own this pointer. - TrustRegionStrategy* trust_region_strategy; + // step, and sizing the trust region radius. + shared_ptr<TrustRegionStrategy> trust_region_strategy; // Object holding the Jacobian matrix. It is assumed that the // sparsity structure of the matrix has already been initialized // and will remain constant for the life time of the - // optimization. The Options struct does not own this pointer. - SparseMatrix* jacobian; + // optimization. + shared_ptr<SparseMatrix> jacobian; - Minimizer* inner_iteration_minimizer; - double inner_iteration_tolerance; - - // Use a bounds constrained optimization algorithm. - bool is_constrained; + shared_ptr<CoordinateDescentMinimizer> inner_iteration_minimizer; }; + static Minimizer* Create(MinimizerType minimizer_type); static bool RunCallbacks(const Options& options, const IterationSummary& iteration_summary, Solver::Summary* summary); diff --git a/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.cc b/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.cc index 190715bee43..1525de90d60 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.cc @@ -37,6 +37,7 @@ #include "ceres/parameter_block.h" #include "ceres/program.h" #include "ceres/residual_block.h" +#include "ceres/wall_time.h" #include "glog/logging.h" namespace ceres { @@ -45,8 +46,10 @@ namespace internal { int ComputeStableSchurOrdering(const Program& program, vector<ParameterBlock*>* ordering) { CHECK_NOTNULL(ordering)->clear(); - + EventLogger event_logger("ComputeStableSchurOrdering"); scoped_ptr<Graph< ParameterBlock*> > graph(CreateHessianGraph(program)); + event_logger.AddEvent("CreateHessianGraph"); + const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); const HashSet<ParameterBlock*>& vertices = graph->vertices(); for (int i = 0; i < parameter_blocks.size(); ++i) { @@ -54,8 +57,10 @@ int ComputeStableSchurOrdering(const Program& program, ordering->push_back(parameter_blocks[i]); } } + event_logger.AddEvent("Preordering"); int independent_set_size = StableIndependentSetOrdering(*graph, ordering); + event_logger.AddEvent("StableIndependentSet"); // Add the excluded blocks to back of the ordering vector. for (int i = 0; i < parameter_blocks.size(); ++i) { @@ -64,6 +69,7 @@ int ComputeStableSchurOrdering(const Program& program, ordering->push_back(parameter_block); } } + event_logger.AddEvent("ConstantParameterBlocks"); return independent_set_size; } @@ -109,8 +115,7 @@ void ComputeRecursiveIndependentSetOrdering(const Program& program, } } -Graph<ParameterBlock*>* -CreateHessianGraph(const Program& program) { +Graph<ParameterBlock*>* CreateHessianGraph(const Program& program) { Graph<ParameterBlock*>* graph = CHECK_NOTNULL(new Graph<ParameterBlock*>); const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); for (int i = 0; i < parameter_blocks.size(); ++i) { @@ -144,5 +149,21 @@ CreateHessianGraph(const Program& program) { return graph; } +void OrderingToGroupSizes(const ParameterBlockOrdering* ordering, + vector<int>* group_sizes) { + CHECK_NOTNULL(group_sizes)->clear(); + if (ordering == NULL) { + return; + } + + const map<int, set<double*> >& group_to_elements = + ordering->group_to_elements(); + for (map<int, set<double*> >::const_iterator it = group_to_elements.begin(); + it != group_to_elements.end(); + ++it) { + group_sizes->push_back(it->second.size()); + } +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.h b/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.h index 4675cb8dc7c..5de99511138 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.h +++ b/extern/libmv/third_party/ceres/internal/ceres/parameter_block_ordering.h @@ -78,6 +78,11 @@ void ComputeRecursiveIndependentSetOrdering(const Program& program, // parameter blocks, if they co-occur in a residual block. Graph<ParameterBlock*>* CreateHessianGraph(const Program& program); +// Iterate over each of the groups in order of their priority and fill +// summary with their sizes. +void OrderingToGroupSizes(const ParameterBlockOrdering* ordering, + vector<int>* group_sizes); + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/preconditioner.cc index 505a47d3d61..062347fccc1 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/preconditioner.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/preconditioner.cc @@ -37,6 +37,16 @@ namespace internal { Preconditioner::~Preconditioner() { } +PreconditionerType Preconditioner::PreconditionerForZeroEBlocks( + PreconditionerType preconditioner_type) { + if (preconditioner_type == SCHUR_JACOBI || + preconditioner_type == CLUSTER_JACOBI || + preconditioner_type == CLUSTER_TRIDIAGONAL) { + return JACOBI; + } + return preconditioner_type; +} + SparseMatrixPreconditionerWrapper::SparseMatrixPreconditionerWrapper( const SparseMatrix* matrix) : matrix_(CHECK_NOTNULL(matrix)) { diff --git a/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h index 21cbc00b542..e8d5994269a 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h +++ b/extern/libmv/third_party/ceres/internal/ceres/preconditioner.h @@ -36,6 +36,7 @@ #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/linear_operator.h" #include "ceres/sparse_matrix.h" +#include "ceres/types.h" namespace ceres { namespace internal { @@ -95,6 +96,14 @@ class Preconditioner : public LinearOperator { int f_block_size; }; + // If the optimization problem is such that there are no remaining + // e-blocks, ITERATIVE_SCHUR with a Schur type preconditioner cannot + // be used. This function returns JACOBI if a preconditioner for + // ITERATIVE_SCHUR is used. The input preconditioner_type is + // returned otherwise. + static PreconditionerType PreconditionerForZeroEBlocks( + PreconditionerType preconditioner_type); + virtual ~Preconditioner(); // Update the numerical value of the preconditioner for the linear diff --git a/extern/libmv/third_party/ceres/internal/ceres/preprocessor.cc b/extern/libmv/third_party/ceres/internal/ceres/preprocessor.cc new file mode 100644 index 00000000000..318c5e2ebef --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/preprocessor.cc @@ -0,0 +1,113 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameragarwal@google.com (Sameer Agarwal) + +#include "ceres/callbacks.h" +#include "ceres/gradient_checking_cost_function.h" +#include "ceres/line_search_preprocessor.h" +#include "ceres/preprocessor.h" +#include "ceres/problem_impl.h" +#include "ceres/solver.h" +#include "ceres/trust_region_preprocessor.h" + +namespace ceres { +namespace internal { + +Preprocessor* Preprocessor::Create(MinimizerType minimizer_type) { + if (minimizer_type == TRUST_REGION) { + return new TrustRegionPreprocessor; + } + + if (minimizer_type == LINE_SEARCH) { + return new LineSearchPreprocessor; + } + + LOG(FATAL) << "Unknown minimizer_type: " << minimizer_type; + return NULL; +} + +Preprocessor::~Preprocessor() { +} + +void ChangeNumThreadsIfNeeded(Solver::Options* options) { +#ifndef CERES_USE_OPENMP + if (options->num_threads > 1) { + LOG(WARNING) + << "OpenMP support is not compiled into this binary; " + << "only options.num_threads = 1 is supported. Switching " + << "to single threaded mode."; + options->num_threads = 1; + } + + // Only the Trust Region solver currently uses a linear solver. + if (options->minimizer_type == TRUST_REGION && + options->num_linear_solver_threads > 1) { + LOG(WARNING) + << "OpenMP support is not compiled into this binary; " + << "only options.num_linear_solver_threads=1 is supported. Switching " + << "to single threaded mode."; + options->num_linear_solver_threads = 1; + } +#endif // CERES_USE_OPENMP +} + +void SetupCommonMinimizerOptions(PreprocessedProblem* pp) { + const Solver::Options& options = pp->options; + Program* program = pp->reduced_program.get(); + + // Assuming that the parameter blocks in the program have been + // reordered as needed, extract them into a contiguous vector. + pp->reduced_parameters.resize(program->NumParameters()); + double* reduced_parameters = pp->reduced_parameters.data(); + program->ParameterBlocksToStateVector(reduced_parameters); + + Minimizer::Options& minimizer_options = pp->minimizer_options; + minimizer_options = Minimizer::Options(options); + minimizer_options.evaluator = pp->evaluator; + + if (options.logging_type != SILENT) { + pp->logging_callback.reset( + new LoggingCallback(options.minimizer_type, + options.minimizer_progress_to_stdout)); + minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), + pp->logging_callback.get()); + } + + if (options.update_state_every_iteration) { + pp->state_updating_callback.reset( + new StateUpdatingCallback(program, reduced_parameters)); + // This must get pushed to the front of the callbacks so that it + // is run before any of the user callbacks. + minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), + pp->state_updating_callback.get()); + } +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/preprocessor.h b/extern/libmv/third_party/ceres/internal/ceres/preprocessor.h new file mode 100644 index 00000000000..b4ca5b11747 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/preprocessor.h @@ -0,0 +1,119 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_PREPROCESSOR_H_ +#define CERES_INTERNAL_PREPROCESSOR_H_ + +#include "ceres/coordinate_descent_minimizer.h" +#include "ceres/evaluator.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/port.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/iteration_callback.h" +#include "ceres/linear_solver.h" +#include "ceres/minimizer.h" +#include "ceres/problem_impl.h" +#include "ceres/program.h" +#include "ceres/solver.h" + +namespace ceres { +namespace internal { + +struct PreprocessedProblem; + +// Given a Problem object and a Solver::Options object indicating the +// configuration of the solver, the job of the Preprocessor is to +// analyze the Problem and perform the setup needed to solve it using +// the desired Minimization algorithm. The setup involves removing +// redundancies in the input problem (inactive parameter and residual +// blocks), finding fill reducing orderings as needed, configuring and +// creating various objects needed by the Minimizer to solve the +// problem such as an evaluator, a linear solver etc. +// +// Each Minimizer (LineSearchMinimizer and TrustRegionMinimizer) comes +// with a corresponding Preprocessor (LineSearchPreprocessor and +// TrustRegionPreprocessor) that knows about its needs and performs +// the preprocessing needed. +// +// The output of the Preprocessor is stored in a PreprocessedProblem +// object. +class Preprocessor { +public: + // Factory. + static Preprocessor* Create(MinimizerType minimizer_type); + virtual ~Preprocessor(); + virtual bool Preprocess(const Solver::Options& options, + ProblemImpl* problem, + PreprocessedProblem* pp) = 0; +}; + +// A PreprocessedProblem is the result of running the Preprocessor on +// a Problem and Solver::Options object. +struct PreprocessedProblem { + PreprocessedProblem() + : fixed_cost(0.0) { + } + + string error; + Solver::Options options; + LinearSolver::Options linear_solver_options; + Evaluator::Options evaluator_options; + Minimizer::Options minimizer_options; + + ProblemImpl* problem; + scoped_ptr<ProblemImpl> gradient_checking_problem; + scoped_ptr<Program> reduced_program; + scoped_ptr<LinearSolver> linear_solver; + scoped_ptr<IterationCallback> logging_callback; + scoped_ptr<IterationCallback> state_updating_callback; + + shared_ptr<Evaluator> evaluator; + shared_ptr<CoordinateDescentMinimizer> inner_iteration_minimizer; + + vector<double*> removed_parameter_blocks; + Vector reduced_parameters; + double fixed_cost; +}; + +// Common functions used by various preprocessors. + +// If OpenMP support is not available and user has requested more than +// one thread, then set the *_num_threads options as needed to 1. +void ChangeNumThreadsIfNeeded(Solver::Options* options); + +// Extract the effective parameter vector from the preprocessed +// problem and setup bits of the Minimizer::Options object that are +// common to all Preprocessors. +void SetupCommonMinimizerOptions(PreprocessedProblem* pp); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_PREPROCESSOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem.cc b/extern/libmv/third_party/ceres/internal/ceres/problem.cc index 674694dd506..bbfaa98769f 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/problem.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/problem.cc @@ -251,6 +251,16 @@ void Problem::GetParameterBlocksForResidualBlock( parameter_blocks); } +const CostFunction* Problem::GetCostFunctionForResidualBlock( + const ResidualBlockId residual_block) const { + return problem_impl_->GetCostFunctionForResidualBlock(residual_block); +} + +const LossFunction* Problem::GetLossFunctionForResidualBlock( + const ResidualBlockId residual_block) const { + return problem_impl_->GetLossFunctionForResidualBlock(residual_block); +} + void Problem::GetResidualBlocksForParameterBlock( const double* values, vector<ResidualBlockId>* residual_blocks) const { diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc index 7c86efb4921..67cac94d6ac 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc @@ -823,6 +823,16 @@ void ProblemImpl::GetParameterBlocksForResidualBlock( } } +const CostFunction* ProblemImpl::GetCostFunctionForResidualBlock( + const ResidualBlockId residual_block) const { + return residual_block->cost_function(); +} + +const LossFunction* ProblemImpl::GetLossFunctionForResidualBlock( + const ResidualBlockId residual_block) const { + return residual_block->loss_function(); +} + void ProblemImpl::GetResidualBlocksForParameterBlock( const double* values, vector<ResidualBlockId>* residual_blocks) const { diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h index 7b5547bd95a..3d84de83c5a 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h +++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h @@ -157,6 +157,11 @@ class ProblemImpl { const ResidualBlockId residual_block, vector<double*>* parameter_blocks) const; + const CostFunction* GetCostFunctionForResidualBlock( + const ResidualBlockId residual_block) const; + const LossFunction* GetLossFunctionForResidualBlock( + const ResidualBlockId residual_block) const; + void GetResidualBlocksForParameterBlock( const double* values, vector<ResidualBlockId>* residual_blocks) const; diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.cc b/extern/libmv/third_party/ceres/internal/ceres/program.cc index 9e5c51bd696..1d0a1573e3b 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/program.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/program.cc @@ -32,6 +32,7 @@ #include <map> #include <vector> +#include "ceres/array_utils.h" #include "ceres/casts.h" #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/cost_function.h" @@ -44,6 +45,7 @@ #include "ceres/problem.h" #include "ceres/residual_block.h" #include "ceres/stl_util.h" +#include "ceres/triplet_sparse_matrix.h" namespace ceres { namespace internal { @@ -170,6 +172,259 @@ bool Program::IsValid() const { return true; } +bool Program::ParameterBlocksAreFinite(string* message) const { + CHECK_NOTNULL(message); + for (int i = 0; i < parameter_blocks_.size(); ++i) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + const double* array = parameter_block->user_state(); + const int size = parameter_block->Size(); + const int invalid_index = FindInvalidValue(size, array); + if (invalid_index != size) { + *message = StringPrintf( + "ParameterBlock: %p with size %d has at least one invalid value.\n" + "First invalid value is at index: %d.\n" + "Parameter block values: ", + array, size, invalid_index); + AppendArrayToString(size, array, message); + return false; + } + } + return true; +} + +bool Program::IsBoundsConstrained() const { + for (int i = 0; i < parameter_blocks_.size(); ++i) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + if (parameter_block->IsConstant()) { + continue; + } + const int size = parameter_block->Size(); + for (int j = 0; j < size; ++j) { + const double lower_bound = parameter_block->LowerBoundForParameter(j); + const double upper_bound = parameter_block->UpperBoundForParameter(j); + if (lower_bound > -std::numeric_limits<double>::max() || + upper_bound < std::numeric_limits<double>::max()) { + return true; + } + } + } + return false; +} + +bool Program::IsFeasible(string* message) const { + CHECK_NOTNULL(message); + for (int i = 0; i < parameter_blocks_.size(); ++i) { + const ParameterBlock* parameter_block = parameter_blocks_[i]; + const double* parameters = parameter_block->user_state(); + const int size = parameter_block->Size(); + if (parameter_block->IsConstant()) { + // Constant parameter blocks must start in the feasible region + // to ultimately produce a feasible solution, since Ceres cannot + // change them. + for (int j = 0; j < size; ++j) { + const double lower_bound = parameter_block->LowerBoundForParameter(j); + const double upper_bound = parameter_block->UpperBoundForParameter(j); + if (parameters[j] < lower_bound || parameters[j] > upper_bound) { + *message = StringPrintf( + "ParameterBlock: %p with size %d has at least one infeasible " + "value." + "\nFirst infeasible value is at index: %d." + "\nLower bound: %e, value: %e, upper bound: %e" + "\nParameter block values: ", + parameters, size, j, lower_bound, parameters[j], upper_bound); + AppendArrayToString(size, parameters, message); + return false; + } + } + } else { + // Variable parameter blocks must have non-empty feasible + // regions, otherwise there is no way to produce a feasible + // solution. + for (int j = 0; j < size; ++j) { + const double lower_bound = parameter_block->LowerBoundForParameter(j); + const double upper_bound = parameter_block->UpperBoundForParameter(j); + if (lower_bound >= upper_bound) { + *message = StringPrintf( + "ParameterBlock: %p with size %d has at least one infeasible " + "bound." + "\nFirst infeasible bound is at index: %d." + "\nLower bound: %e, upper bound: %e" + "\nParameter block values: ", + parameters, size, j, lower_bound, upper_bound); + AppendArrayToString(size, parameters, message); + return false; + } + } + } + } + + return true; +} + +Program* Program::CreateReducedProgram(vector<double*>* removed_parameter_blocks, + double* fixed_cost, + string* error) const { + CHECK_NOTNULL(removed_parameter_blocks); + CHECK_NOTNULL(fixed_cost); + CHECK_NOTNULL(error); + + scoped_ptr<Program> reduced_program(new Program(*this)); + if (!reduced_program->RemoveFixedBlocks(removed_parameter_blocks, + fixed_cost, + error)) { + return NULL; + } + + reduced_program->SetParameterOffsetsAndIndex(); + return reduced_program.release(); +} + +bool Program::RemoveFixedBlocks(vector<double*>* removed_parameter_blocks, + double* fixed_cost, + string* error) { + CHECK_NOTNULL(removed_parameter_blocks); + CHECK_NOTNULL(fixed_cost); + CHECK_NOTNULL(error); + + scoped_array<double> residual_block_evaluate_scratch; + residual_block_evaluate_scratch.reset( + new double[MaxScratchDoublesNeededForEvaluate()]); + *fixed_cost = 0.0; + + // Mark all the parameters as unused. Abuse the index member of the + // parameter blocks for the marking. + for (int i = 0; i < parameter_blocks_.size(); ++i) { + parameter_blocks_[i]->set_index(-1); + } + + // Filter out residual that have all-constant parameters, and mark + // all the parameter blocks that appear in residuals. + int num_active_residual_blocks = 0; + for (int i = 0; i < residual_blocks_.size(); ++i) { + ResidualBlock* residual_block = residual_blocks_[i]; + int num_parameter_blocks = residual_block->NumParameterBlocks(); + + // Determine if the residual block is fixed, and also mark varying + // parameters that appear in the residual block. + bool all_constant = true; + for (int k = 0; k < num_parameter_blocks; k++) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[k]; + if (!parameter_block->IsConstant()) { + all_constant = false; + parameter_block->set_index(1); + } + } + + if (!all_constant) { + residual_blocks_[num_active_residual_blocks++] = residual_block; + continue; + } + + // The residual is constant and will be removed, so its cost is + // added to the variable fixed_cost. + double cost = 0.0; + if (!residual_block->Evaluate(true, + &cost, + NULL, + NULL, + residual_block_evaluate_scratch.get())) { + *error = StringPrintf("Evaluation of the residual %d failed during " + "removal of fixed residual blocks.", i); + return false; + } + *fixed_cost += cost; + } + residual_blocks_.resize(num_active_residual_blocks); + + // Filter out unused or fixed parameter blocks. + int num_active_parameter_blocks = 0; + removed_parameter_blocks->clear(); + for (int i = 0; i < parameter_blocks_.size(); ++i) { + ParameterBlock* parameter_block = parameter_blocks_[i]; + if (parameter_block->index() == -1) { + removed_parameter_blocks->push_back(parameter_block->mutable_user_state()); + } else { + parameter_blocks_[num_active_parameter_blocks++] = parameter_block; + } + } + parameter_blocks_.resize(num_active_parameter_blocks); + + if (!(((NumResidualBlocks() == 0) && + (NumParameterBlocks() == 0)) || + ((NumResidualBlocks() != 0) && + (NumParameterBlocks() != 0)))) { + *error = "Congratulations, you found a bug in Ceres. Please report it."; + return false; + } + + return true; +} + +bool Program::IsParameterBlockSetIndependent(const set<double*>& independent_set) const { + // Loop over each residual block and ensure that no two parameter + // blocks in the same residual block are part of + // parameter_block_ptrs as that would violate the assumption that it + // is an independent set in the Hessian matrix. + for (vector<ResidualBlock*>::const_iterator it = residual_blocks_.begin(); + it != residual_blocks_.end(); + ++it) { + ParameterBlock* const* parameter_blocks = (*it)->parameter_blocks(); + const int num_parameter_blocks = (*it)->NumParameterBlocks(); + int count = 0; + for (int i = 0; i < num_parameter_blocks; ++i) { + count += independent_set.count( + parameter_blocks[i]->mutable_user_state()); + } + if (count > 1) { + return false; + } + } + return true; +} + +TripletSparseMatrix* Program::CreateJacobianBlockSparsityTranspose() const { + // Matrix to store the block sparsity structure of the Jacobian. + TripletSparseMatrix* tsm = + new TripletSparseMatrix(NumParameterBlocks(), + NumResidualBlocks(), + 10 * NumResidualBlocks()); + int num_nonzeros = 0; + int* rows = tsm->mutable_rows(); + int* cols = tsm->mutable_cols(); + double* values = tsm->mutable_values(); + + for (int c = 0; c < residual_blocks_.size(); ++c) { + const ResidualBlock* residual_block = residual_blocks_[c]; + const int num_parameter_blocks = residual_block->NumParameterBlocks(); + ParameterBlock* const* parameter_blocks = + residual_block->parameter_blocks(); + + for (int j = 0; j < num_parameter_blocks; ++j) { + if (parameter_blocks[j]->IsConstant()) { + continue; + } + + // Re-size the matrix if needed. + if (num_nonzeros >= tsm->max_num_nonzeros()) { + tsm->set_num_nonzeros(num_nonzeros); + tsm->Reserve(2 * num_nonzeros); + rows = tsm->mutable_rows(); + cols = tsm->mutable_cols(); + values = tsm->mutable_values(); + } + + const int r = parameter_blocks[j]->index(); + rows[num_nonzeros] = r; + cols[num_nonzeros] = c; + values[num_nonzeros] = 1.0; + ++num_nonzeros; + } + } + + tsm->set_num_nonzeros(num_nonzeros); + return tsm; +} + int Program::NumResidualBlocks() const { return residual_blocks_.size(); } diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.h b/extern/libmv/third_party/ceres/internal/ceres/program.h index 4288f609cf8..c7b22c4d244 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/program.h +++ b/extern/libmv/third_party/ceres/internal/ceres/program.h @@ -31,6 +31,7 @@ #ifndef CERES_INTERNAL_PROGRAM_H_ #define CERES_INTERNAL_PROGRAM_H_ +#include <set> #include <string> #include <vector> #include "ceres/internal/port.h" @@ -41,6 +42,7 @@ namespace internal { class ParameterBlock; class ProblemImpl; class ResidualBlock; +class TripletSparseMatrix; // A nonlinear least squares optimization problem. This is different from the // similarly-named "Problem" object, which offers a mutation interface for @@ -103,6 +105,47 @@ class Program { // offsets) are correct. bool IsValid() const; + bool ParameterBlocksAreFinite(string* message) const; + + // Returns true if the program has any non-constant parameter blocks + // which have non-trivial bounds constraints. + bool IsBoundsConstrained() const; + + // Returns false, if the program has any constant parameter blocks + // which are not feasible, or any variable parameter blocks which + // have a lower bound greater than or equal to the upper bound. + bool IsFeasible(string* message) const; + + // Loop over each residual block and ensure that no two parameter + // blocks in the same residual block are part of + // parameter_blocks as that would violate the assumption that it + // is an independent set in the Hessian matrix. + bool IsParameterBlockSetIndependent(const set<double*>& independent_set) const; + + // Create a TripletSparseMatrix which contains the zero-one + // structure corresponding to the block sparsity of the transpose of + // the Jacobian matrix. + // + // Caller owns the result. + TripletSparseMatrix* CreateJacobianBlockSparsityTranspose() const; + + // Create a copy of this program and removes constant parameter + // blocks and residual blocks with no varying parameter blocks while + // preserving their relative order. + // + // removed_parameter_blocks on exit will contain the list of + // parameter blocks that were removed. + // + // fixed_cost will be equal to the sum of the costs of the residual + // blocks that were removed. + // + // If there was a problem, then the function will return a NULL + // pointer and error will contain a human readable description of + // the problem. + Program* CreateReducedProgram(vector<double*>* removed_parameter_blocks, + double* fixed_cost, + string* error) const; + // See problem.h for what these do. int NumParameterBlocks() const; int NumParameters() const; @@ -120,6 +163,21 @@ class Program { string ToString() const; private: + // Remove constant parameter blocks and residual blocks with no + // varying parameter blocks while preserving their relative order. + // + // removed_parameter_blocks on exit will contain the list of + // parameter blocks that were removed. + // + // fixed_cost will be equal to the sum of the costs of the residual + // blocks that were removed. + // + // If there was a problem, then the function will return false and + // error will contain a human readable description of the problem. + bool RemoveFixedBlocks(vector<double*>* removed_parameter_blocks, + double* fixed_cost, + string* message); + // The Program does not own the ParameterBlock or ResidualBlock objects. vector<ParameterBlock*> parameter_blocks_; vector<ResidualBlock*> residual_blocks_; diff --git a/extern/libmv/third_party/ceres/internal/ceres/reorder_program.cc b/extern/libmv/third_party/ceres/internal/ceres/reorder_program.cc new file mode 100644 index 00000000000..aa3d4cec396 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/reorder_program.cc @@ -0,0 +1,578 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/reorder_program.h" + +#include <algorithm> +#include <numeric> +#include <vector> + +#include "ceres/cxsparse.h" +#include "ceres/internal/port.h" +#include "ceres/ordered_groups.h" +#include "ceres/parameter_block.h" +#include "ceres/parameter_block_ordering.h" +#include "ceres/problem_impl.h" +#include "ceres/program.h" +#include "ceres/residual_block.h" +#include "ceres/solver.h" +#include "ceres/suitesparse.h" +#include "ceres/triplet_sparse_matrix.h" +#include "ceres/types.h" +#include "Eigen/SparseCore" + +#ifdef CERES_USE_EIGEN_SPARSE +#include "Eigen/OrderingMethods" +#endif + +#include "glog/logging.h" + +namespace ceres { +namespace internal { +namespace { + +// Find the minimum index of any parameter block to the given +// residual. Parameter blocks that have indices greater than +// size_of_first_elimination_group are considered to have an index +// equal to size_of_first_elimination_group. +static int MinParameterBlock(const ResidualBlock* residual_block, + int size_of_first_elimination_group) { + int min_parameter_block_position = size_of_first_elimination_group; + for (int i = 0; i < residual_block->NumParameterBlocks(); ++i) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[i]; + if (!parameter_block->IsConstant()) { + CHECK_NE(parameter_block->index(), -1) + << "Did you forget to call Program::SetParameterOffsetsAndIndex()? " + << "This is a Ceres bug; please contact the developers!"; + min_parameter_block_position = std::min(parameter_block->index(), + min_parameter_block_position); + } + } + return min_parameter_block_position; +} + +#if EIGEN_VERSION_AT_LEAST(3, 2, 2) && defined(CERES_USE_EIGEN_SPARSE) +Eigen::SparseMatrix<int> CreateBlockJacobian( + const TripletSparseMatrix& block_jacobian_transpose) { + typedef Eigen::SparseMatrix<int> SparseMatrix; + typedef Eigen::Triplet<int> Triplet; + + const int* rows = block_jacobian_transpose.rows(); + const int* cols = block_jacobian_transpose.cols(); + int num_nonzeros = block_jacobian_transpose.num_nonzeros(); + std::vector<Triplet> triplets; + triplets.reserve(num_nonzeros); + for (int i = 0; i < num_nonzeros; ++i) { + triplets.push_back(Triplet(cols[i], rows[i], 1)); + } + + SparseMatrix block_jacobian(block_jacobian_transpose.num_cols(), + block_jacobian_transpose.num_rows()); + block_jacobian.setFromTriplets(triplets.begin(), triplets.end()); + return block_jacobian; +} +#endif + +void OrderingForSparseNormalCholeskyUsingSuiteSparse( + const TripletSparseMatrix& tsm_block_jacobian_transpose, + const vector<ParameterBlock*>& parameter_blocks, + const ParameterBlockOrdering& parameter_block_ordering, + int* ordering) { +#ifdef CERES_NO_SUITESPARSE + LOG(FATAL) << "Congratulations, you found a Ceres bug! " + << "Please report this error to the developers."; +#else + SuiteSparse ss; + cholmod_sparse* block_jacobian_transpose = + ss.CreateSparseMatrix( + const_cast<TripletSparseMatrix*>(&tsm_block_jacobian_transpose)); + + // No CAMD or the user did not supply a useful ordering, then just + // use regular AMD. + if (parameter_block_ordering.NumGroups() <= 1 || + !SuiteSparse::IsConstrainedApproximateMinimumDegreeOrderingAvailable()) { + ss.ApproximateMinimumDegreeOrdering(block_jacobian_transpose, &ordering[0]); + } else { + vector<int> constraints; + for (int i = 0; i < parameter_blocks.size(); ++i) { + constraints.push_back( + parameter_block_ordering.GroupId( + parameter_blocks[i]->mutable_user_state())); + } + ss.ConstrainedApproximateMinimumDegreeOrdering(block_jacobian_transpose, + &constraints[0], + ordering); + } + + ss.Free(block_jacobian_transpose); +#endif // CERES_NO_SUITESPARSE +} + +void OrderingForSparseNormalCholeskyUsingCXSparse( + const TripletSparseMatrix& tsm_block_jacobian_transpose, + int* ordering) { +#ifdef CERES_NO_CXSPARSE + LOG(FATAL) << "Congratulations, you found a Ceres bug! " + << "Please report this error to the developers."; +#else // CERES_NO_CXSPARSE + // CXSparse works with J'J instead of J'. So compute the block + // sparsity for J'J and compute an approximate minimum degree + // ordering. + CXSparse cxsparse; + cs_di* block_jacobian_transpose; + block_jacobian_transpose = + cxsparse.CreateSparseMatrix( + const_cast<TripletSparseMatrix*>(&tsm_block_jacobian_transpose)); + cs_di* block_jacobian = cxsparse.TransposeMatrix(block_jacobian_transpose); + cs_di* block_hessian = + cxsparse.MatrixMatrixMultiply(block_jacobian_transpose, block_jacobian); + cxsparse.Free(block_jacobian); + cxsparse.Free(block_jacobian_transpose); + + cxsparse.ApproximateMinimumDegreeOrdering(block_hessian, ordering); + cxsparse.Free(block_hessian); +#endif // CERES_NO_CXSPARSE +} + + +#if EIGEN_VERSION_AT_LEAST(3, 2, 2) +void OrderingForSparseNormalCholeskyUsingEigenSparse( + const TripletSparseMatrix& tsm_block_jacobian_transpose, + int* ordering) { +#ifndef CERES_USE_EIGEN_SPARSE + LOG(FATAL) << + "SPARSE_NORMAL_CHOLESKY cannot be used with EIGEN_SPARSE " + "because Ceres was not built with support for " + "Eigen's SimplicialLDLT decomposition. " + "This requires enabling building with -DEIGENSPARSE=ON."; +#else + + // This conversion from a TripletSparseMatrix to a Eigen::Triplet + // matrix is unfortunate, but unavoidable for now. It is not a + // significant performance penalty in the grand scheme of + // things. The right thing to do here would be to get a compressed + // row sparse matrix representation of the jacobian and go from + // there. But that is a project for another day. + typedef Eigen::SparseMatrix<int> SparseMatrix; + + const SparseMatrix block_jacobian = + CreateBlockJacobian(tsm_block_jacobian_transpose); + const SparseMatrix block_hessian = + block_jacobian.transpose() * block_jacobian; + + Eigen::AMDOrdering<int> amd_ordering; + Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, int> perm; + amd_ordering(block_hessian, perm); + for (int i = 0; i < block_hessian.rows(); ++i) { + ordering[i] = perm.indices()[i]; + } +#endif // CERES_USE_EIGEN_SPARSE +} +#endif + +} // namespace + +bool ApplyOrdering(const ProblemImpl::ParameterMap& parameter_map, + const ParameterBlockOrdering& ordering, + Program* program, + string* error) { + const int num_parameter_blocks = program->NumParameterBlocks(); + if (ordering.NumElements() != num_parameter_blocks) { + *error = StringPrintf("User specified ordering does not have the same " + "number of parameters as the problem. The problem" + "has %d blocks while the ordering has %d blocks.", + num_parameter_blocks, + ordering.NumElements()); + return false; + } + + vector<ParameterBlock*>* parameter_blocks = + program->mutable_parameter_blocks(); + parameter_blocks->clear(); + + const map<int, set<double*> >& groups = + ordering.group_to_elements(); + + for (map<int, set<double*> >::const_iterator group_it = groups.begin(); + group_it != groups.end(); + ++group_it) { + const set<double*>& group = group_it->second; + for (set<double*>::const_iterator parameter_block_ptr_it = group.begin(); + parameter_block_ptr_it != group.end(); + ++parameter_block_ptr_it) { + ProblemImpl::ParameterMap::const_iterator parameter_block_it = + parameter_map.find(*parameter_block_ptr_it); + if (parameter_block_it == parameter_map.end()) { + *error = StringPrintf("User specified ordering contains a pointer " + "to a double that is not a parameter block in " + "the problem. The invalid double is in group: %d", + group_it->first); + return false; + } + parameter_blocks->push_back(parameter_block_it->second); + } + } + return true; +} + +bool LexicographicallyOrderResidualBlocks( + const int size_of_first_elimination_group, + Program* program, + string* error) { + CHECK_GE(size_of_first_elimination_group, 1) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Create a histogram of the number of residuals for each E block. There is an + // extra bucket at the end to catch all non-eliminated F blocks. + vector<int> residual_blocks_per_e_block(size_of_first_elimination_group + 1); + vector<ResidualBlock*>* residual_blocks = program->mutable_residual_blocks(); + vector<int> min_position_per_residual(residual_blocks->size()); + for (int i = 0; i < residual_blocks->size(); ++i) { + ResidualBlock* residual_block = (*residual_blocks)[i]; + int position = MinParameterBlock(residual_block, + size_of_first_elimination_group); + min_position_per_residual[i] = position; + DCHECK_LE(position, size_of_first_elimination_group); + residual_blocks_per_e_block[position]++; + } + + // Run a cumulative sum on the histogram, to obtain offsets to the start of + // each histogram bucket (where each bucket is for the residuals for that + // E-block). + vector<int> offsets(size_of_first_elimination_group + 1); + std::partial_sum(residual_blocks_per_e_block.begin(), + residual_blocks_per_e_block.end(), + offsets.begin()); + CHECK_EQ(offsets.back(), residual_blocks->size()) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + CHECK(find(residual_blocks_per_e_block.begin(), + residual_blocks_per_e_block.end() - 1, 0) != + residual_blocks_per_e_block.end()) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Fill in each bucket with the residual blocks for its corresponding E block. + // Each bucket is individually filled from the back of the bucket to the front + // of the bucket. The filling order among the buckets is dictated by the + // residual blocks. This loop uses the offsets as counters; subtracting one + // from each offset as a residual block is placed in the bucket. When the + // filling is finished, the offset pointerts should have shifted down one + // entry (this is verified below). + vector<ResidualBlock*> reordered_residual_blocks( + (*residual_blocks).size(), static_cast<ResidualBlock*>(NULL)); + for (int i = 0; i < residual_blocks->size(); ++i) { + int bucket = min_position_per_residual[i]; + + // Decrement the cursor, which should now point at the next empty position. + offsets[bucket]--; + + // Sanity. + CHECK(reordered_residual_blocks[offsets[bucket]] == NULL) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + reordered_residual_blocks[offsets[bucket]] = (*residual_blocks)[i]; + } + + // Sanity check #1: The difference in bucket offsets should match the + // histogram sizes. + for (int i = 0; i < size_of_first_elimination_group; ++i) { + CHECK_EQ(residual_blocks_per_e_block[i], offsets[i + 1] - offsets[i]) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + } + // Sanity check #2: No NULL's left behind. + for (int i = 0; i < reordered_residual_blocks.size(); ++i) { + CHECK(reordered_residual_blocks[i] != NULL) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + } + + // Now that the residuals are collected by E block, swap them in place. + swap(*program->mutable_residual_blocks(), reordered_residual_blocks); + return true; +} + +// Pre-order the columns corresponding to the schur complement if +// possible. +void MaybeReorderSchurComplementColumnsUsingSuiteSparse( + const ParameterBlockOrdering& parameter_block_ordering, + Program* program) { +#ifndef CERES_NO_SUITESPARSE + SuiteSparse ss; + if (!SuiteSparse::IsConstrainedApproximateMinimumDegreeOrderingAvailable()) { + return; + } + + vector<int> constraints; + vector<ParameterBlock*>& parameter_blocks = + *(program->mutable_parameter_blocks()); + + for (int i = 0; i < parameter_blocks.size(); ++i) { + constraints.push_back( + parameter_block_ordering.GroupId( + parameter_blocks[i]->mutable_user_state())); + } + + // Renumber the entries of constraints to be contiguous integers + // as camd requires that the group ids be in the range [0, + // parameter_blocks.size() - 1]. + MapValuesToContiguousRange(constraints.size(), &constraints[0]); + + // Compute a block sparse presentation of J'. + scoped_ptr<TripletSparseMatrix> tsm_block_jacobian_transpose( + program->CreateJacobianBlockSparsityTranspose()); + + cholmod_sparse* block_jacobian_transpose = + ss.CreateSparseMatrix(tsm_block_jacobian_transpose.get()); + + vector<int> ordering(parameter_blocks.size(), 0); + ss.ConstrainedApproximateMinimumDegreeOrdering(block_jacobian_transpose, + &constraints[0], + &ordering[0]); + ss.Free(block_jacobian_transpose); + + const vector<ParameterBlock*> parameter_blocks_copy(parameter_blocks); + for (int i = 0; i < program->NumParameterBlocks(); ++i) { + parameter_blocks[i] = parameter_blocks_copy[ordering[i]]; + } + + program->SetParameterOffsetsAndIndex(); +#endif +} + +void MaybeReorderSchurComplementColumnsUsingEigen( + const int size_of_first_elimination_group, + const ProblemImpl::ParameterMap& parameter_map, + Program* program) { +#if !EIGEN_VERSION_AT_LEAST(3, 2, 2) || !defined(CERES_USE_EIGEN_SPARSE) + return; +#else + + scoped_ptr<TripletSparseMatrix> tsm_block_jacobian_transpose( + program->CreateJacobianBlockSparsityTranspose()); + + typedef Eigen::SparseMatrix<int> SparseMatrix; + const SparseMatrix block_jacobian = + CreateBlockJacobian(*tsm_block_jacobian_transpose); + const int num_rows = block_jacobian.rows(); + const int num_cols = block_jacobian.cols(); + + // Vertically partition the jacobian in parameter blocks of type E + // and F. + const SparseMatrix E = + block_jacobian.block(0, + 0, + num_rows, + size_of_first_elimination_group); + const SparseMatrix F = + block_jacobian.block(0, + size_of_first_elimination_group, + num_rows, + num_cols - size_of_first_elimination_group); + + // Block sparsity pattern of the schur complement. + const SparseMatrix block_schur_complement = + F.transpose() * F - F.transpose() * E * E.transpose() * F; + + Eigen::AMDOrdering<int> amd_ordering; + Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic, int> perm; + amd_ordering(block_schur_complement, perm); + + const vector<ParameterBlock*>& parameter_blocks = program->parameter_blocks(); + vector<ParameterBlock*> ordering(num_cols); + + // The ordering of the first size_of_first_elimination_group does + // not matter, so we preserve the existing ordering. + for (int i = 0; i < size_of_first_elimination_group; ++i) { + ordering[i] = parameter_blocks[i]; + } + + // For the rest of the blocks, use the ordering computed using AMD. + for (int i = 0; i < block_schur_complement.cols(); ++i) { + ordering[size_of_first_elimination_group + i] = + parameter_blocks[size_of_first_elimination_group + perm.indices()[i]]; + } + + swap(*program->mutable_parameter_blocks(), ordering); + program->SetParameterOffsetsAndIndex(); +#endif +} + +bool ReorderProgramForSchurTypeLinearSolver( + const LinearSolverType linear_solver_type, + const SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, + const ProblemImpl::ParameterMap& parameter_map, + ParameterBlockOrdering* parameter_block_ordering, + Program* program, + string* error) { + if (parameter_block_ordering->NumElements() != + program->NumParameterBlocks()) { + *error = StringPrintf( + "The program has %d parameter blocks, but the parameter block " + "ordering has %d parameter blocks.", + program->NumParameterBlocks(), + parameter_block_ordering->NumElements()); + return false; + } + + if (parameter_block_ordering->NumGroups() == 1) { + // If the user supplied an parameter_block_ordering with just one + // group, it is equivalent to the user supplying NULL as an + // parameter_block_ordering. Ceres is completely free to choose the + // parameter block ordering as it sees fit. For Schur type solvers, + // this means that the user wishes for Ceres to identify the + // e_blocks, which we do by computing a maximal independent set. + vector<ParameterBlock*> schur_ordering; + const int size_of_first_elimination_group = + ComputeStableSchurOrdering(*program, &schur_ordering); + + CHECK_EQ(schur_ordering.size(), program->NumParameterBlocks()) + << "Congratulations, you found a Ceres bug! Please report this error " + << "to the developers."; + + // Update the parameter_block_ordering object. + for (int i = 0; i < schur_ordering.size(); ++i) { + double* parameter_block = schur_ordering[i]->mutable_user_state(); + const int group_id = (i < size_of_first_elimination_group) ? 0 : 1; + parameter_block_ordering->AddElementToGroup(parameter_block, group_id); + } + + // We could call ApplyOrdering but this is cheaper and + // simpler. + swap(*program->mutable_parameter_blocks(), schur_ordering); + } else { + // The user provided an ordering with more than one elimination + // group. + + // Verify that the first elimination group is an independent set. + const set<double*>& first_elimination_group = + parameter_block_ordering + ->group_to_elements() + .begin() + ->second; + if (!program->IsParameterBlockSetIndependent(first_elimination_group)) { + *error = + StringPrintf("The first elimination group in the parameter block " + "ordering of size %zd is not an independent set", + first_elimination_group.size()); + return false; + } + + if (!ApplyOrdering(parameter_map, + *parameter_block_ordering, + program, + error)) { + return false; + } + } + + program->SetParameterOffsetsAndIndex(); + + const int size_of_first_elimination_group = + parameter_block_ordering->group_to_elements().begin()->second.size(); + + if (linear_solver_type == SPARSE_SCHUR) { + if (sparse_linear_algebra_library_type == SUITE_SPARSE) { + MaybeReorderSchurComplementColumnsUsingSuiteSparse( + *parameter_block_ordering, + program); + } else if (sparse_linear_algebra_library_type == EIGEN_SPARSE) { + MaybeReorderSchurComplementColumnsUsingEigen( + size_of_first_elimination_group, + parameter_map, + program); + } + } + + // Schur type solvers also require that their residual blocks be + // lexicographically ordered. + if (!LexicographicallyOrderResidualBlocks(size_of_first_elimination_group, + program, + error)) { + return false; + } + + return true; +} + +bool ReorderProgramForSparseNormalCholesky( + const SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, + const ParameterBlockOrdering& parameter_block_ordering, + Program* program, + string* error) { + // Compute a block sparse presentation of J'. + scoped_ptr<TripletSparseMatrix> tsm_block_jacobian_transpose( + program->CreateJacobianBlockSparsityTranspose()); + + vector<int> ordering(program->NumParameterBlocks(), 0); + vector<ParameterBlock*>& parameter_blocks = + *(program->mutable_parameter_blocks()); + + if (sparse_linear_algebra_library_type == SUITE_SPARSE) { + OrderingForSparseNormalCholeskyUsingSuiteSparse( + *tsm_block_jacobian_transpose, + parameter_blocks, + parameter_block_ordering, + &ordering[0]); + } else if (sparse_linear_algebra_library_type == CX_SPARSE) { + OrderingForSparseNormalCholeskyUsingCXSparse( + *tsm_block_jacobian_transpose, + &ordering[0]); + } else if (sparse_linear_algebra_library_type == EIGEN_SPARSE) { +#if EIGEN_VERSION_AT_LEAST(3, 2, 2) + OrderingForSparseNormalCholeskyUsingEigenSparse( + *tsm_block_jacobian_transpose, + &ordering[0]); +#else + // For Eigen versions less than 3.2.2, there is nothing to do as + // older versions of Eigen do not expose a method for doing + // symbolic analysis on pre-ordered matrices, so a block + // pre-ordering is a bit pointless. + + return true; +#endif + } + + // Apply ordering. + const vector<ParameterBlock*> parameter_blocks_copy(parameter_blocks); + for (int i = 0; i < program->NumParameterBlocks(); ++i) { + parameter_blocks[i] = parameter_blocks_copy[ordering[i]]; + } + + program->SetParameterOffsetsAndIndex(); + return true; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/reorder_program.h b/extern/libmv/third_party/ceres/internal/ceres/reorder_program.h new file mode 100644 index 00000000000..0474c1fb912 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/reorder_program.h @@ -0,0 +1,101 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_REORDER_PROGRAM_H_ +#define CERES_INTERNAL_REORDER_PROGRAM_H_ + +#include <string> +#include "ceres/internal/port.h" +#include "ceres/parameter_block_ordering.h" +#include "ceres/problem_impl.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class Program; + +// Reorder the parameter blocks in program using the ordering +bool ApplyOrdering(const ProblemImpl::ParameterMap& parameter_map, + const ParameterBlockOrdering& ordering, + Program* program, + string* error); + +// Reorder the residuals for program, if necessary, so that the residuals +// involving each E block occur together. This is a necessary condition for the +// Schur eliminator, which works on these "row blocks" in the jacobian. +bool LexicographicallyOrderResidualBlocks(int size_of_first_elimination_group, + Program* program, + string* error); + +// Schur type solvers require that all parameter blocks eliminated +// by the Schur eliminator occur before others and the residuals be +// sorted in lexicographic order of their parameter blocks. +// +// If the parameter_block_ordering only contains one elimination +// group then a maximal independent set is computed and used as the +// first elimination group, otherwise the user's ordering is used. +// +// If the linear solver type is SPARSE_SCHUR and support for +// constrained fill-reducing ordering is available in the sparse +// linear algebra library (SuiteSparse version >= 4.2.0) then +// columns of the schur complement matrix are ordered to reduce the +// fill-in the Cholesky factorization. +// +// Upon return, ordering contains the parameter block ordering that +// was used to order the program. +bool ReorderProgramForSchurTypeLinearSolver( + LinearSolverType linear_solver_type, + SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, + const ProblemImpl::ParameterMap& parameter_map, + ParameterBlockOrdering* parameter_block_ordering, + Program* program, + string* error); + +// Sparse cholesky factorization routines when doing the sparse +// cholesky factorization of the Jacobian matrix, reorders its +// columns to reduce the fill-in. Compute this permutation and +// re-order the parameter blocks. +// +// When using SuiteSparse, if the parameter_block_ordering contains +// more than one elimination group and support for constrained +// fill-reducing ordering is available in the sparse linear algebra +// library (SuiteSparse version >= 4.2.0) then the fill reducing +// ordering will take it into account, otherwise it will be ignored. +bool ReorderProgramForSparseNormalCholesky( + SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, + const ParameterBlockOrdering& parameter_block_ordering, + Program* program, + string* error); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_REORDER_PROGRAM_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc index d3eef5d4328..33f812b8c96 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// Copyright 2014 Google Inc. All rights reserved. // http://code.google.com/p/ceres-solver/ // // Redistribution and use in source and binary forms, with or without @@ -28,21 +28,22 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) +#include "ceres/internal/port.h" + #include <algorithm> #include <ctime> #include <set> #include <vector> -#include "Eigen/Dense" #include "ceres/block_random_access_dense_matrix.h" #include "ceres/block_random_access_matrix.h" #include "ceres/block_random_access_sparse_matrix.h" #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" +#include "ceres/conjugate_gradients_solver.h" #include "ceres/cxsparse.h" #include "ceres/detect_structure.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/lapack.h" #include "ceres/linear_solver.h" @@ -51,9 +52,66 @@ #include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" #include "ceres/wall_time.h" +#include "Eigen/Dense" +#include "Eigen/SparseCore" namespace ceres { namespace internal { +namespace { + +class BlockRandomAccessSparseMatrixAdapter : public LinearOperator { + public: + explicit BlockRandomAccessSparseMatrixAdapter( + const BlockRandomAccessSparseMatrix& m) + : m_(m) { + } + + virtual ~BlockRandomAccessSparseMatrixAdapter() {} + + // y = y + Ax; + virtual void RightMultiply(const double* x, double* y) const { + m_.SymmetricRightMultiply(x, y); + } + + // y = y + A'x; + virtual void LeftMultiply(const double* x, double* y) const { + m_.SymmetricRightMultiply(x, y); + } + + virtual int num_rows() const { return m_.num_rows(); } + virtual int num_cols() const { return m_.num_rows(); } + + private: + const BlockRandomAccessSparseMatrix& m_; +}; + +class BlockRandomAccessDiagonalMatrixAdapter : public LinearOperator { + public: + explicit BlockRandomAccessDiagonalMatrixAdapter( + const BlockRandomAccessDiagonalMatrix& m) + : m_(m) { + } + + virtual ~BlockRandomAccessDiagonalMatrixAdapter() {} + + // y = y + Ax; + virtual void RightMultiply(const double* x, double* y) const { + m_.RightMultiply(x, y); + } + + // y = y + A'x; + virtual void LeftMultiply(const double* x, double* y) const { + m_.RightMultiply(x, y); + } + + virtual int num_rows() const { return m_.num_rows(); } + virtual int num_cols() const { return m_.num_rows(); } + + private: + const BlockRandomAccessDiagonalMatrix& m_; +}; + +} // namespace LinearSolver::Summary SchurComplementSolver::SolveImpl( BlockSparseMatrix* A, @@ -80,7 +138,7 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl( double* reduced_solution = x + A->num_cols() - lhs_->num_cols(); const LinearSolver::Summary summary = - SolveReducedLinearSystem(reduced_solution); + SolveReducedLinearSystem(per_solve_options, reduced_solution); event_logger.AddEvent("ReducedSolve"); if (summary.termination_type == LINEAR_SOLVER_SUCCESS) { @@ -113,7 +171,9 @@ void DenseSchurComplementSolver::InitStorage( // BlockRandomAccessDenseMatrix. The linear system is solved using // Eigen's Cholesky factorization. LinearSolver::Summary -DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { +DenseSchurComplementSolver::SolveReducedLinearSystem( + const LinearSolver::PerSolveOptions& per_solve_options, + double* solution) { LinearSolver::Summary summary; summary.num_iterations = 0; summary.termination_type = LINEAR_SOLVER_SUCCESS; @@ -138,7 +198,8 @@ DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { .llt(); if (llt.info() != Eigen::Success) { summary.termination_type = LINEAR_SOLVER_FAILURE; - summary.message = "Eigen LLT decomposition failed."; + summary.message = + "Eigen failure. Unable to perform dense Cholesky factorization."; return summary; } @@ -155,8 +216,6 @@ DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { return summary; } -#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE) - SparseSchurComplementSolver::SparseSchurComplementSolver( const LinearSolver::Options& options) : SchurComplementSolver(options), @@ -165,19 +224,15 @@ SparseSchurComplementSolver::SparseSchurComplementSolver( } SparseSchurComplementSolver::~SparseSchurComplementSolver() { -#ifndef CERES_NO_SUITESPARSE if (factor_ != NULL) { ss_.Free(factor_); factor_ = NULL; } -#endif // CERES_NO_SUITESPARSE -#ifndef CERES_NO_CXSPARSE if (cxsparse_factor_ != NULL) { cxsparse_.Free(cxsparse_factor_); cxsparse_factor_ = NULL; } -#endif // CERES_NO_CXSPARSE } // Determine the non-zero blocks in the Schur Complement matrix, and @@ -252,12 +307,25 @@ void SparseSchurComplementSolver::InitStorage( } LinearSolver::Summary -SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { +SparseSchurComplementSolver::SolveReducedLinearSystem( + const LinearSolver::PerSolveOptions& per_solve_options, + double* solution) { + if (options().type == ITERATIVE_SCHUR) { + CHECK(options().use_explicit_schur_complement); + return SolveReducedLinearSystemUsingConjugateGradients(per_solve_options, + solution); + } + switch (options().sparse_linear_algebra_library_type) { case SUITE_SPARSE: - return SolveReducedLinearSystemUsingSuiteSparse(solution); + return SolveReducedLinearSystemUsingSuiteSparse(per_solve_options, + solution); case CX_SPARSE: - return SolveReducedLinearSystemUsingCXSparse(solution); + return SolveReducedLinearSystemUsingCXSparse(per_solve_options, + solution); + case EIGEN_SPARSE: + return SolveReducedLinearSystemUsingEigen(per_solve_options, + solution); default: LOG(FATAL) << "Unknown sparse linear algebra library : " << options().sparse_linear_algebra_library_type; @@ -266,13 +334,24 @@ SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { return LinearSolver::Summary(); } -#ifndef CERES_NO_SUITESPARSE // Solve the system Sx = r, assuming that the matrix S is stored in a // BlockRandomAccessSparseMatrix. The linear system is solved using // CHOLMOD's sparse cholesky factorization routines. LinearSolver::Summary SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse( + const LinearSolver::PerSolveOptions& per_solve_options, double* solution) { +#ifdef CERES_NO_SUITESPARSE + + LinearSolver::Summary summary; + summary.num_iterations = 0; + summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; + summary.message = "Ceres was not built with SuiteSparse support. " + "Therefore, SPARSE_SCHUR cannot be used with SUITE_SPARSE"; + return summary; + +#else + LinearSolver::Summary summary; summary.num_iterations = 0; summary.termination_type = LINEAR_SOLVER_SUCCESS; @@ -326,6 +405,8 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse( if (factor_ == NULL) { ss_.Free(cholmod_lhs); summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; + // No need to set message as it has already been set by the + // symbolic analysis routines above. return summary; } @@ -335,6 +416,8 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse( ss_.Free(cholmod_lhs); if (summary.termination_type != LINEAR_SOLVER_SUCCESS) { + // No need to set message as it has already been set by the + // numeric factorization routine above. return summary; } @@ -346,6 +429,8 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse( ss_.Free(cholmod_rhs); if (cholmod_solution == NULL) { + summary.message = + "SuiteSparse failure. Unable to perform triangular solve."; summary.termination_type = LINEAR_SOLVER_FAILURE; return summary; } @@ -354,23 +439,27 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse( = VectorRef(static_cast<double*>(cholmod_solution->x), num_rows); ss_.Free(cholmod_solution); return summary; -} -#else -LinearSolver::Summary -SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse( - double* solution) { - LOG(FATAL) << "No SuiteSparse support in Ceres."; - return LinearSolver::Summary(); -} #endif // CERES_NO_SUITESPARSE +} -#ifndef CERES_NO_CXSPARSE // Solve the system Sx = r, assuming that the matrix S is stored in a // BlockRandomAccessSparseMatrix. The linear system is solved using // CXSparse's sparse cholesky factorization routines. LinearSolver::Summary SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse( + const LinearSolver::PerSolveOptions& per_solve_options, double* solution) { +#ifdef CERES_NO_CXSPARSE + + LinearSolver::Summary summary; + summary.num_iterations = 0; + summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; + summary.message = "Ceres was not built with CXSparse support. " + "Therefore, SPARSE_SCHUR cannot be used with CX_SPARSE"; + return summary; + +#else + LinearSolver::Summary summary; summary.num_iterations = 0; summary.termination_type = LINEAR_SOLVER_SUCCESS; @@ -407,16 +496,169 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse( cxsparse_.Free(lhs); return summary; +#endif // CERES_NO_CXPARSE } + +// Solve the system Sx = r, assuming that the matrix S is stored in a +// BlockRandomAccessSparseMatrix. The linear system is solved using +// Eigen's sparse cholesky factorization routines. +LinearSolver::Summary +SparseSchurComplementSolver::SolveReducedLinearSystemUsingEigen( + const LinearSolver::PerSolveOptions& per_solve_options, + double* solution) { +#ifndef CERES_USE_EIGEN_SPARSE + + LinearSolver::Summary summary; + summary.num_iterations = 0; + summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; + summary.message = + "SPARSE_SCHUR cannot be used with EIGEN_SPARSE. " + "Ceres was not built with support for " + "Eigen's SimplicialLDLT decomposition. " + "This requires enabling building with -DEIGENSPARSE=ON."; + return summary; + #else + EventLogger event_logger("SchurComplementSolver::EigenSolve"); + LinearSolver::Summary summary; + summary.num_iterations = 0; + summary.termination_type = LINEAR_SOLVER_SUCCESS; + summary.message = "Success."; + + // Extract the TripletSparseMatrix that is used for actually storing S. + TripletSparseMatrix* tsm = + const_cast<TripletSparseMatrix*>( + down_cast<const BlockRandomAccessSparseMatrix*>(lhs())->matrix()); + const int num_rows = tsm->num_rows(); + + // The case where there are no f blocks, and the system is block + // diagonal. + if (num_rows == 0) { + return summary; + } + + // This is an upper triangular matrix. + CompressedRowSparseMatrix crsm(*tsm); + // Map this to a column major, lower triangular matrix. + Eigen::MappedSparseMatrix<double, Eigen::ColMajor> eigen_lhs( + crsm.num_rows(), + crsm.num_rows(), + crsm.num_nonzeros(), + crsm.mutable_rows(), + crsm.mutable_cols(), + crsm.mutable_values()); + event_logger.AddEvent("ToCompressedRowSparseMatrix"); + + // Compute symbolic factorization if one does not exist. + if (simplicial_ldlt_.get() == NULL) { + simplicial_ldlt_.reset(new SimplicialLDLT); + // This ordering is quite bad. The scalar ordering produced by the + // AMD algorithm is quite bad and can be an order of magnitude + // worse than the one computed using the block version of the + // algorithm. + simplicial_ldlt_->analyzePattern(eigen_lhs); + event_logger.AddEvent("Analysis"); + if (simplicial_ldlt_->info() != Eigen::Success) { + summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; + summary.message = + "Eigen failure. Unable to find symbolic factorization."; + return summary; + } + } + + simplicial_ldlt_->factorize(eigen_lhs); + event_logger.AddEvent("Factorize"); + if (simplicial_ldlt_->info() != Eigen::Success) { + summary.termination_type = LINEAR_SOLVER_FAILURE; + summary.message = "Eigen failure. Unable to find numeric factoriztion."; + return summary; + } + + VectorRef(solution, num_rows) = + simplicial_ldlt_->solve(ConstVectorRef(rhs(), num_rows)); + event_logger.AddEvent("Solve"); + if (simplicial_ldlt_->info() != Eigen::Success) { + summary.termination_type = LINEAR_SOLVER_FAILURE; + summary.message = "Eigen failure. Unable to do triangular solve."; + } + + return summary; +#endif // CERES_USE_EIGEN_SPARSE +} + LinearSolver::Summary -SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse( +SparseSchurComplementSolver::SolveReducedLinearSystemUsingConjugateGradients( + const LinearSolver::PerSolveOptions& per_solve_options, double* solution) { - LOG(FATAL) << "No CXSparse support in Ceres."; - return LinearSolver::Summary(); + const int num_rows = lhs()->num_rows(); + // The case where there are no f blocks, and the system is block + // diagonal. + if (num_rows == 0) { + LinearSolver::Summary summary; + summary.num_iterations = 0; + summary.termination_type = LINEAR_SOLVER_SUCCESS; + summary.message = "Success."; + return summary; + } + + // Only SCHUR_JACOBI is supported over here right now. + CHECK_EQ(options().preconditioner_type, SCHUR_JACOBI); + + if (preconditioner_.get() == NULL) { + preconditioner_.reset(new BlockRandomAccessDiagonalMatrix(blocks_)); + } + + BlockRandomAccessSparseMatrix* sc = + down_cast<BlockRandomAccessSparseMatrix*>( + const_cast<BlockRandomAccessMatrix*>(lhs())); + + // Extract block diagonal from the Schur complement to construct the + // schur_jacobi preconditioner. + for (int i = 0; i < blocks_.size(); ++i) { + const int block_size = blocks_[i]; + + int sc_r, sc_c, sc_row_stride, sc_col_stride; + CellInfo* sc_cell_info = + CHECK_NOTNULL(sc->GetCell(i, i, + &sc_r, &sc_c, + &sc_row_stride, &sc_col_stride)); + MatrixRef sc_m(sc_cell_info->values, sc_row_stride, sc_col_stride); + + int pre_r, pre_c, pre_row_stride, pre_col_stride; + CellInfo* pre_cell_info = CHECK_NOTNULL( + preconditioner_->GetCell(i, i, + &pre_r, &pre_c, + &pre_row_stride, &pre_col_stride)); + MatrixRef pre_m(pre_cell_info->values, pre_row_stride, pre_col_stride); + + pre_m.block(pre_r, pre_c, block_size, block_size) = + sc_m.block(sc_r, sc_c, block_size, block_size); + } + preconditioner_->Invert(); + + VectorRef(solution, num_rows).setZero(); + + scoped_ptr<LinearOperator> lhs_adapter( + new BlockRandomAccessSparseMatrixAdapter(*sc)); + scoped_ptr<LinearOperator> preconditioner_adapter( + new BlockRandomAccessDiagonalMatrixAdapter(*preconditioner_)); + + + LinearSolver::Options cg_options; + cg_options.min_num_iterations = options().min_num_iterations; + cg_options.max_num_iterations = options().max_num_iterations; + ConjugateGradientsSolver cg_solver(cg_options); + + LinearSolver::PerSolveOptions cg_per_solve_options; + cg_per_solve_options.r_tolerance = per_solve_options.r_tolerance; + cg_per_solve_options.q_tolerance = per_solve_options.q_tolerance; + cg_per_solve_options.preconditioner = preconditioner_adapter.get(); + + return cg_solver.Solve(lhs_adapter.get(), + rhs(), + cg_per_solve_options, + solution); } -#endif // CERES_NO_CXPARSE -#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE) } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h index a9978518b17..93d23e3d012 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h @@ -35,6 +35,8 @@ #include <utility> #include <vector> +#include "ceres/internal/port.h" + #include "ceres/block_random_access_matrix.h" #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" @@ -44,6 +46,12 @@ #include "ceres/suitesparse.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" +#include "ceres/block_random_access_diagonal_matrix.h" + +#ifdef CERES_USE_EIGEN_SPARSE +#include "Eigen/SparseCholesky" +#include "Eigen/OrderingMethods" +#endif namespace ceres { namespace internal { @@ -127,6 +135,7 @@ class SchurComplementSolver : public BlockSparseMatrixSolver { private: virtual void InitStorage(const CompressedRowBlockStructure* bs) = 0; virtual LinearSolver::Summary SolveReducedLinearSystem( + const LinearSolver::PerSolveOptions& per_solve_options, double* solution) = 0; LinearSolver::Options options_; @@ -148,12 +157,12 @@ class DenseSchurComplementSolver : public SchurComplementSolver { private: virtual void InitStorage(const CompressedRowBlockStructure* bs); virtual LinearSolver::Summary SolveReducedLinearSystem( + const LinearSolver::PerSolveOptions& per_solve_options, double* solution); CERES_DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver); }; -#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE) // Sparse Cholesky factorization based solver. class SparseSchurComplementSolver : public SchurComplementSolver { public: @@ -163,10 +172,19 @@ class SparseSchurComplementSolver : public SchurComplementSolver { private: virtual void InitStorage(const CompressedRowBlockStructure* bs); virtual LinearSolver::Summary SolveReducedLinearSystem( + const LinearSolver::PerSolveOptions& per_solve_options, double* solution); LinearSolver::Summary SolveReducedLinearSystemUsingSuiteSparse( + const LinearSolver::PerSolveOptions& per_solve_options, double* solution); LinearSolver::Summary SolveReducedLinearSystemUsingCXSparse( + const LinearSolver::PerSolveOptions& per_solve_options, + double* solution); + LinearSolver::Summary SolveReducedLinearSystemUsingEigen( + const LinearSolver::PerSolveOptions& per_solve_options, + double* solution); + LinearSolver::Summary SolveReducedLinearSystemUsingConjugateGradients( + const LinearSolver::PerSolveOptions& per_solve_options, double* solution); // Size of the blocks in the Schur complement. @@ -180,10 +198,28 @@ class SparseSchurComplementSolver : public SchurComplementSolver { CXSparse cxsparse_; // Cached factorization cs_dis* cxsparse_factor_; + +#ifdef CERES_USE_EIGEN_SPARSE + + // The preprocessor gymnastics here are dealing with the fact that + // before version 3.2.2, Eigen did not support a third template + // parameter to specify the ordering. +#if EIGEN_VERSION_AT_LEAST(3,2,2) + typedef Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>, Eigen::Lower, + Eigen::NaturalOrdering<int> > + SimplicialLDLT; +#else + typedef Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>, Eigen::Lower> + SimplicialLDLT; +#endif + + scoped_ptr<SimplicialLDLT> simplicial_ldlt_; +#endif + + scoped_ptr<BlockRandomAccessDiagonalMatrix> preconditioner_; CERES_DISALLOW_COPY_AND_ASSIGN(SparseSchurComplementSolver); }; -#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARE) } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc index 6dc9e89d3cc..cbdb7086102 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.cc @@ -32,7 +32,6 @@ #include <utility> #include <vector> -#include "Eigen/Dense" #include "ceres/block_random_access_diagonal_matrix.h" #include "ceres/block_sparse_matrix.h" #include "ceres/collections_port.h" @@ -55,12 +54,12 @@ SchurJacobiPreconditioner::SchurJacobiPreconditioner( << "Jacobian should have atleast 1 f_block for " << "SCHUR_JACOBI preconditioner."; - block_size_.resize(num_blocks); + vector<int> blocks(num_blocks); for (int i = 0; i < num_blocks; ++i) { - block_size_[i] = bs.cols[i + options_.elimination_groups[0]].size; + blocks[i] = bs.cols[i + options_.elimination_groups[0]].size; } - m_.reset(new BlockRandomAccessDiagonalMatrix(block_size_)); + m_.reset(new BlockRandomAccessDiagonalMatrix(blocks)); InitEliminator(bs); } @@ -99,32 +98,13 @@ bool SchurJacobiPreconditioner::UpdateImpl(const BlockSparseMatrix& A, // Compute a subset of the entries of the Schur complement. eliminator_->Eliminate(&A, b.data(), D, m_.get(), rhs.data()); + m_->Invert(); return true; } void SchurJacobiPreconditioner::RightMultiply(const double* x, double* y) const { - CHECK_NOTNULL(x); - CHECK_NOTNULL(y); - - const double* lhs_values = - down_cast<BlockRandomAccessDiagonalMatrix*>(m_.get())->matrix()->values(); - - // This loop can be easily multi-threaded with OpenMP if need be. - for (int i = 0; i < block_size_.size(); ++i) { - const int block_size = block_size_[i]; - ConstMatrixRef block(lhs_values, block_size, block_size); - - VectorRef(y, block_size) = - block - .selfadjointView<Eigen::Upper>() - .llt() - .solve(ConstVectorRef(x, block_size)); - - x += block_size; - y += block_size; - lhs_values += block_size * block_size; - } + m_->RightMultiply(x, y); } int SchurJacobiPreconditioner::num_rows() const { diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h index aecb0151083..8b528e25075 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_jacobi_preconditioner.h @@ -94,11 +94,7 @@ class SchurJacobiPreconditioner : public BlockSparseMatrixPreconditioner { virtual bool UpdateImpl(const BlockSparseMatrix& A, const double* D); Preconditioner::Options options_; - - // Sizes of the blocks in the schur complement. - vector<int> block_size_; scoped_ptr<SchurEliminatorBase> eliminator_; - // Preconditioner matrix. scoped_ptr<BlockRandomAccessDiagonalMatrix> m_; CERES_DISALLOW_COPY_AND_ASSIGN(SchurJacobiPreconditioner); diff --git a/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.cc b/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.cc index 0a8b20cfe29..f0f7e0e1e06 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.cc @@ -44,7 +44,7 @@ namespace internal { int ComputeSingleLinkageClustering( const SingleLinkageClusteringOptions& options, - const Graph<int>& graph, + const WeightedGraph<int>& graph, HashMap<int, int>* membership) { CHECK_NOTNULL(membership)->clear(); diff --git a/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.h b/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.h index e6fdeabea61..79c4da114c2 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.h +++ b/extern/libmv/third_party/ceres/internal/ceres/single_linkage_clustering.h @@ -64,7 +64,7 @@ struct SingleLinkageClusteringOptions { // identified by the algorithm. int ComputeSingleLinkageClustering( const SingleLinkageClusteringOptions& options, - const Graph<int>& graph, + const WeightedGraph<int>& graph, HashMap<int, int>* membership); } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/small_blas.h b/extern/libmv/third_party/ceres/internal/ceres/small_blas.h index 26228e49306..5639664b925 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/small_blas.h +++ b/extern/libmv/third_party/ceres/internal/ceres/small_blas.h @@ -42,30 +42,6 @@ namespace ceres { namespace internal { -// Remove the ".noalias()" annotation from the matrix matrix -// mutliplies to produce a correct build with the Android NDK, -// including versions 6, 7, 8, and 8b, when built with STLPort and the -// non-standalone toolchain (i.e. ndk-build). This appears to be a -// compiler bug; if the workaround is not in place, the line -// -// block.noalias() -= A * B; -// -// gets compiled to -// -// block.noalias() += A * B; -// -// which breaks schur elimination. Introducing a temporary by removing the -// .noalias() annotation causes the issue to disappear. Tracking this -// issue down was tricky, since the test suite doesn't run when built with -// the non-standalone toolchain. -// -// TODO(keir): Make a reproduction case for this and send it upstream. -#ifdef CERES_WORK_AROUND_ANDROID_NDK_COMPILER_BUG -#define CERES_MAYBE_NOALIAS -#else -#define CERES_MAYBE_NOALIAS .noalias() -#endif - // The following three macros are used to share code and reduce // template junk across the various GEMM variants. #define CERES_GEMM_BEGIN(name) \ @@ -168,11 +144,11 @@ CERES_GEMM_BEGIN(MatrixMatrixMultiplyEigen) { block(Cref, start_row_c, start_col_c, num_row_a, num_col_b); if (kOperation > 0) { - block CERES_MAYBE_NOALIAS += Aref * Bref; + block.noalias() += Aref * Bref; } else if (kOperation < 0) { - block CERES_MAYBE_NOALIAS -= Aref * Bref; + block.noalias() -= Aref * Bref; } else { - block CERES_MAYBE_NOALIAS = Aref * Bref; + block.noalias() = Aref * Bref; } } @@ -228,11 +204,11 @@ CERES_GEMM_BEGIN(MatrixTransposeMatrixMultiplyEigen) { start_row_c, start_col_c, num_col_a, num_col_b); if (kOperation > 0) { - block CERES_MAYBE_NOALIAS += Aref.transpose() * Bref; + block.noalias() += Aref.transpose() * Bref; } else if (kOperation < 0) { - block CERES_MAYBE_NOALIAS -= Aref.transpose() * Bref; + block.noalias() -= Aref.transpose() * Bref; } else { - block CERES_MAYBE_NOALIAS = Aref.transpose() * Bref; + block.noalias() = Aref.transpose() * Bref; } } @@ -394,8 +370,6 @@ inline void MatrixTransposeVectorMultiply(const double* A, #endif // CERES_NO_CUSTOM_BLAS } - -#undef CERES_MAYBE_NOALIAS #undef CERES_GEMM_BEGIN #undef CERES_GEMM_EIGEN_HEADER #undef CERES_GEMM_NAIVE_HEADER diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver.cc b/extern/libmv/third_party/ceres/internal/ceres/solver.cc index 53a9b4b7220..3512e156f9e 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/solver.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// Copyright 2014 Google Inc. All rights reserved. // http://code.google.com/p/ceres-solver/ // // Redistribution and use in source and binary forms, with or without @@ -31,17 +31,282 @@ #include "ceres/solver.h" +#include <algorithm> +#include <sstream> // NOLINT #include <vector> +#include "ceres/gradient_checking_cost_function.h" +#include "ceres/internal/port.h" +#include "ceres/parameter_block_ordering.h" +#include "ceres/preprocessor.h" #include "ceres/problem.h" #include "ceres/problem_impl.h" #include "ceres/program.h" -#include "ceres/solver_impl.h" +#include "ceres/solver_utils.h" #include "ceres/stringprintf.h" +#include "ceres/types.h" #include "ceres/wall_time.h" namespace ceres { namespace { +#define OPTION_OP(x, y, OP) \ + if (!(options.x OP y)) { \ + std::stringstream ss; \ + ss << "Invalid configuration. "; \ + ss << string("Solver::Options::" #x " = ") << options.x << ". "; \ + ss << "Violated constraint: "; \ + ss << string("Solver::Options::" #x " " #OP " "#y); \ + *error = ss.str(); \ + return false; \ + } + +#define OPTION_OP_OPTION(x, y, OP) \ + if (!(options.x OP options.y)) { \ + std::stringstream ss; \ + ss << "Invalid configuration. "; \ + ss << string("Solver::Options::" #x " = ") << options.x << ". "; \ + ss << string("Solver::Options::" #y " = ") << options.y << ". "; \ + ss << "Violated constraint: "; \ + ss << string("Solver::Options::" #x); \ + ss << string(#OP " Solver::Options::" #y "."); \ + *error = ss.str(); \ + return false; \ + } + +#define OPTION_GE(x, y) OPTION_OP(x, y, >=); +#define OPTION_GT(x, y) OPTION_OP(x, y, >); +#define OPTION_LE(x, y) OPTION_OP(x, y, <=); +#define OPTION_LT(x, y) OPTION_OP(x, y, <); +#define OPTION_LE_OPTION(x, y) OPTION_OP_OPTION(x, y, <=) +#define OPTION_LT_OPTION(x, y) OPTION_OP_OPTION(x, y, <) + +bool CommonOptionsAreValid(const Solver::Options& options, string* error) { + OPTION_GE(max_num_iterations, 0); + OPTION_GE(max_solver_time_in_seconds, 0.0); + OPTION_GE(function_tolerance, 0.0); + OPTION_GE(gradient_tolerance, 0.0); + OPTION_GE(parameter_tolerance, 0.0); + OPTION_GT(num_threads, 0); + OPTION_GT(num_linear_solver_threads, 0); + if (options.check_gradients) { + OPTION_GT(gradient_check_relative_precision, 0.0); + OPTION_GT(numeric_derivative_relative_step_size, 0.0); + } + return true; +} + +bool TrustRegionOptionsAreValid(const Solver::Options& options, string* error) { + OPTION_GT(initial_trust_region_radius, 0.0); + OPTION_GT(min_trust_region_radius, 0.0); + OPTION_GT(max_trust_region_radius, 0.0); + OPTION_LE_OPTION(min_trust_region_radius, max_trust_region_radius); + OPTION_LE_OPTION(min_trust_region_radius, initial_trust_region_radius); + OPTION_LE_OPTION(initial_trust_region_radius, max_trust_region_radius); + OPTION_GE(min_relative_decrease, 0.0); + OPTION_GE(min_lm_diagonal, 0.0); + OPTION_GE(max_lm_diagonal, 0.0); + OPTION_LE_OPTION(min_lm_diagonal, max_lm_diagonal); + OPTION_GE(max_num_consecutive_invalid_steps, 0); + OPTION_GT(eta, 0.0); + OPTION_GE(min_linear_solver_iterations, 0); + OPTION_GE(max_linear_solver_iterations, 1); + OPTION_LE_OPTION(min_linear_solver_iterations, max_linear_solver_iterations); + + if (options.use_inner_iterations) { + OPTION_GE(inner_iteration_tolerance, 0.0); + } + + if (options.use_nonmonotonic_steps) { + OPTION_GT(max_consecutive_nonmonotonic_steps, 0); + } + + if (options.linear_solver_type == ITERATIVE_SCHUR && + options.use_explicit_schur_complement && + options.preconditioner_type != SCHUR_JACOBI) { + *error = "use_explicit_schur_complement only supports " + "SCHUR_JACOBI as the preconditioner."; + return false; + } + + if (options.preconditioner_type == CLUSTER_JACOBI && + options.sparse_linear_algebra_library_type != SUITE_SPARSE) { + *error = "CLUSTER_JACOBI requires " + "Solver::Options::sparse_linear_algebra_library_type to be " + "SUITE_SPARSE"; + return false; + } + + if (options.preconditioner_type == CLUSTER_TRIDIAGONAL && + options.sparse_linear_algebra_library_type != SUITE_SPARSE) { + *error = "CLUSTER_TRIDIAGONAL requires " + "Solver::Options::sparse_linear_algebra_library_type to be " + "SUITE_SPARSE"; + return false; + } + +#ifdef CERES_NO_LAPACK + if (options.dense_linear_algebra_library_type == LAPACK) { + if (options.linear_solver_type == DENSE_NORMAL_CHOLESKY) { + *error = "Can't use DENSE_NORMAL_CHOLESKY with LAPACK because " + "LAPACK was not enabled when Ceres was built."; + return false; + } + + if (options.linear_solver_type == DENSE_QR) { + *error = "Can't use DENSE_QR with LAPACK because " + "LAPACK was not enabled when Ceres was built."; + return false; + } + + if (options.linear_solver_type == DENSE_SCHUR) { + *error = "Can't use DENSE_SCHUR with LAPACK because " + "LAPACK was not enabled when Ceres was built."; + return false; + } + } +#endif + +#ifdef CERES_NO_SUITESPARSE + if (options.sparse_linear_algebra_library_type == SUITE_SPARSE) { + if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY) { + *error = "Can't use SPARSE_NORMAL_CHOLESKY with SUITESPARSE because " + "SuiteSparse was not enabled when Ceres was built."; + return false; + } + + if (options.linear_solver_type == SPARSE_SCHUR) { + *error = "Can't use SPARSE_SCHUR with SUITESPARSE because " + "SuiteSparse was not enabled when Ceres was built."; + return false; + } + + if (options.preconditioner_type == CLUSTER_JACOBI) { + *error = "CLUSTER_JACOBI preconditioner not supported. " + "SuiteSparse was not enabled when Ceres was built."; + return false; + } + + if (options.preconditioner_type == CLUSTER_TRIDIAGONAL) { + *error = "CLUSTER_TRIDIAGONAL preconditioner not supported. " + "SuiteSparse was not enabled when Ceres was built."; + return false; + } + } +#endif + +#ifdef CERES_NO_CXSPARSE + if (options.sparse_linear_algebra_library_type == CX_SPARSE) { + if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY) { + *error = "Can't use SPARSE_NORMAL_CHOLESKY with CX_SPARSE because " + "CXSparse was not enabled when Ceres was built."; + return false; + } + + if (options.linear_solver_type == SPARSE_SCHUR) { + *error = "Can't use SPARSE_SCHUR with CX_SPARSE because " + "CXSparse was not enabled when Ceres was built."; + return false; + } + } +#endif + +#ifndef CERES_USE_EIGEN_SPARSE + if (options.sparse_linear_algebra_library_type == EIGEN_SPARSE) { + if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY) { + *error = "Can't use SPARSE_NORMAL_CHOLESKY with EIGEN_SPARSE because " + "Eigen's sparse linear algebra was not enabled when Ceres was " + "built."; + return false; + } + + if (options.linear_solver_type == SPARSE_SCHUR) { + *error = "Can't use SPARSE_SCHUR with EIGEN_SPARSE because " + "Eigen's sparse linear algebra was not enabled when Ceres was " + "built."; + return false; + } + } +#endif + + if (options.trust_region_strategy_type == DOGLEG) { + if (options.linear_solver_type == ITERATIVE_SCHUR || + options.linear_solver_type == CGNR) { + *error = "DOGLEG only supports exact factorization based linear " + "solvers. If you want to use an iterative solver please " + "use LEVENBERG_MARQUARDT as the trust_region_strategy_type"; + return false; + } + } + + if (options.trust_region_minimizer_iterations_to_dump.size() > 0 && + options.trust_region_problem_dump_format_type != CONSOLE && + options.trust_region_problem_dump_directory.empty()) { + *error = "Solver::Options::trust_region_problem_dump_directory is empty."; + return false; + } + + if (options.dynamic_sparsity && + options.linear_solver_type != SPARSE_NORMAL_CHOLESKY) { + *error = "Dynamic sparsity is only supported with SPARSE_NORMAL_CHOLESKY."; + return false; + } + + return true; +} + +bool LineSearchOptionsAreValid(const Solver::Options& options, string* error) { + OPTION_GT(max_lbfgs_rank, 0); + OPTION_GT(min_line_search_step_size, 0.0); + OPTION_GT(max_line_search_step_contraction, 0.0); + OPTION_LT(max_line_search_step_contraction, 1.0); + OPTION_LT_OPTION(max_line_search_step_contraction, + min_line_search_step_contraction); + OPTION_LE(min_line_search_step_contraction, 1.0); + OPTION_GT(max_num_line_search_step_size_iterations, 0); + OPTION_GT(line_search_sufficient_function_decrease, 0.0); + OPTION_LT_OPTION(line_search_sufficient_function_decrease, + line_search_sufficient_curvature_decrease); + OPTION_LT(line_search_sufficient_curvature_decrease, 1.0); + OPTION_GT(max_line_search_step_expansion, 1.0); + + if ((options.line_search_direction_type == ceres::BFGS || + options.line_search_direction_type == ceres::LBFGS) && + options.line_search_type != ceres::WOLFE) { + *error = + string("Invalid configuration: Solver::Options::line_search_type = ") + + string(LineSearchTypeToString(options.line_search_type)) + + string(". When using (L)BFGS, " + "Solver::Options::line_search_type must be set to WOLFE."); + return false; + } + + // Warn user if they have requested BISECTION interpolation, but constraints + // on max/min step size change during line search prevent bisection scaling + // from occurring. Warn only, as this is likely a user mistake, but one which + // does not prevent us from continuing. + LOG_IF(WARNING, + (options.line_search_interpolation_type == ceres::BISECTION && + (options.max_line_search_step_contraction > 0.5 || + options.min_line_search_step_contraction < 0.5))) + << "Line search interpolation type is BISECTION, but specified " + << "max_line_search_step_contraction: " + << options.max_line_search_step_contraction << ", and " + << "min_line_search_step_contraction: " + << options.min_line_search_step_contraction + << ", prevent bisection (0.5) scaling, continuing with solve regardless."; + + return true; +} + +#undef OPTION_OP +#undef OPTION_OP_OPTION +#undef OPTION_GT +#undef OPTION_GE +#undef OPTION_LE +#undef OPTION_LT +#undef OPTION_LE_OPTION +#undef OPTION_LT_OPTION + void StringifyOrdering(const vector<int>& ordering, string* report) { if (ordering.size() == 0) { internal::StringAppendF(report, "AUTOMATIC"); @@ -54,19 +319,211 @@ void StringifyOrdering(const vector<int>& ordering, string* report) { internal::StringAppendF(report, "%d", ordering.back()); } +void SummarizeGivenProgram(const internal::Program& program, + Solver::Summary* summary) { + summary->num_parameter_blocks = program.NumParameterBlocks(); + summary->num_parameters = program.NumParameters(); + summary->num_effective_parameters = program.NumEffectiveParameters(); + summary->num_residual_blocks = program.NumResidualBlocks(); + summary->num_residuals = program.NumResiduals(); +} + +void SummarizeReducedProgram(const internal::Program& program, + Solver::Summary* summary) { + summary->num_parameter_blocks_reduced = program.NumParameterBlocks(); + summary->num_parameters_reduced = program.NumParameters(); + summary->num_effective_parameters_reduced = program.NumEffectiveParameters(); + summary->num_residual_blocks_reduced = program.NumResidualBlocks(); + summary->num_residuals_reduced = program.NumResiduals(); +} + +void PreSolveSummarize(const Solver::Options& options, + const internal::ProblemImpl* problem, + Solver::Summary* summary) { + SummarizeGivenProgram(problem->program(), summary); + internal::OrderingToGroupSizes(options.linear_solver_ordering.get(), + &(summary->linear_solver_ordering_given)); + internal::OrderingToGroupSizes(options.inner_iteration_ordering.get(), + &(summary->inner_iteration_ordering_given)); + + summary->dense_linear_algebra_library_type = options.dense_linear_algebra_library_type; // NOLINT + summary->dogleg_type = options.dogleg_type; + summary->inner_iteration_time_in_seconds = 0.0; + summary->inner_iterations_given = options.use_inner_iterations; + summary->line_search_direction_type = options.line_search_direction_type; // NOLINT + summary->line_search_interpolation_type = options.line_search_interpolation_type; // NOLINT + summary->line_search_type = options.line_search_type; + summary->linear_solver_type_given = options.linear_solver_type; + summary->max_lbfgs_rank = options.max_lbfgs_rank; + summary->minimizer_type = options.minimizer_type; + summary->nonlinear_conjugate_gradient_type = options.nonlinear_conjugate_gradient_type; // NOLINT + summary->num_linear_solver_threads_given = options.num_linear_solver_threads; // NOLINT + summary->num_threads_given = options.num_threads; + summary->preconditioner_type_given = options.preconditioner_type; + summary->sparse_linear_algebra_library_type = options.sparse_linear_algebra_library_type; // NOLINT + summary->trust_region_strategy_type = options.trust_region_strategy_type; // NOLINT + summary->visibility_clustering_type = options.visibility_clustering_type; // NOLINT +} + +void PostSolveSummarize(const internal::PreprocessedProblem& pp, + Solver::Summary* summary) { + internal::OrderingToGroupSizes(pp.options.linear_solver_ordering.get(), + &(summary->linear_solver_ordering_used)); + internal::OrderingToGroupSizes(pp.options.inner_iteration_ordering.get(), + &(summary->inner_iteration_ordering_used)); + + summary->inner_iterations_used = pp.inner_iteration_minimizer.get() != NULL; // NOLINT + summary->linear_solver_type_used = pp.options.linear_solver_type; + summary->num_linear_solver_threads_used = pp.options.num_linear_solver_threads; // NOLINT + summary->num_threads_used = pp.options.num_threads; + summary->preconditioner_type_used = pp.options.preconditioner_type; // NOLINT + + internal::SetSummaryFinalCost(summary); + + if (pp.reduced_program.get() != NULL) { + SummarizeReducedProgram(*pp.reduced_program, summary); + } + + // It is possible that no evaluator was created. This would be the + // case if the preprocessor failed, or if the reduced problem did + // not contain any parameter blocks. Thus, only extract the + // evaluator statistics if one exists. + if (pp.evaluator.get() != NULL) { + const map<string, double>& evaluator_time_statistics = + pp.evaluator->TimeStatistics(); + summary->residual_evaluation_time_in_seconds = + FindWithDefault(evaluator_time_statistics, "Evaluator::Residual", 0.0); + summary->jacobian_evaluation_time_in_seconds = + FindWithDefault(evaluator_time_statistics, "Evaluator::Jacobian", 0.0); + } + + // Again, like the evaluator, there may or may not be a linear + // solver from which we can extract run time statistics. In + // particular the line search solver does not use a linear solver. + if (pp.linear_solver.get() != NULL) { + const map<string, double>& linear_solver_time_statistics = + pp.linear_solver->TimeStatistics(); + summary->linear_solver_time_in_seconds = + FindWithDefault(linear_solver_time_statistics, + "LinearSolver::Solve", + 0.0); + } +} + +void Minimize(internal::PreprocessedProblem* pp, + Solver::Summary* summary) { + using internal::Program; + using internal::scoped_ptr; + using internal::Minimizer; + + Program* program = pp->reduced_program.get(); + if (pp->reduced_program->NumParameterBlocks() == 0) { + summary->message = "Function tolerance reached. " + "No non-constant parameter blocks found."; + summary->termination_type = CONVERGENCE; + VLOG_IF(1, pp->options.logging_type != SILENT) << summary->message; + summary->initial_cost = summary->fixed_cost; + summary->final_cost = summary->fixed_cost; + return; + } + + scoped_ptr<Minimizer> minimizer( + Minimizer::Create(pp->options.minimizer_type)); + minimizer->Minimize(pp->minimizer_options, + pp->reduced_parameters.data(), + summary); + + if (summary->IsSolutionUsable()) { + program->StateVectorToParameterBlocks(pp->reduced_parameters.data()); + program->CopyParameterBlockStateToUserState(); + } +} + } // namespace +bool Solver::Options::IsValid(string* error) const { + if (!CommonOptionsAreValid(*this, error)) { + return false; + } + + if (minimizer_type == TRUST_REGION) { + return TrustRegionOptionsAreValid(*this, error); + } + + CHECK_EQ(minimizer_type, LINE_SEARCH); + return LineSearchOptionsAreValid(*this, error); +} + Solver::~Solver() {} void Solver::Solve(const Solver::Options& options, Problem* problem, Solver::Summary* summary) { - double start_time_seconds = internal::WallTimeInSeconds(); - internal::ProblemImpl* problem_impl = - CHECK_NOTNULL(problem)->problem_impl_.get(); - internal::SolverImpl::Solve(options, problem_impl, summary); - summary->total_time_in_seconds = - internal::WallTimeInSeconds() - start_time_seconds; + using internal::PreprocessedProblem; + using internal::Preprocessor; + using internal::ProblemImpl; + using internal::Program; + using internal::scoped_ptr; + using internal::WallTimeInSeconds; + + CHECK_NOTNULL(problem); + CHECK_NOTNULL(summary); + + double start_time = WallTimeInSeconds(); + *summary = Summary(); + if (!options.IsValid(&summary->message)) { + LOG(ERROR) << "Terminating: " << summary->message; + return; + } + + ProblemImpl* problem_impl = problem->problem_impl_.get(); + Program* program = problem_impl->mutable_program(); + PreSolveSummarize(options, problem_impl, summary); + + // Make sure that all the parameter blocks states are set to the + // values provided by the user. + program->SetParameterBlockStatePtrsToUserStatePtrs(); + + scoped_ptr<internal::ProblemImpl> gradient_checking_problem; + if (options.check_gradients) { + gradient_checking_problem.reset( + CreateGradientCheckingProblemImpl( + problem_impl, + options.numeric_derivative_relative_step_size, + options.gradient_check_relative_precision)); + problem_impl = gradient_checking_problem.get(); + program = problem_impl->mutable_program(); + } + + scoped_ptr<Preprocessor> preprocessor( + Preprocessor::Create(options.minimizer_type)); + PreprocessedProblem pp; + const bool status = preprocessor->Preprocess(options, problem_impl, &pp); + summary->fixed_cost = pp.fixed_cost; + summary->preprocessor_time_in_seconds = WallTimeInSeconds() - start_time; + + if (status) { + const double minimizer_start_time = WallTimeInSeconds(); + Minimize(&pp, summary); + summary->minimizer_time_in_seconds = + WallTimeInSeconds() - minimizer_start_time; + } else { + summary->message = pp.error; + } + + const double postprocessor_start_time = WallTimeInSeconds(); + problem_impl = problem->problem_impl_.get(); + program = problem_impl->mutable_program(); + // On exit, ensure that the parameter blocks again point at the user + // provided values and the parameter blocks are numbered according + // to their position in the original user provided program. + program->SetParameterBlockStatePtrsToUserStatePtrs(); + program->SetParameterOffsetsAndIndex(); + PostSolveSummarize(pp, summary); + summary->postprocessor_time_in_seconds = + WallTimeInSeconds() - postprocessor_start_time; + + summary->total_time_in_seconds = WallTimeInSeconds() - start_time; } void Solve(const Solver::Options& options, @@ -114,7 +571,8 @@ Solver::Summary::Summary() linear_solver_type_used(SPARSE_NORMAL_CHOLESKY), inner_iterations_given(false), inner_iterations_used(false), - preconditioner_type(IDENTITY), + preconditioner_type_given(IDENTITY), + preconditioner_type_used(IDENTITY), visibility_clustering_type(CANONICAL_VIEWS), trust_region_strategy_type(LEVENBERG_MARQUARDT), dense_linear_algebra_library_type(EIGEN), @@ -142,10 +600,9 @@ string Solver::Summary::BriefReport() const { }; string Solver::Summary::FullReport() const { - string report = - "\n" - "Ceres Solver Report\n" - "-------------------\n"; + using internal::VersionString; + + string report = string("\nSolver Summary (v " + VersionString() + ")\n\n"); StringAppendF(&report, "%45s %21s\n", "Original", "Reduced"); StringAppendF(&report, "Parameter blocks % 25d% 25d\n", @@ -177,8 +634,8 @@ string Solver::Summary::FullReport() const { if (linear_solver_type_used == SPARSE_NORMAL_CHOLESKY || linear_solver_type_used == SPARSE_SCHUR || (linear_solver_type_used == ITERATIVE_SCHUR && - (preconditioner_type == CLUSTER_JACOBI || - preconditioner_type == CLUSTER_TRIDIAGONAL))) { + (preconditioner_type_used == CLUSTER_JACOBI || + preconditioner_type_used == CLUSTER_TRIDIAGONAL))) { StringAppendF(&report, "\nSparse linear algebra library %15s\n", SparseLinearAlgebraLibraryTypeToString( sparse_linear_algebra_library_type)); @@ -205,12 +662,12 @@ string Solver::Summary::FullReport() const { if (linear_solver_type_given == CGNR || linear_solver_type_given == ITERATIVE_SCHUR) { StringAppendF(&report, "Preconditioner %25s%25s\n", - PreconditionerTypeToString(preconditioner_type), - PreconditionerTypeToString(preconditioner_type)); + PreconditionerTypeToString(preconditioner_type_given), + PreconditionerTypeToString(preconditioner_type_used)); } - if (preconditioner_type == CLUSTER_JACOBI || - preconditioner_type == CLUSTER_TRIDIAGONAL) { + if (preconditioner_type_used == CLUSTER_JACOBI || + preconditioner_type_used == CLUSTER_TRIDIAGONAL) { StringAppendF(&report, "Visibility clustering%24s%25s\n", VisibilityClusteringTypeToString( visibility_clustering_type), @@ -345,9 +802,7 @@ string Solver::Summary::FullReport() const { }; bool Solver::Summary::IsSolutionUsable() const { - return (termination_type == CONVERGENCE || - termination_type == NO_CONVERGENCE || - termination_type == USER_SUCCESS); + return internal::IsSolutionUsable(*this); } } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc deleted file mode 100644 index 2bf6cd26212..00000000000 --- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc +++ /dev/null @@ -1,1851 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. -// http://code.google.com/p/ceres-solver/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Author: keir@google.com (Keir Mierle) - -#include "ceres/solver_impl.h" - -#include <cstdio> -#include <iostream> // NOLINT -#include <numeric> -#include <string> -#include "ceres/coordinate_descent_minimizer.h" -#include "ceres/cxsparse.h" -#include "ceres/evaluator.h" -#include "ceres/gradient_checking_cost_function.h" -#include "ceres/iteration_callback.h" -#include "ceres/levenberg_marquardt_strategy.h" -#include "ceres/line_search_minimizer.h" -#include "ceres/linear_solver.h" -#include "ceres/map_util.h" -#include "ceres/minimizer.h" -#include "ceres/ordered_groups.h" -#include "ceres/parameter_block.h" -#include "ceres/parameter_block_ordering.h" -#include "ceres/problem.h" -#include "ceres/problem_impl.h" -#include "ceres/program.h" -#include "ceres/residual_block.h" -#include "ceres/stringprintf.h" -#include "ceres/suitesparse.h" -#include "ceres/trust_region_minimizer.h" -#include "ceres/wall_time.h" - -namespace ceres { -namespace internal { -namespace { - -// Callback for updating the user's parameter blocks. Updates are only -// done if the step is successful. -class StateUpdatingCallback : public IterationCallback { - public: - StateUpdatingCallback(Program* program, double* parameters) - : program_(program), parameters_(parameters) {} - - CallbackReturnType operator()(const IterationSummary& summary) { - if (summary.step_is_successful) { - program_->StateVectorToParameterBlocks(parameters_); - program_->CopyParameterBlockStateToUserState(); - } - return SOLVER_CONTINUE; - } - - private: - Program* program_; - double* parameters_; -}; - -void SetSummaryFinalCost(Solver::Summary* summary) { - summary->final_cost = summary->initial_cost; - // We need the loop here, instead of just looking at the last - // iteration because the minimizer maybe making non-monotonic steps. - for (int i = 0; i < summary->iterations.size(); ++i) { - const IterationSummary& iteration_summary = summary->iterations[i]; - summary->final_cost = min(iteration_summary.cost, summary->final_cost); - } -} - -// Callback for logging the state of the minimizer to STDERR or STDOUT -// depending on the user's preferences and logging level. -class TrustRegionLoggingCallback : public IterationCallback { - public: - explicit TrustRegionLoggingCallback(bool log_to_stdout) - : log_to_stdout_(log_to_stdout) {} - - ~TrustRegionLoggingCallback() {} - - CallbackReturnType operator()(const IterationSummary& summary) { - const char* kReportRowFormat = - "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e " - "rho:% 3.2e mu:% 3.2e li:% 3d it:% 3.2e tt:% 3.2e"; - string output = StringPrintf(kReportRowFormat, - summary.iteration, - summary.cost, - summary.cost_change, - summary.gradient_max_norm, - summary.step_norm, - summary.relative_decrease, - summary.trust_region_radius, - summary.linear_solver_iterations, - summary.iteration_time_in_seconds, - summary.cumulative_time_in_seconds); - if (log_to_stdout_) { - cout << output << endl; - } else { - VLOG(1) << output; - } - return SOLVER_CONTINUE; - } - - private: - const bool log_to_stdout_; -}; - -// Callback for logging the state of the minimizer to STDERR or STDOUT -// depending on the user's preferences and logging level. -class LineSearchLoggingCallback : public IterationCallback { - public: - explicit LineSearchLoggingCallback(bool log_to_stdout) - : log_to_stdout_(log_to_stdout) {} - - ~LineSearchLoggingCallback() {} - - CallbackReturnType operator()(const IterationSummary& summary) { - const char* kReportRowFormat = - "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e " - "s:% 3.2e e:% 3d it:% 3.2e tt:% 3.2e"; - string output = StringPrintf(kReportRowFormat, - summary.iteration, - summary.cost, - summary.cost_change, - summary.gradient_max_norm, - summary.step_norm, - summary.step_size, - summary.line_search_function_evaluations, - summary.iteration_time_in_seconds, - summary.cumulative_time_in_seconds); - if (log_to_stdout_) { - cout << output << endl; - } else { - VLOG(1) << output; - } - return SOLVER_CONTINUE; - } - - private: - const bool log_to_stdout_; -}; - - -// Basic callback to record the execution of the solver to a file for -// offline analysis. -class FileLoggingCallback : public IterationCallback { - public: - explicit FileLoggingCallback(const string& filename) - : fptr_(NULL) { - fptr_ = fopen(filename.c_str(), "w"); - CHECK_NOTNULL(fptr_); - } - - virtual ~FileLoggingCallback() { - if (fptr_ != NULL) { - fclose(fptr_); - } - } - - virtual CallbackReturnType operator()(const IterationSummary& summary) { - fprintf(fptr_, - "%4d %e %e\n", - summary.iteration, - summary.cost, - summary.cumulative_time_in_seconds); - return SOLVER_CONTINUE; - } - private: - FILE* fptr_; -}; - -// Iterate over each of the groups in order of their priority and fill -// summary with their sizes. -void SummarizeOrdering(ParameterBlockOrdering* ordering, - vector<int>* summary) { - CHECK_NOTNULL(summary)->clear(); - if (ordering == NULL) { - return; - } - - const map<int, set<double*> >& group_to_elements = - ordering->group_to_elements(); - for (map<int, set<double*> >::const_iterator it = group_to_elements.begin(); - it != group_to_elements.end(); - ++it) { - summary->push_back(it->second.size()); - } -} - -void SummarizeGivenProgram(const Program& program, Solver::Summary* summary) { - summary->num_parameter_blocks = program.NumParameterBlocks(); - summary->num_parameters = program.NumParameters(); - summary->num_effective_parameters = program.NumEffectiveParameters(); - summary->num_residual_blocks = program.NumResidualBlocks(); - summary->num_residuals = program.NumResiduals(); -} - -void SummarizeReducedProgram(const Program& program, Solver::Summary* summary) { - summary->num_parameter_blocks_reduced = program.NumParameterBlocks(); - summary->num_parameters_reduced = program.NumParameters(); - summary->num_effective_parameters_reduced = program.NumEffectiveParameters(); - summary->num_residual_blocks_reduced = program.NumResidualBlocks(); - summary->num_residuals_reduced = program.NumResiduals(); -} - -bool ParameterBlocksAreFinite(const ProblemImpl* problem, - string* message) { - CHECK_NOTNULL(message); - const Program& program = problem->program(); - const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); - for (int i = 0; i < parameter_blocks.size(); ++i) { - const double* array = parameter_blocks[i]->user_state(); - const int size = parameter_blocks[i]->Size(); - const int invalid_index = FindInvalidValue(size, array); - if (invalid_index != size) { - *message = StringPrintf( - "ParameterBlock: %p with size %d has at least one invalid value.\n" - "First invalid value is at index: %d.\n" - "Parameter block values: ", - array, size, invalid_index); - AppendArrayToString(size, array, message); - return false; - } - } - return true; -} - -bool LineSearchOptionsAreValid(const Solver::Options& options, - string* message) { - // Validate values for configuration parameters supplied by user. - if ((options.line_search_direction_type == ceres::BFGS || - options.line_search_direction_type == ceres::LBFGS) && - options.line_search_type != ceres::WOLFE) { - *message = - string("Invalid configuration: require line_search_type == " - "ceres::WOLFE when using (L)BFGS to ensure that underlying " - "assumptions are guaranteed to be satisfied."); - return false; - } - if (options.max_lbfgs_rank <= 0) { - *message = - string("Invalid configuration: require max_lbfgs_rank > 0"); - return false; - } - if (options.min_line_search_step_size <= 0.0) { - *message = - "Invalid configuration: require min_line_search_step_size > 0.0."; - return false; - } - if (options.line_search_sufficient_function_decrease <= 0.0) { - *message = - string("Invalid configuration: require ") + - string("line_search_sufficient_function_decrease > 0.0."); - return false; - } - if (options.max_line_search_step_contraction <= 0.0 || - options.max_line_search_step_contraction >= 1.0) { - *message = string("Invalid configuration: require ") + - string("0.0 < max_line_search_step_contraction < 1.0."); - return false; - } - if (options.min_line_search_step_contraction <= - options.max_line_search_step_contraction || - options.min_line_search_step_contraction > 1.0) { - *message = string("Invalid configuration: require ") + - string("max_line_search_step_contraction < ") + - string("min_line_search_step_contraction <= 1.0."); - return false; - } - // Warn user if they have requested BISECTION interpolation, but constraints - // on max/min step size change during line search prevent bisection scaling - // from occurring. Warn only, as this is likely a user mistake, but one which - // does not prevent us from continuing. - LOG_IF(WARNING, - (options.line_search_interpolation_type == ceres::BISECTION && - (options.max_line_search_step_contraction > 0.5 || - options.min_line_search_step_contraction < 0.5))) - << "Line search interpolation type is BISECTION, but specified " - << "max_line_search_step_contraction: " - << options.max_line_search_step_contraction << ", and " - << "min_line_search_step_contraction: " - << options.min_line_search_step_contraction - << ", prevent bisection (0.5) scaling, continuing with solve regardless."; - if (options.max_num_line_search_step_size_iterations <= 0) { - *message = string("Invalid configuration: require ") + - string("max_num_line_search_step_size_iterations > 0."); - return false; - } - if (options.line_search_sufficient_curvature_decrease <= - options.line_search_sufficient_function_decrease || - options.line_search_sufficient_curvature_decrease > 1.0) { - *message = string("Invalid configuration: require ") + - string("line_search_sufficient_function_decrease < ") + - string("line_search_sufficient_curvature_decrease < 1.0."); - return false; - } - if (options.max_line_search_step_expansion <= 1.0) { - *message = string("Invalid configuration: require ") + - string("max_line_search_step_expansion > 1.0."); - return false; - } - return true; -} - -// Returns true if the program has any non-constant parameter blocks -// which have non-trivial bounds constraints. -bool IsBoundsConstrained(const Program& program) { - const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); - for (int i = 0; i < parameter_blocks.size(); ++i) { - const ParameterBlock* parameter_block = parameter_blocks[i]; - if (parameter_block->IsConstant()) { - continue; - } - const int size = parameter_block->Size(); - for (int j = 0; j < size; ++j) { - const double lower_bound = parameter_block->LowerBoundForParameter(j); - const double upper_bound = parameter_block->UpperBoundForParameter(j); - if (lower_bound > -std::numeric_limits<double>::max() || - upper_bound < std::numeric_limits<double>::max()) { - return true; - } - } - } - return false; -} - -// Returns false, if the problem has any constant parameter blocks -// which are not feasible, or any variable parameter blocks which have -// a lower bound greater than or equal to the upper bound. -bool ParameterBlocksAreFeasible(const ProblemImpl* problem, string* message) { - CHECK_NOTNULL(message); - const Program& program = problem->program(); - const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); - for (int i = 0; i < parameter_blocks.size(); ++i) { - const ParameterBlock* parameter_block = parameter_blocks[i]; - const double* parameters = parameter_block->user_state(); - const int size = parameter_block->Size(); - if (parameter_block->IsConstant()) { - // Constant parameter blocks must start in the feasible region - // to ultimately produce a feasible solution, since Ceres cannot - // change them. - for (int j = 0; j < size; ++j) { - const double lower_bound = parameter_block->LowerBoundForParameter(j); - const double upper_bound = parameter_block->UpperBoundForParameter(j); - if (parameters[j] < lower_bound || parameters[j] > upper_bound) { - *message = StringPrintf( - "ParameterBlock: %p with size %d has at least one infeasible " - "value." - "\nFirst infeasible value is at index: %d." - "\nLower bound: %e, value: %e, upper bound: %e" - "\nParameter block values: ", - parameters, size, j, lower_bound, parameters[j], upper_bound); - AppendArrayToString(size, parameters, message); - return false; - } - } - } else { - // Variable parameter blocks must have non-empty feasible - // regions, otherwise there is no way to produce a feasible - // solution. - for (int j = 0; j < size; ++j) { - const double lower_bound = parameter_block->LowerBoundForParameter(j); - const double upper_bound = parameter_block->UpperBoundForParameter(j); - if (lower_bound >= upper_bound) { - *message = StringPrintf( - "ParameterBlock: %p with size %d has at least one infeasible " - "bound." - "\nFirst infeasible bound is at index: %d." - "\nLower bound: %e, upper bound: %e" - "\nParameter block values: ", - parameters, size, j, lower_bound, upper_bound); - AppendArrayToString(size, parameters, message); - return false; - } - } - } - } - - return true; -} - - -} // namespace - -void SolverImpl::TrustRegionMinimize( - const Solver::Options& options, - Program* program, - CoordinateDescentMinimizer* inner_iteration_minimizer, - Evaluator* evaluator, - LinearSolver* linear_solver, - Solver::Summary* summary) { - Minimizer::Options minimizer_options(options); - minimizer_options.is_constrained = IsBoundsConstrained(*program); - - // The optimizer works on contiguous parameter vectors; allocate - // some. - Vector parameters(program->NumParameters()); - - // Collect the discontiguous parameters into a contiguous state - // vector. - program->ParameterBlocksToStateVector(parameters.data()); - - scoped_ptr<IterationCallback> file_logging_callback; - if (!options.solver_log.empty()) { - file_logging_callback.reset(new FileLoggingCallback(options.solver_log)); - minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), - file_logging_callback.get()); - } - - TrustRegionLoggingCallback logging_callback( - options.minimizer_progress_to_stdout); - if (options.logging_type != SILENT) { - minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), - &logging_callback); - } - - StateUpdatingCallback updating_callback(program, parameters.data()); - if (options.update_state_every_iteration) { - // This must get pushed to the front of the callbacks so that it is run - // before any of the user callbacks. - minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), - &updating_callback); - } - - minimizer_options.evaluator = evaluator; - scoped_ptr<SparseMatrix> jacobian(evaluator->CreateJacobian()); - - minimizer_options.jacobian = jacobian.get(); - minimizer_options.inner_iteration_minimizer = inner_iteration_minimizer; - - TrustRegionStrategy::Options trust_region_strategy_options; - trust_region_strategy_options.linear_solver = linear_solver; - trust_region_strategy_options.initial_radius = - options.initial_trust_region_radius; - trust_region_strategy_options.max_radius = options.max_trust_region_radius; - trust_region_strategy_options.min_lm_diagonal = options.min_lm_diagonal; - trust_region_strategy_options.max_lm_diagonal = options.max_lm_diagonal; - trust_region_strategy_options.trust_region_strategy_type = - options.trust_region_strategy_type; - trust_region_strategy_options.dogleg_type = options.dogleg_type; - scoped_ptr<TrustRegionStrategy> strategy( - TrustRegionStrategy::Create(trust_region_strategy_options)); - minimizer_options.trust_region_strategy = strategy.get(); - - TrustRegionMinimizer minimizer; - double minimizer_start_time = WallTimeInSeconds(); - minimizer.Minimize(minimizer_options, parameters.data(), summary); - - // If the user aborted mid-optimization or the optimization - // terminated because of a numerical failure, then do not update - // user state. - if (summary->termination_type != USER_FAILURE && - summary->termination_type != FAILURE) { - program->StateVectorToParameterBlocks(parameters.data()); - program->CopyParameterBlockStateToUserState(); - } - - summary->minimizer_time_in_seconds = - WallTimeInSeconds() - minimizer_start_time; -} - -void SolverImpl::LineSearchMinimize( - const Solver::Options& options, - Program* program, - Evaluator* evaluator, - Solver::Summary* summary) { - Minimizer::Options minimizer_options(options); - - // The optimizer works on contiguous parameter vectors; allocate some. - Vector parameters(program->NumParameters()); - - // Collect the discontiguous parameters into a contiguous state vector. - program->ParameterBlocksToStateVector(parameters.data()); - - // TODO(sameeragarwal): Add support for logging the configuration - // and more detailed stats. - scoped_ptr<IterationCallback> file_logging_callback; - if (!options.solver_log.empty()) { - file_logging_callback.reset(new FileLoggingCallback(options.solver_log)); - minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), - file_logging_callback.get()); - } - - LineSearchLoggingCallback logging_callback( - options.minimizer_progress_to_stdout); - if (options.logging_type != SILENT) { - minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), - &logging_callback); - } - - StateUpdatingCallback updating_callback(program, parameters.data()); - if (options.update_state_every_iteration) { - // This must get pushed to the front of the callbacks so that it is run - // before any of the user callbacks. - minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), - &updating_callback); - } - - minimizer_options.evaluator = evaluator; - - LineSearchMinimizer minimizer; - double minimizer_start_time = WallTimeInSeconds(); - minimizer.Minimize(minimizer_options, parameters.data(), summary); - - // If the user aborted mid-optimization or the optimization - // terminated because of a numerical failure, then do not update - // user state. - if (summary->termination_type != USER_FAILURE && - summary->termination_type != FAILURE) { - program->StateVectorToParameterBlocks(parameters.data()); - program->CopyParameterBlockStateToUserState(); - } - - summary->minimizer_time_in_seconds = - WallTimeInSeconds() - minimizer_start_time; -} - -void SolverImpl::Solve(const Solver::Options& options, - ProblemImpl* problem_impl, - Solver::Summary* summary) { - VLOG(2) << "Initial problem: " - << problem_impl->NumParameterBlocks() - << " parameter blocks, " - << problem_impl->NumParameters() - << " parameters, " - << problem_impl->NumResidualBlocks() - << " residual blocks, " - << problem_impl->NumResiduals() - << " residuals."; - *CHECK_NOTNULL(summary) = Solver::Summary(); - if (options.minimizer_type == TRUST_REGION) { - TrustRegionSolve(options, problem_impl, summary); - } else { - LineSearchSolve(options, problem_impl, summary); - } -} - -void SolverImpl::TrustRegionSolve(const Solver::Options& original_options, - ProblemImpl* original_problem_impl, - Solver::Summary* summary) { - EventLogger event_logger("TrustRegionSolve"); - double solver_start_time = WallTimeInSeconds(); - - Program* original_program = original_problem_impl->mutable_program(); - ProblemImpl* problem_impl = original_problem_impl; - - summary->minimizer_type = TRUST_REGION; - - SummarizeGivenProgram(*original_program, summary); - SummarizeOrdering(original_options.linear_solver_ordering.get(), - &(summary->linear_solver_ordering_given)); - SummarizeOrdering(original_options.inner_iteration_ordering.get(), - &(summary->inner_iteration_ordering_given)); - - Solver::Options options(original_options); - -#ifndef CERES_USE_OPENMP - if (options.num_threads > 1) { - LOG(WARNING) - << "OpenMP support is not compiled into this binary; " - << "only options.num_threads=1 is supported. Switching " - << "to single threaded mode."; - options.num_threads = 1; - } - if (options.num_linear_solver_threads > 1) { - LOG(WARNING) - << "OpenMP support is not compiled into this binary; " - << "only options.num_linear_solver_threads=1 is supported. Switching " - << "to single threaded mode."; - options.num_linear_solver_threads = 1; - } -#endif - - summary->num_threads_given = original_options.num_threads; - summary->num_threads_used = options.num_threads; - - if (options.trust_region_minimizer_iterations_to_dump.size() > 0 && - options.trust_region_problem_dump_format_type != CONSOLE && - options.trust_region_problem_dump_directory.empty()) { - summary->message = - "Solver::Options::trust_region_problem_dump_directory is empty."; - LOG(ERROR) << summary->message; - return; - } - - if (!ParameterBlocksAreFinite(problem_impl, &summary->message)) { - LOG(ERROR) << "Terminating: " << summary->message; - return; - } - - if (!ParameterBlocksAreFeasible(problem_impl, &summary->message)) { - LOG(ERROR) << "Terminating: " << summary->message; - return; - } - - event_logger.AddEvent("Init"); - - original_program->SetParameterBlockStatePtrsToUserStatePtrs(); - event_logger.AddEvent("SetParameterBlockPtrs"); - - // If the user requests gradient checking, construct a new - // ProblemImpl by wrapping the CostFunctions of problem_impl inside - // GradientCheckingCostFunction and replacing problem_impl with - // gradient_checking_problem_impl. - scoped_ptr<ProblemImpl> gradient_checking_problem_impl; - if (options.check_gradients) { - VLOG(1) << "Checking Gradients"; - gradient_checking_problem_impl.reset( - CreateGradientCheckingProblemImpl( - problem_impl, - options.numeric_derivative_relative_step_size, - options.gradient_check_relative_precision)); - - // From here on, problem_impl will point to the gradient checking - // version. - problem_impl = gradient_checking_problem_impl.get(); - } - - if (options.linear_solver_ordering.get() != NULL) { - if (!IsOrderingValid(options, problem_impl, &summary->message)) { - LOG(ERROR) << summary->message; - return; - } - event_logger.AddEvent("CheckOrdering"); - } else { - options.linear_solver_ordering.reset(new ParameterBlockOrdering); - const ProblemImpl::ParameterMap& parameter_map = - problem_impl->parameter_map(); - for (ProblemImpl::ParameterMap::const_iterator it = parameter_map.begin(); - it != parameter_map.end(); - ++it) { - options.linear_solver_ordering->AddElementToGroup(it->first, 0); - } - event_logger.AddEvent("ConstructOrdering"); - } - - // Create the three objects needed to minimize: the transformed program, the - // evaluator, and the linear solver. - scoped_ptr<Program> reduced_program(CreateReducedProgram(&options, - problem_impl, - &summary->fixed_cost, - &summary->message)); - - event_logger.AddEvent("CreateReducedProgram"); - if (reduced_program == NULL) { - return; - } - - SummarizeOrdering(options.linear_solver_ordering.get(), - &(summary->linear_solver_ordering_used)); - SummarizeReducedProgram(*reduced_program, summary); - - if (summary->num_parameter_blocks_reduced == 0) { - summary->preprocessor_time_in_seconds = - WallTimeInSeconds() - solver_start_time; - - double post_process_start_time = WallTimeInSeconds(); - - summary->message = - "Terminating: Function tolerance reached. " - "No non-constant parameter blocks found."; - summary->termination_type = CONVERGENCE; - VLOG_IF(1, options.logging_type != SILENT) << summary->message; - - summary->initial_cost = summary->fixed_cost; - summary->final_cost = summary->fixed_cost; - - // Ensure the program state is set to the user parameters on the way out. - original_program->SetParameterBlockStatePtrsToUserStatePtrs(); - original_program->SetParameterOffsetsAndIndex(); - - summary->postprocessor_time_in_seconds = - WallTimeInSeconds() - post_process_start_time; - return; - } - - scoped_ptr<LinearSolver> - linear_solver(CreateLinearSolver(&options, &summary->message)); - event_logger.AddEvent("CreateLinearSolver"); - if (linear_solver == NULL) { - return; - } - - summary->linear_solver_type_given = original_options.linear_solver_type; - summary->linear_solver_type_used = options.linear_solver_type; - - summary->preconditioner_type = options.preconditioner_type; - summary->visibility_clustering_type = options.visibility_clustering_type; - - summary->num_linear_solver_threads_given = - original_options.num_linear_solver_threads; - summary->num_linear_solver_threads_used = options.num_linear_solver_threads; - - summary->dense_linear_algebra_library_type = - options.dense_linear_algebra_library_type; - summary->sparse_linear_algebra_library_type = - options.sparse_linear_algebra_library_type; - - summary->trust_region_strategy_type = options.trust_region_strategy_type; - summary->dogleg_type = options.dogleg_type; - - scoped_ptr<Evaluator> evaluator(CreateEvaluator(options, - problem_impl->parameter_map(), - reduced_program.get(), - &summary->message)); - - event_logger.AddEvent("CreateEvaluator"); - - if (evaluator == NULL) { - return; - } - - scoped_ptr<CoordinateDescentMinimizer> inner_iteration_minimizer; - if (options.use_inner_iterations) { - if (reduced_program->parameter_blocks().size() < 2) { - LOG(WARNING) << "Reduced problem only contains one parameter block." - << "Disabling inner iterations."; - } else { - inner_iteration_minimizer.reset( - CreateInnerIterationMinimizer(options, - *reduced_program, - problem_impl->parameter_map(), - summary)); - if (inner_iteration_minimizer == NULL) { - LOG(ERROR) << summary->message; - return; - } - } - } - event_logger.AddEvent("CreateInnerIterationMinimizer"); - - double minimizer_start_time = WallTimeInSeconds(); - summary->preprocessor_time_in_seconds = - minimizer_start_time - solver_start_time; - - // Run the optimization. - TrustRegionMinimize(options, - reduced_program.get(), - inner_iteration_minimizer.get(), - evaluator.get(), - linear_solver.get(), - summary); - event_logger.AddEvent("Minimize"); - - double post_process_start_time = WallTimeInSeconds(); - - SetSummaryFinalCost(summary); - - // Ensure the program state is set to the user parameters on the way - // out. - original_program->SetParameterBlockStatePtrsToUserStatePtrs(); - original_program->SetParameterOffsetsAndIndex(); - - const map<string, double>& linear_solver_time_statistics = - linear_solver->TimeStatistics(); - summary->linear_solver_time_in_seconds = - FindWithDefault(linear_solver_time_statistics, - "LinearSolver::Solve", - 0.0); - - const map<string, double>& evaluator_time_statistics = - evaluator->TimeStatistics(); - - summary->residual_evaluation_time_in_seconds = - FindWithDefault(evaluator_time_statistics, "Evaluator::Residual", 0.0); - summary->jacobian_evaluation_time_in_seconds = - FindWithDefault(evaluator_time_statistics, "Evaluator::Jacobian", 0.0); - - // Stick a fork in it, we're done. - summary->postprocessor_time_in_seconds = - WallTimeInSeconds() - post_process_start_time; - event_logger.AddEvent("PostProcess"); -} - -void SolverImpl::LineSearchSolve(const Solver::Options& original_options, - ProblemImpl* original_problem_impl, - Solver::Summary* summary) { - double solver_start_time = WallTimeInSeconds(); - - Program* original_program = original_problem_impl->mutable_program(); - ProblemImpl* problem_impl = original_problem_impl; - - SummarizeGivenProgram(*original_program, summary); - summary->minimizer_type = LINE_SEARCH; - summary->line_search_direction_type = - original_options.line_search_direction_type; - summary->max_lbfgs_rank = original_options.max_lbfgs_rank; - summary->line_search_type = original_options.line_search_type; - summary->line_search_interpolation_type = - original_options.line_search_interpolation_type; - summary->nonlinear_conjugate_gradient_type = - original_options.nonlinear_conjugate_gradient_type; - - if (!LineSearchOptionsAreValid(original_options, &summary->message)) { - LOG(ERROR) << summary->message; - return; - } - - if (IsBoundsConstrained(problem_impl->program())) { - summary->message = "LINE_SEARCH Minimizer does not support bounds."; - LOG(ERROR) << "Terminating: " << summary->message; - return; - } - - Solver::Options options(original_options); - - // This ensures that we get a Block Jacobian Evaluator along with - // none of the Schur nonsense. This file will have to be extensively - // refactored to deal with the various bits of cleanups related to - // line search. - options.linear_solver_type = CGNR; - - -#ifndef CERES_USE_OPENMP - if (options.num_threads > 1) { - LOG(WARNING) - << "OpenMP support is not compiled into this binary; " - << "only options.num_threads=1 is supported. Switching " - << "to single threaded mode."; - options.num_threads = 1; - } -#endif // CERES_USE_OPENMP - - summary->num_threads_given = original_options.num_threads; - summary->num_threads_used = options.num_threads; - - if (!ParameterBlocksAreFinite(problem_impl, &summary->message)) { - LOG(ERROR) << "Terminating: " << summary->message; - return; - } - - if (options.linear_solver_ordering.get() != NULL) { - if (!IsOrderingValid(options, problem_impl, &summary->message)) { - LOG(ERROR) << summary->message; - return; - } - } else { - options.linear_solver_ordering.reset(new ParameterBlockOrdering); - const ProblemImpl::ParameterMap& parameter_map = - problem_impl->parameter_map(); - for (ProblemImpl::ParameterMap::const_iterator it = parameter_map.begin(); - it != parameter_map.end(); - ++it) { - options.linear_solver_ordering->AddElementToGroup(it->first, 0); - } - } - - - original_program->SetParameterBlockStatePtrsToUserStatePtrs(); - - // If the user requests gradient checking, construct a new - // ProblemImpl by wrapping the CostFunctions of problem_impl inside - // GradientCheckingCostFunction and replacing problem_impl with - // gradient_checking_problem_impl. - scoped_ptr<ProblemImpl> gradient_checking_problem_impl; - if (options.check_gradients) { - VLOG(1) << "Checking Gradients"; - gradient_checking_problem_impl.reset( - CreateGradientCheckingProblemImpl( - problem_impl, - options.numeric_derivative_relative_step_size, - options.gradient_check_relative_precision)); - - // From here on, problem_impl will point to the gradient checking - // version. - problem_impl = gradient_checking_problem_impl.get(); - } - - // Create the three objects needed to minimize: the transformed program, the - // evaluator, and the linear solver. - scoped_ptr<Program> reduced_program(CreateReducedProgram(&options, - problem_impl, - &summary->fixed_cost, - &summary->message)); - if (reduced_program == NULL) { - return; - } - - SummarizeReducedProgram(*reduced_program, summary); - if (summary->num_parameter_blocks_reduced == 0) { - summary->preprocessor_time_in_seconds = - WallTimeInSeconds() - solver_start_time; - - summary->message = - "Terminating: Function tolerance reached. " - "No non-constant parameter blocks found."; - summary->termination_type = CONVERGENCE; - VLOG_IF(1, options.logging_type != SILENT) << summary->message; - - const double post_process_start_time = WallTimeInSeconds(); - SetSummaryFinalCost(summary); - - // Ensure the program state is set to the user parameters on the way out. - original_program->SetParameterBlockStatePtrsToUserStatePtrs(); - original_program->SetParameterOffsetsAndIndex(); - - summary->postprocessor_time_in_seconds = - WallTimeInSeconds() - post_process_start_time; - return; - } - - scoped_ptr<Evaluator> evaluator(CreateEvaluator(options, - problem_impl->parameter_map(), - reduced_program.get(), - &summary->message)); - if (evaluator == NULL) { - return; - } - - const double minimizer_start_time = WallTimeInSeconds(); - summary->preprocessor_time_in_seconds = - minimizer_start_time - solver_start_time; - - // Run the optimization. - LineSearchMinimize(options, reduced_program.get(), evaluator.get(), summary); - - const double post_process_start_time = WallTimeInSeconds(); - - SetSummaryFinalCost(summary); - - // Ensure the program state is set to the user parameters on the way out. - original_program->SetParameterBlockStatePtrsToUserStatePtrs(); - original_program->SetParameterOffsetsAndIndex(); - - const map<string, double>& evaluator_time_statistics = - evaluator->TimeStatistics(); - - summary->residual_evaluation_time_in_seconds = - FindWithDefault(evaluator_time_statistics, "Evaluator::Residual", 0.0); - summary->jacobian_evaluation_time_in_seconds = - FindWithDefault(evaluator_time_statistics, "Evaluator::Jacobian", 0.0); - - // Stick a fork in it, we're done. - summary->postprocessor_time_in_seconds = - WallTimeInSeconds() - post_process_start_time; -} - -bool SolverImpl::IsOrderingValid(const Solver::Options& options, - const ProblemImpl* problem_impl, - string* error) { - if (options.linear_solver_ordering->NumElements() != - problem_impl->NumParameterBlocks()) { - *error = "Number of parameter blocks in user supplied ordering " - "does not match the number of parameter blocks in the problem"; - return false; - } - - const Program& program = problem_impl->program(); - const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); - for (vector<ParameterBlock*>::const_iterator it = parameter_blocks.begin(); - it != parameter_blocks.end(); - ++it) { - if (!options.linear_solver_ordering - ->IsMember(const_cast<double*>((*it)->user_state()))) { - *error = "Problem contains a parameter block that is not in " - "the user specified ordering."; - return false; - } - } - - if (IsSchurType(options.linear_solver_type) && - options.linear_solver_ordering->NumGroups() > 1) { - const vector<ResidualBlock*>& residual_blocks = program.residual_blocks(); - const set<double*>& e_blocks = - options.linear_solver_ordering->group_to_elements().begin()->second; - if (!IsParameterBlockSetIndependent(e_blocks, residual_blocks)) { - *error = "The user requested the use of a Schur type solver. " - "But the first elimination group in the ordering is not an " - "independent set."; - return false; - } - } - return true; -} - -bool SolverImpl::IsParameterBlockSetIndependent( - const set<double*>& parameter_block_ptrs, - const vector<ResidualBlock*>& residual_blocks) { - // Loop over each residual block and ensure that no two parameter - // blocks in the same residual block are part of - // parameter_block_ptrs as that would violate the assumption that it - // is an independent set in the Hessian matrix. - for (vector<ResidualBlock*>::const_iterator it = residual_blocks.begin(); - it != residual_blocks.end(); - ++it) { - ParameterBlock* const* parameter_blocks = (*it)->parameter_blocks(); - const int num_parameter_blocks = (*it)->NumParameterBlocks(); - int count = 0; - for (int i = 0; i < num_parameter_blocks; ++i) { - count += parameter_block_ptrs.count( - parameter_blocks[i]->mutable_user_state()); - } - if (count > 1) { - return false; - } - } - return true; -} - - -// Strips varying parameters and residuals, maintaining order, and updating -// orderings. -bool SolverImpl::RemoveFixedBlocksFromProgram( - Program* program, - ParameterBlockOrdering* linear_solver_ordering, - ParameterBlockOrdering* inner_iteration_ordering, - double* fixed_cost, - string* error) { - scoped_array<double> residual_block_evaluate_scratch; - if (fixed_cost != NULL) { - residual_block_evaluate_scratch.reset( - new double[program->MaxScratchDoublesNeededForEvaluate()]); - *fixed_cost = 0.0; - } - - vector<ParameterBlock*>* parameter_blocks = - program->mutable_parameter_blocks(); - vector<ResidualBlock*>* residual_blocks = - program->mutable_residual_blocks(); - - // Mark all the parameters as unused. Abuse the index member of the - // parameter blocks for the marking. - for (int i = 0; i < parameter_blocks->size(); ++i) { - (*parameter_blocks)[i]->set_index(-1); - } - - // Filter out residual that have all-constant parameters, and mark all the - // parameter blocks that appear in residuals. - int num_active_residual_blocks = 0; - for (int i = 0; i < residual_blocks->size(); ++i) { - ResidualBlock* residual_block = (*residual_blocks)[i]; - int num_parameter_blocks = residual_block->NumParameterBlocks(); - - // Determine if the residual block is fixed, and also mark varying - // parameters that appear in the residual block. - bool all_constant = true; - for (int k = 0; k < num_parameter_blocks; k++) { - ParameterBlock* parameter_block = residual_block->parameter_blocks()[k]; - if (!parameter_block->IsConstant()) { - all_constant = false; - parameter_block->set_index(1); - } - } - - if (!all_constant) { - (*residual_blocks)[num_active_residual_blocks++] = residual_block; - } else if (fixed_cost != NULL) { - // The residual is constant and will be removed, so its cost is - // added to the variable fixed_cost. - double cost = 0.0; - if (!residual_block->Evaluate(true, - &cost, - NULL, - NULL, - residual_block_evaluate_scratch.get())) { - *error = StringPrintf("Evaluation of the residual %d failed during " - "removal of fixed residual blocks.", i); - return false; - } - *fixed_cost += cost; - } - } - residual_blocks->resize(num_active_residual_blocks); - - // Filter out unused or fixed parameter blocks, and update the - // linear_solver_ordering and the inner_iteration_ordering (if - // present). - int num_active_parameter_blocks = 0; - for (int i = 0; i < parameter_blocks->size(); ++i) { - ParameterBlock* parameter_block = (*parameter_blocks)[i]; - if (parameter_block->index() == -1) { - // Parameter block is constant. - if (linear_solver_ordering != NULL) { - linear_solver_ordering->Remove(parameter_block->mutable_user_state()); - } - - // It is not necessary that the inner iteration ordering contain - // this parameter block. But calling Remove is safe, as it will - // just return false. - if (inner_iteration_ordering != NULL) { - inner_iteration_ordering->Remove(parameter_block->mutable_user_state()); - } - continue; - } - - (*parameter_blocks)[num_active_parameter_blocks++] = parameter_block; - } - parameter_blocks->resize(num_active_parameter_blocks); - - if (!(((program->NumResidualBlocks() == 0) && - (program->NumParameterBlocks() == 0)) || - ((program->NumResidualBlocks() != 0) && - (program->NumParameterBlocks() != 0)))) { - *error = "Congratulations, you found a bug in Ceres. Please report it."; - return false; - } - - return true; -} - -Program* SolverImpl::CreateReducedProgram(Solver::Options* options, - ProblemImpl* problem_impl, - double* fixed_cost, - string* error) { - CHECK_NOTNULL(options->linear_solver_ordering.get()); - Program* original_program = problem_impl->mutable_program(); - scoped_ptr<Program> transformed_program(new Program(*original_program)); - - ParameterBlockOrdering* linear_solver_ordering = - options->linear_solver_ordering.get(); - const int min_group_id = - linear_solver_ordering->group_to_elements().begin()->first; - ParameterBlockOrdering* inner_iteration_ordering = - options->inner_iteration_ordering.get(); - if (!RemoveFixedBlocksFromProgram(transformed_program.get(), - linear_solver_ordering, - inner_iteration_ordering, - fixed_cost, - error)) { - return NULL; - } - - VLOG(2) << "Reduced problem: " - << transformed_program->NumParameterBlocks() - << " parameter blocks, " - << transformed_program->NumParameters() - << " parameters, " - << transformed_program->NumResidualBlocks() - << " residual blocks, " - << transformed_program->NumResiduals() - << " residuals."; - - if (transformed_program->NumParameterBlocks() == 0) { - LOG(WARNING) << "No varying parameter blocks to optimize; " - << "bailing early."; - return transformed_program.release(); - } - - if (IsSchurType(options->linear_solver_type) && - linear_solver_ordering->GroupSize(min_group_id) == 0) { - // If the user requested the use of a Schur type solver, and - // supplied a non-NULL linear_solver_ordering object with more than - // one elimination group, then it can happen that after all the - // parameter blocks which are fixed or unused have been removed from - // the program and the ordering, there are no more parameter blocks - // in the first elimination group. - // - // In such a case, the use of a Schur type solver is not possible, - // as they assume there is at least one e_block. Thus, we - // automatically switch to the closest solver to the one indicated - // by the user. - AlternateLinearSolverForSchurTypeLinearSolver(options); - } - - if (IsSchurType(options->linear_solver_type)) { - if (!ReorderProgramForSchurTypeLinearSolver( - options->linear_solver_type, - options->sparse_linear_algebra_library_type, - problem_impl->parameter_map(), - linear_solver_ordering, - transformed_program.get(), - error)) { - return NULL; - } - return transformed_program.release(); - } - - if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY && - !options->dynamic_sparsity) { - if (!ReorderProgramForSparseNormalCholesky( - options->sparse_linear_algebra_library_type, - linear_solver_ordering, - transformed_program.get(), - error)) { - return NULL; - } - - return transformed_program.release(); - } - - transformed_program->SetParameterOffsetsAndIndex(); - return transformed_program.release(); -} - -LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options, - string* error) { - CHECK_NOTNULL(options); - CHECK_NOTNULL(options->linear_solver_ordering.get()); - CHECK_NOTNULL(error); - - if (options->trust_region_strategy_type == DOGLEG) { - if (options->linear_solver_type == ITERATIVE_SCHUR || - options->linear_solver_type == CGNR) { - *error = "DOGLEG only supports exact factorization based linear " - "solvers. If you want to use an iterative solver please " - "use LEVENBERG_MARQUARDT as the trust_region_strategy_type"; - return NULL; - } - } - -#ifdef CERES_NO_LAPACK - if (options->linear_solver_type == DENSE_NORMAL_CHOLESKY && - options->dense_linear_algebra_library_type == LAPACK) { - *error = "Can't use DENSE_NORMAL_CHOLESKY with LAPACK because " - "LAPACK was not enabled when Ceres was built."; - return NULL; - } - - if (options->linear_solver_type == DENSE_QR && - options->dense_linear_algebra_library_type == LAPACK) { - *error = "Can't use DENSE_QR with LAPACK because " - "LAPACK was not enabled when Ceres was built."; - return NULL; - } - - if (options->linear_solver_type == DENSE_SCHUR && - options->dense_linear_algebra_library_type == LAPACK) { - *error = "Can't use DENSE_SCHUR with LAPACK because " - "LAPACK was not enabled when Ceres was built."; - return NULL; - } -#endif - -#ifdef CERES_NO_SUITESPARSE - if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY && - options->sparse_linear_algebra_library_type == SUITE_SPARSE) { - *error = "Can't use SPARSE_NORMAL_CHOLESKY with SUITESPARSE because " - "SuiteSparse was not enabled when Ceres was built."; - return NULL; - } - - if (options->preconditioner_type == CLUSTER_JACOBI) { - *error = "CLUSTER_JACOBI preconditioner not suppored. Please build Ceres " - "with SuiteSparse support."; - return NULL; - } - - if (options->preconditioner_type == CLUSTER_TRIDIAGONAL) { - *error = "CLUSTER_TRIDIAGONAL preconditioner not suppored. Please build " - "Ceres with SuiteSparse support."; - return NULL; - } -#endif - -#ifdef CERES_NO_CXSPARSE - if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY && - options->sparse_linear_algebra_library_type == CX_SPARSE) { - *error = "Can't use SPARSE_NORMAL_CHOLESKY with CXSPARSE because " - "CXSparse was not enabled when Ceres was built."; - return NULL; - } -#endif - -#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) - if (options->linear_solver_type == SPARSE_SCHUR) { - *error = "Can't use SPARSE_SCHUR because neither SuiteSparse nor" - "CXSparse was enabled when Ceres was compiled."; - return NULL; - } -#endif - - if (options->max_linear_solver_iterations <= 0) { - *error = "Solver::Options::max_linear_solver_iterations is not positive."; - return NULL; - } - if (options->min_linear_solver_iterations <= 0) { - *error = "Solver::Options::min_linear_solver_iterations is not positive."; - return NULL; - } - if (options->min_linear_solver_iterations > - options->max_linear_solver_iterations) { - *error = "Solver::Options::min_linear_solver_iterations > " - "Solver::Options::max_linear_solver_iterations."; - return NULL; - } - - LinearSolver::Options linear_solver_options; - linear_solver_options.min_num_iterations = - options->min_linear_solver_iterations; - linear_solver_options.max_num_iterations = - options->max_linear_solver_iterations; - linear_solver_options.type = options->linear_solver_type; - linear_solver_options.preconditioner_type = options->preconditioner_type; - linear_solver_options.visibility_clustering_type = - options->visibility_clustering_type; - linear_solver_options.sparse_linear_algebra_library_type = - options->sparse_linear_algebra_library_type; - linear_solver_options.dense_linear_algebra_library_type = - options->dense_linear_algebra_library_type; - linear_solver_options.use_postordering = options->use_postordering; - linear_solver_options.dynamic_sparsity = options->dynamic_sparsity; - - // Ignore user's postordering preferences and force it to be true if - // cholmod_camd is not available. This ensures that the linear - // solver does not assume that a fill-reducing pre-ordering has been - // done. -#if !defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CAMD) - if (IsSchurType(linear_solver_options.type) && - options->sparse_linear_algebra_library_type == SUITE_SPARSE) { - linear_solver_options.use_postordering = true; - } -#endif - - linear_solver_options.num_threads = options->num_linear_solver_threads; - options->num_linear_solver_threads = linear_solver_options.num_threads; - - const map<int, set<double*> >& groups = - options->linear_solver_ordering->group_to_elements(); - for (map<int, set<double*> >::const_iterator it = groups.begin(); - it != groups.end(); - ++it) { - linear_solver_options.elimination_groups.push_back(it->second.size()); - } - // Schur type solvers, expect at least two elimination groups. If - // there is only one elimination group, then CreateReducedProgram - // guarantees that this group only contains e_blocks. Thus we add a - // dummy elimination group with zero blocks in it. - if (IsSchurType(linear_solver_options.type) && - linear_solver_options.elimination_groups.size() == 1) { - linear_solver_options.elimination_groups.push_back(0); - } - - return LinearSolver::Create(linear_solver_options); -} - - -// Find the minimum index of any parameter block to the given residual. -// Parameter blocks that have indices greater than num_eliminate_blocks are -// considered to have an index equal to num_eliminate_blocks. -static int MinParameterBlock(const ResidualBlock* residual_block, - int num_eliminate_blocks) { - int min_parameter_block_position = num_eliminate_blocks; - for (int i = 0; i < residual_block->NumParameterBlocks(); ++i) { - ParameterBlock* parameter_block = residual_block->parameter_blocks()[i]; - if (!parameter_block->IsConstant()) { - CHECK_NE(parameter_block->index(), -1) - << "Did you forget to call Program::SetParameterOffsetsAndIndex()? " - << "This is a Ceres bug; please contact the developers!"; - min_parameter_block_position = std::min(parameter_block->index(), - min_parameter_block_position); - } - } - return min_parameter_block_position; -} - -// Reorder the residuals for program, if necessary, so that the residuals -// involving each E block occur together. This is a necessary condition for the -// Schur eliminator, which works on these "row blocks" in the jacobian. -bool SolverImpl::LexicographicallyOrderResidualBlocks( - const int num_eliminate_blocks, - Program* program, - string* error) { - CHECK_GE(num_eliminate_blocks, 1) - << "Congratulations, you found a Ceres bug! Please report this error " - << "to the developers."; - - // Create a histogram of the number of residuals for each E block. There is an - // extra bucket at the end to catch all non-eliminated F blocks. - vector<int> residual_blocks_per_e_block(num_eliminate_blocks + 1); - vector<ResidualBlock*>* residual_blocks = program->mutable_residual_blocks(); - vector<int> min_position_per_residual(residual_blocks->size()); - for (int i = 0; i < residual_blocks->size(); ++i) { - ResidualBlock* residual_block = (*residual_blocks)[i]; - int position = MinParameterBlock(residual_block, num_eliminate_blocks); - min_position_per_residual[i] = position; - DCHECK_LE(position, num_eliminate_blocks); - residual_blocks_per_e_block[position]++; - } - - // Run a cumulative sum on the histogram, to obtain offsets to the start of - // each histogram bucket (where each bucket is for the residuals for that - // E-block). - vector<int> offsets(num_eliminate_blocks + 1); - std::partial_sum(residual_blocks_per_e_block.begin(), - residual_blocks_per_e_block.end(), - offsets.begin()); - CHECK_EQ(offsets.back(), residual_blocks->size()) - << "Congratulations, you found a Ceres bug! Please report this error " - << "to the developers."; - - CHECK(find(residual_blocks_per_e_block.begin(), - residual_blocks_per_e_block.end() - 1, 0) != - residual_blocks_per_e_block.end()) - << "Congratulations, you found a Ceres bug! Please report this error " - << "to the developers."; - - // Fill in each bucket with the residual blocks for its corresponding E block. - // Each bucket is individually filled from the back of the bucket to the front - // of the bucket. The filling order among the buckets is dictated by the - // residual blocks. This loop uses the offsets as counters; subtracting one - // from each offset as a residual block is placed in the bucket. When the - // filling is finished, the offset pointerts should have shifted down one - // entry (this is verified below). - vector<ResidualBlock*> reordered_residual_blocks( - (*residual_blocks).size(), static_cast<ResidualBlock*>(NULL)); - for (int i = 0; i < residual_blocks->size(); ++i) { - int bucket = min_position_per_residual[i]; - - // Decrement the cursor, which should now point at the next empty position. - offsets[bucket]--; - - // Sanity. - CHECK(reordered_residual_blocks[offsets[bucket]] == NULL) - << "Congratulations, you found a Ceres bug! Please report this error " - << "to the developers."; - - reordered_residual_blocks[offsets[bucket]] = (*residual_blocks)[i]; - } - - // Sanity check #1: The difference in bucket offsets should match the - // histogram sizes. - for (int i = 0; i < num_eliminate_blocks; ++i) { - CHECK_EQ(residual_blocks_per_e_block[i], offsets[i + 1] - offsets[i]) - << "Congratulations, you found a Ceres bug! Please report this error " - << "to the developers."; - } - // Sanity check #2: No NULL's left behind. - for (int i = 0; i < reordered_residual_blocks.size(); ++i) { - CHECK(reordered_residual_blocks[i] != NULL) - << "Congratulations, you found a Ceres bug! Please report this error " - << "to the developers."; - } - - // Now that the residuals are collected by E block, swap them in place. - swap(*program->mutable_residual_blocks(), reordered_residual_blocks); - return true; -} - -Evaluator* SolverImpl::CreateEvaluator( - const Solver::Options& options, - const ProblemImpl::ParameterMap& parameter_map, - Program* program, - string* error) { - Evaluator::Options evaluator_options; - evaluator_options.linear_solver_type = options.linear_solver_type; - evaluator_options.num_eliminate_blocks = - (options.linear_solver_ordering->NumGroups() > 0 && - IsSchurType(options.linear_solver_type)) - ? (options.linear_solver_ordering - ->group_to_elements().begin() - ->second.size()) - : 0; - evaluator_options.num_threads = options.num_threads; - evaluator_options.dynamic_sparsity = options.dynamic_sparsity; - return Evaluator::Create(evaluator_options, program, error); -} - -CoordinateDescentMinimizer* SolverImpl::CreateInnerIterationMinimizer( - const Solver::Options& options, - const Program& program, - const ProblemImpl::ParameterMap& parameter_map, - Solver::Summary* summary) { - summary->inner_iterations_given = true; - - scoped_ptr<CoordinateDescentMinimizer> inner_iteration_minimizer( - new CoordinateDescentMinimizer); - scoped_ptr<ParameterBlockOrdering> inner_iteration_ordering; - ParameterBlockOrdering* ordering_ptr = NULL; - - if (options.inner_iteration_ordering.get() == NULL) { - // Find a recursive decomposition of the Hessian matrix as a set - // of independent sets of decreasing size and invert it. This - // seems to work better in practice, i.e., Cameras before - // points. - inner_iteration_ordering.reset(new ParameterBlockOrdering); - ComputeRecursiveIndependentSetOrdering(program, - inner_iteration_ordering.get()); - inner_iteration_ordering->Reverse(); - ordering_ptr = inner_iteration_ordering.get(); - } else { - const map<int, set<double*> >& group_to_elements = - options.inner_iteration_ordering->group_to_elements(); - - // Iterate over each group and verify that it is an independent - // set. - map<int, set<double*> >::const_iterator it = group_to_elements.begin(); - for ( ; it != group_to_elements.end(); ++it) { - if (!IsParameterBlockSetIndependent(it->second, - program.residual_blocks())) { - summary->message = - StringPrintf("The user-provided " - "parameter_blocks_for_inner_iterations does not " - "form an independent set. Group Id: %d", it->first); - return NULL; - } - } - ordering_ptr = options.inner_iteration_ordering.get(); - } - - if (!inner_iteration_minimizer->Init(program, - parameter_map, - *ordering_ptr, - &summary->message)) { - return NULL; - } - - summary->inner_iterations_used = true; - summary->inner_iteration_time_in_seconds = 0.0; - SummarizeOrdering(ordering_ptr, &(summary->inner_iteration_ordering_used)); - return inner_iteration_minimizer.release(); -} - -void SolverImpl::AlternateLinearSolverForSchurTypeLinearSolver( - Solver::Options* options) { - if (!IsSchurType(options->linear_solver_type)) { - return; - } - - string msg = "No e_blocks remaining. Switching from "; - if (options->linear_solver_type == SPARSE_SCHUR) { - options->linear_solver_type = SPARSE_NORMAL_CHOLESKY; - msg += "SPARSE_SCHUR to SPARSE_NORMAL_CHOLESKY."; - } else if (options->linear_solver_type == DENSE_SCHUR) { - // TODO(sameeragarwal): This is probably not a great choice. - // Ideally, we should have a DENSE_NORMAL_CHOLESKY, that can - // take a BlockSparseMatrix as input. - options->linear_solver_type = DENSE_QR; - msg += "DENSE_SCHUR to DENSE_QR."; - } else if (options->linear_solver_type == ITERATIVE_SCHUR) { - options->linear_solver_type = CGNR; - if (options->preconditioner_type != IDENTITY) { - msg += StringPrintf("ITERATIVE_SCHUR with %s preconditioner " - "to CGNR with JACOBI preconditioner.", - PreconditionerTypeToString( - options->preconditioner_type)); - // CGNR currently only supports the JACOBI preconditioner. - options->preconditioner_type = JACOBI; - } else { - msg += "ITERATIVE_SCHUR with IDENTITY preconditioner" - "to CGNR with IDENTITY preconditioner."; - } - } - LOG(WARNING) << msg; -} - -bool SolverImpl::ApplyUserOrdering( - const ProblemImpl::ParameterMap& parameter_map, - const ParameterBlockOrdering* parameter_block_ordering, - Program* program, - string* error) { - const int num_parameter_blocks = program->NumParameterBlocks(); - if (parameter_block_ordering->NumElements() != num_parameter_blocks) { - *error = StringPrintf("User specified ordering does not have the same " - "number of parameters as the problem. The problem" - "has %d blocks while the ordering has %d blocks.", - num_parameter_blocks, - parameter_block_ordering->NumElements()); - return false; - } - - vector<ParameterBlock*>* parameter_blocks = - program->mutable_parameter_blocks(); - parameter_blocks->clear(); - - const map<int, set<double*> >& groups = - parameter_block_ordering->group_to_elements(); - - for (map<int, set<double*> >::const_iterator group_it = groups.begin(); - group_it != groups.end(); - ++group_it) { - const set<double*>& group = group_it->second; - for (set<double*>::const_iterator parameter_block_ptr_it = group.begin(); - parameter_block_ptr_it != group.end(); - ++parameter_block_ptr_it) { - ProblemImpl::ParameterMap::const_iterator parameter_block_it = - parameter_map.find(*parameter_block_ptr_it); - if (parameter_block_it == parameter_map.end()) { - *error = StringPrintf("User specified ordering contains a pointer " - "to a double that is not a parameter block in " - "the problem. The invalid double is in group: %d", - group_it->first); - return false; - } - parameter_blocks->push_back(parameter_block_it->second); - } - } - return true; -} - - -TripletSparseMatrix* SolverImpl::CreateJacobianBlockSparsityTranspose( - const Program* program) { - - // Matrix to store the block sparsity structure of the Jacobian. - TripletSparseMatrix* tsm = - new TripletSparseMatrix(program->NumParameterBlocks(), - program->NumResidualBlocks(), - 10 * program->NumResidualBlocks()); - int num_nonzeros = 0; - int* rows = tsm->mutable_rows(); - int* cols = tsm->mutable_cols(); - double* values = tsm->mutable_values(); - - const vector<ResidualBlock*>& residual_blocks = program->residual_blocks(); - for (int c = 0; c < residual_blocks.size(); ++c) { - const ResidualBlock* residual_block = residual_blocks[c]; - const int num_parameter_blocks = residual_block->NumParameterBlocks(); - ParameterBlock* const* parameter_blocks = - residual_block->parameter_blocks(); - - for (int j = 0; j < num_parameter_blocks; ++j) { - if (parameter_blocks[j]->IsConstant()) { - continue; - } - - // Re-size the matrix if needed. - if (num_nonzeros >= tsm->max_num_nonzeros()) { - tsm->set_num_nonzeros(num_nonzeros); - tsm->Reserve(2 * num_nonzeros); - rows = tsm->mutable_rows(); - cols = tsm->mutable_cols(); - values = tsm->mutable_values(); - } - CHECK_LT(num_nonzeros, tsm->max_num_nonzeros()); - - const int r = parameter_blocks[j]->index(); - rows[num_nonzeros] = r; - cols[num_nonzeros] = c; - values[num_nonzeros] = 1.0; - ++num_nonzeros; - } - } - - tsm->set_num_nonzeros(num_nonzeros); - return tsm; -} - -bool SolverImpl::ReorderProgramForSchurTypeLinearSolver( - const LinearSolverType linear_solver_type, - const SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, - const ProblemImpl::ParameterMap& parameter_map, - ParameterBlockOrdering* parameter_block_ordering, - Program* program, - string* error) { - if (parameter_block_ordering->NumGroups() == 1) { - // If the user supplied an parameter_block_ordering with just one - // group, it is equivalent to the user supplying NULL as an - // parameter_block_ordering. Ceres is completely free to choose the - // parameter block ordering as it sees fit. For Schur type solvers, - // this means that the user wishes for Ceres to identify the - // e_blocks, which we do by computing a maximal independent set. - vector<ParameterBlock*> schur_ordering; - const int num_eliminate_blocks = - ComputeStableSchurOrdering(*program, &schur_ordering); - - CHECK_EQ(schur_ordering.size(), program->NumParameterBlocks()) - << "Congratulations, you found a Ceres bug! Please report this error " - << "to the developers."; - - // Update the parameter_block_ordering object. - for (int i = 0; i < schur_ordering.size(); ++i) { - double* parameter_block = schur_ordering[i]->mutable_user_state(); - const int group_id = (i < num_eliminate_blocks) ? 0 : 1; - parameter_block_ordering->AddElementToGroup(parameter_block, group_id); - } - - // We could call ApplyUserOrdering but this is cheaper and - // simpler. - swap(*program->mutable_parameter_blocks(), schur_ordering); - } else { - // The user provided an ordering with more than one elimination - // group. Trust the user and apply the ordering. - if (!ApplyUserOrdering(parameter_map, - parameter_block_ordering, - program, - error)) { - return false; - } - } - - // Pre-order the columns corresponding to the schur complement if - // possible. -#if !defined(CERES_NO_SUITESPARSE) && !defined(CERES_NO_CAMD) - if (linear_solver_type == SPARSE_SCHUR && - sparse_linear_algebra_library_type == SUITE_SPARSE) { - vector<int> constraints; - vector<ParameterBlock*>& parameter_blocks = - *(program->mutable_parameter_blocks()); - - for (int i = 0; i < parameter_blocks.size(); ++i) { - constraints.push_back( - parameter_block_ordering->GroupId( - parameter_blocks[i]->mutable_user_state())); - } - - // Renumber the entries of constraints to be contiguous integers - // as camd requires that the group ids be in the range [0, - // parameter_blocks.size() - 1]. - SolverImpl::CompactifyArray(&constraints); - - // Set the offsets and index for CreateJacobianSparsityTranspose. - program->SetParameterOffsetsAndIndex(); - // Compute a block sparse presentation of J'. - scoped_ptr<TripletSparseMatrix> tsm_block_jacobian_transpose( - SolverImpl::CreateJacobianBlockSparsityTranspose(program)); - - SuiteSparse ss; - cholmod_sparse* block_jacobian_transpose = - ss.CreateSparseMatrix(tsm_block_jacobian_transpose.get()); - - vector<int> ordering(parameter_blocks.size(), 0); - ss.ConstrainedApproximateMinimumDegreeOrdering(block_jacobian_transpose, - &constraints[0], - &ordering[0]); - ss.Free(block_jacobian_transpose); - - const vector<ParameterBlock*> parameter_blocks_copy(parameter_blocks); - for (int i = 0; i < program->NumParameterBlocks(); ++i) { - parameter_blocks[i] = parameter_blocks_copy[ordering[i]]; - } - } -#endif - - program->SetParameterOffsetsAndIndex(); - // Schur type solvers also require that their residual blocks be - // lexicographically ordered. - const int num_eliminate_blocks = - parameter_block_ordering->group_to_elements().begin()->second.size(); - return LexicographicallyOrderResidualBlocks(num_eliminate_blocks, - program, - error); -} - -bool SolverImpl::ReorderProgramForSparseNormalCholesky( - const SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, - const ParameterBlockOrdering* parameter_block_ordering, - Program* program, - string* error) { - // Set the offsets and index for CreateJacobianSparsityTranspose. - program->SetParameterOffsetsAndIndex(); - // Compute a block sparse presentation of J'. - scoped_ptr<TripletSparseMatrix> tsm_block_jacobian_transpose( - SolverImpl::CreateJacobianBlockSparsityTranspose(program)); - - vector<int> ordering(program->NumParameterBlocks(), 0); - vector<ParameterBlock*>& parameter_blocks = - *(program->mutable_parameter_blocks()); - - if (sparse_linear_algebra_library_type == SUITE_SPARSE) { -#ifdef CERES_NO_SUITESPARSE - *error = "Can't use SPARSE_NORMAL_CHOLESKY with SUITE_SPARSE because " - "SuiteSparse was not enabled when Ceres was built."; - return false; -#else - SuiteSparse ss; - cholmod_sparse* block_jacobian_transpose = - ss.CreateSparseMatrix(tsm_block_jacobian_transpose.get()); - -# ifdef CERES_NO_CAMD - // No cholmod_camd, so ignore user's parameter_block_ordering and - // use plain old AMD. - ss.ApproximateMinimumDegreeOrdering(block_jacobian_transpose, &ordering[0]); -# else - if (parameter_block_ordering->NumGroups() > 1) { - // If the user specified more than one elimination groups use them - // to constrain the ordering. - vector<int> constraints; - for (int i = 0; i < parameter_blocks.size(); ++i) { - constraints.push_back( - parameter_block_ordering->GroupId( - parameter_blocks[i]->mutable_user_state())); - } - ss.ConstrainedApproximateMinimumDegreeOrdering( - block_jacobian_transpose, - &constraints[0], - &ordering[0]); - } else { - ss.ApproximateMinimumDegreeOrdering(block_jacobian_transpose, - &ordering[0]); - } -# endif // CERES_NO_CAMD - - ss.Free(block_jacobian_transpose); -#endif // CERES_NO_SUITESPARSE - - } else if (sparse_linear_algebra_library_type == CX_SPARSE) { -#ifndef CERES_NO_CXSPARSE - - // CXSparse works with J'J instead of J'. So compute the block - // sparsity for J'J and compute an approximate minimum degree - // ordering. - CXSparse cxsparse; - cs_di* block_jacobian_transpose; - block_jacobian_transpose = - cxsparse.CreateSparseMatrix(tsm_block_jacobian_transpose.get()); - cs_di* block_jacobian = cxsparse.TransposeMatrix(block_jacobian_transpose); - cs_di* block_hessian = - cxsparse.MatrixMatrixMultiply(block_jacobian_transpose, block_jacobian); - cxsparse.Free(block_jacobian); - cxsparse.Free(block_jacobian_transpose); - - cxsparse.ApproximateMinimumDegreeOrdering(block_hessian, &ordering[0]); - cxsparse.Free(block_hessian); -#else // CERES_NO_CXSPARSE - *error = "Can't use SPARSE_NORMAL_CHOLESKY with CX_SPARSE because " - "CXSparse was not enabled when Ceres was built."; - return false; -#endif // CERES_NO_CXSPARSE - } else { - *error = "Unknown sparse linear algebra library."; - return false; - } - - // Apply ordering. - const vector<ParameterBlock*> parameter_blocks_copy(parameter_blocks); - for (int i = 0; i < program->NumParameterBlocks(); ++i) { - parameter_blocks[i] = parameter_blocks_copy[ordering[i]]; - } - - program->SetParameterOffsetsAndIndex(); - return true; -} - -void SolverImpl::CompactifyArray(vector<int>* array_ptr) { - vector<int>& array = *array_ptr; - const set<int> unique_group_ids(array.begin(), array.end()); - map<int, int> group_id_map; - for (set<int>::const_iterator it = unique_group_ids.begin(); - it != unique_group_ids.end(); - ++it) { - InsertOrDie(&group_id_map, *it, group_id_map.size()); - } - - for (int i = 0; i < array.size(); ++i) { - array[i] = group_id_map[array[i]]; - } -} - -} // namespace internal -} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h deleted file mode 100644 index 631add59bdb..00000000000 --- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h +++ /dev/null @@ -1,228 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. -// http://code.google.com/p/ceres-solver/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Author: keir@google.com (Keir Mierle) - -#ifndef CERES_INTERNAL_SOLVER_IMPL_H_ -#define CERES_INTERNAL_SOLVER_IMPL_H_ - -#include <set> -#include <string> -#include <vector> -#include "ceres/internal/port.h" -#include "ceres/ordered_groups.h" -#include "ceres/problem_impl.h" -#include "ceres/solver.h" - -namespace ceres { -namespace internal { - -class CoordinateDescentMinimizer; -class Evaluator; -class LinearSolver; -class Program; -class TripletSparseMatrix; - -class SolverImpl { - public: - // Mirrors the interface in solver.h, but exposes implementation - // details for testing internally. - static void Solve(const Solver::Options& options, - ProblemImpl* problem_impl, - Solver::Summary* summary); - - static void TrustRegionSolve(const Solver::Options& options, - ProblemImpl* problem_impl, - Solver::Summary* summary); - - // Run the TrustRegionMinimizer for the given evaluator and configuration. - static void TrustRegionMinimize( - const Solver::Options &options, - Program* program, - CoordinateDescentMinimizer* inner_iteration_minimizer, - Evaluator* evaluator, - LinearSolver* linear_solver, - Solver::Summary* summary); - - static void LineSearchSolve(const Solver::Options& options, - ProblemImpl* problem_impl, - Solver::Summary* summary); - - // Run the LineSearchMinimizer for the given evaluator and configuration. - static void LineSearchMinimize(const Solver::Options &options, - Program* program, - Evaluator* evaluator, - Solver::Summary* summary); - - // Create the transformed Program, which has all the fixed blocks - // and residuals eliminated, and in the case of automatic schur - // ordering, has the E blocks first in the resulting program, with - // options.num_eliminate_blocks set appropriately. - // - // If fixed_cost is not NULL, the residual blocks that are removed - // are evaluated and the sum of their cost is returned in fixed_cost. - static Program* CreateReducedProgram(Solver::Options* options, - ProblemImpl* problem_impl, - double* fixed_cost, - string* message); - - // Create the appropriate linear solver, taking into account any - // config changes decided by CreateTransformedProgram(). The - // selected linear solver, which may be different from what the user - // selected; consider the case that the remaining elimininated - // blocks is zero after removing fixed blocks. - static LinearSolver* CreateLinearSolver(Solver::Options* options, - string* message); - - // Reorder the residuals for program, if necessary, so that the - // residuals involving e block (i.e., the first num_eliminate_block - // parameter blocks) occur together. This is a necessary condition - // for the Schur eliminator. - static bool LexicographicallyOrderResidualBlocks( - const int num_eliminate_blocks, - Program* program, - string* message); - - // Create the appropriate evaluator for the transformed program. - static Evaluator* CreateEvaluator( - const Solver::Options& options, - const ProblemImpl::ParameterMap& parameter_map, - Program* program, - string* message); - - // Remove the fixed or unused parameter blocks and residuals - // depending only on fixed parameters from the program. - // - // If either linear_solver_ordering or inner_iteration_ordering are - // not NULL, the constant parameter blocks are removed from them - // too. - // - // If fixed_cost is not NULL, the residual blocks that are removed - // are evaluated and the sum of their cost is returned in - // fixed_cost. - // - // If a failure is encountered, the function returns false with a - // description of the failure in message. - static bool RemoveFixedBlocksFromProgram( - Program* program, - ParameterBlockOrdering* linear_solver_ordering, - ParameterBlockOrdering* inner_iteration_ordering, - double* fixed_cost, - string* message); - - static bool IsOrderingValid(const Solver::Options& options, - const ProblemImpl* problem_impl, - string* message); - - static bool IsParameterBlockSetIndependent( - const set<double*>& parameter_block_ptrs, - const vector<ResidualBlock*>& residual_blocks); - - static CoordinateDescentMinimizer* CreateInnerIterationMinimizer( - const Solver::Options& options, - const Program& program, - const ProblemImpl::ParameterMap& parameter_map, - Solver::Summary* summary); - - // If the linear solver is of Schur type, then replace it with the - // closest equivalent linear solver. This is done when the user - // requested a Schur type solver but the problem structure makes it - // impossible to use one. - // - // If the linear solver is not of Schur type, the function is a - // no-op. - static void AlternateLinearSolverForSchurTypeLinearSolver( - Solver::Options* options); - - // Create a TripletSparseMatrix which contains the zero-one - // structure corresponding to the block sparsity of the transpose of - // the Jacobian matrix. - // - // Caller owns the result. - static TripletSparseMatrix* CreateJacobianBlockSparsityTranspose( - const Program* program); - - // Reorder the parameter blocks in program using the ordering - static bool ApplyUserOrdering( - const ProblemImpl::ParameterMap& parameter_map, - const ParameterBlockOrdering* parameter_block_ordering, - Program* program, - string* message); - - // Sparse cholesky factorization routines when doing the sparse - // cholesky factorization of the Jacobian matrix, reorders its - // columns to reduce the fill-in. Compute this permutation and - // re-order the parameter blocks. - // - // If the parameter_block_ordering contains more than one - // elimination group and support for constrained fill-reducing - // ordering is available in the sparse linear algebra library - // (SuiteSparse version >= 4.2.0) then the fill reducing - // ordering will take it into account, otherwise it will be ignored. - static bool ReorderProgramForSparseNormalCholesky( - const SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, - const ParameterBlockOrdering* parameter_block_ordering, - Program* program, - string* message); - - // Schur type solvers require that all parameter blocks eliminated - // by the Schur eliminator occur before others and the residuals be - // sorted in lexicographic order of their parameter blocks. - // - // If the parameter_block_ordering only contains one elimination - // group then a maximal independent set is computed and used as the - // first elimination group, otherwise the user's ordering is used. - // - // If the linear solver type is SPARSE_SCHUR and support for - // constrained fill-reducing ordering is available in the sparse - // linear algebra library (SuiteSparse version >= 4.2.0) then - // columns of the schur complement matrix are ordered to reduce the - // fill-in the Cholesky factorization. - // - // Upon return, ordering contains the parameter block ordering that - // was used to order the program. - static bool ReorderProgramForSchurTypeLinearSolver( - const LinearSolverType linear_solver_type, - const SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, - const ProblemImpl::ParameterMap& parameter_map, - ParameterBlockOrdering* parameter_block_ordering, - Program* program, - string* message); - - // array contains a list of (possibly repeating) non-negative - // integers. Let us assume that we have constructed another array - // `p` by sorting and uniqueing the entries of array. - // CompactifyArray replaces each entry in "array" with its position - // in `p`. - static void CompactifyArray(vector<int>* array); -}; - -} // namespace internal -} // namespace ceres - -#endif // CERES_INTERNAL_SOLVER_IMPL_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_utils.cc b/extern/libmv/third_party/ceres/internal/ceres/solver_utils.cc new file mode 100644 index 00000000000..bd304e7ac5d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/solver_utils.cc @@ -0,0 +1,78 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include <string> + +#include "ceres/internal/port.h" +#include "ceres/version.h" + +namespace ceres { +namespace internal { + +string VersionString() { + string value = string(CERES_VERSION_STRING); + +#ifdef CERES_NO_LAPACK + value += "-no_lapack"; +#else + value += "-lapack"; +#endif + +#ifndef CERES_NO_SUITESPARSE + value += "-suitesparse"; +#endif + +#ifndef CERES_NO_CXSPARSE + value += "-cxsparse"; +#endif + +#ifdef CERES_USE_EIGEN_SPARSE + value += "-eigensparse"; +#endif + +#ifdef CERES_RESTRUCT_SCHUR_SPECIALIZATIONS + value += "-no_schur_specializations"; +#endif + +#ifdef CERES_USE_OPENMP + value += "-openmp"; +#else + value += "-no_openmp"; +#endif + +#ifdef CERES_NO_CUSTOM_BLAS + value += "-no_custom_blas"; +#endif + + return value; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_utils.h b/extern/libmv/third_party/ceres/internal/ceres/solver_utils.h new file mode 100644 index 00000000000..41c8a6e1292 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/solver_utils.h @@ -0,0 +1,58 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include <algorithm> +#include <string> + +namespace ceres { +namespace internal { + +template <typename SummaryType> +bool IsSolutionUsable(const SummaryType& summary) { + return (summary.termination_type == CONVERGENCE || + summary.termination_type == NO_CONVERGENCE || + summary.termination_type == USER_SUCCESS); +} + +template <typename SummaryType> +void SetSummaryFinalCost(SummaryType* summary) { + summary->final_cost = summary->initial_cost; + // We need the loop here, instead of just looking at the last + // iteration because the minimizer maybe making non-monotonic steps. + for (int i = 0; i < summary->iterations.size(); ++i) { + const IterationSummary& iteration_summary = summary->iterations[i]; + summary->final_cost = min(iteration_summary.cost, summary->final_cost); + } +} + +string VersionString(); + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc index cf5bb235b46..94f7e5803c4 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc @@ -28,11 +28,6 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) -// This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" - -#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE) - #include "ceres/sparse_normal_cholesky_solver.h" #include <algorithm> @@ -48,9 +43,67 @@ #include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" #include "ceres/wall_time.h" +#include "Eigen/SparseCore" + +#ifdef CERES_USE_EIGEN_SPARSE +#include "Eigen/SparseCholesky" +#endif namespace ceres { namespace internal { +namespace { + +#ifdef CERES_USE_EIGEN_SPARSE +// A templated factorized and solve function, which allows us to use +// the same code independent of whether a AMD or a Natural ordering is +// used. +template <typename SimplicialCholeskySolver> +LinearSolver::Summary SimplicialLDLTSolve( + Eigen::MappedSparseMatrix<double, Eigen::ColMajor>& lhs, + const bool do_symbolic_analysis, + SimplicialCholeskySolver* solver, + double* rhs_and_solution, + EventLogger* event_logger) { + LinearSolver::Summary summary; + summary.num_iterations = 1; + summary.termination_type = LINEAR_SOLVER_SUCCESS; + summary.message = "Success."; + + if (do_symbolic_analysis) { + solver->analyzePattern(lhs); + event_logger->AddEvent("Analyze"); + if (solver->info() != Eigen::Success) { + summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; + summary.message = + "Eigen failure. Unable to find symbolic factorization."; + return summary; + } + } + + solver->factorize(lhs); + event_logger->AddEvent("Factorize"); + if (solver->info() != Eigen::Success) { + summary.termination_type = LINEAR_SOLVER_FAILURE; + summary.message = "Eigen failure. Unable to find numeric factorization."; + return summary; + } + + const Vector rhs = VectorRef(rhs_and_solution, lhs.cols()); + + VectorRef(rhs_and_solution, lhs.cols()) = solver->solve(rhs); + event_logger->AddEvent("Solve"); + if (solver->info() != Eigen::Success) { + summary.termination_type = LINEAR_SOLVER_FAILURE; + summary.message = "Eigen failure. Unable to do triangular solve."; + return summary; + } + + return summary; +} + +#endif // CERES_USE_EIGEN_SPARSE + +} // namespace SparseNormalCholeskySolver::SparseNormalCholeskySolver( const LinearSolver::Options& options) @@ -60,19 +113,15 @@ SparseNormalCholeskySolver::SparseNormalCholeskySolver( } void SparseNormalCholeskySolver::FreeFactorization() { -#ifndef CERES_NO_SUITESPARSE if (factor_ != NULL) { ss_.Free(factor_); factor_ = NULL; } -#endif // CERES_NO_SUITESPARSE -#ifndef CERES_NO_CXSPARSE if (cxsparse_factor_ != NULL) { cxsparse_.Free(cxsparse_factor_); cxsparse_factor_ = NULL; } -#endif // CERES_NO_CXSPARSE } SparseNormalCholeskySolver::~SparseNormalCholeskySolver() { @@ -111,6 +160,9 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( case CX_SPARSE: summary = SolveImplUsingCXSparse(A, per_solve_options, x); break; + case EIGEN_SPARSE: + summary = SolveImplUsingEigen(A, per_solve_options, x); + break; default: LOG(FATAL) << "Unknown sparse linear algebra library : " << options_.sparse_linear_algebra_library_type; @@ -123,11 +175,120 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( return summary; } -#ifndef CERES_NO_CXSPARSE +LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingEigen( + CompressedRowSparseMatrix* A, + const LinearSolver::PerSolveOptions& per_solve_options, + double * rhs_and_solution) { +#ifndef CERES_USE_EIGEN_SPARSE + + LinearSolver::Summary summary; + summary.num_iterations = 0; + summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; + summary.message = + "SPARSE_NORMAL_CHOLESKY cannot be used with EIGEN_SPARSE " + "because Ceres was not built with support for " + "Eigen's SimplicialLDLT decomposition. " + "This requires enabling building with -DEIGENSPARSE=ON."; + return summary; + +#else + + EventLogger event_logger("SparseNormalCholeskySolver::Eigen::Solve"); + // Compute the normal equations. J'J delta = J'f and solve them + // using a sparse Cholesky factorization. Notice that when compared + // to SuiteSparse we have to explicitly compute the normal equations + // before they can be factorized. CHOLMOD/SuiteSparse on the other + // hand can just work off of Jt to compute the Cholesky + // factorization of the normal equations. + // + // TODO(sameeragarwal): See note about how this maybe a bad idea for + // dynamic sparsity. + if (outer_product_.get() == NULL) { + outer_product_.reset( + CompressedRowSparseMatrix::CreateOuterProductMatrixAndProgram( + *A, &pattern_)); + } + + CompressedRowSparseMatrix::ComputeOuterProduct( + *A, pattern_, outer_product_.get()); + + // Map to an upper triangular column major matrix. + // + // outer_product_ is a compressed row sparse matrix and in lower + // triangular form, when mapped to a compressed column sparse + // matrix, it becomes an upper triangular matrix. + Eigen::MappedSparseMatrix<double, Eigen::ColMajor> AtA( + outer_product_->num_rows(), + outer_product_->num_rows(), + outer_product_->num_nonzeros(), + outer_product_->mutable_rows(), + outer_product_->mutable_cols(), + outer_product_->mutable_values()); + + // Dynamic sparsity means that we cannot depend on a static analysis + // of sparsity structure of the jacobian, so we compute a new + // symbolic factorization every time. + if (options_.dynamic_sparsity) { + amd_ldlt_.reset(NULL); + } + + bool do_symbolic_analysis = false; + + // If using post ordering or dynamic sparsity, or an old version of + // Eigen, we cannot depend on a preordered jacobian, so we work with + // a SimplicialLDLT decomposition with AMD ordering. + if (options_.use_postordering || + options_.dynamic_sparsity || + !EIGEN_VERSION_AT_LEAST(3, 2, 2)) { + if (amd_ldlt_.get() == NULL) { + amd_ldlt_.reset(new SimplicialLDLTWithAMDOrdering); + do_symbolic_analysis = true; + } + + return SimplicialLDLTSolve(AtA, + do_symbolic_analysis, + amd_ldlt_.get(), + rhs_and_solution, + &event_logger); + } + +#if EIGEN_VERSION_AT_LEAST(3,2,2) + // The common case + if (natural_ldlt_.get() == NULL) { + natural_ldlt_.reset(new SimplicialLDLTWithNaturalOrdering); + do_symbolic_analysis = true; + } + + return SimplicialLDLTSolve(AtA, + do_symbolic_analysis, + natural_ldlt_.get(), + rhs_and_solution, + &event_logger); +#endif + +#endif // EIGEN_USE_EIGEN_SPARSE +} + + + LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse( CompressedRowSparseMatrix* A, const LinearSolver::PerSolveOptions& per_solve_options, double * rhs_and_solution) { +#ifdef CERES_NO_CXSPARSE + + LinearSolver::Summary summary; + summary.num_iterations = 0; + summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; + summary.message = + "SPARSE_NORMAL_CHOLESKY cannot be used with CX_SPARSE " + "because Ceres was not built with support for CXSparse. " + "This requires enabling building with -DCXSPARSE=ON."; + + return summary; + +#else + EventLogger event_logger("SparseNormalCholeskySolver::CXSparse::Solve"); LinearSolver::Summary summary; @@ -137,11 +298,14 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse( // Compute the normal equations. J'J delta = J'f and solve them // using a sparse Cholesky factorization. Notice that when compared - // to SuiteSparse we have to explicitly compute the transpose of Jt, - // and then the normal equations before they can be - // factorized. CHOLMOD/SuiteSparse on the other hand can just work - // off of Jt to compute the Cholesky factorization of the normal - // equations. + // to SuiteSparse we have to explicitly compute the normal equations + // before they can be factorized. CHOLMOD/SuiteSparse on the other + // hand can just work off of Jt to compute the Cholesky + // factorization of the normal equations. + // + // TODO(sameeragarwal): If dynamic sparsity is enabled, then this is + // not a good idea performance wise, since the jacobian has far too + // many entries and the program will go crazy with memory. if (outer_product_.get() == NULL) { outer_product_.reset( CompressedRowSparseMatrix::CreateOuterProductMatrixAndProgram( @@ -179,30 +343,35 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse( summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; summary.message = "CXSparse failure. Unable to find symbolic factorization."; - } else if (!cxsparse_.SolveCholesky(AtA, cxsparse_factor_, rhs_and_solution)) { + } else if (!cxsparse_.SolveCholesky(AtA, + cxsparse_factor_, + rhs_and_solution)) { summary.termination_type = LINEAR_SOLVER_FAILURE; + summary.message = "CXSparse::SolveCholesky failed."; } event_logger.AddEvent("Solve"); return summary; -} -#else -LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse( - CompressedRowSparseMatrix* A, - const LinearSolver::PerSolveOptions& per_solve_options, - double * rhs_and_solution) { - LOG(FATAL) << "No CXSparse support in Ceres."; - - // Unreachable but MSVC does not know this. - return LinearSolver::Summary(); -} #endif +} -#ifndef CERES_NO_SUITESPARSE LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse( CompressedRowSparseMatrix* A, const LinearSolver::PerSolveOptions& per_solve_options, double * rhs_and_solution) { +#ifdef CERES_NO_SUITESPARSE + + LinearSolver::Summary summary; + summary.num_iterations = 0; + summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; + summary.message = + "SPARSE_NORMAL_CHOLESKY cannot be used with SUITE_SPARSE " + "because Ceres was not built with support for SuiteSparse. " + "This requires enabling building with -DSUITESPARSE=ON."; + return summary; + +#else + EventLogger event_logger("SparseNormalCholeskySolver::SuiteSparse::Solve"); LinearSolver::Summary summary; summary.termination_type = LINEAR_SOLVER_SUCCESS; @@ -226,7 +395,8 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse( if (options_.dynamic_sparsity) { factor_ = ss_.AnalyzeCholesky(&lhs, &summary.message); } else { - factor_ = ss_.AnalyzeCholeskyWithNaturalOrdering(&lhs, &summary.message); + factor_ = ss_.AnalyzeCholeskyWithNaturalOrdering(&lhs, + &summary.message); } } } @@ -234,6 +404,8 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse( if (factor_ == NULL) { summary.termination_type = LINEAR_SOLVER_FATAL_ERROR; + // No need to set message as it has already been set by the + // symbolic analysis routines above. return summary; } @@ -242,7 +414,9 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse( return summary; } - cholmod_dense* rhs = ss_.CreateDenseVector(rhs_and_solution, num_cols, num_cols); + cholmod_dense* rhs = ss_.CreateDenseVector(rhs_and_solution, + num_cols, + num_cols); cholmod_dense* solution = ss_.Solve(factor_, rhs, &summary.message); event_logger.AddEvent("Solve"); @@ -251,25 +425,15 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse( memcpy(rhs_and_solution, solution->x, num_cols * sizeof(*rhs_and_solution)); ss_.Free(solution); } else { + // No need to set message as it has already been set by the + // numeric factorization routine above. summary.termination_type = LINEAR_SOLVER_FAILURE; } event_logger.AddEvent("Teardown"); return summary; -} -#else -LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse( - CompressedRowSparseMatrix* A, - const LinearSolver::PerSolveOptions& per_solve_options, - double * rhs_and_solution) { - LOG(FATAL) << "No SuiteSparse support in Ceres."; - - // Unreachable but MSVC does not know this. - return LinearSolver::Summary(); -} #endif +} } // namespace internal } // namespace ceres - -#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE) diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h index ed777a118ae..12c05245075 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h @@ -34,15 +34,19 @@ #ifndef CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ #define CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ +#include <vector> + // This include must come before any #ifndef check on Ceres compile options. #include "ceres/internal/port.h" -#if !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE) - -#include "ceres/cxsparse.h" #include "ceres/internal/macros.h" #include "ceres/linear_solver.h" #include "ceres/suitesparse.h" +#include "ceres/cxsparse.h" + +#ifdef CERES_USE_EIGEN_SPARSE +#include "Eigen/SparseCholesky" +#endif namespace ceres { namespace internal { @@ -74,6 +78,12 @@ class SparseNormalCholeskySolver : public CompressedRowSparseMatrixSolver { const LinearSolver::PerSolveOptions& options, double* rhs_and_solution); + // Crashes if CERES_USE_EIGEN_SPARSE is not defined. + LinearSolver::Summary SolveImplUsingEigen( + CompressedRowSparseMatrix* A, + const LinearSolver::PerSolveOptions& options, + double* rhs_and_solution); + void FreeFactorization(); SuiteSparse ss_; @@ -83,6 +93,32 @@ class SparseNormalCholeskySolver : public CompressedRowSparseMatrixSolver { CXSparse cxsparse_; // Cached factorization cs_dis* cxsparse_factor_; + +#ifdef CERES_USE_EIGEN_SPARSE + + // The preprocessor gymnastics here are dealing with the fact that + // before version 3.2.2, Eigen did not support a third template + // parameter to specify the ordering. +#if EIGEN_VERSION_AT_LEAST(3,2,2) + typedef Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>, Eigen::Upper, + Eigen::NaturalOrdering<int> > + SimplicialLDLTWithNaturalOrdering; + scoped_ptr<SimplicialLDLTWithNaturalOrdering> natural_ldlt_; + + typedef Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>, Eigen::Upper, + Eigen::AMDOrdering<int> > + SimplicialLDLTWithAMDOrdering; + scoped_ptr<SimplicialLDLTWithAMDOrdering> amd_ldlt_; + +#else + typedef Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>, Eigen::Upper> + SimplicialLDLTWithAMDOrdering; + + scoped_ptr<SimplicialLDLTWithAMDOrdering> amd_ldlt_; +#endif + +#endif + scoped_ptr<CompressedRowSparseMatrix> outer_product_; vector<int> pattern_; const LinearSolver::Options options_; @@ -92,5 +128,4 @@ class SparseNormalCholeskySolver : public CompressedRowSparseMatrixSolver { } // namespace internal } // namespace ceres -#endif // !defined(CERES_NO_SUITESPARSE) || !defined(CERES_NO_CXSPARSE) #endif // CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h index 0a7ea97f2d7..baab8998b29 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h +++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h @@ -283,9 +283,24 @@ class SuiteSparse { #else // CERES_NO_SUITESPARSE -class SuiteSparse {}; typedef void cholmod_factor; +class SuiteSparse { + public: + // Defining this static function even when SuiteSparse is not + // available, allows client code to check for the presence of CAMD + // without checking for the absence of the CERES_NO_CAMD symbol. + // + // This is safer because the symbol maybe missing due to a user + // accidently not including suitesparse.h in their code when + // checking for the symbol. + static bool IsConstrainedApproximateMinimumDegreeOrderingAvailable() { + return false; + } + + void Free(void*) {}; +}; + #endif // CERES_NO_SUITESPARSE #endif // CERES_INTERNAL_SUITESPARSE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc index 4be561960c9..926bced6226 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2012 Google Inc. All rights reserved. +// Copyright 2014 Google Inc. All rights reserved. // http://code.google.com/p/ceres-solver/ // // Redistribution and use in source and binary forms, with or without @@ -40,6 +40,7 @@ #include "Eigen/Core" #include "ceres/array_utils.h" +#include "ceres/coordinate_descent_minimizer.h" #include "ceres/evaluator.h" #include "ceres/file.h" #include "ceres/internal/eigen.h" @@ -128,9 +129,10 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options, double iteration_start_time = start_time; Init(options); - Evaluator* evaluator = CHECK_NOTNULL(options_.evaluator); - SparseMatrix* jacobian = CHECK_NOTNULL(options_.jacobian); - TrustRegionStrategy* strategy = CHECK_NOTNULL(options_.trust_region_strategy); + Evaluator* evaluator = CHECK_NOTNULL(options_.evaluator.get()); + SparseMatrix* jacobian = CHECK_NOTNULL(options_.jacobian.get()); + TrustRegionStrategy* strategy = + CHECK_NOTNULL(options_.trust_region_strategy.get()); const bool is_not_silent = !options.is_silent; @@ -253,7 +255,8 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options, double candidate_cost = cost; double accumulated_candidate_model_cost_change = 0.0; int num_consecutive_invalid_steps = 0; - bool inner_iterations_are_enabled = options.inner_iteration_minimizer != NULL; + bool inner_iterations_are_enabled = + options.inner_iteration_minimizer.get() != NULL; while (true) { bool inner_iterations_were_useful = false; if (!RunCallbacks(options, iteration_summary, summary)) { diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.cc new file mode 100644 index 00000000000..22ea1ec8c80 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.cc @@ -0,0 +1,358 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/trust_region_preprocessor.h" + +#include <numeric> +#include <string> +#include "ceres/callbacks.h" +#include "ceres/evaluator.h" +#include "ceres/linear_solver.h" +#include "ceres/minimizer.h" +#include "ceres/parameter_block.h" +#include "ceres/preconditioner.h" +#include "ceres/preprocessor.h" +#include "ceres/problem_impl.h" +#include "ceres/program.h" +#include "ceres/reorder_program.h" +#include "ceres/suitesparse.h" +#include "ceres/trust_region_strategy.h" +#include "ceres/wall_time.h" + +namespace ceres { +namespace internal { +namespace { + +ParameterBlockOrdering* CreateDefaultLinearSolverOrdering( + const Program& program) { + ParameterBlockOrdering* ordering = new ParameterBlockOrdering; + const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); + for (int i = 0; i < parameter_blocks.size(); ++i) { + ordering->AddElementToGroup( + const_cast<double*>(parameter_blocks[i]->user_state()), 0); + } + return ordering; +} + +// Check if all the user supplied values in the parameter blocks are +// sane or not, and if the program is feasible or not. +bool IsProgramValid(const Program& program, string* error) { + return (program.ParameterBlocksAreFinite(error) && + program.IsFeasible(error)); +} + +void AlternateLinearSolverAndPreconditionerForSchurTypeLinearSolver( + Solver::Options* options) { + if (!IsSchurType(options->linear_solver_type)) { + return; + } + + const LinearSolverType linear_solver_type_given = options->linear_solver_type; + const PreconditionerType preconditioner_type_given = + options->preconditioner_type; + options->linear_solver_type = LinearSolver::LinearSolverForZeroEBlocks( + linear_solver_type_given); + + string message; + if (linear_solver_type_given == ITERATIVE_SCHUR) { + options->preconditioner_type = Preconditioner::PreconditionerForZeroEBlocks( + preconditioner_type_given); + + message = + StringPrintf( + "No E blocks. Switching from %s(%s) to %s(%s).", + LinearSolverTypeToString(linear_solver_type_given), + PreconditionerTypeToString(preconditioner_type_given), + LinearSolverTypeToString(options->linear_solver_type), + PreconditionerTypeToString(options->preconditioner_type)); + } else { + message = + StringPrintf( + "No E blocks. Switching from %s to %s.", + LinearSolverTypeToString(linear_solver_type_given), + LinearSolverTypeToString(options->linear_solver_type)); + } + + VLOG_IF(1, options->logging_type != SILENT) << message; +} + +// For Schur type and SPARSE_NORMAL_CHOLESKY linear solvers, reorder +// the program to reduce fill-in and increase cache coherency. +bool ReorderProgram(PreprocessedProblem* pp) { + Solver::Options& options = pp->options; + if (IsSchurType(options.linear_solver_type)) { + return ReorderProgramForSchurTypeLinearSolver( + options.linear_solver_type, + options.sparse_linear_algebra_library_type, + pp->problem->parameter_map(), + options.linear_solver_ordering.get(), + pp->reduced_program.get(), + &pp->error); + } + + if (options.linear_solver_type == SPARSE_NORMAL_CHOLESKY && + !options.dynamic_sparsity) { + return ReorderProgramForSparseNormalCholesky( + options.sparse_linear_algebra_library_type, + *options.linear_solver_ordering, + pp->reduced_program.get(), + &pp->error); + } + + return true; +} + +// Configure and create a linear solver object. In doing so, if a +// sparse direct factorization based linear solver is being used, then +// find a fill reducing ordering and reorder the program as needed +// too. +bool SetupLinearSolver(PreprocessedProblem* pp) { + Solver::Options& options = pp->options; + if (options.linear_solver_ordering.get() == NULL) { + // If the user has not supplied a linear solver ordering, then we + // assume that they are giving all the freedom to us in choosing + // the best possible ordering. This intent can be indicated by + // putting all the parameter blocks in the same elimination group. + options.linear_solver_ordering.reset( + CreateDefaultLinearSolverOrdering(*pp->reduced_program)); + } else { + // If the user supplied an ordering, then check if the first + // elimination group is still non-empty after the reduced problem + // has been constructed. + // + // This is important for Schur type linear solvers, where the + // first elimination group is special -- it needs to be an + // independent set. + // + // If the first elimination group is empty, then we cannot use the + // user's requested linear solver (and a preconditioner as the + // case may be) so we must use a different one. + ParameterBlockOrdering* ordering = options.linear_solver_ordering.get(); + const int min_group_id = ordering->MinNonZeroGroup(); + ordering->Remove(pp->removed_parameter_blocks); + if (IsSchurType(options.linear_solver_type) && + min_group_id != ordering->MinNonZeroGroup()) { + AlternateLinearSolverAndPreconditionerForSchurTypeLinearSolver( + &options); + } + } + + // Reorder the program to reduce fill in and improve cache coherency + // of the Jacobian. + if (!ReorderProgram(pp)) { + return false; + } + + // Configure the linear solver. + pp->linear_solver_options = LinearSolver::Options(); + pp->linear_solver_options.min_num_iterations = + options.min_linear_solver_iterations; + pp->linear_solver_options.max_num_iterations = + options.max_linear_solver_iterations; + pp->linear_solver_options.type = options.linear_solver_type; + pp->linear_solver_options.preconditioner_type = options.preconditioner_type; + pp->linear_solver_options.visibility_clustering_type = + options.visibility_clustering_type; + pp->linear_solver_options.sparse_linear_algebra_library_type = + options.sparse_linear_algebra_library_type; + pp->linear_solver_options.dense_linear_algebra_library_type = + options.dense_linear_algebra_library_type; + pp->linear_solver_options.use_explicit_schur_complement = + options.use_explicit_schur_complement; + pp->linear_solver_options.dynamic_sparsity = options.dynamic_sparsity; + pp->linear_solver_options.num_threads = options.num_linear_solver_threads; + + // Ignore user's postordering preferences and force it to be true if + // cholmod_camd is not available. This ensures that the linear + // solver does not assume that a fill-reducing pre-ordering has been + // done. + pp->linear_solver_options.use_postordering = options.use_postordering; + if (options.linear_solver_type == SPARSE_SCHUR && + options.sparse_linear_algebra_library_type == SUITE_SPARSE && + !SuiteSparse::IsConstrainedApproximateMinimumDegreeOrderingAvailable()) { + pp->linear_solver_options.use_postordering = true; + } + + OrderingToGroupSizes(options.linear_solver_ordering.get(), + &pp->linear_solver_options.elimination_groups); + + // Schur type solvers expect at least two elimination groups. If + // there is only one elimination group, then it is guaranteed that + // this group only contains e_blocks. Thus we add a dummy + // elimination group with zero blocks in it. + if (IsSchurType(pp->linear_solver_options.type) && + pp->linear_solver_options.elimination_groups.size() == 1) { + pp->linear_solver_options.elimination_groups.push_back(0); + } + + pp->linear_solver.reset(LinearSolver::Create(pp->linear_solver_options)); + return (pp->linear_solver.get() != NULL); +} + +// Configure and create the evaluator. +bool SetupEvaluator(PreprocessedProblem* pp) { + const Solver::Options& options = pp->options; + pp->evaluator_options = Evaluator::Options(); + pp->evaluator_options.linear_solver_type = options.linear_solver_type; + pp->evaluator_options.num_eliminate_blocks = 0; + if (IsSchurType(options.linear_solver_type)) { + pp->evaluator_options.num_eliminate_blocks = + options + .linear_solver_ordering + ->group_to_elements().begin() + ->second.size(); + } + + pp->evaluator_options.num_threads = options.num_threads; + pp->evaluator_options.dynamic_sparsity = options.dynamic_sparsity; + pp->evaluator.reset(Evaluator::Create(pp->evaluator_options, + pp->reduced_program.get(), + &pp->error)); + + return (pp->evaluator.get() != NULL); +} + +// If the user requested inner iterations, then find an inner +// iteration ordering as needed and configure and create a +// CoordinateDescentMinimizer object to perform the inner iterations. +bool SetupInnerIterationMinimizer(PreprocessedProblem* pp) { + Solver::Options& options = pp->options; + if (!options.use_inner_iterations) { + return true; + } + + // With just one parameter block, the outer iteration of the trust + // region method and inner iterations are doing exactly the same + // thing, and thus inner iterations are not needed. + if (pp->reduced_program->NumParameterBlocks() == 1) { + LOG(WARNING) << "Reduced problem only contains one parameter block." + << "Disabling inner iterations."; + return true; + } + + if (options.inner_iteration_ordering.get() != NULL) { + // If the user supplied an ordering, then remove the set of + // inactive parameter blocks from it + options.inner_iteration_ordering->Remove(pp->removed_parameter_blocks); + if (options.inner_iteration_ordering->NumElements() == 0) { + LOG(WARNING) << "No remaining elements in the inner iteration ordering."; + return true; + } + + // Validate the reduced ordering. + if (!CoordinateDescentMinimizer::IsOrderingValid( + *pp->reduced_program, + *options.inner_iteration_ordering, + &pp->error)) { + return false; + } + } else { + // The user did not supply an ordering, so create one. + options.inner_iteration_ordering.reset( + CoordinateDescentMinimizer::CreateOrdering(*pp->reduced_program)); + } + + pp->inner_iteration_minimizer.reset(new CoordinateDescentMinimizer); + return pp->inner_iteration_minimizer->Init(*pp->reduced_program, + pp->problem->parameter_map(), + *options.inner_iteration_ordering, + &pp->error); +} + +// Configure and create a TrustRegionMinimizer object. +void SetupMinimizerOptions(PreprocessedProblem* pp) { + const Solver::Options& options = pp->options; + + SetupCommonMinimizerOptions(pp); + pp->minimizer_options.is_constrained = + pp->reduced_program->IsBoundsConstrained(); + pp->minimizer_options.jacobian.reset(pp->evaluator->CreateJacobian()); + pp->minimizer_options.inner_iteration_minimizer = + pp->inner_iteration_minimizer; + + TrustRegionStrategy::Options strategy_options; + strategy_options.linear_solver = pp->linear_solver.get(); + strategy_options.initial_radius = + options.initial_trust_region_radius; + strategy_options.max_radius = options.max_trust_region_radius; + strategy_options.min_lm_diagonal = options.min_lm_diagonal; + strategy_options.max_lm_diagonal = options.max_lm_diagonal; + strategy_options.trust_region_strategy_type = + options.trust_region_strategy_type; + strategy_options.dogleg_type = options.dogleg_type; + pp->minimizer_options.trust_region_strategy.reset( + CHECK_NOTNULL(TrustRegionStrategy::Create(strategy_options))); +} + +} // namespace + +TrustRegionPreprocessor::~TrustRegionPreprocessor() { +} + +bool TrustRegionPreprocessor::Preprocess(const Solver::Options& options, + ProblemImpl* problem, + PreprocessedProblem* pp) { + CHECK_NOTNULL(pp); + pp->options = options; + ChangeNumThreadsIfNeeded(&pp->options); + + pp->problem = problem; + Program* program = problem->mutable_program(); + if (!IsProgramValid(*program, &pp->error)) { + return false; + } + + pp->reduced_program.reset( + program->CreateReducedProgram(&pp->removed_parameter_blocks, + &pp->fixed_cost, + &pp->error)); + + if (pp->reduced_program.get() == NULL) { + return false; + } + + if (pp->reduced_program->NumParameterBlocks() == 0) { + // The reduced problem has no parameter or residual blocks. There + // is nothing more to do. + return true; + } + + if (!SetupLinearSolver(pp) || + !SetupEvaluator(pp) || + !SetupInnerIterationMinimizer(pp)) { + return false; + } + + SetupMinimizerOptions(pp); + return true; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.h b/extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.h new file mode 100644 index 00000000000..ba70ff92e73 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_preprocessor.h @@ -0,0 +1,50 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: sameragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_TRUST_REGION_PREPROCESSOR_H_ +#define CERES_INTERNAL_TRUST_REGION_PREPROCESSOR_H_ + +#include "ceres/preprocessor.h" + +namespace ceres { +namespace internal { + +class TrustRegionPreprocessor : public Preprocessor { + public: + virtual ~TrustRegionPreprocessor(); + virtual bool Preprocess(const Solver::Options& options, + ProblemImpl* problem, + PreprocessedProblem* preprocessed_problem); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_TRUST_REGION_PREPROCESSOR_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/types.cc b/extern/libmv/third_party/ceres/internal/ceres/types.cc index 5a344ea43d7..47102616ee8 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/types.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/types.cc @@ -96,6 +96,7 @@ const char* SparseLinearAlgebraLibraryTypeToString( switch (type) { CASESTR(SUITE_SPARSE); CASESTR(CX_SPARSE); + CASESTR(EIGEN_SPARSE); default: return "UNKNOWN"; } @@ -107,6 +108,7 @@ bool StringToSparseLinearAlgebraLibraryType( UpperCase(&value); STRENUM(SUITE_SPARSE); STRENUM(CX_SPARSE); + STRENUM(EIGEN_SPARSE); return false; } @@ -240,7 +242,7 @@ const char* NonlinearConjugateGradientTypeToString( NonlinearConjugateGradientType type) { switch (type) { CASESTR(FLETCHER_REEVES); - CASESTR(POLAK_RIBIRERE); + CASESTR(POLAK_RIBIERE); CASESTR(HESTENES_STIEFEL); default: return "UNKNOWN"; @@ -252,7 +254,7 @@ bool StringToNonlinearConjugateGradientType( NonlinearConjugateGradientType* type) { UpperCase(&value); STRENUM(FLETCHER_REEVES); - STRENUM(POLAK_RIBIRERE); + STRENUM(POLAK_RIBIERE); STRENUM(HESTENES_STIEFEL); return false; } @@ -261,8 +263,8 @@ const char* CovarianceAlgorithmTypeToString( CovarianceAlgorithmType type) { switch (type) { CASESTR(DENSE_SVD); - CASESTR(SPARSE_CHOLESKY); - CASESTR(SPARSE_QR); + CASESTR(EIGEN_SPARSE_QR); + CASESTR(SUITE_SPARSE_QR); default: return "UNKNOWN"; } @@ -273,8 +275,8 @@ bool StringToCovarianceAlgorithmType( CovarianceAlgorithmType* type) { UpperCase(&value); STRENUM(DENSE_SVD); - STRENUM(SPARSE_CHOLESKY); - STRENUM(SPARSE_QR); + STRENUM(EIGEN_SPARSE_QR); + STRENUM(SUITE_SPARSE_QR); return false; } diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc index b3ee185581f..da8beedc663 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/visibility.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc @@ -76,7 +76,8 @@ void ComputeVisibility(const CompressedRowBlockStructure& block_structure, } } -Graph<int>* CreateSchurComplementGraph(const vector<set<int> >& visibility) { +WeightedGraph<int>* CreateSchurComplementGraph( + const vector<set<int> >& visibility) { const time_t start_time = time(NULL); // Compute the number of e_blocks/point blocks. Since the visibility // set for each e_block/camera contains the set of e_blocks/points @@ -122,7 +123,7 @@ Graph<int>* CreateSchurComplementGraph(const vector<set<int> >& visibility) { } } - Graph<int>* graph = new Graph<int>(); + WeightedGraph<int>* graph = new WeightedGraph<int>; // Add vertices and initialize the pairs for self edges so that self // edges are guaranteed. This is needed for the Canonical views diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility.h b/extern/libmv/third_party/ceres/internal/ceres/visibility.h index 5ddd3a56082..322efe9bea4 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/visibility.h +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility.h @@ -72,9 +72,10 @@ void ComputeVisibility(const CompressedRowBlockStructure& block_structure, // matrix/Schur complement matrix obtained by eliminating the e_blocks // from the normal equations. // -// Caller acquires ownership of the returned Graph pointer +// Caller acquires ownership of the returned WeightedGraph pointer // (heap-allocated). -Graph<int>* CreateSchurComplementGraph(const vector<set<int> >& visibility); +WeightedGraph<int>* CreateSchurComplementGraph( + const vector<set<int> >& visibility); } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc index 695eedcc8d9..c7ed0493d8c 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc @@ -167,9 +167,9 @@ void VisibilityBasedPreconditioner::ComputeClusterTridiagonalSparsity( // maximum spanning forest of this graph. vector<set<int> > cluster_visibility; ComputeClusterVisibility(visibility, &cluster_visibility); - scoped_ptr<Graph<int> > cluster_graph( + scoped_ptr<WeightedGraph<int> > cluster_graph( CHECK_NOTNULL(CreateClusterGraph(cluster_visibility))); - scoped_ptr<Graph<int> > forest( + scoped_ptr<WeightedGraph<int> > forest( CHECK_NOTNULL(Degree2MaximumSpanningForest(*cluster_graph))); ForestToClusterPairs(*forest, &cluster_pairs_); } @@ -189,7 +189,7 @@ void VisibilityBasedPreconditioner::InitStorage( // memberships for each camera block. void VisibilityBasedPreconditioner::ClusterCameras( const vector<set<int> >& visibility) { - scoped_ptr<Graph<int> > schur_complement_graph( + scoped_ptr<WeightedGraph<int> > schur_complement_graph( CHECK_NOTNULL(CreateSchurComplementGraph(visibility))); HashMap<int, int> membership; @@ -498,7 +498,7 @@ bool VisibilityBasedPreconditioner::IsBlockPairOffDiagonal( // Convert a graph into a list of edges that includes self edges for // each vertex. void VisibilityBasedPreconditioner::ForestToClusterPairs( - const Graph<int>& forest, + const WeightedGraph<int>& forest, HashSet<pair<int, int> >* cluster_pairs) const { CHECK_NOTNULL(cluster_pairs)->clear(); const HashSet<int>& vertices = forest.vertices(); @@ -541,9 +541,9 @@ void VisibilityBasedPreconditioner::ComputeClusterVisibility( // Construct a graph whose vertices are the clusters, and the edge // weights are the number of 3D points visible to cameras in both the // vertices. -Graph<int>* VisibilityBasedPreconditioner::CreateClusterGraph( +WeightedGraph<int>* VisibilityBasedPreconditioner::CreateClusterGraph( const vector<set<int> >& cluster_visibility) const { - Graph<int>* cluster_graph = new Graph<int>; + WeightedGraph<int>* cluster_graph = new WeightedGraph<int>; for (int i = 0; i < num_clusters_; ++i) { cluster_graph->AddVertex(i); diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h index 70cea83bf56..2f6922dce54 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h @@ -156,8 +156,9 @@ class VisibilityBasedPreconditioner : public BlockSparseMatrixPreconditioner { vector<int>* membership_vector) const; void ComputeClusterVisibility(const vector<set<int> >& visibility, vector<set<int> >* cluster_visibility) const; - Graph<int>* CreateClusterGraph(const vector<set<int> >& visibility) const; - void ForestToClusterPairs(const Graph<int>& forest, + WeightedGraph<int>* CreateClusterGraph( + const vector<set<int> >& visibility) const; + void ForestToClusterPairs(const WeightedGraph<int>& forest, HashSet<pair<int, int> >* cluster_pairs) const; void ComputeBlockPairsInPreconditioner(const CompressedRowBlockStructure& bs); bool IsBlockPairInPreconditioner(int block1, int block2) const; diff --git a/extern/lzo/minilzo/README.LZO b/extern/lzo/minilzo/README.LZO index 058eace70a0..83e10e352ff 100644 --- a/extern/lzo/minilzo/README.LZO +++ b/extern/lzo/minilzo/README.LZO @@ -6,8 +6,8 @@ Author : Markus Franz Xaver Johannes Oberhumer <markus@oberhumer.com> http://www.oberhumer.com/opensource/lzo/ - Version : 2.06 - Date : 12 Aug 2011 + Version : 2.08 + Date : 29 Jun 2014 I've created miniLZO for projects where it is inconvenient to include (or require) the full LZO source code just because you @@ -110,9 +110,8 @@ Appendix D: Copyright --------------------- - LZO and miniLZO are Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Markus Franz Xaver Oberhumer <markus@oberhumer.com>. + LZO and miniLZO are Copyright (C) 1996-2014 Markus Franz Xaver Oberhumer + All Rights Reserved. LZO and miniLZO are distributed under the terms of the GNU General Public License (GPL). See the file COPYING. diff --git a/extern/lzo/minilzo/lzoconf.h b/extern/lzo/minilzo/lzoconf.h index 23c6ca93fcc..61be29c5dc2 100644 --- a/extern/lzo/minilzo/lzoconf.h +++ b/extern/lzo/minilzo/lzoconf.h @@ -2,22 +2,7 @@ This file is part of the LZO real-time data compression library. - Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or @@ -44,9 +29,9 @@ #ifndef __LZOCONF_H_INCLUDED #define __LZOCONF_H_INCLUDED 1 -#define LZO_VERSION 0x2060 -#define LZO_VERSION_STRING "2.06" -#define LZO_VERSION_DATE "Aug 12 2011" +#define LZO_VERSION 0x2080 +#define LZO_VERSION_STRING "2.08" +#define LZO_VERSION_DATE "Jun 29 2014" /* internal Autoconf configuration file - only used when building LZO */ #if defined(LZO_HAVE_CONFIG_H) @@ -63,7 +48,7 @@ #if !defined(CHAR_BIT) || (CHAR_BIT != 8) # error "invalid CHAR_BIT" #endif -#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +#if !defined(UCHAR_MAX) || !defined(USHRT_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) # error "check your compiler installation" #endif #if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) @@ -85,14 +70,6 @@ extern "C" { // some core defines ************************************************************************/ -#if !defined(LZO_UINT32_C) -# if (UINT_MAX < LZO_0xffffffffL) -# define LZO_UINT32_C(c) c ## UL -# else -# define LZO_UINT32_C(c) ((c) + 0U) -# endif -#endif - /* memory checkers */ #if !defined(__LZO_CHECKER) # if defined(__BOUNDS_CHECKING_ON) @@ -111,28 +88,31 @@ extern "C" { // integral and pointer types ************************************************************************/ -/* lzo_uint should match size_t */ +/* lzo_uint must match size_t */ #if !defined(LZO_UINT_MAX) -# if defined(LZO_ABI_LLP64) /* WIN64 */ -# if defined(LZO_OS_WIN64) +# if (LZO_ABI_LLP64) +# if (LZO_OS_WIN64) typedef unsigned __int64 lzo_uint; typedef __int64 lzo_int; # else - typedef unsigned long long lzo_uint; - typedef long long lzo_int; + typedef lzo_ullong_t lzo_uint; + typedef lzo_llong_t lzo_int; # endif +# define LZO_SIZEOF_LZO_UINT 8 # define LZO_UINT_MAX 0xffffffffffffffffull # define LZO_INT_MAX 9223372036854775807LL # define LZO_INT_MIN (-1LL - LZO_INT_MAX) -# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */ +# elif (LZO_ABI_IP32L64) /* MIPS R5900 */ typedef unsigned int lzo_uint; typedef int lzo_int; +# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_INT # define LZO_UINT_MAX UINT_MAX # define LZO_INT_MAX INT_MAX # define LZO_INT_MIN INT_MIN # elif (ULONG_MAX >= LZO_0xffffffffL) typedef unsigned long lzo_uint; typedef long lzo_int; +# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LONG # define LZO_UINT_MAX ULONG_MAX # define LZO_INT_MAX LONG_MAX # define LZO_INT_MIN LONG_MIN @@ -141,63 +121,22 @@ extern "C" { # endif #endif -/* Integral types with 32 bits or more. */ -#if !defined(LZO_UINT32_MAX) -# if (UINT_MAX >= LZO_0xffffffffL) - typedef unsigned int lzo_uint32; - typedef int lzo_int32; -# define LZO_UINT32_MAX UINT_MAX -# define LZO_INT32_MAX INT_MAX -# define LZO_INT32_MIN INT_MIN -# elif (ULONG_MAX >= LZO_0xffffffffL) - typedef unsigned long lzo_uint32; - typedef long lzo_int32; -# define LZO_UINT32_MAX ULONG_MAX -# define LZO_INT32_MAX LONG_MAX -# define LZO_INT32_MIN LONG_MIN -# else -# error "lzo_uint32" -# endif -#endif - -/* Integral types with exactly 64 bits. */ -#if !defined(LZO_UINT64_MAX) -# if (LZO_UINT_MAX >= LZO_0xffffffffL) -# if ((((LZO_UINT_MAX) >> 31) >> 31) == 3) -# define lzo_uint64 lzo_uint -# define lzo_int64 lzo_int -# define LZO_UINT64_MAX LZO_UINT_MAX -# define LZO_INT64_MAX LZO_INT_MAX -# define LZO_INT64_MIN LZO_INT_MIN -# endif -# elif (ULONG_MAX >= LZO_0xffffffffL) -# if ((((ULONG_MAX) >> 31) >> 31) == 3) - typedef unsigned long lzo_uint64; - typedef long lzo_int64; -# define LZO_UINT64_MAX ULONG_MAX -# define LZO_INT64_MAX LONG_MAX -# define LZO_INT64_MIN LONG_MIN -# endif -# endif -#endif - -/* The larger type of lzo_uint and lzo_uint32. */ -#if (LZO_UINT_MAX >= LZO_UINT32_MAX) +/* The larger type of lzo_uint and lzo_uint32_t. */ +#if (LZO_SIZEOF_LZO_UINT >= 4) # define lzo_xint lzo_uint #else -# define lzo_xint lzo_uint32 +# define lzo_xint lzo_uint32_t #endif -/* Memory model that allows to access memory at offsets of lzo_uint. */ -#if !defined(__LZO_MMODEL) -# if (LZO_UINT_MAX <= UINT_MAX) -# define __LZO_MMODEL /*empty*/ -# elif defined(LZO_HAVE_MM_HUGE_PTR) -# define __LZO_MMODEL_HUGE 1 -# define __LZO_MMODEL __huge -# else -# define __LZO_MMODEL /*empty*/ -# endif +typedef int lzo_bool; + +/* sanity checks */ +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_UINT) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t)) + +#ifndef __LZO_MMODEL +#define __LZO_MMODEL /*empty*/ #endif /* no typedef here because of const-pointer issues */ @@ -206,21 +145,52 @@ extern "C" { #define lzo_voidp void __LZO_MMODEL * #define lzo_shortp short __LZO_MMODEL * #define lzo_ushortp unsigned short __LZO_MMODEL * -#define lzo_uint32p lzo_uint32 __LZO_MMODEL * -#define lzo_int32p lzo_int32 __LZO_MMODEL * -#if defined(LZO_UINT64_MAX) -#define lzo_uint64p lzo_uint64 __LZO_MMODEL * -#define lzo_int64p lzo_int64 __LZO_MMODEL * -#endif -#define lzo_uintp lzo_uint __LZO_MMODEL * #define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * #define lzo_xintp lzo_xint __LZO_MMODEL * #define lzo_voidpp lzo_voidp __LZO_MMODEL * #define lzo_bytepp lzo_bytep __LZO_MMODEL * -/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */ -#define lzo_byte unsigned char __LZO_MMODEL -typedef int lzo_bool; +#define lzo_int8_tp lzo_int8_t __LZO_MMODEL * +#define lzo_uint8_tp lzo_uint8_t __LZO_MMODEL * +#define lzo_int16_tp lzo_int16_t __LZO_MMODEL * +#define lzo_uint16_tp lzo_uint16_t __LZO_MMODEL * +#define lzo_int32_tp lzo_int32_t __LZO_MMODEL * +#define lzo_uint32_tp lzo_uint32_t __LZO_MMODEL * +#if defined(lzo_int64_t) +#define lzo_int64_tp lzo_int64_t __LZO_MMODEL * +#define lzo_uint64_tp lzo_uint64_t __LZO_MMODEL * +#endif + +/* Older LZO versions used to support ancient systems and memory models + * like 16-bit MSDOS with __huge pointers and Cray PVP, but these + * obsolete configurations are not supported any longer. + */ +#if defined(__LZO_MMODEL_HUGE) +#error "__LZO_MMODEL_HUGE is unsupported" +#endif +#if (LZO_MM_PVP) +#error "LZO_MM_PVP is unsupported" +#endif +#if (LZO_SIZEOF_INT < 4) +#error "LZO_SIZEOF_INT < 4 is unsupported" +#endif +#if (__LZO_UINTPTR_T_IS_POINTER) +#error "__LZO_UINTPTR_T_IS_POINTER is unsupported" +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) >= 4) +/* Strange configurations where sizeof(lzo_uint) != sizeof(size_t) should + * work but have not received much testing lately, so be strict here. + */ +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(size_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(ptrdiff_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_voidp)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep)) /*********************************************************************** @@ -315,7 +285,7 @@ struct lzo_callback_t /* a progress indicator callback function (set to 0 to disable) */ lzo_progress_func_t nprogress; - /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress + /* INFO: the first parameter "self" of the nalloc/nfree/nprogress * callbacks points back to this struct, so you are free to store * some extra info in the following variables. */ lzo_voidp user1; @@ -343,6 +313,9 @@ struct lzo_callback_t #define LZO_E_INPUT_NOT_CONSUMED (-8) #define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ #define LZO_E_INVALID_ARGUMENT (-10) +#define LZO_E_INVALID_ALIGNMENT (-11) /* pointer argument is not properly aligned */ +#define LZO_E_OUTPUT_NOT_CONSUMED (-12) +#define LZO_E_INTERNAL_ERROR (-99) #ifndef lzo_sizeof_dict_t @@ -356,7 +329,7 @@ struct lzo_callback_t * compiler's view of various types are consistent. */ #define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ - (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)sizeof(long),(int)sizeof(lzo_uint32_t),(int)sizeof(lzo_uint),\ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ (int)sizeof(lzo_callback_t)) LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); @@ -379,18 +352,22 @@ LZO_EXTERN(lzo_voidp) lzo_memset(lzo_voidp buf, int c, lzo_uint len); /* checksum functions */ -LZO_EXTERN(lzo_uint32) - lzo_adler32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len); -LZO_EXTERN(lzo_uint32) - lzo_crc32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len); -LZO_EXTERN(const lzo_uint32p) +LZO_EXTERN(lzo_uint32_t) + lzo_adler32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); +LZO_EXTERN(lzo_uint32_t) + lzo_crc32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); +LZO_EXTERN(const lzo_uint32_tp) lzo_get_crc32_table(void); /* misc. */ LZO_EXTERN(int) _lzo_config_check(void); -typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; -typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; -typedef union { void *vp; lzo_bytep bp; lzo_uint u; lzo_uint32 u32; unsigned long l; } lzo_align_t; +typedef union { + lzo_voidp a00; lzo_bytep a01; lzo_uint a02; lzo_xint a03; lzo_uintptr_t a04; + void *a05; unsigned char *a06; unsigned long a07; size_t a08; ptrdiff_t a09; +#if defined(lzo_int64_t) + lzo_uint64_t a10; +#endif +} lzo_align_t; /* align a char pointer on a boundary that is a multiple of 'size' */ LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size); @@ -399,9 +376,30 @@ LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size); /*********************************************************************** -// deprecated macros - only for backward compatibility with LZO v1.xx +// deprecated macros - only for backward compatibility ************************************************************************/ +/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */ +#define lzo_byte unsigned char +/* deprecated type names */ +#define lzo_int32 lzo_int32_t +#define lzo_uint32 lzo_uint32_t +#define lzo_int32p lzo_int32_t __LZO_MMODEL * +#define lzo_uint32p lzo_uint32_t __LZO_MMODEL * +#define LZO_INT32_MAX LZO_INT32_C(2147483647) +#define LZO_UINT32_MAX LZO_UINT32_C(4294967295) +#if defined(lzo_int64_t) +#define lzo_int64 lzo_int64_t +#define lzo_uint64 lzo_uint64_t +#define lzo_int64p lzo_int64_t __LZO_MMODEL * +#define lzo_uint64p lzo_uint64_t __LZO_MMODEL * +#define LZO_INT64_MAX LZO_INT64_C(9223372036854775807) +#define LZO_UINT64_MAX LZO_UINT64_C(18446744073709551615) +#endif +/* deprecated types */ +typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u; +typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u; + #if defined(LZO_CFG_COMPAT) #define __LZOCONF_H 1 @@ -443,4 +441,4 @@ LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size); #endif /* already included */ -/* vim:set ts=4 et: */ +/* vim:set ts=4 sw=4 et: */ diff --git a/extern/lzo/minilzo/lzodefs.h b/extern/lzo/minilzo/lzodefs.h index 0e40e332a8d..f4ae9487ebe 100644 --- a/extern/lzo/minilzo/lzodefs.h +++ b/extern/lzo/minilzo/lzodefs.h @@ -2,22 +2,7 @@ This file is part of the LZO real-time data compression library. - Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or @@ -47,12 +32,6 @@ #if defined(__CYGWIN32__) && !defined(__CYGWIN__) # define __CYGWIN__ __CYGWIN32__ #endif -#if defined(__IBMCPP__) && !defined(__IBMC__) -# define __IBMC__ __IBMCPP__ -#endif -#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) -# define __INTEL_COMPILER __ICL -#endif #if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) # define _ALL_SOURCE 1 #endif @@ -61,19 +40,30 @@ # define __LONG_MAX__ 9223372036854775807L # endif #endif -#if defined(__INTEL_COMPILER) && defined(__linux__) +#if !defined(LZO_CFG_NO_DISABLE_WUNDEF) +#if defined(__ARMCC_VERSION) +# pragma diag_suppress 193 +#elif defined(__clang__) && defined(__clang_minor__) +# pragma clang diagnostic ignored "-Wundef" +#elif defined(__INTEL_COMPILER) # pragma warning(disable: 193) -#endif -#if defined(__KEIL__) && defined(__C166__) -# pragma warning disable = 322 -#elif 0 && defined(__C251__) +#elif defined(__KEIL__) && defined(__C166__) # pragma warning disable = 322 -#endif -#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) -# if (_MSC_VER >= 1300) +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) +# if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) +# pragma GCC diagnostic ignored "-Wundef" +# endif +#elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if ((_MSC_VER-0) >= 1300) # pragma warning(disable: 4668) # endif #endif +#endif +#if 0 && defined(__POCC__) && defined(_WIN32) +# if (__POCC__ >= 400) +# pragma warn(disable: 2216) +# endif +#endif #if 0 && defined(__WATCOMC__) # if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) # pragma warning 203 9 @@ -82,13 +72,29 @@ #if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) # pragma option -h #endif +#if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#ifndef _CRT_NONSTDC_NO_WARNINGS +#define _CRT_NONSTDC_NO_WARNINGS 1 +#endif +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#endif #if 0 -#define LZO_0xffffL 0xfffful -#define LZO_0xffffffffL 0xfffffffful +#define LZO_0xffffUL 0xfffful +#define LZO_0xffffffffUL 0xfffffffful #else -#define LZO_0xffffL 65535ul -#define LZO_0xffffffffL 4294967295ul +#define LZO_0xffffUL 65535ul +#define LZO_0xffffffffUL 4294967295ul #endif +#define LZO_0xffffL LZO_0xffffUL +#define LZO_0xffffffffL LZO_0xffffffffUL #if (LZO_0xffffL == LZO_0xffffffffL) # error "your preprocessor is broken 1" #endif @@ -103,6 +109,13 @@ # error "your preprocessor is broken 4" #endif #endif +#if defined(__COUNTER__) +# ifndef LZO_CFG_USE_COUNTER +# define LZO_CFG_USE_COUNTER 1 +# endif +#else +# undef LZO_CFG_USE_COUNTER +#endif #if (UINT_MAX == LZO_0xffffL) #if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) # if !defined(MSDOS) @@ -233,14 +246,31 @@ #endif #define LZO_PP_STRINGIZE(x) #x #define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT0() /*empty*/ +#define LZO_PP_CONCAT1(a) a #define LZO_PP_CONCAT2(a,b) a ## b #define LZO_PP_CONCAT3(a,b,c) a ## b ## c #define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() +#define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) #define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) #define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) #define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) #define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) +#define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) +#define LZO_PP_EMPTY /*empty*/ +#define LZO_PP_EMPTY0() /*empty*/ +#define LZO_PP_EMPTY1(a) /*empty*/ +#define LZO_PP_EMPTY2(a,b) /*empty*/ +#define LZO_PP_EMPTY3(a,b,c) /*empty*/ +#define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ +#define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ +#define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ +#define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ #if 1 #define LZO_CPP_STRINGIZE(x) #x #define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) @@ -248,12 +278,16 @@ #define LZO_CPP_CONCAT3(a,b,c) a ## b ## c #define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g #define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) #define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) #define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) #define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) +#define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) #endif -#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-!!(b))) - (o)) << 1) + (o)*!!(b)) #if 1 && defined(__cplusplus) # if !defined(__STDC_CONSTANT_MACROS) # define __STDC_CONSTANT_MACROS 1 @@ -263,9 +297,13 @@ # endif #endif #if defined(__cplusplus) -# define LZO_EXTERN_C extern "C" +# define LZO_EXTERN_C extern "C" +# define LZO_EXTERN_C_BEGIN extern "C" { +# define LZO_EXTERN_C_END } #else -# define LZO_EXTERN_C extern +# define LZO_EXTERN_C extern +# define LZO_EXTERN_C_BEGIN /*empty*/ +# define LZO_EXTERN_C_END /*empty*/ #endif #if !defined(__LZO_OS_OVERRIDE) #if (LZO_OS_FREESTANDING) @@ -366,12 +404,12 @@ #elif defined(__VMS) # define LZO_OS_VMS 1 # define LZO_INFO_OS "vms" -#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +#elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PS2 1 # define LZO_INFO_OS "console" # define LZO_INFO_OS_CONSOLE "ps2" -#elif (defined(__mips__) && defined(__psp__)) +#elif defined(__mips__) && defined(__psp__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PSP 1 # define LZO_INFO_OS "console" @@ -399,9 +437,18 @@ # elif defined(__linux__) || defined(__linux) || defined(__LINUX__) # define LZO_OS_POSIX_LINUX 1 # define LZO_INFO_OS_POSIX "linux" -# elif defined(__APPLE__) || defined(__MACOS__) -# define LZO_OS_POSIX_MACOSX 1 -# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__APPLE__) && defined(__MACH__) +# if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) +# define LZO_OS_POSIX_DARWIN 1040 +# define LZO_INFO_OS_POSIX "darwin_iphone" +# elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) +# define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +# define LZO_INFO_OS_POSIX "darwin" +# else +# define LZO_OS_POSIX_DARWIN 1 +# define LZO_INFO_OS_POSIX "darwin" +# endif +# define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN # elif defined(__minix__) || defined(__minix) # define LZO_OS_POSIX_MINIX 1 # define LZO_INFO_OS_POSIX "minix" @@ -436,18 +483,18 @@ #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) # if (UINT_MAX != LZO_0xffffffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif #endif #if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) @@ -463,59 +510,65 @@ # define LZO_INFO_CC "sdcc" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) #elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) -# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) # define LZO_INFO_CC "Pathscale C" # define LZO_INFO_CCVER __PATHSCALE__ -#elif defined(__INTEL_COMPILER) -# define LZO_CC_INTELC 1 +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) +# define LZO_CC_INTELC __INTEL_COMPILER # define LZO_INFO_CC "Intel C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) -# if defined(_WIN32) || defined(_WIN64) -# define LZO_CC_SYNTAX_MSC 1 -# else -# define LZO_CC_SYNTAX_GNUC 1 +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_INTELC_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__POCC__) && defined(_WIN32) # define LZO_CC_PELLESC 1 # define LZO_INFO_CC "Pelles C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) -#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +#elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) -# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else -# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) # if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) -# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__) +# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) # else -# define LZO_CC_CLANG_CLANG 0x010000L +# define LZO_CC_CLANG 0x010000L +# endif +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_CLANG_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif -# define LZO_CC_CLANG LZO_CC_CLANG_GNUC # define LZO_INFO_CC "clang" # define LZO_INFO_CCVER __VERSION__ #elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) -# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else -# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif # define LZO_CC_LLVM LZO_CC_LLVM_GNUC # define LZO_INFO_CC "llvm-gcc" # define LZO_INFO_CCVER __VERSION__ -#elif defined(__GNUC__) && defined(__VERSION__) -# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) -# elif defined(__GNUC_MINOR__) -# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) -# else -# define LZO_CC_GNUC (__GNUC__ * 0x10000L) -# endif -# define LZO_INFO_CC "gcc" -# define LZO_INFO_CCVER __VERSION__ #elif defined(__ACK__) && defined(_ACK) # define LZO_CC_ACK 1 # define LZO_INFO_CC "Amsterdam Compiler Kit C" # define LZO_INFO_CCVER "unknown" +#elif defined(__ARMCC_VERSION) && !defined(__GNUC__) +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) #elif defined(__AZTEC_C__) # define LZO_CC_AZTECC 1 # define LZO_INFO_CC "Aztec C" @@ -540,10 +593,23 @@ # define LZO_CC_DECC 1 # define LZO_INFO_CC "DEC C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) +# define LZO_CC_GHS 1 +# define LZO_INFO_CC "Green Hills C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_GHS_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif #elif defined(__HIGHC__) # define LZO_CC_HIGHC 1 # define LZO_INFO_CC "MetaWare High C" # define LZO_INFO_CCVER "unknown" +#elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) +# define LZO_CC_HPACC __HP_aCC +# define LZO_INFO_CC "HP aCC" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) #elif defined(__IAR_SYSTEMS_ICC__) # define LZO_CC_IARC 1 # define LZO_INFO_CC "IAR C" @@ -552,10 +618,14 @@ # else # define LZO_INFO_CCVER "unknown" # endif -#elif defined(__IBMC__) -# define LZO_CC_IBMC 1 +#elif defined(__IBMC__) && ((__IBMC__-0) > 0) +# define LZO_CC_IBMC __IBMC__ # define LZO_INFO_CC "IBM C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) +# define LZO_CC_IBMC __IBMCPP__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) #elif defined(__KEIL__) && defined(__C166__) # define LZO_CC_KEILC 1 # define LZO_INFO_CC "Keil C" @@ -572,16 +642,8 @@ # else # define LZO_INFO_CCVER "unknown" # endif -#elif defined(_MSC_VER) -# define LZO_CC_MSC 1 -# define LZO_INFO_CC "Microsoft C" -# if defined(_MSC_FULL_VER) -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) -# else -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) -# endif -#elif defined(__MWERKS__) -# define LZO_CC_MWERKS 1 +#elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) +# define LZO_CC_MWERKS __MWERKS__ # define LZO_INFO_CC "Metrowerks C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) #elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) @@ -592,6 +654,15 @@ # define LZO_CC_PACIFICC 1 # define LZO_INFO_CC "Pacific C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) +# else +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" +# endif +# define LZO_INFO_CC "Portland Group PGI C" #elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) # define LZO_CC_PGI 1 # define LZO_INFO_CC "Portland Group PGI C" @@ -606,7 +677,7 @@ # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) #elif defined(__SUNPRO_C) # define LZO_INFO_CC "SunPro C" -# if ((__SUNPRO_C)+0 > 0) +# if ((__SUNPRO_C-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_C # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) # else @@ -615,7 +686,7 @@ # endif #elif defined(__SUNPRO_CC) # define LZO_INFO_CC "SunPro C" -# if ((__SUNPRO_CC)+0 > 0) +# if ((__SUNPRO_CC-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_CC # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) # else @@ -641,16 +712,46 @@ #elif defined(__ZTC__) # define LZO_CC_ZORTECHC 1 # define LZO_INFO_CC "Zortech C" -# if (__ZTC__ == 0x310) +# if ((__ZTC__-0) == 0x310) # define LZO_INFO_CCVER "0x310" # else # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) # endif +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_MSC _MSC_VER +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif #else # define LZO_CC_UNKNOWN 1 # define LZO_INFO_CC "unknown" # define LZO_INFO_CCVER "unknown" #endif +#if (LZO_CC_GNUC) && defined(__OPEN64__) +# if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) +# define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) +# define LZO_CC_OPEN64_GNUC LZO_CC_GNUC +# endif +#endif +#if (LZO_CC_GNUC) && defined(__PCC__) +# if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) +# define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) +# define LZO_CC_PCC_GNUC LZO_CC_GNUC +# endif +#endif #if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) # error "LZO_CC_MSC: _MSC_FULL_VER is not defined" #endif @@ -668,8 +769,10 @@ # define LZO_INFO_ARCH "generic" #elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086 1 -# define LZO_ARCH_IA16 1 # define LZO_INFO_ARCH "i086" +#elif defined(__aarch64__) +# define LZO_ARCH_ARM64 1 +# define LZO_INFO_ARCH "arm64" #elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) # define LZO_ARCH_ALPHA 1 # define LZO_INFO_ARCH "alpha" @@ -685,10 +788,10 @@ # define LZO_INFO_ARCH "arm_thumb" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) # define LZO_ARCH_ARM 1 -# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) +# if defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 1) # define LZO_ARCH_ARM_THUMB 1 # define LZO_INFO_ARCH "arm_thumb" -# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) +# elif defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 2) # define LZO_INFO_ARCH "arm" # else # define LZO_INFO_ARCH "arm" @@ -806,53 +909,147 @@ # error "FIXME - missing define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) -# error "FIXME - missing WIN32 define for CPU architecture" +# error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) -# error "FIXME - missing WIN64 define for CPU architecture" +# error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" #endif #if (LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 #elif 1 && (LZO_OS_DOS16 && defined(BLX286)) # define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 #elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) # define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 #elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) # define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 #endif -#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM) -# error "this should not happen" +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) +# define LZO_ARCH_X64 1 +#elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_AMD64 1 #endif -#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086) -# error "this should not happen" +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) +# define LZO_ARCH_AARCH64 1 +#elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_ARM64 1 +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) +# define LZO_ARCH_X86 1 +#elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_I386 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM_THUMB) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM_THUMB) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086PM && !LZO_ARCH_I086) +# error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I086) # if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_ARCH_I386) # if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif # if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if !defined(LZO_TARGET_FEATURE_SSE2) +# if defined(__SSE2__) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif defined(_MSC_VER) && ((defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) || defined(_M_AMD64)) +# define LZO_TARGET_FEATURE_SSE2 1 +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSSE3) +# if (LZO_TARGET_FEATURE_SSE2) +# if defined(__SSSE3__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# elif defined(_MSC_VER) && defined(__AVX__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSE4_2) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__SSE4_2__) +# define LZO_TARGET_FEATURE_SSE4_2 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__AVX__) +# define LZO_TARGET_FEATURE_AVX 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX2) +# if (LZO_TARGET_FEATURE_AVX) +# if defined(__AVX2__) +# define LZO_TARGET_FEATURE_AVX2 1 +# endif +# endif # endif #endif -#if !defined(__LZO_MM_OVERRIDE) +#if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if defined(__ARM_NEON__) +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if 1 +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#endif +#if 0 +#elif !defined(__LZO_MM_OVERRIDE) #if (LZO_ARCH_I086) #if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" #endif #if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) # define LZO_MM_TINY 1 @@ -879,7 +1076,7 @@ #elif (LZO_CC_ZORTECHC && defined(__VCM__)) # define LZO_MM_LARGE 1 #else -# error "unknown memory model" +# error "unknown LZO_ARCH_I086 memory model" #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) #define LZO_HAVE_MM_HUGE_PTR 1 @@ -902,10 +1099,10 @@ #endif #if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) # if (LZO_OS_DOS16) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # elif (LZO_CC_ZORTECHC) # else -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif #endif #ifdef __cplusplus @@ -937,7 +1134,7 @@ extern "C" { #endif #elif (LZO_ARCH_C166) #if !defined(__MODEL__) -# error "FIXME - C166 __MODEL__" +# error "FIXME - LZO_ARCH_C166 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 1) @@ -951,11 +1148,11 @@ extern "C" { #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else -# error "FIXME - C166 __MODEL__" +# error "FIXME - LZO_ARCH_C166 __MODEL__" #endif #elif (LZO_ARCH_MCS251) #if !defined(__MODEL__) -# error "FIXME - MCS251 __MODEL__" +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) @@ -967,11 +1164,11 @@ extern "C" { #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else -# error "FIXME - MCS251 __MODEL__" +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" #endif #elif (LZO_ARCH_MCS51) #if !defined(__MODEL__) -# error "FIXME - MCS51 __MODEL__" +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" #elif ((__MODEL__) == 1) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) @@ -983,7 +1180,7 @@ extern "C" { #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else -# error "FIXME - MCS51 __MODEL__" +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" #endif #elif (LZO_ARCH_CRAY_PVP) # define LZO_MM_PVP 1 @@ -1010,35 +1207,818 @@ extern "C" { # error "unknown memory model" #endif #endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_gnuc_extension__ __extension__ +#else +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# else +# define LZO_CFG_USE_NEW_STYLE_CASTS 1 +# endif +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(__cplusplus) +# if defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# undef LZO_CFG_USE_NEW_STYLE_CASTS +# endif +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(LZO_REINTERPRET_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast<t> (e)) +# endif +#endif +#if !defined(LZO_REINTERPRET_CAST) +# define LZO_REINTERPRET_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_STATIC_CAST(t,e) (static_cast<t> (e)) +# endif +#endif +#if !defined(LZO_STATIC_CAST) +# define LZO_STATIC_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST2) +# define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) +#endif +#if !defined(LZO_UNCONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_PCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_PCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_PCAST) +# define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) +#endif +#if !defined(LZO_CCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_CCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_CCAST) +# define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) +#endif +#if !defined(LZO_ICONV) +# define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ICAST) +# define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ITRUNC) +# define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(__lzo_cte) +# if (LZO_CC_MSC || LZO_CC_WATCOMC) +# define __lzo_cte(e) ((void)0,(e)) +# elif 1 +# define __lzo_cte(e) ((void)0,(e)) +# endif +#endif +#if !defined(__lzo_cte) +# define __lzo_cte(e) (e) +#endif +#if !defined(LZO_BLOCK_BEGIN) +# define LZO_BLOCK_BEGIN do { +# define LZO_BLOCK_END } while __lzo_cte(0) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {LZO_EXTERN_C int lzo_unused__[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {LZO_EXTERN_C int lzo_unused_func__[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_CLANG >= 0x020800ul) +# define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) +# elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_GHS) +# define __lzo_inline __inline__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_inline __inline__ +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_inline __inline__ +#endif +#endif +#if defined(__lzo_inline) +# ifndef __lzo_HAVE_inline +# define __lzo_HAVE_inline 1 +# endif +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# ifndef __lzo_HAVE_forceinline +# define __lzo_HAVE_forceinline 1 +# endif +#else +# define __lzo_forceinline __lzo_inline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# ifndef __lzo_HAVE_noinline +# define __lzo_HAVE_noinline 1 +# endif +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_static_inline) +#if (LZO_CC_IBMC) +# define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline +#endif +#endif +#if !defined(__lzo_static_inline) +# define __lzo_static_inline static __lzo_inline +#endif +#if !defined(__lzo_static_forceinline) +#if (LZO_CC_IBMC) +# define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline +#endif +#endif +#if !defined(__lzo_static_forceinline) +# define __lzo_static_forceinline static __lzo_forceinline +#endif +#if !defined(__lzo_static_noinline) +#if (LZO_CC_IBMC) +# define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline +#endif +#endif +#if !defined(__lzo_static_noinline) +# define __lzo_static_noinline static __lzo_noinline +#endif +#if !defined(__lzo_c99_extern_inline) +#if defined(__GNUC_GNU_INLINE__) +# define __lzo_c99_extern_inline __lzo_inline +#elif defined(__GNUC_STDC_INLINE__) +# define __lzo_c99_extern_inline extern __lzo_inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_c99_extern_inline extern __lzo_inline +#endif +#if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) +# define __lzo_c99_extern_inline __lzo_inline +#endif +#endif +#if defined(__lzo_c99_extern_inline) +# ifndef __lzo_HAVE_c99_extern_inline +# define __lzo_HAVE_c99_extern_inline 1 +# endif +#else +# define __lzo_c99_extern_inline /*empty*/ +#endif +#if !defined(__lzo_may_alias) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_CLANG >= 0x020900ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#endif +#endif +#if defined(__lzo_may_alias) +# ifndef __lzo_HAVE_may_alias +# define __lzo_HAVE_may_alias 1 +# endif +#else +# define __lzo_may_alias /*empty*/ +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#endif +#endif +#if defined(__lzo_noreturn) +# ifndef __lzo_HAVE_noreturn +# define __lzo_HAVE_noreturn 1 +# endif +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# ifndef __lzo_HAVE_nothrow +# define __lzo_HAVE_nothrow 1 +# endif +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 1210) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_restrict __restrict__ +#endif +#endif +#if defined(__lzo_restrict) +# ifndef __lzo_HAVE_restrict +# define __lzo_HAVE_restrict 1 +# endif +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_GHS) && !defined(__cplusplus) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_IBMC >= 600) +# define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# ifndef __lzo_HAVE_alignof +# define __lzo_HAVE_alignof 1 +# endif +#endif +#if !defined(__lzo_struct_packed) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { +# define __lzo_struct_packed_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_struct_packed(s) _Packed struct s { +# define __lzo_struct_packed_end() }; +#endif +#endif +#if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) +# define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) +#endif +#if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) +# define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() +#endif +#if !defined(__lzo_byte_struct) +#if defined(__lzo_struct_packed) +# define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() +# define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); +# define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); +#endif +#endif +#if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) +# define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) +#endif +#if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) +#if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) +#elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_CILLY || LZO_CC_PCC) +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_align16(s) struct __declspec(align(16)) s { +# define __lzo_struct_align16_end() }; +# define __lzo_struct_align32(s) struct __declspec(align(32)) s { +# define __lzo_struct_align32_end() }; +# define __lzo_struct_align64(s) struct __declspec(align(64)) s { +# define __lzo_struct_align64_end() }; +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_struct_align16(s) struct s { +# define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); +# define __lzo_struct_align32(s) struct s { +# define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); +# define __lzo_struct_align64(s) struct s { +# define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); +#endif +#endif +#if !defined(__lzo_union_um) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_union_am(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_union_um(s) __pragma(pack(push,1)) union s { +# define __lzo_union_um_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_union_um(s) _Packed union s { +# define __lzo_union_um_end() }; +#endif +#endif +#if !defined(__lzo_union_am) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() }; +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# ifndef __lzo_HAVE_constructor +# define __lzo_HAVE_constructor 1 +# endif +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# ifndef __lzo_HAVE_destructor +# define __lzo_HAVE_destructor 1 +# endif +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_IBMC >= 1010) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# ifndef __lzo_HAVE_likely +# define __lzo_HAVE_likely 1 +# endif +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# ifndef __lzo_HAVE_unlikely +# define __lzo_HAVE_unlikely 1 +# endif +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(__lzo_static_unused_void_func) +# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_static_unused_void_func(f) static void __attribute__((__unused__)) f(void) +# else +# define __lzo_static_unused_void_func(f) static __lzo_inline void f(void) +# endif +#endif +#if !defined(__lzo_loop_forever) +# if (LZO_CC_IBMC) +# define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END +# else +# define __lzo_loop_forever() do { ; } while __lzo_cte(1) +# endif +#endif +#if !defined(__lzo_unreachable) +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_GNUC >= 0x040500ul) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 +# define __lzo_unreachable() __builtin_unreachable(); +#endif +#endif +#if defined(__lzo_unreachable) +# ifndef __lzo_HAVE_unreachable +# define __lzo_HAVE_unreachable 1 +# endif +#else +# if 0 +# define __lzo_unreachable() ((void)0); +# else +# define __lzo_unreachable() __lzo_loop_forever(); +# endif +#endif +#ifndef __LZO_CTA_NAME +#if (LZO_CFG_USE_COUNTER) +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) +#else +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) +#endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} +# elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} +# elif (LZO_CC_GNUC >= 0x040700ul) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) +#if defined(__cplusplus) +extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if !defined(LZO_HAVE_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#endif +#ifndef LZO_SIZEOF_SHORT #if defined(SIZEOF_SHORT) # define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#elif defined(__SIZEOF_SHORT__) +# define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) +#endif #endif +#ifndef LZO_SIZEOF_INT #if defined(SIZEOF_INT) # define LZO_SIZEOF_INT (SIZEOF_INT) +#elif defined(__SIZEOF_INT__) +# define LZO_SIZEOF_INT (__SIZEOF_INT__) #endif +#endif +#ifndef LZO_SIZEOF_LONG #if defined(SIZEOF_LONG) # define LZO_SIZEOF_LONG (SIZEOF_LONG) +#elif defined(__SIZEOF_LONG__) +# define LZO_SIZEOF_LONG (__SIZEOF_LONG__) +#endif #endif +#ifndef LZO_SIZEOF_LONG_LONG #if defined(SIZEOF_LONG_LONG) # define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#elif defined(__SIZEOF_LONG_LONG__) +# define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) #endif +#endif +#ifndef LZO_SIZEOF___INT16 #if defined(SIZEOF___INT16) # define LZO_SIZEOF___INT16 (SIZEOF___INT16) #endif +#endif +#ifndef LZO_SIZEOF___INT32 #if defined(SIZEOF___INT32) # define LZO_SIZEOF___INT32 (SIZEOF___INT32) #endif +#endif +#ifndef LZO_SIZEOF___INT64 #if defined(SIZEOF___INT64) # define LZO_SIZEOF___INT64 (SIZEOF___INT64) #endif +#endif +#ifndef LZO_SIZEOF_VOID_P #if defined(SIZEOF_VOID_P) # define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#elif defined(__SIZEOF_POINTER__) +# define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) #endif +#endif +#ifndef LZO_SIZEOF_SIZE_T #if defined(SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#elif defined(__SIZEOF_SIZE_T__) +# define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) +#endif #endif +#ifndef LZO_SIZEOF_PTRDIFF_T #if defined(SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#elif defined(__SIZEOF_PTRDIFF_T__) +# define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) +#endif #endif #define __LZO_LSR(x,b) (((x)+0ul) >> (b)) #if !defined(LZO_SIZEOF_SHORT) @@ -1060,6 +2040,7 @@ extern "C" { # error "LZO_SIZEOF_SHORT" # endif #endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) #if !defined(LZO_SIZEOF_INT) # if (LZO_ARCH_CRAY_PVP) # define LZO_SIZEOF_INT 8 @@ -1081,6 +2062,7 @@ extern "C" { # error "LZO_SIZEOF_INT" # endif #endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) #if !defined(LZO_SIZEOF_LONG) # if (ULONG_MAX == LZO_0xffffffffL) # define LZO_SIZEOF_LONG 4 @@ -1090,6 +2072,8 @@ extern "C" { # define LZO_SIZEOF_LONG 2 # elif (__LZO_LSR(ULONG_MAX,31) == 1) # define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,39) == 1) +# define LZO_SIZEOF_LONG 5 # elif (__LZO_LSR(ULONG_MAX,63) == 1) # define LZO_SIZEOF_LONG 8 # elif (__LZO_LSR(ULONG_MAX,127) == 1) @@ -1098,11 +2082,12 @@ extern "C" { # error "LZO_SIZEOF_LONG" # endif #endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) #if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) #if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) # if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) # if (LZO_CC_GNUC >= 0x030300ul) -# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) # define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG # elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) # define LZO_SIZEOF_LONG_LONG 4 @@ -1116,7 +2101,7 @@ extern "C" { #if (LZO_ARCH_I086 && LZO_CC_DMC) #elif (LZO_CC_CILLY) && defined(__GNUC__) # define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_SIZEOF_LONG_LONG 8 #elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) # define LZO_SIZEOF_LONG_LONG 8 @@ -1138,11 +2123,13 @@ extern "C" { # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) # define LZO_SIZEOF___INT64 8 -#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +#elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) # define LZO_SIZEOF___INT64 8 #elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) # define LZO_SIZEOF_LONG_LONG 8 -#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +#elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) #elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) @@ -1155,87 +2142,127 @@ extern "C" { # undef LZO_SIZEOF_LONG_LONG # endif #endif -#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +#if (LZO_CFG_NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(_NO_LONGLONG) # undef LZO_SIZEOF_LONG_LONG #endif -#if !defined(LZO_SIZEOF_VOID_P) -#if (LZO_ARCH_I086) -# define __LZO_WORDSIZE 2 -# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) -# define LZO_SIZEOF_VOID_P 2 -# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) -# define LZO_SIZEOF_VOID_P 4 +#if !defined(LZO_WORDSIZE) +#if (LZO_ARCH_ALPHA) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AMD64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AVR) +# define LZO_WORDSIZE 1 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define LZO_WORDSIZE 4 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_WORDSIZE 4 # else -# error "LZO_MM" +# define LZO_WORDSIZE 2 # endif -#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) -# define __LZO_WORDSIZE 1 +#elif (LZO_ARCH_I086) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_IA64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_M16C) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_SPU) +# define LZO_WORDSIZE 4 +#elif (LZO_ARCH_Z80) +# define LZO_WORDSIZE 1 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_WORDSIZE 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define LZO_WORDSIZE 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_WORDSIZE 8 +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LP64__) || defined(__LP64) || defined(_LP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_ARCH_AVR) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_H8300) # if defined(__NORMAL_MODE__) -# define __LZO_WORDSIZE 4 # define LZO_SIZEOF_VOID_P 2 # elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) -# define __LZO_WORDSIZE 4 # define LZO_SIZEOF_VOID_P 4 # else -# define __LZO_WORDSIZE 2 # define LZO_SIZEOF_VOID_P 2 # endif # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT # endif +#elif (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif #elif (LZO_ARCH_M16C) -# define __LZO_WORDSIZE 2 # if defined(__m32c_cpu__) || defined(__m32cm_cpu__) # define LZO_SIZEOF_VOID_P 4 # else # define LZO_SIZEOF_VOID_P 2 # endif +#elif (LZO_ARCH_SPU) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_ARCH_Z80) +# define LZO_SIZEOF_VOID_P 2 #elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) -# define __LZO_WORDSIZE 8 # define LZO_SIZEOF_VOID_P 4 -#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) -# define __LZO_WORDSIZE 8 -# define LZO_SIZEOF_VOID_P 8 -#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) -# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG #elif (LZO_OS_OS400 || defined(__OS400__)) -# define __LZO_WORDSIZE LZO_SIZEOF_LONG -# define LZO_SIZEOF_VOID_P 16 -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# if defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# else +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# endif #elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) # define LZO_SIZEOF_VOID_P 8 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -#elif (LZO_ARCH_SPU) -# if 0 -# define __LZO_WORDSIZE 16 -# endif -# define LZO_SIZEOF_VOID_P 4 -#else -# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG #endif #endif -#if !defined(LZO_WORDSIZE) -# if defined(__LZO_WORDSIZE) -# define LZO_WORDSIZE __LZO_WORDSIZE -# else -# define LZO_WORDSIZE LZO_SIZEOF_VOID_P -# endif +#if !defined(LZO_SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG #endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) #if !defined(LZO_SIZEOF_SIZE_T) #if (LZO_ARCH_I086 || LZO_ARCH_M16C) # define LZO_SIZEOF_SIZE_T 2 -#else +#endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P #endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) #endif #if !defined(LZO_SIZEOF_PTRDIFF_T) #if (LZO_ARCH_I086) @@ -1248,11 +2275,18 @@ extern "C" { # define LZO_SIZEOF_PTRDIFF_T 2 # endif # else -# error "LZO_MM" +# error "invalid LZO_ARCH_I086 memory model" # endif -#else +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T #endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) +#endif +#if !defined(LZO_WORDSIZE) +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P #endif #if (LZO_ABI_NEUTRAL_ENDIAN) # undef LZO_ABI_BIG_ENDIAN @@ -1264,7 +2298,7 @@ extern "C" { # define LZO_ABI_LITTLE_ENDIAN 1 #elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) # define LZO_ABI_LITTLE_ENDIAN 1 -#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390) +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) # if (__LITTLE_ENDIAN__ == 1) @@ -1280,6 +2314,19 @@ extern "C" { # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) # define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) +# if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +# elif defined(__BIG_ENDIAN) +# define LZO_ABI_BIG_ENDIAN 1 +# else +# define LZO_ABI_LITTLE_ENDIAN 1 +# endif +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) +# define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) @@ -1287,7 +2334,7 @@ extern "C" { #endif #endif #if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" #endif #if (LZO_ABI_BIG_ENDIAN) # define LZO_INFO_ABI_ENDIAN "be" @@ -1302,6 +2349,9 @@ extern "C" { #elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) # define LZO_ABI_ILP16 1 # define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_LP32 1 +# define LZO_INFO_ABI_PM "lp32" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_ILP32 1 # define LZO_INFO_ABI_PM "ilp32" @@ -1318,7 +2368,8 @@ extern "C" { # define LZO_ABI_IP32L64 1 # define LZO_INFO_ABI_PM "ip32l64" #endif -#if !defined(__LZO_LIBC_OVERRIDE) +#if 0 +#elif !defined(__LZO_LIBC_OVERRIDE) #if (LZO_LIBC_NAKED) # define LZO_INFO_LIBC "naked" #elif (LZO_LIBC_FREESTANDING) @@ -1329,6 +2380,9 @@ extern "C" { # define LZO_INFO_LIBC "isoc90" #elif (LZO_LIBC_ISOC99) # define LZO_INFO_LIBC "isoc99" +#elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" #elif defined(__dietlibc__) # define LZO_LIBC_DIETLIBC 1 # define LZO_INFO_LIBC "dietlibc" @@ -1337,13 +2391,13 @@ extern "C" { # define LZO_INFO_LIBC "newlib" #elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) # if defined(__UCLIBC_SUBLEVEL__) -# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) # else # define LZO_LIBC_UCLIBC 0x00090bL # endif -# define LZO_INFO_LIBC "uclibc" +# define LZO_INFO_LIBC "uc" "libc" #elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) -# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) # define LZO_INFO_LIBC "glibc" #elif (LZO_CC_MWERKS) && defined(__MSL__) # define LZO_LIBC_MSL __MSL__ @@ -1356,424 +2410,160 @@ extern "C" { # define LZO_INFO_LIBC "default" #endif #endif -#if !defined(__lzo_gnuc_extension__) -#if (LZO_CC_GNUC >= 0x020800ul) -# define __lzo_gnuc_extension__ __extension__ -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_gnuc_extension__ __extension__ -#else -# define __lzo_gnuc_extension__ /*empty*/ -#endif -#endif -#if !defined(__lzo_ua_volatile) -# define __lzo_ua_volatile volatile -#endif -#if !defined(__lzo_alignof) -#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) -# define __lzo_alignof(e) __alignof__(e) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) -# define __lzo_alignof(e) __alignof__(e) -#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) -# define __lzo_alignof(e) __alignof(e) -#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) -# define __lzo_alignof(e) __alignof__(e) -#endif -#endif -#if defined(__lzo_alignof) -# define __lzo_HAVE_alignof 1 -#endif -#if !defined(__lzo_constructor) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_constructor __attribute__((__constructor__,__used__)) -#elif (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_constructor __attribute__((__constructor__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_constructor __attribute__((__constructor__)) -#endif -#endif -#if defined(__lzo_constructor) -# define __lzo_HAVE_constructor 1 -#endif -#if !defined(__lzo_destructor) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_destructor __attribute__((__destructor__,__used__)) -#elif (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_destructor __attribute__((__destructor__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_destructor __attribute__((__destructor__)) -#endif -#endif -#if defined(__lzo_destructor) -# define __lzo_HAVE_destructor 1 -#endif -#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) -# error "this should not happen" -#endif -#if !defined(__lzo_inline) -#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) -#elif defined(__cplusplus) -# define __lzo_inline inline -#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) -# define __lzo_inline __inline -#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) -# define __lzo_inline __inline__ -#elif (LZO_CC_DMC) -# define __lzo_inline __inline -#elif (LZO_CC_INTELC) -# define __lzo_inline __inline -#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) -# define __lzo_inline __inline -#elif (LZO_CC_MSC && (_MSC_VER >= 900)) -# define __lzo_inline __inline -#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) -# define __lzo_inline __inline__ -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define __lzo_inline inline -#endif +#if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_CC_GNUC) +# define LZO_ASM_SYNTAX_GNUC 1 #endif -#if defined(__lzo_inline) -# define __lzo_HAVE_inline 1 +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) +# define __LZO_ASM_CLOBBER "memory" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #else -# define __lzo_inline /*empty*/ -#endif -#if !defined(__lzo_forceinline) -#if (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) -# define __lzo_forceinline __forceinline -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) -# define __lzo_forceinline __forceinline -#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +# define __LZO_ASM_CLOBBER "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_CC : "cc" +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #endif #endif -#if defined(__lzo_forceinline) -# define __lzo_HAVE_forceinline 1 -#else -# define __lzo_forceinline /*empty*/ -#endif -#if !defined(__lzo_noinline) -#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) -# define __lzo_noinline __attribute__((__noinline__,__used__)) -#elif (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) -# define __lzo_noinline __declspec(noinline) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) -# define __lzo_noinline __declspec(noinline) -#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) -# if defined(__cplusplus) -# else -# define __lzo_noinline __declspec(noinline) +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 # endif -#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) -# define __lzo_noinline __attribute__((__noinline__)) -#endif -#endif -#if defined(__lzo_noinline) -# define __lzo_HAVE_noinline 1 -#else -# define __lzo_noinline /*empty*/ -#endif -#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) -# error "this should not happen" -#endif -#if !defined(__lzo_noreturn) -#if (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) -# define __lzo_noreturn __declspec(noreturn) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) -# define __lzo_noreturn __declspec(noreturn) -#endif -#endif -#if defined(__lzo_noreturn) -# define __lzo_HAVE_noreturn 1 -#else -# define __lzo_noreturn /*empty*/ -#endif -#if !defined(__lzo_nothrow) -#if (LZO_CC_GNUC >= 0x030300ul) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) -# define __lzo_nothrow __declspec(nothrow) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) -# define __lzo_nothrow __declspec(nothrow) -#endif -#endif -#if defined(__lzo_nothrow) -# define __lzo_HAVE_nothrow 1 -#else -# define __lzo_nothrow /*empty*/ -#endif -#if !defined(__lzo_restrict) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_CLANG || LZO_CC_LLVM) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) -# define __lzo_restrict __restrict -#endif -#endif -#if defined(__lzo_restrict) -# define __lzo_HAVE_restrict 1 -#else -# define __lzo_restrict /*empty*/ -#endif -#if !defined(__lzo_likely) && !defined(__lzo_unlikely) -#if (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#endif -#endif -#if defined(__lzo_likely) -# define __lzo_HAVE_likely 1 -#else -# define __lzo_likely(e) (e) -#endif -#if defined(__lzo_unlikely) -# define __lzo_HAVE_unlikely 1 -#else -# define __lzo_unlikely(e) (e) -#endif -#if !defined(LZO_UNUSED) -# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) -# define LZO_UNUSED(var) ((void) &var) -# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) -# define LZO_UNUSED(var) if (&var) ; else -# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define LZO_UNUSED(var) ((void) var) -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_UNUSED(var) if (&var) ; else -# elif (LZO_CC_KEILC) -# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} -# elif (LZO_CC_PACIFICC) -# define LZO_UNUSED(var) ((void) sizeof(var)) -# elif (LZO_CC_WATCOMC) && defined(__cplusplus) -# define LZO_UNUSED(var) ((void) var) -# else -# define LZO_UNUSED(var) ((void) &var) +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 # endif -#endif -#if !defined(LZO_UNUSED_FUNC) -# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) -# define LZO_UNUSED_FUNC(func) ((void) func) -# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) -# define LZO_UNUSED_FUNC(func) if (func) ; else -# elif (LZO_CC_CLANG || LZO_CC_LLVM) -# define LZO_UNUSED_FUNC(func) ((void) &func) -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_UNUSED_FUNC(func) if (func) ; else -# elif (LZO_CC_MSC) -# define LZO_UNUSED_FUNC(func) ((void) &func) -# elif (LZO_CC_KEILC || LZO_CC_PELLESC) -# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} -# else -# define LZO_UNUSED_FUNC(func) ((void) func) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 # endif -#endif -#if !defined(LZO_UNUSED_LABEL) -# if (LZO_CC_WATCOMC) && defined(__cplusplus) -# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l -# elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) -# define LZO_UNUSED_LABEL(l) if (0) goto l -# else -# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +#elif (LZO_ARCH_ARM) +# if defined(__ARM_FEATURE_UNALIGNED) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 6) && !defined(__TARGET_PROFILE_M) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif # endif -#endif -#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) -# if 0 -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var -# elif 0 && (LZO_CC_GNUC) -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var -# else -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +#elif (LZO_ARCH_ARM64) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 # endif -#endif -#if !defined(LZO_UNCONST_CAST) -# if 0 && defined(__cplusplus) -# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e)) -# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e)))))) -# else -# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((const void *) (e))))) +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 # endif -#endif -#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) -# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; -# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; -# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; -# else -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 # endif -#endif -#if !defined(LZO_COMPILE_TIME_ASSERT) -# if (LZO_CC_AZTECC) -# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} -# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# else -# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +#elif (LZO_ARCH_CRIS) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 # endif -#endif -#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) -# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) -# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -# define __lzo_cdecl __cdecl -# define __lzo_cdecl_atexit /*empty*/ -# define __lzo_cdecl_main __cdecl -# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) -# define __lzo_cdecl_qsort __pascal -# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) -# define __lzo_cdecl_qsort _stdcall -# else -# define __lzo_cdecl_qsort __cdecl -# endif -# elif (LZO_CC_WATCOMC) -# define __lzo_cdecl __cdecl -# else -# define __lzo_cdecl __cdecl -# define __lzo_cdecl_atexit __cdecl -# define __lzo_cdecl_main __cdecl -# define __lzo_cdecl_qsort __cdecl +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 # endif -# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) -# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) -# define __lzo_cdecl_sighandler __pascal -# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) -# define __lzo_cdecl_sighandler _stdcall -# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) -# define __lzo_cdecl_sighandler __clrcall -# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) -# if defined(_DLL) -# define __lzo_cdecl_sighandler _far _cdecl _loadds -# elif defined(_MT) -# define __lzo_cdecl_sighandler _far _cdecl -# else -# define __lzo_cdecl_sighandler _cdecl -# endif -# else -# define __lzo_cdecl_sighandler __cdecl +#elif (LZO_ARCH_I386) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 # endif -#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) -# define __lzo_cdecl __cdecl -#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) -# define __lzo_cdecl cdecl -#endif -#if !defined(__lzo_cdecl) -# define __lzo_cdecl /*empty*/ -#endif -#if !defined(__lzo_cdecl_atexit) -# define __lzo_cdecl_atexit /*empty*/ -#endif -#if !defined(__lzo_cdecl_main) -# define __lzo_cdecl_main /*empty*/ -#endif -#if !defined(__lzo_cdecl_qsort) -# define __lzo_cdecl_qsort /*empty*/ -#endif -#if !defined(__lzo_cdecl_sighandler) -# define __lzo_cdecl_sighandler /*empty*/ -#endif -#if !defined(__lzo_cdecl_va) -# define __lzo_cdecl_va __lzo_cdecl -#endif -#if !(LZO_CFG_NO_WINDOWS_H) -#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) -# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) -# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) -# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) -# else -# define LZO_HAVE_WINDOWS_H 1 +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 # endif -#endif -#endif -#if (LZO_ARCH_ALPHA) -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_AVOID_SHORT 1 -# define LZO_OPT_AVOID_USHORT 1 -#elif (LZO_ARCH_AMD64) -# define LZO_OPT_AVOID_INT_INDEX 1 -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# define LZO_OPT_UNALIGNED64 1 -#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) -#elif (LZO_ARCH_ARM) -# define LZO_OPT_AVOID_SHORT 1 -# define LZO_OPT_AVOID_USHORT 1 -#elif (LZO_ARCH_CRIS) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -#elif (LZO_ARCH_I386) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 #elif (LZO_ARCH_IA64) -# define LZO_OPT_AVOID_INT_INDEX 1 -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 #elif (LZO_ARCH_M68K) -# define LZO_OPT_PREFER_POSTINC 1 -# define LZO_OPT_PREFER_PREDEC 1 +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 # if defined(__mc68020__) && !defined(__mcoldfire__) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif # endif #elif (LZO_ARCH_MIPS) -# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 #elif (LZO_ARCH_POWERPC) -# define LZO_OPT_PREFER_PREINC 1 -# define LZO_OPT_PREFER_PREDEC 1 +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 # if (LZO_ABI_BIG_ENDIAN) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif # endif #elif (LZO_ARCH_S390) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# if (LZO_SIZEOF_SIZE_T == 8) -# define LZO_OPT_UNALIGNED64 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif # endif #elif (LZO_ARCH_SH) -# define LZO_OPT_PREFER_POSTINC 1 -# define LZO_OPT_PREFER_PREDEC 1 +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 #endif #ifndef LZO_CFG_NO_INLINE_ASM -#if (LZO_CC_LLVM) +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_INLINE_ASM 1 +#elif (LZO_CC_LLVM) # define LZO_CFG_NO_INLINE_ASM 1 #endif #endif +#if (LZO_CFG_NO_INLINE_ASM) +# undef LZO_ASM_SYNTAX_MSC +# undef LZO_ASM_SYNTAX_GNUC +# undef __LZO_ASM_CLOBBER +# undef __LZO_ASM_CLOBBER_LIST_CC +# undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY +# undef __LZO_ASM_CLOBBER_LIST_EMPTY +#endif #ifndef LZO_CFG_NO_UNALIGNED #if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) # define LZO_CFG_NO_UNALIGNED 1 @@ -1784,25 +2574,6 @@ extern "C" { # undef LZO_OPT_UNALIGNED32 # undef LZO_OPT_UNALIGNED64 #endif -#if (LZO_CFG_NO_INLINE_ASM) -#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) -# define LZO_ASM_SYNTAX_MSC 1 -#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) -#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) -#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) -# define LZO_ASM_SYNTAX_GNUC 1 -#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) -# define LZO_ASM_SYNTAX_GNUC 1 -#endif -#if (LZO_ASM_SYNTAX_GNUC) -#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) -# define __LZO_ASM_CLOBBER "ax" -#elif (LZO_CC_INTELC) -# define __LZO_ASM_CLOBBER "memory" -#else -# define __LZO_ASM_CLOBBER "cc", "memory" -#endif -#endif #if defined(__LZO_INFOSTR_MM) #elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) # define __LZO_INFOSTR_MM "" @@ -1846,7 +2617,382 @@ extern "C" { #define LZO_INFO_STRING \ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER +#if !(LZO_CFG_SKIP_LZO_TYPES) +#if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) +# error "missing defines for sizes" +#endif +#if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) +# error "missing defines for sizes" +#endif +#if !defined(lzo_llong_t) +#if (LZO_SIZEOF_LONG_LONG+0 > 0) +__lzo_gnuc_extension__ typedef long long lzo_llong_t__; +__lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; +# define lzo_llong_t lzo_llong_t__ +# define lzo_ullong_t lzo_ullong_t__ +#endif +#endif +#if !defined(lzo_int16e_t) +#if (LZO_SIZEOF_LONG == 2) +# define lzo_int16e_t long +# define lzo_uint16e_t unsigned long +#elif (LZO_SIZEOF_INT == 2) +# define lzo_int16e_t int +# define lzo_uint16e_t unsigned int +#elif (LZO_SIZEOF_SHORT == 2) +# define lzo_int16e_t short int +# define lzo_uint16e_t unsigned short int +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) + typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); + typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); +# define lzo_int16e_t lzo_int16e_hi_t__ +# define lzo_uint16e_t lzo_uint16e_hi_t__ +#elif (LZO_SIZEOF___INT16 == 2) +# define lzo_int16e_t __int16 +# define lzo_uint16e_t unsigned __int16 +#else +#endif +#endif +#if defined(lzo_int16e_t) +# define LZO_SIZEOF_LZO_INT16E_T 2 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) +#endif +#if !defined(lzo_int32e_t) +#if (LZO_SIZEOF_LONG == 4) +# define lzo_int32e_t long int +# define lzo_uint32e_t unsigned long int +#elif (LZO_SIZEOF_INT == 4) +# define lzo_int32e_t int +# define lzo_uint32e_t unsigned int +#elif (LZO_SIZEOF_SHORT == 4) +# define lzo_int32e_t short int +# define lzo_uint32e_t unsigned short int +#elif (LZO_SIZEOF_LONG_LONG == 4) +# define lzo_int32e_t lzo_llong_t +# define lzo_uint32e_t lzo_ullong_t +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +#elif (LZO_SIZEOF___INT32 == 4) +# define lzo_int32e_t __int32 +# define lzo_uint32e_t unsigned __int32 +#else +#endif +#endif +#if defined(lzo_int32e_t) +# define LZO_SIZEOF_LZO_INT32E_T 4 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) +#endif +#if !defined(lzo_int64e_t) +#if (LZO_SIZEOF___INT64 == 8) +# if (LZO_CC_BORLANDC) && !(LZO_CFG_TYPE_PREFER___INT64) +# define LZO_CFG_TYPE_PREFER___INT64 1 +# endif +#endif +#if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int64e_t int +# define lzo_uint64e_t unsigned int +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG == 8) +# define lzo_int64e_t long int +# define lzo_uint64e_t unsigned long int +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG +#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_TYPE_PREFER___INT64) +# define lzo_int64e_t lzo_llong_t +# define lzo_uint64e_t lzo_ullong_t +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0ll) +# define LZO_UINT64_C(c) ((c) + 0ull) +# elif 0 +# define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) +# define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) +# else +# define LZO_INT64_C(c) (c##LL) +# define LZO_UINT64_C(c) (c##ULL) +# endif +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG_LONG +#elif (LZO_SIZEOF___INT64 == 8) +# define lzo_int64e_t __int64 +# define lzo_uint64e_t unsigned __int64 +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0i64) +# define LZO_UINT64_C(c) ((c) + 0ui64) +# else +# define LZO_INT64_C(c) (c##i64) +# define LZO_UINT64_C(c) (c##ui64) +# endif +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF___INT64 +#else +#endif +#endif +#if defined(lzo_int64e_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) +#endif +#if !defined(lzo_int32l_t) +#if defined(lzo_int32e_t) +# define lzo_int32l_t lzo_int32e_t +# define lzo_uint32l_t lzo_uint32e_t +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T +#elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int32l_t int +# define lzo_uint32l_t unsigned int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= 4) +# define lzo_int32l_t long int +# define lzo_uint32l_t unsigned long int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG +#else +# error "lzo_int32l_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) +#endif +#if !defined(lzo_int64l_t) +#if defined(lzo_int64e_t) +# define lzo_int64l_t lzo_int64e_t +# define lzo_uint64l_t lzo_uint64e_t +# define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T +#else +#endif +#endif +#if defined(lzo_int64l_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) +#endif +#if !defined(lzo_int32f_t) +#if (LZO_SIZEOF_SIZE_T >= 8) +# define lzo_int32f_t lzo_int64l_t +# define lzo_uint32f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T +#else +# define lzo_int32f_t lzo_int32l_t +# define lzo_uint32f_t lzo_uint32l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) +#endif +#if !defined(lzo_int64f_t) +#if defined(lzo_int64l_t) +# define lzo_int64f_t lzo_int64l_t +# define lzo_uint64f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T +#else +#endif +#endif +#if defined(lzo_int64f_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) +#endif +#if !defined(lzo_intptr_t) +#if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) +# define __LZO_INTPTR_T_IS_POINTER 1 + typedef char* lzo_intptr_t; + typedef char* lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P +#elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) + typedef __w64 int lzo_intptr_t; + typedef __w64 unsigned int lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) +# define lzo_intptr_t short +# define lzo_uintptr_t unsigned short +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT +#elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_intptr_t int +# define lzo_uintptr_t unsigned int +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t long +# define lzo_uintptr_t unsigned long +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG +#elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t lzo_int64l_t +# define lzo_uintptr_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T +#else +# error "lzo_intptr_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) +#endif +#if !defined(lzo_word_t) +#if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) +#if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) +# define lzo_word_t lzo_uintptr_t +# define lzo_sword_t lzo_intptr_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T +#elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) +# define lzo_word_t unsigned long +# define lzo_sword_t long +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG +#elif (LZO_WORDSIZE == LZO_SIZEOF_INT) +# define lzo_word_t unsigned int +# define lzo_sword_t int +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT +#elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) +# define lzo_word_t unsigned short +# define lzo_sword_t short +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT +#elif (LZO_WORDSIZE == 1) +# define lzo_word_t unsigned char +# define lzo_sword_t signed char +# define LZO_SIZEOF_LZO_WORD_T 1 +#elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) +# define lzo_word_t lzo_uint64l_t +# define lzo_sword_t lzo_int64l_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +#elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) +#if 0 + typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); + typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); +# define lzo_word_t lzo_word_t +# define lzo_sword_t lzo_sword_t +# define LZO_SIZEOF_LZO_WORD_T 16 +#endif +#else +# error "lzo_word_t" +#endif +#endif +#endif +#if 1 && defined(lzo_word_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) +#endif +#if 1 +#define lzo_int8_t signed char +#define lzo_uint8_t unsigned char +#define LZO_SIZEOF_LZO_INT8_T 1 +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) +#endif +#if defined(lzo_int16e_t) +#define lzo_int16_t lzo_int16e_t +#define lzo_uint16_t lzo_uint16e_t +#define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) +#endif +#if defined(lzo_int32e_t) +#define lzo_int32_t lzo_int32e_t +#define lzo_uint32_t lzo_uint32e_t +#define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) +#endif +#if defined(lzo_int64e_t) +#define lzo_int64_t lzo_int64e_t +#define lzo_uint64_t lzo_uint64e_t +#define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) +#endif +#if 1 +#define lzo_int_least32_t lzo_int32l_t +#define lzo_uint_least32_t lzo_uint32l_t +#define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) +#endif +#if defined(lzo_int64l_t) +#define lzo_int_least64_t lzo_int64l_t +#define lzo_uint_least64_t lzo_uint64l_t +#define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) +#endif +#if 1 +#define lzo_int_fast32_t lzo_int32f_t +#define lzo_uint_fast32_t lzo_uint32f_t +#define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) +#endif +#if defined(lzo_int64f_t) +#define lzo_int_fast64_t lzo_int64f_t +#define lzo_uint_fast64_t lzo_uint64f_t +#define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) +#endif +#if !defined(LZO_INT16_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) ((c) + 0) +# define LZO_UINT16_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) ((c) + 0L) +# define LZO_UINT16_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) (c) +# define LZO_UINT16_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) (c##L) +# define LZO_UINT16_C(c) (c##UL) +# else +# error "LZO_INT16_C" +# endif +#endif +#if !defined(LZO_INT32_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) ((c) + 0) +# define LZO_UINT32_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) ((c) + 0L) +# define LZO_UINT32_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) (c) +# define LZO_UINT32_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) (c##L) +# define LZO_UINT32_C(c) (c##UL) +# elif (LZO_SIZEOF_LONG_LONG >= 4) +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# else +# error "LZO_INT32_C" +# endif +#endif +#if !defined(LZO_INT64_C) && defined(lzo_int64l_t) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) ((c) + 0) +# define LZO_UINT64_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) ((c) + 0L) +# define LZO_UINT64_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) (c) +# define LZO_UINT64_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) (c##L) +# define LZO_UINT64_C(c) (c##UL) +# else +# error "LZO_INT64_C" +# endif +#endif +#endif #endif /* already included */ -/* vim:set ts=4 et: */ +/* vim:set ts=4 sw=4 et: */ diff --git a/extern/lzo/minilzo/minilzo.c b/extern/lzo/minilzo/minilzo.c index 34ce0f090bd..ab2be5f4fd0 100644 --- a/extern/lzo/minilzo/minilzo.c +++ b/extern/lzo/minilzo/minilzo.c @@ -2,22 +2,7 @@ This file is part of the LZO real-time data compression library. - Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or @@ -67,12 +52,6 @@ #if defined(__CYGWIN32__) && !defined(__CYGWIN__) # define __CYGWIN__ __CYGWIN32__ #endif -#if defined(__IBMCPP__) && !defined(__IBMC__) -# define __IBMC__ __IBMCPP__ -#endif -#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) -# define __INTEL_COMPILER __ICL -#endif #if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) # define _ALL_SOURCE 1 #endif @@ -81,19 +60,30 @@ # define __LONG_MAX__ 9223372036854775807L # endif #endif -#if defined(__INTEL_COMPILER) && defined(__linux__) +#if !defined(LZO_CFG_NO_DISABLE_WUNDEF) +#if defined(__ARMCC_VERSION) +# pragma diag_suppress 193 +#elif defined(__clang__) && defined(__clang_minor__) +# pragma clang diagnostic ignored "-Wundef" +#elif defined(__INTEL_COMPILER) # pragma warning(disable: 193) -#endif -#if defined(__KEIL__) && defined(__C166__) -# pragma warning disable = 322 -#elif 0 && defined(__C251__) +#elif defined(__KEIL__) && defined(__C166__) # pragma warning disable = 322 -#endif -#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) -# if (_MSC_VER >= 1300) +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) +# if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) +# pragma GCC diagnostic ignored "-Wundef" +# endif +#elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if ((_MSC_VER-0) >= 1300) # pragma warning(disable: 4668) # endif #endif +#endif +#if 0 && defined(__POCC__) && defined(_WIN32) +# if (__POCC__ >= 400) +# pragma warn(disable: 2216) +# endif +#endif #if 0 && defined(__WATCOMC__) # if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) # pragma warning 203 9 @@ -102,13 +92,29 @@ #if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) # pragma option -h #endif +#if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#ifndef _CRT_NONSTDC_NO_WARNINGS +#define _CRT_NONSTDC_NO_WARNINGS 1 +#endif +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#endif #if 0 -#define LZO_0xffffL 0xfffful -#define LZO_0xffffffffL 0xfffffffful +#define LZO_0xffffUL 0xfffful +#define LZO_0xffffffffUL 0xfffffffful #else -#define LZO_0xffffL 65535ul -#define LZO_0xffffffffL 4294967295ul +#define LZO_0xffffUL 65535ul +#define LZO_0xffffffffUL 4294967295ul #endif +#define LZO_0xffffL LZO_0xffffUL +#define LZO_0xffffffffL LZO_0xffffffffUL #if (LZO_0xffffL == LZO_0xffffffffL) # error "your preprocessor is broken 1" #endif @@ -123,6 +129,13 @@ # error "your preprocessor is broken 4" #endif #endif +#if defined(__COUNTER__) +# ifndef LZO_CFG_USE_COUNTER +# define LZO_CFG_USE_COUNTER 1 +# endif +#else +# undef LZO_CFG_USE_COUNTER +#endif #if (UINT_MAX == LZO_0xffffL) #if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) # if !defined(MSDOS) @@ -253,14 +266,31 @@ #endif #define LZO_PP_STRINGIZE(x) #x #define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT0() /*empty*/ +#define LZO_PP_CONCAT1(a) a #define LZO_PP_CONCAT2(a,b) a ## b #define LZO_PP_CONCAT3(a,b,c) a ## b ## c #define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() +#define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) #define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) #define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) #define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) #define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) +#define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) +#define LZO_PP_EMPTY /*empty*/ +#define LZO_PP_EMPTY0() /*empty*/ +#define LZO_PP_EMPTY1(a) /*empty*/ +#define LZO_PP_EMPTY2(a,b) /*empty*/ +#define LZO_PP_EMPTY3(a,b,c) /*empty*/ +#define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ +#define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ +#define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ +#define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ #if 1 #define LZO_CPP_STRINGIZE(x) #x #define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) @@ -268,12 +298,16 @@ #define LZO_CPP_CONCAT3(a,b,c) a ## b ## c #define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g #define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) #define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) #define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) #define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) +#define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) #endif -#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-!!(b))) - (o)) << 1) + (o)*!!(b)) #if 1 && defined(__cplusplus) # if !defined(__STDC_CONSTANT_MACROS) # define __STDC_CONSTANT_MACROS 1 @@ -283,9 +317,13 @@ # endif #endif #if defined(__cplusplus) -# define LZO_EXTERN_C extern "C" +# define LZO_EXTERN_C extern "C" +# define LZO_EXTERN_C_BEGIN extern "C" { +# define LZO_EXTERN_C_END } #else -# define LZO_EXTERN_C extern +# define LZO_EXTERN_C extern +# define LZO_EXTERN_C_BEGIN /*empty*/ +# define LZO_EXTERN_C_END /*empty*/ #endif #if !defined(__LZO_OS_OVERRIDE) #if (LZO_OS_FREESTANDING) @@ -386,12 +424,12 @@ #elif defined(__VMS) # define LZO_OS_VMS 1 # define LZO_INFO_OS "vms" -#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +#elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PS2 1 # define LZO_INFO_OS "console" # define LZO_INFO_OS_CONSOLE "ps2" -#elif (defined(__mips__) && defined(__psp__)) +#elif defined(__mips__) && defined(__psp__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PSP 1 # define LZO_INFO_OS "console" @@ -419,9 +457,18 @@ # elif defined(__linux__) || defined(__linux) || defined(__LINUX__) # define LZO_OS_POSIX_LINUX 1 # define LZO_INFO_OS_POSIX "linux" -# elif defined(__APPLE__) || defined(__MACOS__) -# define LZO_OS_POSIX_MACOSX 1 -# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__APPLE__) && defined(__MACH__) +# if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) +# define LZO_OS_POSIX_DARWIN 1040 +# define LZO_INFO_OS_POSIX "darwin_iphone" +# elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) +# define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +# define LZO_INFO_OS_POSIX "darwin" +# else +# define LZO_OS_POSIX_DARWIN 1 +# define LZO_INFO_OS_POSIX "darwin" +# endif +# define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN # elif defined(__minix__) || defined(__minix) # define LZO_OS_POSIX_MINIX 1 # define LZO_INFO_OS_POSIX "minix" @@ -456,18 +503,18 @@ #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) # if (UINT_MAX != LZO_0xffffffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif #endif #if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) @@ -483,59 +530,65 @@ # define LZO_INFO_CC "sdcc" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) #elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) -# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) # define LZO_INFO_CC "Pathscale C" # define LZO_INFO_CCVER __PATHSCALE__ -#elif defined(__INTEL_COMPILER) -# define LZO_CC_INTELC 1 +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) +# define LZO_CC_INTELC __INTEL_COMPILER # define LZO_INFO_CC "Intel C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) -# if defined(_WIN32) || defined(_WIN64) -# define LZO_CC_SYNTAX_MSC 1 -# else -# define LZO_CC_SYNTAX_GNUC 1 +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_INTELC_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__POCC__) && defined(_WIN32) # define LZO_CC_PELLESC 1 # define LZO_INFO_CC "Pelles C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) -#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +#elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) -# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else -# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) # if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) -# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__) +# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) # else -# define LZO_CC_CLANG_CLANG 0x010000L +# define LZO_CC_CLANG 0x010000L +# endif +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_CLANG_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif -# define LZO_CC_CLANG LZO_CC_CLANG_GNUC # define LZO_INFO_CC "clang" # define LZO_INFO_CCVER __VERSION__ #elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) -# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else -# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif # define LZO_CC_LLVM LZO_CC_LLVM_GNUC # define LZO_INFO_CC "llvm-gcc" # define LZO_INFO_CCVER __VERSION__ -#elif defined(__GNUC__) && defined(__VERSION__) -# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) -# elif defined(__GNUC_MINOR__) -# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) -# else -# define LZO_CC_GNUC (__GNUC__ * 0x10000L) -# endif -# define LZO_INFO_CC "gcc" -# define LZO_INFO_CCVER __VERSION__ #elif defined(__ACK__) && defined(_ACK) # define LZO_CC_ACK 1 # define LZO_INFO_CC "Amsterdam Compiler Kit C" # define LZO_INFO_CCVER "unknown" +#elif defined(__ARMCC_VERSION) && !defined(__GNUC__) +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) #elif defined(__AZTEC_C__) # define LZO_CC_AZTECC 1 # define LZO_INFO_CC "Aztec C" @@ -560,10 +613,23 @@ # define LZO_CC_DECC 1 # define LZO_INFO_CC "DEC C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) +# define LZO_CC_GHS 1 +# define LZO_INFO_CC "Green Hills C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_GHS_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif #elif defined(__HIGHC__) # define LZO_CC_HIGHC 1 # define LZO_INFO_CC "MetaWare High C" # define LZO_INFO_CCVER "unknown" +#elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) +# define LZO_CC_HPACC __HP_aCC +# define LZO_INFO_CC "HP aCC" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) #elif defined(__IAR_SYSTEMS_ICC__) # define LZO_CC_IARC 1 # define LZO_INFO_CC "IAR C" @@ -572,10 +638,14 @@ # else # define LZO_INFO_CCVER "unknown" # endif -#elif defined(__IBMC__) -# define LZO_CC_IBMC 1 +#elif defined(__IBMC__) && ((__IBMC__-0) > 0) +# define LZO_CC_IBMC __IBMC__ # define LZO_INFO_CC "IBM C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) +# define LZO_CC_IBMC __IBMCPP__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) #elif defined(__KEIL__) && defined(__C166__) # define LZO_CC_KEILC 1 # define LZO_INFO_CC "Keil C" @@ -592,16 +662,8 @@ # else # define LZO_INFO_CCVER "unknown" # endif -#elif defined(_MSC_VER) -# define LZO_CC_MSC 1 -# define LZO_INFO_CC "Microsoft C" -# if defined(_MSC_FULL_VER) -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) -# else -# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) -# endif -#elif defined(__MWERKS__) -# define LZO_CC_MWERKS 1 +#elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) +# define LZO_CC_MWERKS __MWERKS__ # define LZO_INFO_CC "Metrowerks C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) #elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) @@ -612,6 +674,15 @@ # define LZO_CC_PACIFICC 1 # define LZO_INFO_CC "Pacific C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) +# else +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" +# endif +# define LZO_INFO_CC "Portland Group PGI C" #elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) # define LZO_CC_PGI 1 # define LZO_INFO_CC "Portland Group PGI C" @@ -626,7 +697,7 @@ # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) #elif defined(__SUNPRO_C) # define LZO_INFO_CC "SunPro C" -# if ((__SUNPRO_C)+0 > 0) +# if ((__SUNPRO_C-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_C # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) # else @@ -635,7 +706,7 @@ # endif #elif defined(__SUNPRO_CC) # define LZO_INFO_CC "SunPro C" -# if ((__SUNPRO_CC)+0 > 0) +# if ((__SUNPRO_CC-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_CC # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) # else @@ -661,16 +732,46 @@ #elif defined(__ZTC__) # define LZO_CC_ZORTECHC 1 # define LZO_INFO_CC "Zortech C" -# if (__ZTC__ == 0x310) +# if ((__ZTC__-0) == 0x310) # define LZO_INFO_CCVER "0x310" # else # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) # endif +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_MSC _MSC_VER +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif #else # define LZO_CC_UNKNOWN 1 # define LZO_INFO_CC "unknown" # define LZO_INFO_CCVER "unknown" #endif +#if (LZO_CC_GNUC) && defined(__OPEN64__) +# if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) +# define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) +# define LZO_CC_OPEN64_GNUC LZO_CC_GNUC +# endif +#endif +#if (LZO_CC_GNUC) && defined(__PCC__) +# if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) +# define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) +# define LZO_CC_PCC_GNUC LZO_CC_GNUC +# endif +#endif #if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) # error "LZO_CC_MSC: _MSC_FULL_VER is not defined" #endif @@ -688,8 +789,10 @@ # define LZO_INFO_ARCH "generic" #elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086 1 -# define LZO_ARCH_IA16 1 # define LZO_INFO_ARCH "i086" +#elif defined(__aarch64__) +# define LZO_ARCH_ARM64 1 +# define LZO_INFO_ARCH "arm64" #elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) # define LZO_ARCH_ALPHA 1 # define LZO_INFO_ARCH "alpha" @@ -705,10 +808,10 @@ # define LZO_INFO_ARCH "arm_thumb" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) # define LZO_ARCH_ARM 1 -# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) +# if defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 1) # define LZO_ARCH_ARM_THUMB 1 # define LZO_INFO_ARCH "arm_thumb" -# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) +# elif defined(__CPU_MODE__) && ((__CPU_MODE__-0) == 2) # define LZO_INFO_ARCH "arm" # else # define LZO_INFO_ARCH "arm" @@ -826,53 +929,147 @@ # error "FIXME - missing define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) -# error "FIXME - missing WIN32 define for CPU architecture" +# error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) -# error "FIXME - missing WIN64 define for CPU architecture" +# error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" #endif #if (LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 #elif 1 && (LZO_OS_DOS16 && defined(BLX286)) # define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 #elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) # define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 #elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) # define LZO_ARCH_I086PM 1 -# define LZO_ARCH_IA16PM 1 #endif -#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM) -# error "this should not happen" +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) +# define LZO_ARCH_X64 1 +#elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_AMD64 1 +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) +# define LZO_ARCH_AARCH64 1 +#elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_ARM64 1 +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) +# define LZO_ARCH_X86 1 +#elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_I386 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" #endif -#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086) -# error "this should not happen" +#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM_THUMB) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM_THUMB) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086PM && !LZO_ARCH_I086) +# error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I086) # if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_ARCH_I386) # if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif # if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if !defined(LZO_TARGET_FEATURE_SSE2) +# if defined(__SSE2__) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif defined(_MSC_VER) && ((defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) || defined(_M_AMD64)) +# define LZO_TARGET_FEATURE_SSE2 1 +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSSE3) +# if (LZO_TARGET_FEATURE_SSE2) +# if defined(__SSSE3__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# elif defined(_MSC_VER) && defined(__AVX__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSE4_2) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__SSE4_2__) +# define LZO_TARGET_FEATURE_SSE4_2 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__AVX__) +# define LZO_TARGET_FEATURE_AVX 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX2) +# if (LZO_TARGET_FEATURE_AVX) +# if defined(__AVX2__) +# define LZO_TARGET_FEATURE_AVX2 1 +# endif +# endif +# endif +#endif +#if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if defined(__ARM_NEON__) +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if 1 +# define LZO_TARGET_FEATURE_NEON 1 +# endif # endif #endif -#if !defined(__LZO_MM_OVERRIDE) +#if 0 +#elif !defined(__LZO_MM_OVERRIDE) #if (LZO_ARCH_I086) #if (UINT_MAX != LZO_0xffffL) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" #endif #if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) # define LZO_MM_TINY 1 @@ -899,7 +1096,7 @@ #elif (LZO_CC_ZORTECHC && defined(__VCM__)) # define LZO_MM_LARGE 1 #else -# error "unknown memory model" +# error "unknown LZO_ARCH_I086 memory model" #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) #define LZO_HAVE_MM_HUGE_PTR 1 @@ -922,10 +1119,10 @@ #endif #if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) # if (LZO_OS_DOS16) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # elif (LZO_CC_ZORTECHC) # else -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" # endif #endif #ifdef __cplusplus @@ -957,7 +1154,7 @@ extern "C" { #endif #elif (LZO_ARCH_C166) #if !defined(__MODEL__) -# error "FIXME - C166 __MODEL__" +# error "FIXME - LZO_ARCH_C166 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 1) @@ -971,11 +1168,11 @@ extern "C" { #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else -# error "FIXME - C166 __MODEL__" +# error "FIXME - LZO_ARCH_C166 __MODEL__" #endif #elif (LZO_ARCH_MCS251) #if !defined(__MODEL__) -# error "FIXME - MCS251 __MODEL__" +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) @@ -987,11 +1184,11 @@ extern "C" { #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else -# error "FIXME - MCS251 __MODEL__" +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" #endif #elif (LZO_ARCH_MCS51) #if !defined(__MODEL__) -# error "FIXME - MCS51 __MODEL__" +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" #elif ((__MODEL__) == 1) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) @@ -1003,7 +1200,7 @@ extern "C" { #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else -# error "FIXME - MCS51 __MODEL__" +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" #endif #elif (LZO_ARCH_CRAY_PVP) # define LZO_MM_PVP 1 @@ -1030,35 +1227,818 @@ extern "C" { # error "unknown memory model" #endif #endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_gnuc_extension__ __extension__ +#else +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# else +# define LZO_CFG_USE_NEW_STYLE_CASTS 1 +# endif +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(__cplusplus) +# if defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# undef LZO_CFG_USE_NEW_STYLE_CASTS +# endif +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(LZO_REINTERPRET_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast<t> (e)) +# endif +#endif +#if !defined(LZO_REINTERPRET_CAST) +# define LZO_REINTERPRET_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_STATIC_CAST(t,e) (static_cast<t> (e)) +# endif +#endif +#if !defined(LZO_STATIC_CAST) +# define LZO_STATIC_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST2) +# define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) +#endif +#if !defined(LZO_UNCONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_PCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_PCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_PCAST) +# define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) +#endif +#if !defined(LZO_CCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_CCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_CCAST) +# define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) +#endif +#if !defined(LZO_ICONV) +# define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ICAST) +# define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ITRUNC) +# define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(__lzo_cte) +# if (LZO_CC_MSC || LZO_CC_WATCOMC) +# define __lzo_cte(e) ((void)0,(e)) +# elif 1 +# define __lzo_cte(e) ((void)0,(e)) +# endif +#endif +#if !defined(__lzo_cte) +# define __lzo_cte(e) (e) +#endif +#if !defined(LZO_BLOCK_BEGIN) +# define LZO_BLOCK_BEGIN do { +# define LZO_BLOCK_END } while __lzo_cte(0) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {LZO_EXTERN_C int lzo_unused__[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {LZO_EXTERN_C int lzo_unused_func__[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_CLANG >= 0x020800ul) +# define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) +# elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_GHS) +# define __lzo_inline __inline__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_inline __inline__ +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_inline __inline__ +#endif +#endif +#if defined(__lzo_inline) +# ifndef __lzo_HAVE_inline +# define __lzo_HAVE_inline 1 +# endif +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# ifndef __lzo_HAVE_forceinline +# define __lzo_HAVE_forceinline 1 +# endif +#else +# define __lzo_forceinline __lzo_inline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# ifndef __lzo_HAVE_noinline +# define __lzo_HAVE_noinline 1 +# endif +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_static_inline) +#if (LZO_CC_IBMC) +# define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline +#endif +#endif +#if !defined(__lzo_static_inline) +# define __lzo_static_inline static __lzo_inline +#endif +#if !defined(__lzo_static_forceinline) +#if (LZO_CC_IBMC) +# define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline +#endif +#endif +#if !defined(__lzo_static_forceinline) +# define __lzo_static_forceinline static __lzo_forceinline +#endif +#if !defined(__lzo_static_noinline) +#if (LZO_CC_IBMC) +# define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline +#endif +#endif +#if !defined(__lzo_static_noinline) +# define __lzo_static_noinline static __lzo_noinline +#endif +#if !defined(__lzo_c99_extern_inline) +#if defined(__GNUC_GNU_INLINE__) +# define __lzo_c99_extern_inline __lzo_inline +#elif defined(__GNUC_STDC_INLINE__) +# define __lzo_c99_extern_inline extern __lzo_inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_c99_extern_inline extern __lzo_inline +#endif +#if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) +# define __lzo_c99_extern_inline __lzo_inline +#endif +#endif +#if defined(__lzo_c99_extern_inline) +# ifndef __lzo_HAVE_c99_extern_inline +# define __lzo_HAVE_c99_extern_inline 1 +# endif +#else +# define __lzo_c99_extern_inline /*empty*/ +#endif +#if !defined(__lzo_may_alias) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_CLANG >= 0x020900ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#endif +#endif +#if defined(__lzo_may_alias) +# ifndef __lzo_HAVE_may_alias +# define __lzo_HAVE_may_alias 1 +# endif +#else +# define __lzo_may_alias /*empty*/ +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#endif +#endif +#if defined(__lzo_noreturn) +# ifndef __lzo_HAVE_noreturn +# define __lzo_HAVE_noreturn 1 +# endif +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# ifndef __lzo_HAVE_nothrow +# define __lzo_HAVE_nothrow 1 +# endif +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 1210) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_restrict __restrict__ +#endif +#endif +#if defined(__lzo_restrict) +# ifndef __lzo_HAVE_restrict +# define __lzo_HAVE_restrict 1 +# endif +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_GHS) && !defined(__cplusplus) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_IBMC >= 600) +# define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# ifndef __lzo_HAVE_alignof +# define __lzo_HAVE_alignof 1 +# endif +#endif +#if !defined(__lzo_struct_packed) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { +# define __lzo_struct_packed_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_struct_packed(s) _Packed struct s { +# define __lzo_struct_packed_end() }; +#endif +#endif +#if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) +# define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) +#endif +#if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) +# define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() +#endif +#if !defined(__lzo_byte_struct) +#if defined(__lzo_struct_packed) +# define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() +# define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); +# define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); +#endif +#endif +#if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) +# define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) +#endif +#if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) +#if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) +#elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_CILLY || LZO_CC_PCC) +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_align16(s) struct __declspec(align(16)) s { +# define __lzo_struct_align16_end() }; +# define __lzo_struct_align32(s) struct __declspec(align(32)) s { +# define __lzo_struct_align32_end() }; +# define __lzo_struct_align64(s) struct __declspec(align(64)) s { +# define __lzo_struct_align64_end() }; +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_struct_align16(s) struct s { +# define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); +# define __lzo_struct_align32(s) struct s { +# define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); +# define __lzo_struct_align64(s) struct s { +# define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); +#endif +#endif +#if !defined(__lzo_union_um) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_union_am(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_union_um(s) __pragma(pack(push,1)) union s { +# define __lzo_union_um_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_union_um(s) _Packed union s { +# define __lzo_union_um_end() }; +#endif +#endif +#if !defined(__lzo_union_am) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() }; +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# ifndef __lzo_HAVE_constructor +# define __lzo_HAVE_constructor 1 +# endif +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# ifndef __lzo_HAVE_destructor +# define __lzo_HAVE_destructor 1 +# endif +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_IBMC >= 1010) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# ifndef __lzo_HAVE_likely +# define __lzo_HAVE_likely 1 +# endif +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# ifndef __lzo_HAVE_unlikely +# define __lzo_HAVE_unlikely 1 +# endif +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(__lzo_static_unused_void_func) +# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_static_unused_void_func(f) static void __attribute__((__unused__)) f(void) +# else +# define __lzo_static_unused_void_func(f) static __lzo_inline void f(void) +# endif +#endif +#if !defined(__lzo_loop_forever) +# if (LZO_CC_IBMC) +# define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END +# else +# define __lzo_loop_forever() do { ; } while __lzo_cte(1) +# endif +#endif +#if !defined(__lzo_unreachable) +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_GNUC >= 0x040500ul) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 +# define __lzo_unreachable() __builtin_unreachable(); +#endif +#endif +#if defined(__lzo_unreachable) +# ifndef __lzo_HAVE_unreachable +# define __lzo_HAVE_unreachable 1 +# endif +#else +# if 0 +# define __lzo_unreachable() ((void)0); +# else +# define __lzo_unreachable() __lzo_loop_forever(); +# endif +#endif +#ifndef __LZO_CTA_NAME +#if (LZO_CFG_USE_COUNTER) +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) +#else +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) +#endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} +# elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} +# elif (LZO_CC_GNUC >= 0x040700ul) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) +#if defined(__cplusplus) +extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if !defined(LZO_HAVE_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#endif +#ifndef LZO_SIZEOF_SHORT #if defined(SIZEOF_SHORT) # define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#elif defined(__SIZEOF_SHORT__) +# define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) +#endif #endif +#ifndef LZO_SIZEOF_INT #if defined(SIZEOF_INT) # define LZO_SIZEOF_INT (SIZEOF_INT) +#elif defined(__SIZEOF_INT__) +# define LZO_SIZEOF_INT (__SIZEOF_INT__) #endif +#endif +#ifndef LZO_SIZEOF_LONG #if defined(SIZEOF_LONG) # define LZO_SIZEOF_LONG (SIZEOF_LONG) +#elif defined(__SIZEOF_LONG__) +# define LZO_SIZEOF_LONG (__SIZEOF_LONG__) +#endif #endif +#ifndef LZO_SIZEOF_LONG_LONG #if defined(SIZEOF_LONG_LONG) # define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#elif defined(__SIZEOF_LONG_LONG__) +# define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) +#endif #endif +#ifndef LZO_SIZEOF___INT16 #if defined(SIZEOF___INT16) # define LZO_SIZEOF___INT16 (SIZEOF___INT16) #endif +#endif +#ifndef LZO_SIZEOF___INT32 #if defined(SIZEOF___INT32) # define LZO_SIZEOF___INT32 (SIZEOF___INT32) #endif +#endif +#ifndef LZO_SIZEOF___INT64 #if defined(SIZEOF___INT64) # define LZO_SIZEOF___INT64 (SIZEOF___INT64) #endif +#endif +#ifndef LZO_SIZEOF_VOID_P #if defined(SIZEOF_VOID_P) # define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#elif defined(__SIZEOF_POINTER__) +# define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) #endif +#endif +#ifndef LZO_SIZEOF_SIZE_T #if defined(SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#elif defined(__SIZEOF_SIZE_T__) +# define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) +#endif #endif +#ifndef LZO_SIZEOF_PTRDIFF_T #if defined(SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#elif defined(__SIZEOF_PTRDIFF_T__) +# define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) +#endif #endif #define __LZO_LSR(x,b) (((x)+0ul) >> (b)) #if !defined(LZO_SIZEOF_SHORT) @@ -1080,6 +2060,7 @@ extern "C" { # error "LZO_SIZEOF_SHORT" # endif #endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) #if !defined(LZO_SIZEOF_INT) # if (LZO_ARCH_CRAY_PVP) # define LZO_SIZEOF_INT 8 @@ -1101,6 +2082,7 @@ extern "C" { # error "LZO_SIZEOF_INT" # endif #endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) #if !defined(LZO_SIZEOF_LONG) # if (ULONG_MAX == LZO_0xffffffffL) # define LZO_SIZEOF_LONG 4 @@ -1110,6 +2092,8 @@ extern "C" { # define LZO_SIZEOF_LONG 2 # elif (__LZO_LSR(ULONG_MAX,31) == 1) # define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,39) == 1) +# define LZO_SIZEOF_LONG 5 # elif (__LZO_LSR(ULONG_MAX,63) == 1) # define LZO_SIZEOF_LONG 8 # elif (__LZO_LSR(ULONG_MAX,127) == 1) @@ -1118,11 +2102,12 @@ extern "C" { # error "LZO_SIZEOF_LONG" # endif #endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) #if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) #if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) # if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) # if (LZO_CC_GNUC >= 0x030300ul) -# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) # define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG # elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) # define LZO_SIZEOF_LONG_LONG 4 @@ -1136,7 +2121,7 @@ extern "C" { #if (LZO_ARCH_I086 && LZO_CC_DMC) #elif (LZO_CC_CILLY) && defined(__GNUC__) # define LZO_SIZEOF_LONG_LONG 8 -#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_SIZEOF_LONG_LONG 8 #elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) # define LZO_SIZEOF_LONG_LONG 8 @@ -1158,11 +2143,13 @@ extern "C" { # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) # define LZO_SIZEOF___INT64 8 -#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +#elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) # define LZO_SIZEOF___INT64 8 #elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) # define LZO_SIZEOF_LONG_LONG 8 -#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +#elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) #elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) @@ -1175,87 +2162,127 @@ extern "C" { # undef LZO_SIZEOF_LONG_LONG # endif #endif -#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +#if (LZO_CFG_NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(_NO_LONGLONG) # undef LZO_SIZEOF_LONG_LONG #endif -#if !defined(LZO_SIZEOF_VOID_P) -#if (LZO_ARCH_I086) -# define __LZO_WORDSIZE 2 -# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) -# define LZO_SIZEOF_VOID_P 2 -# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) -# define LZO_SIZEOF_VOID_P 4 +#if !defined(LZO_WORDSIZE) +#if (LZO_ARCH_ALPHA) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AMD64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AVR) +# define LZO_WORDSIZE 1 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define LZO_WORDSIZE 4 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_WORDSIZE 4 # else -# error "LZO_MM" +# define LZO_WORDSIZE 2 # endif -#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) -# define __LZO_WORDSIZE 1 +#elif (LZO_ARCH_I086) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_IA64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_M16C) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_SPU) +# define LZO_WORDSIZE 4 +#elif (LZO_ARCH_Z80) +# define LZO_WORDSIZE 1 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_WORDSIZE 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define LZO_WORDSIZE 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_WORDSIZE 8 +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LP64__) || defined(__LP64) || defined(_LP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_ARCH_AVR) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_H8300) # if defined(__NORMAL_MODE__) -# define __LZO_WORDSIZE 4 # define LZO_SIZEOF_VOID_P 2 # elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) -# define __LZO_WORDSIZE 4 # define LZO_SIZEOF_VOID_P 4 # else -# define __LZO_WORDSIZE 2 # define LZO_SIZEOF_VOID_P 2 # endif # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT # endif +#elif (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif #elif (LZO_ARCH_M16C) -# define __LZO_WORDSIZE 2 # if defined(__m32c_cpu__) || defined(__m32cm_cpu__) # define LZO_SIZEOF_VOID_P 4 # else # define LZO_SIZEOF_VOID_P 2 # endif +#elif (LZO_ARCH_SPU) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_ARCH_Z80) +# define LZO_SIZEOF_VOID_P 2 #elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) -# define __LZO_WORDSIZE 8 # define LZO_SIZEOF_VOID_P 4 -#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) -# define __LZO_WORDSIZE 8 -# define LZO_SIZEOF_VOID_P 8 -#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) -# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG #elif (LZO_OS_OS400 || defined(__OS400__)) -# define __LZO_WORDSIZE LZO_SIZEOF_LONG -# define LZO_SIZEOF_VOID_P 16 -# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG -# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# if defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# else +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# endif #elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) # define LZO_SIZEOF_VOID_P 8 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG -#elif (LZO_ARCH_SPU) -# if 0 -# define __LZO_WORDSIZE 16 -# endif -# define LZO_SIZEOF_VOID_P 4 -#else -# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG #endif #endif -#if !defined(LZO_WORDSIZE) -# if defined(__LZO_WORDSIZE) -# define LZO_WORDSIZE __LZO_WORDSIZE -# else -# define LZO_WORDSIZE LZO_SIZEOF_VOID_P -# endif +#if !defined(LZO_SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG #endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) #if !defined(LZO_SIZEOF_SIZE_T) #if (LZO_ARCH_I086 || LZO_ARCH_M16C) # define LZO_SIZEOF_SIZE_T 2 -#else +#endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P #endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) #endif #if !defined(LZO_SIZEOF_PTRDIFF_T) #if (LZO_ARCH_I086) @@ -1268,11 +2295,18 @@ extern "C" { # define LZO_SIZEOF_PTRDIFF_T 2 # endif # else -# error "LZO_MM" +# error "invalid LZO_ARCH_I086 memory model" # endif -#else +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T #endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) +#endif +#if !defined(LZO_WORDSIZE) +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P #endif #if (LZO_ABI_NEUTRAL_ENDIAN) # undef LZO_ABI_BIG_ENDIAN @@ -1284,7 +2318,7 @@ extern "C" { # define LZO_ABI_LITTLE_ENDIAN 1 #elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) # define LZO_ABI_LITTLE_ENDIAN 1 -#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390) +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) # if (__LITTLE_ENDIAN__ == 1) @@ -1300,6 +2334,19 @@ extern "C" { # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) # define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) +# if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +# elif defined(__BIG_ENDIAN) +# define LZO_ABI_BIG_ENDIAN 1 +# else +# define LZO_ABI_LITTLE_ENDIAN 1 +# endif +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) +# define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) @@ -1307,7 +2354,7 @@ extern "C" { #endif #endif #if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) -# error "this should not happen" +# error "unexpected configuration - check your compiler defines" #endif #if (LZO_ABI_BIG_ENDIAN) # define LZO_INFO_ABI_ENDIAN "be" @@ -1322,6 +2369,9 @@ extern "C" { #elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) # define LZO_ABI_ILP16 1 # define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_LP32 1 +# define LZO_INFO_ABI_PM "lp32" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_ILP32 1 # define LZO_INFO_ABI_PM "ilp32" @@ -1338,7 +2388,8 @@ extern "C" { # define LZO_ABI_IP32L64 1 # define LZO_INFO_ABI_PM "ip32l64" #endif -#if !defined(__LZO_LIBC_OVERRIDE) +#if 0 +#elif !defined(__LZO_LIBC_OVERRIDE) #if (LZO_LIBC_NAKED) # define LZO_INFO_LIBC "naked" #elif (LZO_LIBC_FREESTANDING) @@ -1349,6 +2400,9 @@ extern "C" { # define LZO_INFO_LIBC "isoc90" #elif (LZO_LIBC_ISOC99) # define LZO_INFO_LIBC "isoc99" +#elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" #elif defined(__dietlibc__) # define LZO_LIBC_DIETLIBC 1 # define LZO_INFO_LIBC "dietlibc" @@ -1357,13 +2411,13 @@ extern "C" { # define LZO_INFO_LIBC "newlib" #elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) # if defined(__UCLIBC_SUBLEVEL__) -# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) # else # define LZO_LIBC_UCLIBC 0x00090bL # endif -# define LZO_INFO_LIBC "uclibc" +# define LZO_INFO_LIBC "uc" "libc" #elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) -# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) # define LZO_INFO_LIBC "glibc" #elif (LZO_CC_MWERKS) && defined(__MSL__) # define LZO_LIBC_MSL __MSL__ @@ -1376,424 +2430,160 @@ extern "C" { # define LZO_INFO_LIBC "default" #endif #endif -#if !defined(__lzo_gnuc_extension__) -#if (LZO_CC_GNUC >= 0x020800ul) -# define __lzo_gnuc_extension__ __extension__ -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_gnuc_extension__ __extension__ -#else -# define __lzo_gnuc_extension__ /*empty*/ -#endif -#endif -#if !defined(__lzo_ua_volatile) -# define __lzo_ua_volatile volatile -#endif -#if !defined(__lzo_alignof) -#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) -# define __lzo_alignof(e) __alignof__(e) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) -# define __lzo_alignof(e) __alignof__(e) -#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) -# define __lzo_alignof(e) __alignof(e) -#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) -# define __lzo_alignof(e) __alignof__(e) -#endif -#endif -#if defined(__lzo_alignof) -# define __lzo_HAVE_alignof 1 -#endif -#if !defined(__lzo_constructor) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_constructor __attribute__((__constructor__,__used__)) -#elif (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_constructor __attribute__((__constructor__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_constructor __attribute__((__constructor__)) -#endif -#endif -#if defined(__lzo_constructor) -# define __lzo_HAVE_constructor 1 -#endif -#if !defined(__lzo_destructor) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_destructor __attribute__((__destructor__,__used__)) -#elif (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_destructor __attribute__((__destructor__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_destructor __attribute__((__destructor__)) -#endif -#endif -#if defined(__lzo_destructor) -# define __lzo_HAVE_destructor 1 -#endif -#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) -# error "this should not happen" -#endif -#if !defined(__lzo_inline) -#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) -#elif defined(__cplusplus) -# define __lzo_inline inline -#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) -# define __lzo_inline __inline -#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) -# define __lzo_inline __inline__ -#elif (LZO_CC_DMC) -# define __lzo_inline __inline -#elif (LZO_CC_INTELC) -# define __lzo_inline __inline -#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) -# define __lzo_inline __inline -#elif (LZO_CC_MSC && (_MSC_VER >= 900)) -# define __lzo_inline __inline -#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) -# define __lzo_inline __inline__ -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -# define __lzo_inline inline -#endif +#if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_CC_GNUC) +# define LZO_ASM_SYNTAX_GNUC 1 #endif -#if defined(__lzo_inline) -# define __lzo_HAVE_inline 1 +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) +# define __LZO_ASM_CLOBBER "memory" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #else -# define __lzo_inline /*empty*/ -#endif -#if !defined(__lzo_forceinline) -#if (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) -# define __lzo_forceinline __forceinline -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) -# define __lzo_forceinline __forceinline -#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) -# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +# define __LZO_ASM_CLOBBER "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_CC : "cc" +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #endif #endif -#if defined(__lzo_forceinline) -# define __lzo_HAVE_forceinline 1 -#else -# define __lzo_forceinline /*empty*/ -#endif -#if !defined(__lzo_noinline) -#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) -# define __lzo_noinline __attribute__((__noinline__,__used__)) -#elif (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) -# define __lzo_noinline __declspec(noinline) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_noinline __attribute__((__noinline__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) -# define __lzo_noinline __declspec(noinline) -#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) -# if defined(__cplusplus) -# else -# define __lzo_noinline __declspec(noinline) +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 # endif -#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) -# define __lzo_noinline __attribute__((__noinline__)) -#endif -#endif -#if defined(__lzo_noinline) -# define __lzo_HAVE_noinline 1 -#else -# define __lzo_noinline /*empty*/ -#endif -#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) -# error "this should not happen" -#endif -#if !defined(__lzo_noreturn) -#if (LZO_CC_GNUC >= 0x020700ul) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) -# define __lzo_noreturn __declspec(noreturn) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_noreturn __attribute__((__noreturn__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) -# define __lzo_noreturn __declspec(noreturn) -#endif -#endif -#if defined(__lzo_noreturn) -# define __lzo_HAVE_noreturn 1 -#else -# define __lzo_noreturn /*empty*/ -#endif -#if !defined(__lzo_nothrow) -#if (LZO_CC_GNUC >= 0x030300ul) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) -# define __lzo_nothrow __declspec(nothrow) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_nothrow __attribute__((__nothrow__)) -#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) -# define __lzo_nothrow __declspec(nothrow) -#endif -#endif -#if defined(__lzo_nothrow) -# define __lzo_HAVE_nothrow 1 -#else -# define __lzo_nothrow /*empty*/ -#endif -#if !defined(__lzo_restrict) -#if (LZO_CC_GNUC >= 0x030400ul) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_CLANG || LZO_CC_LLVM) -# define __lzo_restrict __restrict__ -#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) -# define __lzo_restrict __restrict -#endif -#endif -#if defined(__lzo_restrict) -# define __lzo_HAVE_restrict 1 -#else -# define __lzo_restrict /*empty*/ -#endif -#if !defined(__lzo_likely) && !defined(__lzo_unlikely) -#if (LZO_CC_GNUC >= 0x030200ul) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define __lzo_likely(e) (__builtin_expect(!!(e),1)) -# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) -#endif -#endif -#if defined(__lzo_likely) -# define __lzo_HAVE_likely 1 -#else -# define __lzo_likely(e) (e) -#endif -#if defined(__lzo_unlikely) -# define __lzo_HAVE_unlikely 1 -#else -# define __lzo_unlikely(e) (e) -#endif -#if !defined(LZO_UNUSED) -# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) -# define LZO_UNUSED(var) ((void) &var) -# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) -# define LZO_UNUSED(var) if (&var) ; else -# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define LZO_UNUSED(var) ((void) var) -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_UNUSED(var) if (&var) ; else -# elif (LZO_CC_KEILC) -# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} -# elif (LZO_CC_PACIFICC) -# define LZO_UNUSED(var) ((void) sizeof(var)) -# elif (LZO_CC_WATCOMC) && defined(__cplusplus) -# define LZO_UNUSED(var) ((void) var) -# else -# define LZO_UNUSED(var) ((void) &var) +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 # endif -#endif -#if !defined(LZO_UNUSED_FUNC) -# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) -# define LZO_UNUSED_FUNC(func) ((void) func) -# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) -# define LZO_UNUSED_FUNC(func) if (func) ; else -# elif (LZO_CC_CLANG || LZO_CC_LLVM) -# define LZO_UNUSED_FUNC(func) ((void) &func) -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_UNUSED_FUNC(func) if (func) ; else -# elif (LZO_CC_MSC) -# define LZO_UNUSED_FUNC(func) ((void) &func) -# elif (LZO_CC_KEILC || LZO_CC_PELLESC) -# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} -# else -# define LZO_UNUSED_FUNC(func) ((void) func) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 # endif -#endif -#if !defined(LZO_UNUSED_LABEL) -# if (LZO_CC_WATCOMC) && defined(__cplusplus) -# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l -# elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) -# define LZO_UNUSED_LABEL(l) if (0) goto l -# else -# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +#elif (LZO_ARCH_ARM) +# if defined(__ARM_FEATURE_UNALIGNED) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM+0) >= 6) && !defined(__TARGET_PROFILE_M) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif # endif -#endif -#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) -# if 0 -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var -# elif 0 && (LZO_CC_GNUC) -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var -# else -# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +#elif (LZO_ARCH_ARM64) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 # endif -#endif -#if !defined(LZO_UNCONST_CAST) -# if 0 && defined(__cplusplus) -# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e)) -# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) -# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e)))))) -# else -# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((const void *) (e))))) +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 # endif -#endif -#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) -# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; -# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; -# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; -# else -# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 # endif -#endif -#if !defined(LZO_COMPILE_TIME_ASSERT) -# if (LZO_CC_AZTECC) -# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} -# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# elif (LZO_CC_MSC && (_MSC_VER < 900)) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) -# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; -# else -# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +#elif (LZO_ARCH_CRIS) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 # endif -#endif -#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) -# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) -# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) -# define __lzo_cdecl __cdecl -# define __lzo_cdecl_atexit /*empty*/ -# define __lzo_cdecl_main __cdecl -# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) -# define __lzo_cdecl_qsort __pascal -# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) -# define __lzo_cdecl_qsort _stdcall -# else -# define __lzo_cdecl_qsort __cdecl -# endif -# elif (LZO_CC_WATCOMC) -# define __lzo_cdecl __cdecl -# else -# define __lzo_cdecl __cdecl -# define __lzo_cdecl_atexit __cdecl -# define __lzo_cdecl_main __cdecl -# define __lzo_cdecl_qsort __cdecl +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 # endif -# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) -# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) -# define __lzo_cdecl_sighandler __pascal -# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) -# define __lzo_cdecl_sighandler _stdcall -# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) -# define __lzo_cdecl_sighandler __clrcall -# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) -# if defined(_DLL) -# define __lzo_cdecl_sighandler _far _cdecl _loadds -# elif defined(_MT) -# define __lzo_cdecl_sighandler _far _cdecl -# else -# define __lzo_cdecl_sighandler _cdecl -# endif -# else -# define __lzo_cdecl_sighandler __cdecl +#elif (LZO_ARCH_I386) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 # endif -#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) -# define __lzo_cdecl __cdecl -#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) -# define __lzo_cdecl cdecl -#endif -#if !defined(__lzo_cdecl) -# define __lzo_cdecl /*empty*/ -#endif -#if !defined(__lzo_cdecl_atexit) -# define __lzo_cdecl_atexit /*empty*/ -#endif -#if !defined(__lzo_cdecl_main) -# define __lzo_cdecl_main /*empty*/ -#endif -#if !defined(__lzo_cdecl_qsort) -# define __lzo_cdecl_qsort /*empty*/ -#endif -#if !defined(__lzo_cdecl_sighandler) -# define __lzo_cdecl_sighandler /*empty*/ -#endif -#if !defined(__lzo_cdecl_va) -# define __lzo_cdecl_va __lzo_cdecl -#endif -#if !(LZO_CFG_NO_WINDOWS_H) -#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) -# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) -# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) -# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) -# else -# define LZO_HAVE_WINDOWS_H 1 +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 # endif -#endif -#endif -#if (LZO_ARCH_ALPHA) -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_AVOID_SHORT 1 -# define LZO_OPT_AVOID_USHORT 1 -#elif (LZO_ARCH_AMD64) -# define LZO_OPT_AVOID_INT_INDEX 1 -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# define LZO_OPT_UNALIGNED64 1 -#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) -#elif (LZO_ARCH_ARM) -# define LZO_OPT_AVOID_SHORT 1 -# define LZO_OPT_AVOID_USHORT 1 -#elif (LZO_ARCH_CRIS) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -#elif (LZO_ARCH_I386) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 #elif (LZO_ARCH_IA64) -# define LZO_OPT_AVOID_INT_INDEX 1 -# define LZO_OPT_AVOID_UINT_INDEX 1 -# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 #elif (LZO_ARCH_M68K) -# define LZO_OPT_PREFER_POSTINC 1 -# define LZO_OPT_PREFER_PREDEC 1 +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 # if defined(__mc68020__) && !defined(__mcoldfire__) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif # endif #elif (LZO_ARCH_MIPS) -# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 #elif (LZO_ARCH_POWERPC) -# define LZO_OPT_PREFER_PREINC 1 -# define LZO_OPT_PREFER_PREDEC 1 +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 # if (LZO_ABI_BIG_ENDIAN) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif # endif #elif (LZO_ARCH_S390) -# define LZO_OPT_UNALIGNED16 1 -# define LZO_OPT_UNALIGNED32 1 -# if (LZO_SIZEOF_SIZE_T == 8) -# define LZO_OPT_UNALIGNED64 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif # endif #elif (LZO_ARCH_SH) -# define LZO_OPT_PREFER_POSTINC 1 -# define LZO_OPT_PREFER_PREDEC 1 +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 #endif #ifndef LZO_CFG_NO_INLINE_ASM -#if (LZO_CC_LLVM) +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_INLINE_ASM 1 +#elif (LZO_CC_LLVM) # define LZO_CFG_NO_INLINE_ASM 1 #endif #endif +#if (LZO_CFG_NO_INLINE_ASM) +# undef LZO_ASM_SYNTAX_MSC +# undef LZO_ASM_SYNTAX_GNUC +# undef __LZO_ASM_CLOBBER +# undef __LZO_ASM_CLOBBER_LIST_CC +# undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY +# undef __LZO_ASM_CLOBBER_LIST_EMPTY +#endif #ifndef LZO_CFG_NO_UNALIGNED #if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) # define LZO_CFG_NO_UNALIGNED 1 @@ -1804,25 +2594,6 @@ extern "C" { # undef LZO_OPT_UNALIGNED32 # undef LZO_OPT_UNALIGNED64 #endif -#if (LZO_CFG_NO_INLINE_ASM) -#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) -# define LZO_ASM_SYNTAX_MSC 1 -#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) -#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) -#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) -# define LZO_ASM_SYNTAX_GNUC 1 -#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) -# define LZO_ASM_SYNTAX_GNUC 1 -#endif -#if (LZO_ASM_SYNTAX_GNUC) -#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) -# define __LZO_ASM_CLOBBER "ax" -#elif (LZO_CC_INTELC) -# define __LZO_ASM_CLOBBER "memory" -#else -# define __LZO_ASM_CLOBBER "cc", "memory" -#endif -#endif #if defined(__LZO_INFOSTR_MM) #elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) # define __LZO_INFOSTR_MM "" @@ -1866,6 +2637,381 @@ extern "C" { #define LZO_INFO_STRING \ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER +#if !(LZO_CFG_SKIP_LZO_TYPES) +#if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) +# error "missing defines for sizes" +#endif +#if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) +# error "missing defines for sizes" +#endif +#if !defined(lzo_llong_t) +#if (LZO_SIZEOF_LONG_LONG+0 > 0) +__lzo_gnuc_extension__ typedef long long lzo_llong_t__; +__lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; +# define lzo_llong_t lzo_llong_t__ +# define lzo_ullong_t lzo_ullong_t__ +#endif +#endif +#if !defined(lzo_int16e_t) +#if (LZO_SIZEOF_LONG == 2) +# define lzo_int16e_t long +# define lzo_uint16e_t unsigned long +#elif (LZO_SIZEOF_INT == 2) +# define lzo_int16e_t int +# define lzo_uint16e_t unsigned int +#elif (LZO_SIZEOF_SHORT == 2) +# define lzo_int16e_t short int +# define lzo_uint16e_t unsigned short int +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) + typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); + typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); +# define lzo_int16e_t lzo_int16e_hi_t__ +# define lzo_uint16e_t lzo_uint16e_hi_t__ +#elif (LZO_SIZEOF___INT16 == 2) +# define lzo_int16e_t __int16 +# define lzo_uint16e_t unsigned __int16 +#else +#endif +#endif +#if defined(lzo_int16e_t) +# define LZO_SIZEOF_LZO_INT16E_T 2 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) +#endif +#if !defined(lzo_int32e_t) +#if (LZO_SIZEOF_LONG == 4) +# define lzo_int32e_t long int +# define lzo_uint32e_t unsigned long int +#elif (LZO_SIZEOF_INT == 4) +# define lzo_int32e_t int +# define lzo_uint32e_t unsigned int +#elif (LZO_SIZEOF_SHORT == 4) +# define lzo_int32e_t short int +# define lzo_uint32e_t unsigned short int +#elif (LZO_SIZEOF_LONG_LONG == 4) +# define lzo_int32e_t lzo_llong_t +# define lzo_uint32e_t lzo_ullong_t +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +#elif (LZO_SIZEOF___INT32 == 4) +# define lzo_int32e_t __int32 +# define lzo_uint32e_t unsigned __int32 +#else +#endif +#endif +#if defined(lzo_int32e_t) +# define LZO_SIZEOF_LZO_INT32E_T 4 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) +#endif +#if !defined(lzo_int64e_t) +#if (LZO_SIZEOF___INT64 == 8) +# if (LZO_CC_BORLANDC) && !(LZO_CFG_TYPE_PREFER___INT64) +# define LZO_CFG_TYPE_PREFER___INT64 1 +# endif +#endif +#if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int64e_t int +# define lzo_uint64e_t unsigned int +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG == 8) +# define lzo_int64e_t long int +# define lzo_uint64e_t unsigned long int +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG +#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_TYPE_PREFER___INT64) +# define lzo_int64e_t lzo_llong_t +# define lzo_uint64e_t lzo_ullong_t +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0ll) +# define LZO_UINT64_C(c) ((c) + 0ull) +# elif 0 +# define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) +# define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) +# else +# define LZO_INT64_C(c) (c##LL) +# define LZO_UINT64_C(c) (c##ULL) +# endif +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF_LONG_LONG +#elif (LZO_SIZEOF___INT64 == 8) +# define lzo_int64e_t __int64 +# define lzo_uint64e_t unsigned __int64 +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0i64) +# define LZO_UINT64_C(c) ((c) + 0ui64) +# else +# define LZO_INT64_C(c) (c##i64) +# define LZO_UINT64_C(c) (c##ui64) +# endif +# define LZO_SIZEOF_LZO_INT64E_T LZO_SIZEOF___INT64 +#else +#endif +#endif +#if defined(lzo_int64e_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) +#endif +#if !defined(lzo_int32l_t) +#if defined(lzo_int32e_t) +# define lzo_int32l_t lzo_int32e_t +# define lzo_uint32l_t lzo_uint32e_t +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T +#elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int32l_t int +# define lzo_uint32l_t unsigned int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= 4) +# define lzo_int32l_t long int +# define lzo_uint32l_t unsigned long int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG +#else +# error "lzo_int32l_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) +#endif +#if !defined(lzo_int64l_t) +#if defined(lzo_int64e_t) +# define lzo_int64l_t lzo_int64e_t +# define lzo_uint64l_t lzo_uint64e_t +# define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T +#else +#endif +#endif +#if defined(lzo_int64l_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) +#endif +#if !defined(lzo_int32f_t) +#if (LZO_SIZEOF_SIZE_T >= 8) +# define lzo_int32f_t lzo_int64l_t +# define lzo_uint32f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T +#else +# define lzo_int32f_t lzo_int32l_t +# define lzo_uint32f_t lzo_uint32l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) +#endif +#if !defined(lzo_int64f_t) +#if defined(lzo_int64l_t) +# define lzo_int64f_t lzo_int64l_t +# define lzo_uint64f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T +#else +#endif +#endif +#if defined(lzo_int64f_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) +#endif +#if !defined(lzo_intptr_t) +#if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) +# define __LZO_INTPTR_T_IS_POINTER 1 + typedef char* lzo_intptr_t; + typedef char* lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P +#elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) + typedef __w64 int lzo_intptr_t; + typedef __w64 unsigned int lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) +# define lzo_intptr_t short +# define lzo_uintptr_t unsigned short +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT +#elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_intptr_t int +# define lzo_uintptr_t unsigned int +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t long +# define lzo_uintptr_t unsigned long +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG +#elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t lzo_int64l_t +# define lzo_uintptr_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T +#else +# error "lzo_intptr_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) +#endif +#if !defined(lzo_word_t) +#if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) +#if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) +# define lzo_word_t lzo_uintptr_t +# define lzo_sword_t lzo_intptr_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T +#elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) +# define lzo_word_t unsigned long +# define lzo_sword_t long +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG +#elif (LZO_WORDSIZE == LZO_SIZEOF_INT) +# define lzo_word_t unsigned int +# define lzo_sword_t int +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT +#elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) +# define lzo_word_t unsigned short +# define lzo_sword_t short +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT +#elif (LZO_WORDSIZE == 1) +# define lzo_word_t unsigned char +# define lzo_sword_t signed char +# define LZO_SIZEOF_LZO_WORD_T 1 +#elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) +# define lzo_word_t lzo_uint64l_t +# define lzo_sword_t lzo_int64l_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +#elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) +#if 0 + typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); + typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); +# define lzo_word_t lzo_word_t +# define lzo_sword_t lzo_sword_t +# define LZO_SIZEOF_LZO_WORD_T 16 +#endif +#else +# error "lzo_word_t" +#endif +#endif +#endif +#if 1 && defined(lzo_word_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) +#endif +#if 1 +#define lzo_int8_t signed char +#define lzo_uint8_t unsigned char +#define LZO_SIZEOF_LZO_INT8_T 1 +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) +#endif +#if defined(lzo_int16e_t) +#define lzo_int16_t lzo_int16e_t +#define lzo_uint16_t lzo_uint16e_t +#define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) +#endif +#if defined(lzo_int32e_t) +#define lzo_int32_t lzo_int32e_t +#define lzo_uint32_t lzo_uint32e_t +#define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) +#endif +#if defined(lzo_int64e_t) +#define lzo_int64_t lzo_int64e_t +#define lzo_uint64_t lzo_uint64e_t +#define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) +#endif +#if 1 +#define lzo_int_least32_t lzo_int32l_t +#define lzo_uint_least32_t lzo_uint32l_t +#define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) +#endif +#if defined(lzo_int64l_t) +#define lzo_int_least64_t lzo_int64l_t +#define lzo_uint_least64_t lzo_uint64l_t +#define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) +#endif +#if 1 +#define lzo_int_fast32_t lzo_int32f_t +#define lzo_uint_fast32_t lzo_uint32f_t +#define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) +#endif +#if defined(lzo_int64f_t) +#define lzo_int_fast64_t lzo_int64f_t +#define lzo_uint_fast64_t lzo_uint64f_t +#define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) +#endif +#if !defined(LZO_INT16_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) ((c) + 0) +# define LZO_UINT16_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) ((c) + 0L) +# define LZO_UINT16_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) (c) +# define LZO_UINT16_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) (c##L) +# define LZO_UINT16_C(c) (c##UL) +# else +# error "LZO_INT16_C" +# endif +#endif +#if !defined(LZO_INT32_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) ((c) + 0) +# define LZO_UINT32_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) ((c) + 0L) +# define LZO_UINT32_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) (c) +# define LZO_UINT32_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) (c##L) +# define LZO_UINT32_C(c) (c##UL) +# elif (LZO_SIZEOF_LONG_LONG >= 4) +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# else +# error "LZO_INT32_C" +# endif +#endif +#if !defined(LZO_INT64_C) && defined(lzo_int64l_t) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) ((c) + 0) +# define LZO_UINT64_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) ((c) + 0L) +# define LZO_UINT64_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) (c) +# define LZO_UINT64_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) (c##L) +# define LZO_UINT64_C(c) (c##UL) +# else +# error "LZO_INT64_C" +# endif +#endif +#endif #endif @@ -1874,7 +3020,7 @@ extern "C" { #undef LZO_HAVE_CONFIG_H #include "minilzo.h" -#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2060) +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2080) # error "version mismatch in miniLZO source files" #endif @@ -1886,23 +3032,9 @@ extern "C" { #define __LZO_CONF_H 1 #if !defined(__LZO_IN_MINILZO) -#if (LZO_CFG_FREESTANDING) +#if defined(LZO_CFG_FREESTANDING) && (LZO_CFG_FREESTANDING) # define LZO_LIBC_FREESTANDING 1 # define LZO_OS_FREESTANDING 1 -# define ACC_LIBC_FREESTANDING 1 -# define ACC_OS_FREESTANDING 1 -#endif -#if (LZO_CFG_NO_UNALIGNED) -# define ACC_CFG_NO_UNALIGNED 1 -#endif -#if (LZO_ARCH_GENERIC) -# define ACC_ARCH_GENERIC 1 -#endif -#if (LZO_ABI_NEUTRAL_ENDIAN) -# define ACC_ABI_NEUTRAL_ENDIAN 1 -#endif -#if (LZO_HAVE_CONFIG_H) -# define ACC_CONFIG_NO_HEADER 1 #endif #if defined(LZO_CFG_EXTRA_CONFIG_HEADER) # include LZO_CFG_EXTRA_CONFIG_HEADER @@ -1911,22 +3043,27 @@ extern "C" { # error "include this file first" #endif #include "lzo/lzoconf.h" +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER2) +# include LZO_CFG_EXTRA_CONFIG_HEADER2 +#endif #endif -#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED) +#if (LZO_VERSION < 0x2080) || !defined(__LZOCONF_H_INCLUDED) # error "version mismatch" #endif -#if (LZO_CC_BORLANDC && LZO_ARCH_I086) -# pragma option -h +#if (LZO_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1100)) +# pragma warning(disable: 4702) #endif - #if (LZO_CC_MSC && (_MSC_VER >= 1000)) # pragma warning(disable: 4127 4701) +# pragma warning(disable: 4514 4710 4711) #endif #if (LZO_CC_MSC && (_MSC_VER >= 1300)) # pragma warning(disable: 4820) -# pragma warning(disable: 4514 4710 4711) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1800)) +# pragma warning(disable: 4746) #endif #if (LZO_CC_SUNPROC) @@ -1937,48 +3074,15 @@ extern "C" { #endif #endif -#if (__LZO_MMODEL_HUGE) && !(LZO_HAVE_MM_HUGE_PTR) -# error "this should not happen - check defines for __huge" -#endif - -#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING) -#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) -# define ACC_WANT_ACC_INCD_H 1 -# define ACC_WANT_ACC_INCE_H 1 -# define ACC_WANT_ACC_INCI_H 1 +#if defined(__LZO_IN_MINILZO) || (LZO_CFG_FREESTANDING) #elif 1 # include <string.h> #else -# define ACC_WANT_ACC_INCD_H 1 +# define LZO_WANT_ACC_INCD_H 1 #endif - -#if (LZO_ARCH_I086) -# define ACC_MM_AHSHIFT LZO_MM_AHSHIFT -# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0]) -# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1]) -# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o))) -#endif - -#if !defined(lzo_uintptr_t) -# if defined(__LZO_MMODEL_HUGE) -# define lzo_uintptr_t unsigned long -# elif 1 && defined(LZO_OS_OS400) && (LZO_SIZEOF_VOID_P == 16) -# define __LZO_UINTPTR_T_IS_POINTER 1 - typedef char* lzo_uintptr_t; -# define lzo_uintptr_t lzo_uintptr_t -# elif (LZO_SIZEOF_SIZE_T == LZO_SIZEOF_VOID_P) -# define lzo_uintptr_t size_t -# elif (LZO_SIZEOF_LONG == LZO_SIZEOF_VOID_P) -# define lzo_uintptr_t unsigned long -# elif (LZO_SIZEOF_INT == LZO_SIZEOF_VOID_P) -# define lzo_uintptr_t unsigned int -# elif (LZO_SIZEOF_LONG_LONG == LZO_SIZEOF_VOID_P) -# define lzo_uintptr_t unsigned long long -# else -# define lzo_uintptr_t size_t -# endif +#if defined(LZO_HAVE_CONFIG_H) +# define LZO_CFG_NO_CONFIG_HEADER 1 #endif -LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) #if 1 && !defined(LZO_CFG_FREESTANDING) #if 1 && !defined(HAVE_STRING_H) @@ -2002,6 +3106,23 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) #include <string.h> #endif +#if 1 || defined(lzo_int8_t) || defined(lzo_uint8_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint8_t) == 1) +#endif +#if 1 || defined(lzo_int16_t) || defined(lzo_uint16_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint16_t) == 2) +#endif +#if 1 || defined(lzo_int32_t) || defined(lzo_uint32_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32_t) == 4) +#endif +#if defined(lzo_int64_t) || defined(lzo_uint64_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64_t) == 8) +#endif + #if (LZO_CFG_FREESTANDING) # undef HAVE_MEMCMP # undef HAVE_MEMCPY @@ -2012,28 +3133,28 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) #if !(HAVE_MEMCMP) # undef memcmp # define memcmp(a,b,c) lzo_memcmp(a,b,c) -#elif !(__LZO_MMODEL_HUGE) +#else # undef lzo_memcmp # define lzo_memcmp(a,b,c) memcmp(a,b,c) #endif #if !(HAVE_MEMCPY) # undef memcpy # define memcpy(a,b,c) lzo_memcpy(a,b,c) -#elif !(__LZO_MMODEL_HUGE) +#else # undef lzo_memcpy # define lzo_memcpy(a,b,c) memcpy(a,b,c) #endif #if !(HAVE_MEMMOVE) # undef memmove # define memmove(a,b,c) lzo_memmove(a,b,c) -#elif !(__LZO_MMODEL_HUGE) +#else # undef lzo_memmove # define lzo_memmove(a,b,c) memmove(a,b,c) #endif #if !(HAVE_MEMSET) # undef memset # define memset(a,b,c) lzo_memset(a,b,c) -#elif !(__LZO_MMODEL_HUGE) +#else # undef lzo_memset # define lzo_memset(a,b,c) memset(a,b,c) #endif @@ -2058,27 +3179,29 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) # define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) #endif -#if !defined(__lzo_inline) -# define __lzo_inline /*empty*/ -#endif -#if !defined(__lzo_forceinline) -# define __lzo_forceinline /*empty*/ -#endif -#if !defined(__lzo_noinline) -# define __lzo_noinline /*empty*/ -#endif - #if (LZO_CFG_PGO) -# undef __acc_likely -# undef __acc_unlikely # undef __lzo_likely # undef __lzo_unlikely -# define __acc_likely(e) (e) -# define __acc_unlikely(e) (e) # define __lzo_likely(e) (e) # define __lzo_unlikely(e) (e) #endif +#undef _ +#undef __ +#undef ___ +#undef ____ +#undef _p0 +#undef _p1 +#undef _p2 +#undef _p3 +#undef _p4 +#undef _s0 +#undef _s1 +#undef _s2 +#undef _s3 +#undef _s4 +#undef _ww + #if 1 # define LZO_BYTE(x) ((unsigned char) (x)) #else @@ -2097,84 +3220,548 @@ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) #define LZO_SIZE(bits) (1u << (bits)) #define LZO_MASK(bits) (LZO_SIZE(bits) - 1) -#define LZO_LSIZE(bits) (1ul << (bits)) -#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) - #define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) #define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) #if !defined(DMUL) #if 0 -# define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b))) +# define DMUL(a,b) ((lzo_xint) ((lzo_uint32_t)(a) * (lzo_uint32_t)(b))) #else # define DMUL(a,b) ((lzo_xint) ((a) * (b))) #endif #endif -#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386 || LZO_ARCH_POWERPC) -# if (LZO_SIZEOF_SHORT == 2) -# define LZO_UNALIGNED_OK_2 1 -# endif -# if (LZO_SIZEOF_INT == 4) -# define LZO_UNALIGNED_OK_4 1 -# endif +#ifndef __LZO_FUNC_H +#define __LZO_FUNC_H 1 + +#if !defined(LZO_BITOPS_USE_ASM_BITSCAN) && !defined(LZO_BITOPS_USE_GNUC_BITSCAN) && !defined(LZO_BITOPS_USE_MSC_BITSCAN) +#if 1 && (LZO_ARCH_AMD64) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_ASM_SYNTAX_GNUC) +#define LZO_BITOPS_USE_ASM_BITSCAN 1 +#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul)))) +#define LZO_BITOPS_USE_GNUC_BITSCAN 1 +#elif (LZO_OS_WIN32 || LZO_OS_WIN64) && ((LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 1010)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) +#define LZO_BITOPS_USE_MSC_BITSCAN 1 +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +#include <intrin.h> #endif -#if 1 && (LZO_ARCH_AMD64) -# if defined(LZO_UINT64_MAX) -# define LZO_UNALIGNED_OK_8 1 -# endif +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) #endif -#if (LZO_CFG_NO_UNALIGNED) -# undef LZO_UNALIGNED_OK_2 -# undef LZO_UNALIGNED_OK_4 -# undef LZO_UNALIGNED_OK_8 -#endif - -#undef UA_GET16 -#undef UA_SET16 -#undef UA_COPY16 -#undef UA_GET32 -#undef UA_SET32 -#undef UA_COPY32 -#undef UA_GET64 -#undef UA_SET64 -#undef UA_COPY64 -#if defined(LZO_UNALIGNED_OK_2) - LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(unsigned short) == 2) -# if 1 && defined(ACC_UA_COPY16) -# define UA_GET16 ACC_UA_GET16 -# define UA_SET16 ACC_UA_SET16 -# define UA_COPY16 ACC_UA_COPY16 -# else -# define UA_GET16(p) (* (__lzo_ua_volatile const lzo_ushortp) (__lzo_ua_volatile const lzo_voidp) (p)) -# define UA_SET16(p,v) ((* (__lzo_ua_volatile lzo_ushortp) (__lzo_ua_volatile lzo_voidp) (p)) = (unsigned short) (v)) -# define UA_COPY16(d,s) UA_SET16(d, UA_GET16(s)) -# endif +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64) +#pragma intrinsic(_BitScanReverse64) +#pragma intrinsic(_BitScanForward64) #endif -#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) - LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) -# if 1 && defined(ACC_UA_COPY32) -# define UA_GET32 ACC_UA_GET32 -# define UA_SET32 ACC_UA_SET32 -# define UA_COPY32 ACC_UA_COPY32 -# else -# define UA_GET32(p) (* (__lzo_ua_volatile const lzo_uint32p) (__lzo_ua_volatile const lzo_voidp) (p)) -# define UA_SET32(p,v) ((* (__lzo_ua_volatile lzo_uint32p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint32) (v)) -# define UA_COPY32(d,s) UA_SET32(d, UA_GET32(s)) -# endif #endif -#if defined(LZO_UNALIGNED_OK_8) - LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64) == 8) -# if 1 && defined(ACC_UA_COPY64) -# define UA_GET64 ACC_UA_GET64 -# define UA_SET64 ACC_UA_SET64 -# define UA_COPY64 ACC_UA_COPY64 -# else -# define UA_GET64(p) (* (__lzo_ua_volatile const lzo_uint64p) (__lzo_ua_volatile const lzo_voidp) (p)) -# define UA_SET64(p,v) ((* (__lzo_ua_volatile lzo_uint64p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint64) (v)) -# define UA_COPY64(d,s) UA_SET64(d, UA_GET64(s)) -# endif +#endif + +__lzo_static_forceinline unsigned lzo_bitops_ctlz32_func(lzo_uint32_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) + unsigned long r; (void) _BitScanReverse(&r, v); return (unsigned) r ^ 31; +#define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint32_t r; + __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r ^ 31; +#define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT == 4) + unsigned r; r = (unsigned) __builtin_clz(v); return r; +#define lzo_bitops_ctlz32(v) ((unsigned) __builtin_clz(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} + +#if defined(lzo_uint64_t) +__lzo_static_forceinline unsigned lzo_bitops_ctlz64_func(lzo_uint64_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) + unsigned long r; (void) _BitScanReverse64(&r, v); return (unsigned) r ^ 63; +#define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint64_t r; + __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r ^ 63; +#define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_clzl(v); return r; +#define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzl(v)) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG == 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_clzll(v); return r; +#define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzll(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} +#endif + +__lzo_static_forceinline unsigned lzo_bitops_cttz32_func(lzo_uint32_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) + unsigned long r; (void) _BitScanForward(&r, v); return (unsigned) r; +#define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint32_t r; + __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r; +#define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT >= 4) + unsigned r; r = (unsigned) __builtin_ctz(v); return r; +#define lzo_bitops_cttz32(v) ((unsigned) __builtin_ctz(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} + +#if defined(lzo_uint64_t) +__lzo_static_forceinline unsigned lzo_bitops_cttz64_func(lzo_uint64_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) + unsigned long r; (void) _BitScanForward64(&r, v); return (unsigned) r; +#define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint64_t r; + __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r; +#define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG >= 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_ctzl(v); return r; +#define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzl(v)) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG >= 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_ctzll(v); return r; +#define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzll(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} +#endif + +#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +static void __attribute__((__unused__)) +#else +__lzo_static_forceinline void +#endif +lzo_bitops_unused_funcs(void) +{ + LZO_UNUSED_FUNC(lzo_bitops_ctlz32_func); + LZO_UNUSED_FUNC(lzo_bitops_cttz32_func); +#if defined(lzo_uint64_t) + LZO_UNUSED_FUNC(lzo_bitops_ctlz64_func); + LZO_UNUSED_FUNC(lzo_bitops_cttz64_func); +#endif + LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); +} + +#if defined(__lzo_alignof) && !(LZO_CFG_NO_UNALIGNED) +#ifndef __lzo_memops_tcheck +#define __lzo_memops_tcheck(t,a,b) ((void)0, sizeof(t) == (a) && __lzo_alignof(t) == (b)) +#endif +#endif +#ifndef lzo_memops_TU0p +#define lzo_memops_TU0p void __LZO_MMODEL * +#endif +#ifndef lzo_memops_TU1p +#define lzo_memops_TU1p unsigned char __LZO_MMODEL * +#endif +#ifndef lzo_memops_TU2p +#if (LZO_OPT_UNALIGNED16) +typedef lzo_uint16_t __lzo_may_alias lzo_memops_TU2; +#define lzo_memops_TU2p volatile lzo_memops_TU2 * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU2_struct,2) +typedef struct lzo_memops_TU2_struct lzo_memops_TU2; +#else +struct lzo_memops_TU2_struct { unsigned char a[2]; } __lzo_may_alias; +typedef struct lzo_memops_TU2_struct lzo_memops_TU2; +#endif +#ifndef lzo_memops_TU2p +#define lzo_memops_TU2p lzo_memops_TU2 * +#endif +#endif +#ifndef lzo_memops_TU4p +#if (LZO_OPT_UNALIGNED32) +typedef lzo_uint32_t __lzo_may_alias lzo_memops_TU4; +#define lzo_memops_TU4p volatile lzo_memops_TU4 __LZO_MMODEL * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU4_struct,4) +typedef struct lzo_memops_TU4_struct lzo_memops_TU4; +#else +struct lzo_memops_TU4_struct { unsigned char a[4]; } __lzo_may_alias; +typedef struct lzo_memops_TU4_struct lzo_memops_TU4; +#endif +#ifndef lzo_memops_TU4p +#define lzo_memops_TU4p lzo_memops_TU4 __LZO_MMODEL * +#endif +#endif +#ifndef lzo_memops_TU8p +#if (LZO_OPT_UNALIGNED64) +typedef lzo_uint64_t __lzo_may_alias lzo_memops_TU8; +#define lzo_memops_TU8p volatile lzo_memops_TU8 __LZO_MMODEL * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU8_struct,8) +typedef struct lzo_memops_TU8_struct lzo_memops_TU8; +#else +struct lzo_memops_TU8_struct { unsigned char a[8]; } __lzo_may_alias; +typedef struct lzo_memops_TU8_struct lzo_memops_TU8; +#endif +#ifndef lzo_memops_TU8p +#define lzo_memops_TU8p lzo_memops_TU8 __LZO_MMODEL * +#endif +#endif +#ifndef lzo_memops_set_TU1p +#define lzo_memops_set_TU1p volatile lzo_memops_TU1p +#endif +#ifndef lzo_memops_move_TU1p +#define lzo_memops_move_TU1p lzo_memops_TU1p +#endif +#define LZO_MEMOPS_SET1(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__1 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__1[0] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET2(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__2 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__2[0] = LZO_BYTE(cc); d__2[1] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET3(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__3 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__3[0] = LZO_BYTE(cc); d__3[1] = LZO_BYTE(cc); d__3[2] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET4(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__4 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__4[0] = LZO_BYTE(cc); d__4[1] = LZO_BYTE(cc); d__4[2] = LZO_BYTE(cc); d__4[3] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE1(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__1 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__1 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__1[0] = s__1[0]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE2(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__2 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__2 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__2[0] = s__2[0]; d__2[1] = s__2[1]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE3(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__3 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__3 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__3[0] = s__3[0]; d__3[1] = s__3[1]; d__3[2] = s__3[2]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE4(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__4 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__4 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__4[0] = s__4[0]; d__4[1] = s__4[1]; d__4[2] = s__4[2]; d__4[3] = s__4[3]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE8(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__8 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__8 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__8[0] = s__8[0]; d__8[1] = s__8[1]; d__8[2] = s__8[2]; d__8[3] = s__8[3]; \ + d__8[4] = s__8[4]; d__8[5] = s__8[5]; d__8[6] = s__8[6]; d__8[7] = s__8[7]; \ + LZO_BLOCK_END +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU1p)0)==1) +#define LZO_MEMOPS_COPY1(dd,ss) LZO_MEMOPS_MOVE1(dd,ss) +#if (LZO_OPT_UNALIGNED16) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2) +#define LZO_MEMOPS_COPY2(dd,ss) \ + * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss) +#elif defined(__lzo_memops_tcheck) +#define LZO_MEMOPS_COPY2(dd,ss) \ + LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU2,2,1)) { \ + * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE2(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY2(dd,ss) LZO_MEMOPS_MOVE2(dd,ss) +#endif +#if (LZO_OPT_UNALIGNED32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4) +#define LZO_MEMOPS_COPY4(dd,ss) \ + * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss) +#elif defined(__lzo_memops_tcheck) +#define LZO_MEMOPS_COPY4(dd,ss) \ + LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU4,4,1)) { \ + * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE4(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY4(dd,ss) LZO_MEMOPS_MOVE4(dd,ss) +#endif +#if (LZO_WORDSIZE != 8) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END +#else +#if (LZO_OPT_UNALIGNED64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8) +#define LZO_MEMOPS_COPY8(dd,ss) \ + * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss) +#elif (LZO_OPT_UNALIGNED32) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END +#elif defined(__lzo_memops_tcheck) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN if (__lzo_memops_tcheck(lzo_memops_TU8,8,1)) { \ + * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE8(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY8(dd,ss) LZO_MEMOPS_MOVE8(dd,ss) +#endif +#endif +#define LZO_MEMOPS_COPYN(dd,ss,nn) \ + LZO_BLOCK_BEGIN \ + lzo_memops_TU1p d__n = (lzo_memops_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_TU1p s__n = (const lzo_memops_TU1p) (const lzo_memops_TU0p) (ss); \ + lzo_uint n__n = (nn); \ + while ((void)0, n__n >= 8) { LZO_MEMOPS_COPY8(d__n, s__n); d__n += 8; s__n += 8; n__n -= 8; } \ + if ((void)0, n__n >= 4) { LZO_MEMOPS_COPY4(d__n, s__n); d__n += 4; s__n += 4; n__n -= 4; } \ + if ((void)0, n__n > 0) do { *d__n++ = *s__n++; } while (--n__n > 0); \ + LZO_BLOCK_END + +__lzo_static_forceinline lzo_uint16_t lzo_memops_get_le16(const lzo_voidp ss) +{ + lzo_uint16_t v; +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY2(&v, ss); +#elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + const lzo_memops_TU2p s = (const lzo_memops_TU2p) ss; + unsigned long vv; + __asm__("lhbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); + v = (lzo_uint16_t) vv; +#else + const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; + v = (lzo_uint16_t) (((lzo_uint16_t)s[0]) | ((lzo_uint16_t)s[1] << 8)); +#endif + return v; +} +#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE16(ss) * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss) +#else +#define LZO_MEMOPS_GET_LE16(ss) lzo_memops_get_le16(ss) +#endif + +__lzo_static_forceinline lzo_uint32_t lzo_memops_get_le32(const lzo_voidp ss) +{ + lzo_uint32_t v; +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY4(&v, ss); +#elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + const lzo_memops_TU4p s = (const lzo_memops_TU4p) ss; + unsigned long vv; + __asm__("lwbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); + v = (lzo_uint32_t) vv; +#else + const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; + v = (lzo_uint32_t) (((lzo_uint32_t)s[0]) | ((lzo_uint32_t)s[1] << 8) | ((lzo_uint32_t)s[2] << 16) | ((lzo_uint32_t)s[3] << 24)); +#endif + return v; +} +#if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE32(ss) * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss) +#else +#define LZO_MEMOPS_GET_LE32(ss) lzo_memops_get_le32(ss) +#endif + +#if (LZO_OPT_UNALIGNED64) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE64(ss) * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss) +#endif + +__lzo_static_forceinline lzo_uint16_t lzo_memops_get_ne16(const lzo_voidp ss) +{ + lzo_uint16_t v; + LZO_MEMOPS_COPY2(&v, ss); + return v; +} +#if (LZO_OPT_UNALIGNED16) +#define LZO_MEMOPS_GET_NE16(ss) * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss) +#else +#define LZO_MEMOPS_GET_NE16(ss) lzo_memops_get_ne16(ss) +#endif + +__lzo_static_forceinline lzo_uint32_t lzo_memops_get_ne32(const lzo_voidp ss) +{ + lzo_uint32_t v; + LZO_MEMOPS_COPY4(&v, ss); + return v; +} +#if (LZO_OPT_UNALIGNED32) +#define LZO_MEMOPS_GET_NE32(ss) * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss) +#else +#define LZO_MEMOPS_GET_NE32(ss) lzo_memops_get_ne32(ss) +#endif + +#if (LZO_OPT_UNALIGNED64) +#define LZO_MEMOPS_GET_NE64(ss) * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss) +#endif + +__lzo_static_forceinline void lzo_memops_put_le16(lzo_voidp dd, lzo_uint16_t vv) +{ +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY2(dd, &vv); +#elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + lzo_memops_TU2p d = (lzo_memops_TU2p) dd; + unsigned long v = vv; + __asm__("sthbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); +#else + lzo_memops_TU1p d = (lzo_memops_TU1p) dd; + d[0] = LZO_BYTE((vv ) & 0xff); + d[1] = LZO_BYTE((vv >> 8) & 0xff); +#endif +} +#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_PUT_LE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_LE16(dd,vv) lzo_memops_put_le16(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_le32(lzo_voidp dd, lzo_uint32_t vv) +{ +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY4(dd, &vv); +#elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + lzo_memops_TU4p d = (lzo_memops_TU4p) dd; + unsigned long v = vv; + __asm__("stwbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); +#else + lzo_memops_TU1p d = (lzo_memops_TU1p) dd; + d[0] = LZO_BYTE((vv ) & 0xff); + d[1] = LZO_BYTE((vv >> 8) & 0xff); + d[2] = LZO_BYTE((vv >> 16) & 0xff); + d[3] = LZO_BYTE((vv >> 24) & 0xff); +#endif +} +#if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_PUT_LE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_LE32(dd,vv) lzo_memops_put_le32(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_ne16(lzo_voidp dd, lzo_uint16_t vv) +{ + LZO_MEMOPS_COPY2(dd, &vv); +} +#if (LZO_OPT_UNALIGNED16) +#define LZO_MEMOPS_PUT_NE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_NE16(dd,vv) lzo_memops_put_ne16(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_ne32(lzo_voidp dd, lzo_uint32_t vv) +{ + LZO_MEMOPS_COPY4(dd, &vv); +} +#if (LZO_OPT_UNALIGNED32) +#define LZO_MEMOPS_PUT_NE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_NE32(dd,vv) lzo_memops_put_ne32(dd,vv) +#endif + +#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +static void __attribute__((__unused__)) +#else +__lzo_static_forceinline void +#endif +lzo_memops_unused_funcs(void) +{ + LZO_UNUSED_FUNC(lzo_memops_get_le16); + LZO_UNUSED_FUNC(lzo_memops_get_le32); + LZO_UNUSED_FUNC(lzo_memops_get_ne16); + LZO_UNUSED_FUNC(lzo_memops_get_ne32); + LZO_UNUSED_FUNC(lzo_memops_put_le16); + LZO_UNUSED_FUNC(lzo_memops_put_le32); + LZO_UNUSED_FUNC(lzo_memops_put_ne16); + LZO_UNUSED_FUNC(lzo_memops_put_ne32); + LZO_UNUSED_FUNC(lzo_memops_unused_funcs); +} + +#endif + +#ifndef UA_SET1 +#define UA_SET1 LZO_MEMOPS_SET1 +#endif +#ifndef UA_SET2 +#define UA_SET2 LZO_MEMOPS_SET2 +#endif +#ifndef UA_SET3 +#define UA_SET3 LZO_MEMOPS_SET3 +#endif +#ifndef UA_SET4 +#define UA_SET4 LZO_MEMOPS_SET4 +#endif +#ifndef UA_MOVE1 +#define UA_MOVE1 LZO_MEMOPS_MOVE1 +#endif +#ifndef UA_MOVE2 +#define UA_MOVE2 LZO_MEMOPS_MOVE2 +#endif +#ifndef UA_MOVE3 +#define UA_MOVE3 LZO_MEMOPS_MOVE3 +#endif +#ifndef UA_MOVE4 +#define UA_MOVE4 LZO_MEMOPS_MOVE4 +#endif +#ifndef UA_MOVE8 +#define UA_MOVE8 LZO_MEMOPS_MOVE8 +#endif +#ifndef UA_COPY1 +#define UA_COPY1 LZO_MEMOPS_COPY1 +#endif +#ifndef UA_COPY2 +#define UA_COPY2 LZO_MEMOPS_COPY2 +#endif +#ifndef UA_COPY3 +#define UA_COPY3 LZO_MEMOPS_COPY3 +#endif +#ifndef UA_COPY4 +#define UA_COPY4 LZO_MEMOPS_COPY4 +#endif +#ifndef UA_COPY8 +#define UA_COPY8 LZO_MEMOPS_COPY8 +#endif +#ifndef UA_COPYN +#define UA_COPYN LZO_MEMOPS_COPYN +#endif +#ifndef UA_COPYN_X +#define UA_COPYN_X LZO_MEMOPS_COPYN +#endif +#ifndef UA_GET_LE16 +#define UA_GET_LE16 LZO_MEMOPS_GET_LE16 +#endif +#ifndef UA_GET_LE32 +#define UA_GET_LE32 LZO_MEMOPS_GET_LE32 +#endif +#ifdef LZO_MEMOPS_GET_LE64 +#ifndef UA_GET_LE64 +#define UA_GET_LE64 LZO_MEMOPS_GET_LE64 +#endif +#endif +#ifndef UA_GET_NE16 +#define UA_GET_NE16 LZO_MEMOPS_GET_NE16 +#endif +#ifndef UA_GET_NE32 +#define UA_GET_NE32 LZO_MEMOPS_GET_NE32 +#endif +#ifdef LZO_MEMOPS_GET_NE64 +#ifndef UA_GET_NE64 +#define UA_GET_NE64 LZO_MEMOPS_GET_NE64 +#endif +#endif +#ifndef UA_PUT_LE16 +#define UA_PUT_LE16 LZO_MEMOPS_PUT_LE16 +#endif +#ifndef UA_PUT_LE32 +#define UA_PUT_LE32 LZO_MEMOPS_PUT_LE32 +#endif +#ifndef UA_PUT_NE16 +#define UA_PUT_NE16 LZO_MEMOPS_PUT_NE16 +#endif +#ifndef UA_PUT_NE32 +#define UA_PUT_NE32 LZO_MEMOPS_PUT_NE32 #endif #define MEMCPY8_DS(dest,src,len) \ @@ -2195,25 +3782,10 @@ LZO_EXTERN(const lzo_bytep) lzo_copyright(void); extern "C" { #endif -#if !defined(lzo_uintptr_t) -# if (__LZO_MMODEL_HUGE) -# define lzo_uintptr_t unsigned long -# else -# define lzo_uintptr_t acc_uintptr_t -# ifdef __ACC_INTPTR_T_IS_POINTER -# define __LZO_UINTPTR_T_IS_POINTER 1 -# endif -# endif -#endif - #if (LZO_ARCH_I086) -#define PTR(a) ((lzo_bytep) (a)) -#define PTR_ALIGNED_4(a) ((ACC_PTR_FP_OFF(a) & 3) == 0) -#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0) +#error "LZO_ARCH_I086 is unsupported" #elif (LZO_MM_PVP) -#define PTR(a) ((lzo_bytep) (a)) -#define PTR_ALIGNED_8(a) ((((lzo_uintptr_t)(a)) >> 61) == 0) -#define PTR_ALIGNED2_8(a,b) ((((lzo_uintptr_t)(a)|(lzo_uintptr_t)(b)) >> 61) == 0) +#error "LZO_MM_PVP is unsupported" #else #define PTR(a) ((lzo_uintptr_t) (a)) #define PTR_LINEAR(a) PTR(a) @@ -2243,24 +3815,28 @@ typedef union unsigned long a_ulong; lzo_int a_lzo_int; lzo_uint a_lzo_uint; - lzo_int32 a_lzo_int32; - lzo_uint32 a_lzo_uint32; -#if defined(LZO_UINT64_MAX) - lzo_int64 a_lzo_int64; - lzo_uint64 a_lzo_uint64; -#endif + lzo_xint a_lzo_xint; + lzo_int16_t a_lzo_int16_t; + lzo_uint16_t a_lzo_uint16_t; + lzo_int32_t a_lzo_int32_t; + lzo_uint32_t a_lzo_uint32_t; +#if defined(lzo_uint64_t) + lzo_int64_t a_lzo_int64_t; + lzo_uint64_t a_lzo_uint64_t; +#endif + size_t a_size_t; ptrdiff_t a_ptrdiff_t; lzo_uintptr_t a_lzo_uintptr_t; - lzo_voidp a_lzo_voidp; void * a_void_p; - lzo_bytep a_lzo_bytep; - lzo_bytepp a_lzo_bytepp; - lzo_uintp a_lzo_uintp; - lzo_uint * a_lzo_uint_p; - lzo_uint32p a_lzo_uint32p; - lzo_uint32 * a_lzo_uint32_p; - unsigned char * a_uchar_p; char * a_char_p; + unsigned char * a_uchar_p; + const void * a_c_void_p; + const char * a_c_char_p; + const unsigned char * a_c_uchar_p; + lzo_voidp a_lzo_voidp; + lzo_bytep a_lzo_bytep; + const lzo_voidp a_c_lzo_voidp; + const lzo_bytep a_c_lzo_bytep; } lzo_full_align_t; @@ -2276,18 +3852,14 @@ lzo_full_align_t; #ifndef LZO_DICT_USE_PTR #define LZO_DICT_USE_PTR 1 -#if 0 && (LZO_ARCH_I086) -# undef LZO_DICT_USE_PTR -# define LZO_DICT_USE_PTR 0 -#endif #endif #if (LZO_DICT_USE_PTR) # define lzo_dict_t const lzo_bytep -# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +# define lzo_dict_p lzo_dict_t * #else # define lzo_dict_t lzo_uint -# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +# define lzo_dict_p lzo_dict_t * #endif #endif @@ -2300,10 +3872,9 @@ __lzo_ptr_linear(const lzo_voidp ptr) lzo_uintptr_t p; #if (LZO_ARCH_I086) - p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr)); +#error "LZO_ARCH_I086 is unsupported" #elif (LZO_MM_PVP) - p = (lzo_uintptr_t) (ptr); - p = (p << 3) | (p >> 61); +#error "LZO_MM_PVP is unsupported" #else p = (lzo_uintptr_t) PTR_LINEAR(ptr); #endif @@ -2314,9 +3885,8 @@ __lzo_ptr_linear(const lzo_voidp ptr) LZO_PUBLIC(unsigned) __lzo_align_gap(const lzo_voidp ptr, lzo_uint size) { -#if defined(__LZO_UINTPTR_T_IS_POINTER) - size_t n = (size_t) ptr; - n = (((n + size - 1) / size) * size) - n; +#if (__LZO_UINTPTR_T_IS_POINTER) +#error "__LZO_UINTPTR_T_IS_POINTER is unsupported" #else lzo_uintptr_t p, n; p = __lzo_ptr_linear(ptr); @@ -2342,7 +3912,7 @@ static const char __lzo_copyright[] = #else "\r\n\n" "LZO data compression library.\n" - "$Copyright: LZO Copyright (C) 1996-2011 Markus Franz Xaver Johannes Oberhumer\n" + "$Copyright: LZO Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer\n" "<markus@oberhumer.com>\n" "http://www.oberhumer.com $\n\n" "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" @@ -2352,11 +3922,7 @@ static const char __lzo_copyright[] = LZO_PUBLIC(const lzo_bytep) lzo_copyright(void) { -#if (LZO_OS_DOS16 && LZO_CC_TURBOC) - return (lzo_voidp) __lzo_copyright; -#else return (const lzo_bytep) __lzo_copyright; -#endif } LZO_PUBLIC(unsigned) @@ -2393,16 +3959,16 @@ _lzo_version_date(void) #define LZO_NMAX 5552 #define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 -#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); -#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); -#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); -#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1) +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2) +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4) +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8) -LZO_PUBLIC(lzo_uint32) -lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len) +LZO_PUBLIC(lzo_uint32_t) +lzo_adler32(lzo_uint32_t adler, const lzo_bytep buf, lzo_uint len) { - lzo_uint32 s1 = adler & 0xffff; - lzo_uint32 s2 = (adler >> 16) & 0xffff; + lzo_uint32_t s1 = adler & 0xffff; + lzo_uint32_t s2 = (adler >> 16) & 0xffff; unsigned k; if (buf == NULL) @@ -2459,8 +4025,8 @@ lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len) LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP) - const lzo_hbyte_p p1 = (const lzo_hbyte_p) s1; - const lzo_hbyte_p p2 = (const lzo_hbyte_p) s2; + const lzo_hbyte_p p1 = LZO_STATIC_CAST(const lzo_hbyte_p, s1); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, s2); if __lzo_likely(len > 0) do { int d = *p1 - *p2; @@ -2476,8 +4042,8 @@ LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY) - lzo_hbyte_p p1 = (lzo_hbyte_p) dest; - const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); if (!(len > 0) || p1 == p2) return dest; do @@ -2491,8 +4057,8 @@ LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE) - lzo_hbyte_p p1 = (lzo_hbyte_p) dest; - const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); if (!(len > 0) || p1 == p2) return dest; if (p1 < p2) @@ -2514,16 +4080,17 @@ LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p sr return memmove(dest, src, len); #endif } -LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len) +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int cc, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET) - lzo_hbyte_p p = (lzo_hbyte_p) s; + lzo_hbyte_p p = LZO_STATIC_CAST(lzo_hbyte_p, s); + unsigned char c = LZO_ITRUNC(unsigned char, cc); if __lzo_likely(len > 0) do - *p++ = (unsigned char) c; + *p++ = c; while __lzo_likely(--len > 0); return s; #else - return memset(s, c, len); + return memset(s, cc, len); #endif } #undef LZOLIB_PUBLIC @@ -2532,103 +4099,28 @@ LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len) #if !defined(__LZO_IN_MINILZO) -#define ACC_WANT_ACC_CHK_CH 1 -#undef ACCCHK_ASSERT - - ACCCHK_ASSERT_IS_SIGNED_T(lzo_int) - ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) - - ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32) - ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32) - ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) - ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4) -#if defined(LZO_UINT64_MAX) - ACCCHK_ASSERT(sizeof(lzo_uint64) == 8) - ACCCHK_ASSERT_IS_SIGNED_T(lzo_int64) - ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint64) -#endif - -#if !defined(__LZO_UINTPTR_T_IS_POINTER) - ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) -#endif - ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) - - ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) - ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32)) - ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint)) - ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint)) +#define LZO_WANT_ACC_CHK_CH 1 +#undef LZOCHK_ASSERT + LZOCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) + LZOCHK_ASSERT_IS_SIGNED_T(lzo_int) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) +#if !(__LZO_UINTPTR_T_IS_POINTER) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) #endif -#undef ACCCHK_ASSERT + LZOCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) -#define WANT_lzo_bitops_clz32 1 -#define WANT_lzo_bitops_clz64 1 -#define WANT_lzo_bitops_ctz32 1 -#define WANT_lzo_bitops_ctz64 1 - -#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) -#include <intrin.h> -#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0 -#pragma intrinsic(_BitScanReverse) -static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v) -{ - unsigned long r; - (void) _BitScanReverse(&r, v); - return (unsigned) r; -} -#define lzo_bitops_clz32 lzo_bitops_clz32 -#endif -#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0 -#pragma intrinsic(_BitScanReverse64) -static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v) -{ - unsigned long r; - (void) _BitScanReverse64(&r, v); - return (unsigned) r; -} -#define lzo_bitops_clz64 lzo_bitops_clz64 -#endif -#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) -#pragma intrinsic(_BitScanForward) -static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v) -{ - unsigned long r; - (void) _BitScanForward(&r, v); - return (unsigned) r; -} -#define lzo_bitops_ctz32 lzo_bitops_ctz32 -#endif -#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) -#pragma intrinsic(_BitScanForward64) -static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v) -{ - unsigned long r; - (void) _BitScanForward64(&r, v); - return (unsigned) r; -} -#define lzo_bitops_ctz64 lzo_bitops_ctz64 #endif +#undef LZOCHK_ASSERT -#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul)))) -#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) -#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v)) -#endif -#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) -#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v)) -#endif -#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) -#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v)) -#endif -#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) -#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v)) -#endif -#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32) -#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v)) -#endif -#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX) -#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v)) -#endif +union lzo_config_check_union { + lzo_uint a[2]; + unsigned char b[2*LZO_MAX(8,sizeof(lzo_uint))]; +#if defined(lzo_uint64_t) + lzo_uint64_t c[2]; #endif +}; #if 0 #define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off))) @@ -2642,73 +4134,101 @@ static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off) LZO_PUBLIC(int) _lzo_config_check(void) { - lzo_bool r = 1; - union { - lzo_xint a[2]; unsigned char b[2*LZO_MAX(8,sizeof(lzo_xint))]; -#if defined(LZO_UNALIGNED_OK_8) - lzo_uint64 c[2]; -#endif - unsigned short x[2]; lzo_uint32 y[2]; lzo_uint z[2]; - } u; +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030100ul && LZO_CC_CLANG < 0x030300ul)) +# if 0 + volatile +# endif +#endif + union lzo_config_check_union u; lzo_voidp p; + unsigned r = 1; u.a[0] = u.a[1] = 0; p = u2p(&u, 0); r &= ((* (lzo_bytep) p) == 0); -#if !defined(LZO_CFG_NO_CONFIG_CHECK) -#if defined(LZO_ABI_BIG_ENDIAN) +#if !(LZO_CFG_NO_CONFIG_CHECK) +#if (LZO_ABI_BIG_ENDIAN) u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128; p = u2p(&u, 0); r &= ((* (lzo_uintp) p) == 128); #endif -#if defined(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ABI_LITTLE_ENDIAN) u.a[0] = u.a[1] = 0; u.b[0] = 128; p = u2p(&u, 0); r &= ((* (lzo_uintp) p) == 128); #endif -#if defined(LZO_UNALIGNED_OK_2) u.a[0] = u.a[1] = 0; - u.b[0] = 1; u.b[sizeof(unsigned short) + 1] = 2; + u.b[0] = 1; u.b[3] = 2; p = u2p(&u, 1); - r &= ((* (lzo_ushortp) p) == 0); + r &= UA_GET_NE16(p) == 0; + r &= UA_GET_LE16(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE16(p) == 128; + u.b[2] = 129; + r &= UA_GET_LE16(p) == LZO_UINT16_C(0x8180); +#if (LZO_ABI_BIG_ENDIAN) + r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8081); +#endif +#if (LZO_ABI_LITTLE_ENDIAN) + r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8180); #endif -#if defined(LZO_UNALIGNED_OK_4) u.a[0] = u.a[1] = 0; - u.b[0] = 3; u.b[sizeof(lzo_uint32) + 1] = 4; + u.b[0] = 3; u.b[5] = 4; p = u2p(&u, 1); - r &= ((* (lzo_uint32p) p) == 0); + r &= UA_GET_NE32(p) == 0; + r &= UA_GET_LE32(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE32(p) == 128; + u.b[2] = 129; u.b[3] = 130; u.b[4] = 131; + r &= UA_GET_LE32(p) == LZO_UINT32_C(0x83828180); +#if (LZO_ABI_BIG_ENDIAN) + r &= UA_GET_NE32(p) == LZO_UINT32_C(0x80818283); #endif -#if defined(LZO_UNALIGNED_OK_8) +#if (LZO_ABI_LITTLE_ENDIAN) + r &= UA_GET_NE32(p) == LZO_UINT32_C(0x83828180); +#endif +#if defined(UA_GET_NE64) u.c[0] = u.c[1] = 0; - u.b[0] = 5; u.b[sizeof(lzo_uint64) + 1] = 6; + u.b[0] = 5; u.b[9] = 6; p = u2p(&u, 1); - r &= ((* (lzo_uint64p) p) == 0); -#endif -#if defined(lzo_bitops_clz32) - { unsigned i; lzo_uint32 v = 1; - for (i = 0; i < 32; i++, v <<= 1) - r &= lzo_bitops_clz32(v) == 31 - i; - } -#endif -#if defined(lzo_bitops_clz64) - { unsigned i; lzo_uint64 v = 1; - for (i = 0; i < 64; i++, v <<= 1) - r &= lzo_bitops_clz64(v) == 63 - i; - } -#endif -#if defined(lzo_bitops_ctz32) - { unsigned i; lzo_uint32 v = 1; - for (i = 0; i < 32; i++, v <<= 1) - r &= lzo_bitops_ctz32(v) == i; - } -#endif -#if defined(lzo_bitops_ctz64) - { unsigned i; lzo_uint64 v = 1; - for (i = 0; i < 64; i++, v <<= 1) - r &= lzo_bitops_ctz64(v) == i; - } -#endif -#endif + u.c[0] = u.c[1] = 0; + r &= UA_GET_NE64(p) == 0; +#if defined(UA_GET_LE64) + r &= UA_GET_LE64(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE64(p) == 128; +#endif +#endif +#if defined(lzo_bitops_ctlz32) + { unsigned i = 0; lzo_uint32_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_ctlz32(v) == 31 - i; + r &= lzo_bitops_ctlz32_func(v) == 31 - i; + }} +#endif +#if defined(lzo_bitops_ctlz64) + { unsigned i = 0; lzo_uint64_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_ctlz64(v) == 63 - i; + r &= lzo_bitops_ctlz64_func(v) == 63 - i; + }} +#endif +#if defined(lzo_bitops_cttz32) + { unsigned i = 0; lzo_uint32_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_cttz32(v) == i; + r &= lzo_bitops_cttz32_func(v) == i; + }} +#endif +#if defined(lzo_bitops_cttz64) + { unsigned i = 0; lzo_uint64_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_cttz64(v) == i; + r &= lzo_bitops_cttz64_func(v) == i; + }} +#endif +#endif + LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); return r == 1 ? LZO_E_OK : LZO_E_ERROR; } @@ -2722,11 +4242,11 @@ __lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, #if defined(__LZO_IN_MINILZO) #elif (LZO_CC_MSC && ((_MSC_VER) < 700)) #else -#define ACC_WANT_ACC_CHK_CH 1 -#undef ACCCHK_ASSERT -#define ACCCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#define LZO_WANT_ACC_CHK_CH 1 +#undef LZOCHK_ASSERT +#define LZOCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) #endif -#undef ACCCHK_ASSERT +#undef LZOCHK_ASSERT if (v == 0) return LZO_E_ERROR; @@ -2734,7 +4254,7 @@ __lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, r = (s1 == -1 || s1 == (int) sizeof(short)) && (s2 == -1 || s2 == (int) sizeof(int)) && (s3 == -1 || s3 == (int) sizeof(long)) && - (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32_t)) && (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && (s7 == -1 || s7 == (int) sizeof(char *)) && @@ -2777,11 +4297,11 @@ int __far __pascal LibMain ( int a, short b, short c, long d ) #if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) -#if 1 && defined(UA_GET32) +#if 1 && defined(UA_GET_LE32) #undef LZO_DICT_USE_PTR #define LZO_DICT_USE_PTR 0 #undef lzo_dict_t -#define lzo_dict_t unsigned short +#define lzo_dict_t lzo_uint16_t #endif #define LZO_NEED_DICT_H 1 @@ -3086,81 +4606,7 @@ DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) #endif #if 1 && defined(DO_COMPRESS) && !defined(do_compress) -# define do_compress LZO_CPP_ECONCAT2(DO_COMPRESS,_core) -#endif - -#if defined(UA_GET64) && (LZO_ABI_BIG_ENDIAN) -# define WANT_lzo_bitops_clz64 1 -#elif defined(UA_GET64) && (LZO_ABI_LITTLE_ENDIAN) -# define WANT_lzo_bitops_ctz64 1 -#elif defined(UA_GET32) && (LZO_ABI_BIG_ENDIAN) -# define WANT_lzo_bitops_clz32 1 -#elif defined(UA_GET32) && (LZO_ABI_LITTLE_ENDIAN) -# define WANT_lzo_bitops_ctz32 1 -#endif - -#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) -#include <intrin.h> -#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0 -#pragma intrinsic(_BitScanReverse) -static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v) -{ - unsigned long r; - (void) _BitScanReverse(&r, v); - return (unsigned) r; -} -#define lzo_bitops_clz32 lzo_bitops_clz32 -#endif -#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0 -#pragma intrinsic(_BitScanReverse64) -static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v) -{ - unsigned long r; - (void) _BitScanReverse64(&r, v); - return (unsigned) r; -} -#define lzo_bitops_clz64 lzo_bitops_clz64 -#endif -#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) -#pragma intrinsic(_BitScanForward) -static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v) -{ - unsigned long r; - (void) _BitScanForward(&r, v); - return (unsigned) r; -} -#define lzo_bitops_ctz32 lzo_bitops_ctz32 -#endif -#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) -#pragma intrinsic(_BitScanForward64) -static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v) -{ - unsigned long r; - (void) _BitScanForward64(&r, v); - return (unsigned) r; -} -#define lzo_bitops_ctz64 lzo_bitops_ctz64 -#endif - -#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul)))) -#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) -#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v)) -#endif -#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) -#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v)) -#endif -#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) -#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v)) -#endif -#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) -#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v)) -#endif -#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32) -#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v)) -#endif -#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX) -#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v)) -#endif +# define do_compress LZO_PP_ECONCAT2(DO_COMPRESS,_core) #endif static __lzo_noinline lzo_uint @@ -3168,7 +4614,7 @@ do_compress ( const lzo_bytep in , lzo_uint in_len, lzo_bytep out, lzo_uintp out_len, lzo_uint ti, lzo_voidp wrkmem) { - register const lzo_bytep ip; + const lzo_bytep ip; lzo_bytep op; const lzo_bytep const in_end = in + in_len; const lzo_bytep const ip_end = in + in_len - 20; @@ -3207,8 +4653,8 @@ next: goto literal; try_match: -#if defined(UA_GET32) - if (UA_GET32(m_pos) != UA_GET32(ip)) +#if (LZO_OPT_UNALIGNED32) + if (UA_GET_NE32(m_pos) != UA_GET_NE32(ip)) #else if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3]) #endif @@ -3223,50 +4669,43 @@ literal: lzo_uint m_off; lzo_uint m_len; { - lzo_uint32 dv; + lzo_uint32_t dv; lzo_uint dindex; literal: ip += 1 + ((ip - ii) >> 5); next: if __lzo_unlikely(ip >= ip_end) break; - dv = UA_GET32(ip); + dv = UA_GET_LE32(ip); dindex = DINDEX(dv,ip); GINDEX(m_off,m_pos,in+dict,dindex,in); UPDATE_I(dict,0,dindex,ip,in); - if __lzo_unlikely(dv != UA_GET32(m_pos)) + if __lzo_unlikely(dv != UA_GET_LE32(m_pos)) goto literal; } #endif ii -= ti; ti = 0; { - register lzo_uint t = pd(ip,ii); + lzo_uint t = pd(ip,ii); if (t != 0) { if (t <= 3) { - op[-2] |= LZO_BYTE(t); -#if defined(UA_COPY32) - UA_COPY32(op, ii); + op[-2] = LZO_BYTE(op[-2] | t); +#if (LZO_OPT_UNALIGNED32) + UA_COPY4(op, ii); op += t; #else { do *op++ = *ii++; while (--t > 0); } #endif } -#if defined(UA_COPY32) || defined(UA_COPY64) +#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) else if (t <= 16) { *op++ = LZO_BYTE(t - 3); -#if defined(UA_COPY64) - UA_COPY64(op, ii); - UA_COPY64(op+8, ii+8); -#else - UA_COPY32(op, ii); - UA_COPY32(op+4, ii+4); - UA_COPY32(op+8, ii+8); - UA_COPY32(op+12, ii+12); -#endif + UA_COPY8(op, ii); + UA_COPY8(op+8, ii+8); op += t; } #endif @@ -3276,31 +4715,21 @@ next: *op++ = LZO_BYTE(t - 3); else { - register lzo_uint tt = t - 18; + lzo_uint tt = t - 18; *op++ = 0; while __lzo_unlikely(tt > 255) { tt -= 255; -#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) - * (volatile unsigned char *) op++ = 0; -#else - *op++ = 0; -#endif + UA_SET1(op, 0); + op++; } assert(tt > 0); *op++ = LZO_BYTE(tt); } -#if defined(UA_COPY32) || defined(UA_COPY64) +#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) do { -#if defined(UA_COPY64) - UA_COPY64(op, ii); - UA_COPY64(op+8, ii+8); -#else - UA_COPY32(op, ii); - UA_COPY32(op+4, ii+4); - UA_COPY32(op+8, ii+8); - UA_COPY32(op+12, ii+12); -#endif + UA_COPY8(op, ii); + UA_COPY8(op+8, ii+8); op += 16; ii += 16; t -= 16; } while (t >= 16); if (t > 0) #endif @@ -3310,26 +4739,26 @@ next: } m_len = 4; { -#if defined(UA_GET64) - lzo_uint64 v; - v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len); +#if (LZO_OPT_UNALIGNED64) + lzo_uint64_t v; + v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); if __lzo_unlikely(v == 0) { do { m_len += 8; - v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len); + v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); if __lzo_unlikely(ip + m_len >= ip_end) goto m_len_done; } while (v == 0); } -#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_clz64) - m_len += lzo_bitops_clz64(v) / CHAR_BIT; +#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz64) + m_len += lzo_bitops_ctlz64(v) / CHAR_BIT; #elif (LZO_ABI_BIG_ENDIAN) if ((v >> (64 - CHAR_BIT)) == 0) do { v <<= CHAR_BIT; m_len += 1; } while ((v >> (64 - CHAR_BIT)) == 0); -#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz64) - m_len += lzo_bitops_ctz64(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz64) + m_len += lzo_bitops_cttz64(v) / CHAR_BIT; #elif (LZO_ABI_LITTLE_ENDIAN) if ((v & UCHAR_MAX) == 0) do { v >>= CHAR_BIT; @@ -3340,26 +4769,30 @@ next: m_len += 1; } while (ip[m_len] == m_pos[m_len]); #endif -#elif defined(UA_GET32) - lzo_uint32 v; - v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len); +#elif (LZO_OPT_UNALIGNED32) + lzo_uint32_t v; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); if __lzo_unlikely(v == 0) { do { m_len += 4; - v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len); + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); + if (v != 0) + break; + m_len += 4; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); if __lzo_unlikely(ip + m_len >= ip_end) goto m_len_done; } while (v == 0); } -#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_clz32) - m_len += lzo_bitops_clz32(v) / CHAR_BIT; +#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz32) + m_len += lzo_bitops_ctlz32(v) / CHAR_BIT; #elif (LZO_ABI_BIG_ENDIAN) if ((v >> (32 - CHAR_BIT)) == 0) do { v <<= CHAR_BIT; m_len += 1; } while ((v >> (32 - CHAR_BIT)) == 0); -#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz32) - m_len += lzo_bitops_ctz32(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz32) + m_len += lzo_bitops_cttz32(v) / CHAR_BIT; #elif (LZO_ABI_LITTLE_ENDIAN) if ((v & UCHAR_MAX) == 0) do { v >>= CHAR_BIT; @@ -3374,6 +4807,27 @@ next: if __lzo_unlikely(ip[m_len] == m_pos[m_len]) { do { m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; if __lzo_unlikely(ip + m_len >= ip_end) goto m_len_done; } while (ip[m_len] == m_pos[m_len]); @@ -3407,11 +4861,8 @@ m_len_done: while __lzo_unlikely(m_len > 255) { m_len -= 255; -#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) - * (volatile unsigned char *) op++ = 0; -#else - *op++ = 0; -#endif + UA_SET1(op, 0); + op++; } *op++ = LZO_BYTE(m_len); } @@ -3430,11 +4881,8 @@ m_len_done: while __lzo_unlikely(m_len > 255) { m_len -= 255; -#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) - * (volatile unsigned char *) op++ = 0; -#else - *op++ = 0; -#endif + UA_SET1(op, 0); + op++; } *op++ = LZO_BYTE(m_len); } @@ -3485,7 +4933,7 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, if (op == out && t <= 238) *op++ = LZO_BYTE(17 + t); else if (t <= 3) - op[-2] |= LZO_BYTE(t); + op[-2] = LZO_BYTE(op[-2] | t); else if (t <= 18) *op++ = LZO_BYTE(t - 3); else @@ -3496,17 +4944,14 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, while (tt > 255) { tt -= 255; -#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) - - * (volatile unsigned char *) op++ = 0; -#else - *op++ = 0; -#endif + UA_SET1(op, 0); + op++; } assert(tt > 0); *op++ = LZO_BYTE(tt); } - do *op++ = *ii++; while (--t > 0); + UA_COPYN(op, ii, t); + op += t; } *op++ = M4_MARKER | 1; @@ -3543,10 +4988,13 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, #undef TEST_IP #undef TEST_OP +#undef TEST_IP_AND_TEST_OP #undef TEST_LB #undef TEST_LBO #undef NEED_IP #undef NEED_OP +#undef TEST_IV +#undef TEST_OV #undef HAVE_TEST_IP #undef HAVE_TEST_OP #undef HAVE_NEED_IP @@ -3561,6 +5009,7 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, # if (LZO_TEST_OVERRUN_INPUT >= 2) # define NEED_IP(x) \ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun # endif #endif @@ -3572,12 +5021,13 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, # undef TEST_OP # define NEED_OP(x) \ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun # endif #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) -# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun -# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +# define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun #else # define TEST_LB(m_pos) ((void) 0) # define TEST_LBO(m_pos,o) ((void) 0) @@ -3598,15 +5048,27 @@ DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, # define TEST_OP 1 #endif +#if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) +#elif defined(HAVE_TEST_IP) +# define TEST_IP_AND_TEST_OP TEST_IP +#elif defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP TEST_OP +#else +# define TEST_IP_AND_TEST_OP 1 +#endif + #if defined(NEED_IP) # define HAVE_NEED_IP 1 #else # define NEED_IP(x) ((void) 0) +# define TEST_IV(x) ((void) 0) #endif #if defined(NEED_OP) # define HAVE_NEED_OP 1 #else # define NEED_OP(x) ((void) 0) +# define TEST_OV(x) ((void) 0) #endif #if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) @@ -3623,14 +5085,14 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, lzo_voidp wrkmem ) #endif { - register lzo_bytep op; - register const lzo_bytep ip; - register lzo_uint t; + lzo_bytep op; + const lzo_bytep ip; + lzo_uint t; #if defined(COPY_DICT) lzo_uint m_off; const lzo_bytep dict_end; #else - register const lzo_bytep m_pos; + const lzo_bytep m_pos; #endif const lzo_bytep const ip_end = in + in_len; @@ -3665,43 +5127,45 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, op = out; ip = in; + NEED_IP(1); if (*ip > 17) { t = *ip++ - 17; if (t < 4) goto match_next; - assert(t > 0); NEED_OP(t); NEED_IP(t+1); + assert(t > 0); NEED_OP(t); NEED_IP(t+3); do *op++ = *ip++; while (--t > 0); goto first_literal_run; } - while (TEST_IP && TEST_OP) + for (;;) { + NEED_IP(3); t = *ip++; if (t >= 16) goto match; if (t == 0) { - NEED_IP(1); while (*ip == 0) { t += 255; ip++; + TEST_IV(t); NEED_IP(1); } t += 15 + *ip++; } - assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); -#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) + assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) t += 3; if (t >= 8) do { - UA_COPY64(op,ip); + UA_COPY8(op,ip); op += 8; ip += 8; t -= 8; } while (t >= 8); if (t >= 4) { - UA_COPY32(op,ip); + UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } if (t > 0) @@ -3709,19 +5173,19 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } } -#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) -#if !defined(LZO_UNALIGNED_OK_4) +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) if (PTR_ALIGNED2_4(op,ip)) { #endif - UA_COPY32(op,ip); + UA_COPY4(op,ip); op += 4; ip += 4; if (--t > 0) { if (t >= 4) { do { - UA_COPY32(op,ip); + UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *ip++; while (--t > 0); @@ -3729,12 +5193,12 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, else do *op++ = *ip++; while (--t > 0); } -#if !defined(LZO_UNALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) } else #endif #endif -#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8) +#if !(LZO_OPT_UNALIGNED32) { *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; do *op++ = *ip++; while (--t > 0); @@ -3770,7 +5234,7 @@ first_literal_run: #endif goto match_done; - do { + for (;;) { match: if (t >= 64) { @@ -3830,14 +5294,15 @@ match: t &= 31; if (t == 0) { - NEED_IP(1); while (*ip == 0) { t += 255; ip++; + TEST_OV(t); NEED_IP(1); } t += 31 + *ip++; + NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) @@ -3853,9 +5318,9 @@ match: m_pos = op - off; last_m_off = off; } -#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) m_pos = op - 1; - m_pos -= UA_GET16(ip) >> 2; + m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos = op - 1; m_pos -= (ip[0] >> 2) + (ip[1] << 6); @@ -3874,14 +5339,15 @@ match: t &= 7; if (t == 0) { - NEED_IP(1); while (*ip == 0) { t += 255; ip++; + TEST_OV(t); NEED_IP(1); } t += 7 + *ip++; + NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) @@ -3899,8 +5365,8 @@ match: #else #if defined(LZO1Z) m_pos -= (ip[0] << 6) + (ip[1] >> 2); -#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) - m_pos -= UA_GET16(ip) >> 2; +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif @@ -3948,18 +5414,18 @@ match: #else TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); -#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) if (op - m_pos >= 8) { t += (3 - 1); if (t >= 8) do { - UA_COPY64(op,m_pos); + UA_COPY8(op,m_pos); op += 8; m_pos += 8; t -= 8; } while (t >= 8); if (t >= 4) { - UA_COPY32(op,m_pos); + UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } if (t > 0) @@ -3969,8 +5435,8 @@ match: } } else -#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) -#if !defined(LZO_UNALIGNED_OK_4) +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) { assert((op - m_pos) >= 4); @@ -3978,10 +5444,10 @@ match: if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { #endif - UA_COPY32(op,m_pos); + UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4 - (3 - 1); do { - UA_COPY32(op,m_pos); + UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *m_pos++; while (--t > 0); @@ -4006,7 +5472,7 @@ match_done: break; match_next: - assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); #if 0 do *op++ = *ip++; while (--t > 0); #else @@ -4014,16 +5480,10 @@ match_next: if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } #endif t = *ip++; - } while (TEST_IP && TEST_OP); + } } -#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) - *out_len = pd(op, out); - return LZO_E_EOF_NOT_FOUND; -#endif - eof_found: - assert(t == 1); *out_len = pd(op, out); return (ip == ip_end ? LZO_E_OK : (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); @@ -4069,10 +5529,13 @@ lookbehind_overrun: #undef TEST_IP #undef TEST_OP +#undef TEST_IP_AND_TEST_OP #undef TEST_LB #undef TEST_LBO #undef NEED_IP #undef NEED_OP +#undef TEST_IV +#undef TEST_OV #undef HAVE_TEST_IP #undef HAVE_TEST_OP #undef HAVE_NEED_IP @@ -4087,6 +5550,7 @@ lookbehind_overrun: # if (LZO_TEST_OVERRUN_INPUT >= 2) # define NEED_IP(x) \ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun # endif #endif @@ -4098,12 +5562,13 @@ lookbehind_overrun: # undef TEST_OP # define NEED_OP(x) \ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun # endif #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) -# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun -# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +# define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun #else # define TEST_LB(m_pos) ((void) 0) # define TEST_LBO(m_pos,o) ((void) 0) @@ -4124,15 +5589,27 @@ lookbehind_overrun: # define TEST_OP 1 #endif +#if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) +#elif defined(HAVE_TEST_IP) +# define TEST_IP_AND_TEST_OP TEST_IP +#elif defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP TEST_OP +#else +# define TEST_IP_AND_TEST_OP 1 +#endif + #if defined(NEED_IP) # define HAVE_NEED_IP 1 #else # define NEED_IP(x) ((void) 0) +# define TEST_IV(x) ((void) 0) #endif #if defined(NEED_OP) # define HAVE_NEED_OP 1 #else # define NEED_OP(x) ((void) 0) +# define TEST_OV(x) ((void) 0) #endif #if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) @@ -4149,14 +5626,14 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, lzo_voidp wrkmem ) #endif { - register lzo_bytep op; - register const lzo_bytep ip; - register lzo_uint t; + lzo_bytep op; + const lzo_bytep ip; + lzo_uint t; #if defined(COPY_DICT) lzo_uint m_off; const lzo_bytep dict_end; #else - register const lzo_bytep m_pos; + const lzo_bytep m_pos; #endif const lzo_bytep const ip_end = in + in_len; @@ -4191,43 +5668,45 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, op = out; ip = in; + NEED_IP(1); if (*ip > 17) { t = *ip++ - 17; if (t < 4) goto match_next; - assert(t > 0); NEED_OP(t); NEED_IP(t+1); + assert(t > 0); NEED_OP(t); NEED_IP(t+3); do *op++ = *ip++; while (--t > 0); goto first_literal_run; } - while (TEST_IP && TEST_OP) + for (;;) { + NEED_IP(3); t = *ip++; if (t >= 16) goto match; if (t == 0) { - NEED_IP(1); while (*ip == 0) { t += 255; ip++; + TEST_IV(t); NEED_IP(1); } t += 15 + *ip++; } - assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); -#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) + assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) t += 3; if (t >= 8) do { - UA_COPY64(op,ip); + UA_COPY8(op,ip); op += 8; ip += 8; t -= 8; } while (t >= 8); if (t >= 4) { - UA_COPY32(op,ip); + UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } if (t > 0) @@ -4235,19 +5714,19 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } } -#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) -#if !defined(LZO_UNALIGNED_OK_4) +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) if (PTR_ALIGNED2_4(op,ip)) { #endif - UA_COPY32(op,ip); + UA_COPY4(op,ip); op += 4; ip += 4; if (--t > 0) { if (t >= 4) { do { - UA_COPY32(op,ip); + UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *ip++; while (--t > 0); @@ -4255,12 +5734,12 @@ DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, else do *op++ = *ip++; while (--t > 0); } -#if !defined(LZO_UNALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) } else #endif #endif -#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8) +#if !(LZO_OPT_UNALIGNED32) { *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; do *op++ = *ip++; while (--t > 0); @@ -4296,7 +5775,7 @@ first_literal_run: #endif goto match_done; - do { + for (;;) { match: if (t >= 64) { @@ -4356,14 +5835,15 @@ match: t &= 31; if (t == 0) { - NEED_IP(1); while (*ip == 0) { t += 255; ip++; + TEST_OV(t); NEED_IP(1); } t += 31 + *ip++; + NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) @@ -4379,9 +5859,9 @@ match: m_pos = op - off; last_m_off = off; } -#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) m_pos = op - 1; - m_pos -= UA_GET16(ip) >> 2; + m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos = op - 1; m_pos -= (ip[0] >> 2) + (ip[1] << 6); @@ -4400,14 +5880,15 @@ match: t &= 7; if (t == 0) { - NEED_IP(1); while (*ip == 0) { t += 255; ip++; + TEST_OV(t); NEED_IP(1); } t += 7 + *ip++; + NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) @@ -4425,8 +5906,8 @@ match: #else #if defined(LZO1Z) m_pos -= (ip[0] << 6) + (ip[1] >> 2); -#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) - m_pos -= UA_GET16(ip) >> 2; +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif @@ -4474,18 +5955,18 @@ match: #else TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); -#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) if (op - m_pos >= 8) { t += (3 - 1); if (t >= 8) do { - UA_COPY64(op,m_pos); + UA_COPY8(op,m_pos); op += 8; m_pos += 8; t -= 8; } while (t >= 8); if (t >= 4) { - UA_COPY32(op,m_pos); + UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } if (t > 0) @@ -4495,8 +5976,8 @@ match: } } else -#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) -#if !defined(LZO_UNALIGNED_OK_4) +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) { assert((op - m_pos) >= 4); @@ -4504,10 +5985,10 @@ match: if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { #endif - UA_COPY32(op,m_pos); + UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4 - (3 - 1); do { - UA_COPY32(op,m_pos); + UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *m_pos++; while (--t > 0); @@ -4532,7 +6013,7 @@ match_done: break; match_next: - assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); #if 0 do *op++ = *ip++; while (--t > 0); #else @@ -4540,16 +6021,10 @@ match_next: if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } #endif t = *ip++; - } while (TEST_IP && TEST_OP); + } } -#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) - *out_len = pd(op, out); - return LZO_E_EOF_NOT_FOUND; -#endif - eof_found: - assert(t == 1); *out_len = pd(op, out); return (ip == ip_end ? LZO_E_OK : (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); @@ -4576,4 +6051,3 @@ lookbehind_overrun: #endif /***** End of minilzo.c *****/ - diff --git a/extern/lzo/minilzo/minilzo.h b/extern/lzo/minilzo/minilzo.h index f2c104856e3..79374546748 100644 --- a/extern/lzo/minilzo/minilzo.h +++ b/extern/lzo/minilzo/minilzo.h @@ -2,22 +2,7 @@ This file is part of the LZO real-time data compression library. - Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer - Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or @@ -50,7 +35,7 @@ #ifndef __MINILZO_H #define __MINILZO_H 1 -#define MINILZO_VERSION 0x2060 +#define MINILZO_VERSION 0x2080 #ifdef __LZOCONF_H # error "you cannot use both LZO and miniLZO" @@ -78,7 +63,7 @@ extern "C" { */ #define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS -#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32_t) (16384L * lzo_sizeof_dict_t)) #define LZO1X_MEM_DECOMPRESS (0) @@ -101,11 +86,6 @@ lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, lzo_voidp wrkmem /* NOT USED */ ); -#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3) - -#define LZO_HEAP_ALLOC(var,size) \ - lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/intern/atomic/atomic_ops.h b/intern/atomic/atomic_ops.h index 127552f8bd4..f63ff630c40 100644 --- a/intern/atomic/atomic_ops.h +++ b/intern/atomic/atomic_ops.h @@ -79,37 +79,57 @@ ATOMIC_INLINE uint64_t atomic_add_uint64(uint64_t *p, uint64_t x) { - return (__sync_add_and_fetch(p, x)); + return __sync_add_and_fetch(p, x); } ATOMIC_INLINE uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x) { - return (__sync_sub_and_fetch(p, x)); + return __sync_sub_and_fetch(p, x); +} + +ATOMIC_INLINE uint64_t +atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new) +{ + return __sync_val_compare_and_swap(v, old, _new); } #elif (defined(_MSC_VER)) ATOMIC_INLINE uint64_t atomic_add_uint64(uint64_t *p, uint64_t x) { - return (InterlockedExchangeAdd64(p, x)); + return InterlockedExchangeAdd64(p, x); } ATOMIC_INLINE uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x) { - return (InterlockedExchangeAdd64(p, -((int64_t)x))); + return InterlockedExchangeAdd64(p, -((int64_t)x)); +} + +ATOMIC_INLINE uint64_t +atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new) +{ + return InterlockedCompareExchange64((int64_t *)v, _new, old); } #elif (defined(__APPLE__)) ATOMIC_INLINE uint64_t atomic_add_uint64(uint64_t *p, uint64_t x) { - return (uint64_t)(OSAtomicAdd64((int64_t)x, (int64_t *)p)); + return (uint64_t)OSAtomicAdd64((int64_t)x, (int64_t *)p); } ATOMIC_INLINE uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x) { - return (uint64_t)(OSAtomicAdd64(-((int64_t)x), (int64_t *)p)); + return (uint64_t)OSAtomicAdd64(-((int64_t)x), (int64_t *)p); +} + +ATOMIC_INLINE uint64_t +atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new) +{ + uint64_t init_val = *v; + OSAtomicCompareAndSwap64((int64_t)old, (int64_t)_new, (int64_t *)v); + return init_val; } # elif (defined(__amd64__) || defined(__x86_64__)) ATOMIC_INLINE uint64_t @@ -120,7 +140,7 @@ atomic_add_uint64(uint64_t *p, uint64_t x) : "+r" (x), "=m" (*p) /* Outputs. */ : "m" (*p) /* Inputs. */ ); - return (x); + return x; } ATOMIC_INLINE uint64_t @@ -132,8 +152,21 @@ atomic_sub_uint64(uint64_t *p, uint64_t x) : "+r" (x), "=m" (*p) /* Outputs. */ : "m" (*p) /* Inputs. */ ); - return (x); + return x; } + +ATOMIC_INLINE uint64_t +atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new) +{ + uint64_t ret; + asm volatile ( + "lock; cmpxchgq %2,%1" + : "=a" (ret), "+m" (*v) + : "r" (_new), "0" (old) + : "memory"); + return ret; +} + # elif (defined(JEMALLOC_ATOMIC9)) ATOMIC_INLINE uint64_t atomic_add_uint64(uint64_t *p, uint64_t x) @@ -144,7 +177,7 @@ atomic_add_uint64(uint64_t *p, uint64_t x) */ assert(sizeof(uint64_t) == sizeof(unsigned long)); - return (atomic_fetchadd_long(p, (unsigned long)x) + x); + return atomic_fetchadd_long(p, (unsigned long)x) + x; } ATOMIC_INLINE uint64_t @@ -152,19 +185,33 @@ atomic_sub_uint64(uint64_t *p, uint64_t x) { assert(sizeof(uint64_t) == sizeof(unsigned long)); - return (atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x); + return atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x; +} + +ATOMIC_INLINE uint64_t +atomic_cas_uint32(uint64_t *v, uint64_t old, uint64_t _new) +{ + assert(sizeof(uint64_t) == sizeof(unsigned long)); + + return atomic_cmpset_long(v, old, _new); } # elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8)) ATOMIC_INLINE uint64_t atomic_add_uint64(uint64_t *p, uint64_t x) { - return (__sync_add_and_fetch(p, x)); + return __sync_add_and_fetch(p, x); } ATOMIC_INLINE uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x) { - return (__sync_sub_and_fetch(p, x)); + return __sync_sub_and_fetch(p, x); +} + +ATOMIC_INLINE uint64_t +atomic_cas_uint32(uint64_t *v, uint64_t old, uint64_t _new) +{ + return __sync_val_compare_and_swap(v, old, _new); } # else # error "Missing implementation for 64-bit atomic operations" @@ -177,37 +224,57 @@ atomic_sub_uint64(uint64_t *p, uint64_t x) ATOMIC_INLINE uint32_t atomic_add_uint32(uint32_t *p, uint32_t x) { - return (__sync_add_and_fetch(p, x)); + return __sync_add_and_fetch(p, x); } ATOMIC_INLINE uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x) { - return (__sync_sub_and_fetch(p, x)); + return __sync_sub_and_fetch(p, x); +} + +ATOMIC_INLINE uint32_t +atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new) +{ + return __sync_val_compare_and_swap(v, old, _new); } #elif (defined(_MSC_VER)) ATOMIC_INLINE uint32_t atomic_add_uint32(uint32_t *p, uint32_t x) { - return (InterlockedExchangeAdd(p, x)); + return InterlockedExchangeAdd(p, x); } ATOMIC_INLINE uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x) { - return (InterlockedExchangeAdd(p, -((int32_t)x))); + return InterlockedExchangeAdd(p, -((int32_t)x)); +} + +ATOMIC_INLINE uint32_t +atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new) +{ + return InterlockedCompareExchange((long *)v, _new, old); } #elif (defined(__APPLE__)) ATOMIC_INLINE uint32_t atomic_add_uint32(uint32_t *p, uint32_t x) { - return (uint32_t)(OSAtomicAdd32((int32_t)x, (int32_t *)p)); + return (uint32_t)OSAtomicAdd32((int32_t)x, (int32_t *)p); } ATOMIC_INLINE uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x) { - return (uint32_t)(OSAtomicAdd32(-((int32_t)x), (int32_t *)p)); + return (uint32_t)OSAtomicAdd32(-((int32_t)x), (int32_t *)p); +} + +ATOMIC_INLINE uint32_t +atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new) +{ + uint32_t init_val = *v; + OSAtomicCompareAndSwap32((int32_t)old, (int32_t)_new, (int32_t *)v); + return init_val; } #elif (defined(__i386__) || defined(__amd64__) || defined(__x86_64__)) ATOMIC_INLINE uint32_t @@ -218,7 +285,7 @@ atomic_add_uint32(uint32_t *p, uint32_t x) : "+r" (x), "=m" (*p) /* Outputs. */ : "m" (*p) /* Inputs. */ ); - return (x); + return x; } ATOMIC_INLINE uint32_t @@ -230,31 +297,55 @@ atomic_sub_uint32(uint32_t *p, uint32_t x) : "+r" (x), "=m" (*p) /* Outputs. */ : "m" (*p) /* Inputs. */ ); - return (x); + return x; +} + +ATOMIC_INLINE uint32_t +atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new) +{ + uint32_t ret; + asm volatile ( + "lock; cmpxchgl %2,%1" + : "=a" (ret), "+m" (*v) + : "r" (_new), "0" (old) + : "memory"); + return ret; } #elif (defined(JEMALLOC_ATOMIC9)) ATOMIC_INLINE uint32_t atomic_add_uint32(uint32_t *p, uint32_t x) { - return (atomic_fetchadd_32(p, x) + x); + return atomic_fetchadd_32(p, x) + x; } ATOMIC_INLINE uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x) { - return (atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x); + return atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x; } -#elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4)) + +ATOMIC_INLINE uint32_t +atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new) +{ + return atomic_cmpset_32(v, old, _new); +} +#elif defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4) ATOMIC_INLINE uint32_t atomic_add_uint32(uint32_t *p, uint32_t x) { - return (__sync_add_and_fetch(p, x)); + return __sync_add_and_fetch(p, x); } ATOMIC_INLINE uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x) { - return (__sync_sub_and_fetch(p, x)); + return __sync_sub_and_fetch(p, x); +} + +ATOMIC_INLINE uint32_t +atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new) +{ + return __sync_val_compare_and_swap(v, old, _new); } #else # error "Missing implementation for 32-bit atomic operations" @@ -268,9 +359,9 @@ atomic_add_z(size_t *p, size_t x) assert(sizeof(size_t) == 1 << LG_SIZEOF_PTR); #if (LG_SIZEOF_PTR == 3) - return ((size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x)); + return (size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x); #elif (LG_SIZEOF_PTR == 2) - return ((size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x)); + return (size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x); #endif } @@ -280,11 +371,27 @@ atomic_sub_z(size_t *p, size_t x) assert(sizeof(size_t) == 1 << LG_SIZEOF_PTR); #if (LG_SIZEOF_PTR == 3) - return ((size_t)atomic_add_uint64((uint64_t *)p, - (uint64_t)-((int64_t)x))); + return (size_t)atomic_add_uint64((uint64_t *)p, + (uint64_t)-((int64_t)x)); #elif (LG_SIZEOF_PTR == 2) - return ((size_t)atomic_add_uint32((uint32_t *)p, - (uint32_t)-((int32_t)x))); + return (size_t)atomic_add_uint32((uint32_t *)p, + (uint32_t)-((int32_t)x)); +#endif +} + +ATOMIC_INLINE size_t +atomic_cas_z(size_t *v, size_t old, size_t _new) +{ + assert(sizeof(size_t) == 1 << LG_SIZEOF_PTR); + +#if (LG_SIZEOF_PTR == 3) + return (size_t)atomic_cas_uint64((uint64_t *)v, + (uint64_t)old, + (uint64_t)_new); +#elif (LG_SIZEOF_PTR == 2) + return (size_t)atomic_cas_uint32((uint32_t *)v, + (uint32_t)old, + (uint32_t)_new); #endif } @@ -296,9 +403,9 @@ atomic_add_u(unsigned *p, unsigned x) assert(sizeof(unsigned) == 1 << LG_SIZEOF_INT); #if (LG_SIZEOF_INT == 3) - return ((unsigned)atomic_add_uint64((uint64_t *)p, (uint64_t)x)); + return (unsigned)atomic_add_uint64((uint64_t *)p, (uint64_t)x); #elif (LG_SIZEOF_INT == 2) - return ((unsigned)atomic_add_uint32((uint32_t *)p, (uint32_t)x)); + return (unsigned)atomic_add_uint32((uint32_t *)p, (uint32_t)x); #endif } @@ -308,11 +415,27 @@ atomic_sub_u(unsigned *p, unsigned x) assert(sizeof(unsigned) == 1 << LG_SIZEOF_INT); #if (LG_SIZEOF_INT == 3) - return ((unsigned)atomic_add_uint64((uint64_t *)p, - (uint64_t)-((int64_t)x))); + return (unsigned)atomic_add_uint64((uint64_t *)p, + (uint64_t)-((int64_t)x)); #elif (LG_SIZEOF_INT == 2) - return ((unsigned)atomic_add_uint32((uint32_t *)p, - (uint32_t)-((int32_t)x))); + return (unsigned)atomic_add_uint32((uint32_t *)p, + (uint32_t)-((int32_t)x)); +#endif +} + +ATOMIC_INLINE unsigned +atomic_cas_u(unsigned *v, unsigned old, unsigned _new) +{ + assert(sizeof(unsigned) == 1 << LG_SIZEOF_INT); + +#if (LG_SIZEOF_PTR == 3) + return (unsigned)atomic_cas_uint64((uint64_t *)v, + (uint64_t)old, + (uint64_t)_new); +#elif (LG_SIZEOF_PTR == 2) + return (unsigned)atomic_cas_uint32((uint32_t *)v, + (uint32_t)old, + (uint32_t)_new); #endif } diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index ccf6aac945e..981499b3a91 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -128,6 +128,30 @@ add_definitions( -DWITH_MULTI ) +# Logging capabilities using GLog library. +if(WITH_CYCLES_LOGGING) + add_definitions(-DWITH_CYCLES_LOGGING) + add_definitions(-DGOOGLE_GLOG_DLL_DECL=) + if(WIN32) + include_directories( + SYSTEM + ../../extern/libmv/third_party/glog/src/windows + ../../extern/libmv/third_party/gflags + ) + else() + include_directories( + SYSTEM + ../../extern/libmv/third_party/glog/src + ../../extern/libmv/third_party/gflags + ) + endif() +endif() + +# Debugging capabilities (debug passes etc). +if(WITH_CYCLES_DEBUG) + add_definitions(-DWITH_CYCLES_DEBUG) +endif() + include_directories( SYSTEM ${BOOST_INCLUDE_DIR} diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index 2d7fbe9c593..b399844534d 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -59,6 +59,9 @@ if env['WITH_BF_CYCLES_OSL']: defs.append('OSL_STATIC_LIBRARY') incs.append(cycles['BF_OSL_INC']) +if env['WITH_BF_CYCLES_DEBUG']: + defs.append('WITH_CYCLES_DEBUG') + incs.extend('. bvh render device kernel kernel/osl kernel/svm util subd'.split()) incs.extend('#intern/guardedalloc #source/blender/makesrna #source/blender/makesdna #source/blender/blenlib'.split()) incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.split()) diff --git a/intern/cycles/app/io_export_cycles_xml.py b/intern/cycles/app/io_export_cycles_xml.py index e310d928b26..ad8fb9d3dd3 100644 --- a/intern/cycles/app/io_export_cycles_xml.py +++ b/intern/cycles/app/io_export_cycles_xml.py @@ -111,19 +111,29 @@ class ExportCyclesXML(bpy.types.Operator, ExportHelper): # generate mesh node nverts = "" verts = "" + uvs = "" P = "" for v in mesh.vertices: P += "%f %f %f " % (v.co[0], v.co[1], v.co[2]) - for i, f in enumerate(mesh.tessfaces): - nverts += str(len(f.vertices)) + " " + verts_and_uvs = zip(mesh.tessfaces, mesh.tessface_uv_textures.active.data) + + for f, uvf in verts_and_uvs: + vcount = len(f.vertices) + nverts += str(vcount) + " " for v in f.vertices: verts += str(v) + " " - verts += " " - - node = etree.Element('mesh', attrib={'nverts': nverts, 'verts': verts, 'P': P}) + + uvs += str(uvf.uv1[0]) + " " + str(uvf.uv1[1]) + " " + uvs += str(uvf.uv2[0]) + " " + str(uvf.uv2[1]) + " " + uvs += str(uvf.uv3[0]) + " " + str(uvf.uv3[1]) + " " + if vcount==4: + uvs += " " + str(uvf.uv4[0]) + " " + str(uvf.uv4[1]) + " " + + + node = etree.Element('mesh', attrib={'nverts': nverts.strip(), 'verts': verts.strip(), 'P': P, 'UV' : uvs.strip()}) # write to file write(node, filepath) @@ -139,3 +149,4 @@ def unregister(): if __name__ == "__main__": register() + diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h index 2772b9ac8a7..cfd0c3ef264 100644 --- a/intern/cycles/blender/CCL_api.h +++ b/intern/cycles/blender/CCL_api.h @@ -36,6 +36,10 @@ CCLDeviceInfo *CCL_compute_device_list(int device_type); void *CCL_python_module_init(void); +void CCL_init_logging(const char *argv0); +void CCL_start_debug_logging(void); +void CCL_logging_verbosity_set(int verbosity); + #ifdef __cplusplus } #endif diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index e97ad2e71f5..e1d592d32b4 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -26,6 +26,7 @@ set(SRC blender_object.cpp blender_particles.cpp blender_curves.cpp + blender_logging.cpp blender_python.cpp blender_session.cpp blender_shader.cpp diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index d1d27df8dc3..8c60ea31053 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -33,6 +33,7 @@ import bpy from . import engine from . import version_update + class CyclesRender(bpy.types.RenderEngine): bl_idname = 'CYCLES' bl_label = "Cycles Render" diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 0ac0e0f091e..597ac1a9ce0 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -37,7 +37,7 @@ if _cycles.with_network: enum_feature_set = ( ('SUPPORTED', "Supported", "Only use finished and supported features"), - ('EXPERIMENTAL', "Experimental", "Use experimental and incomplete features that might be broken or change in the future"), + ('EXPERIMENTAL', "Experimental", "Use experimental and incomplete features that might be broken or change in the future", 'ERROR', 1), ) enum_displacement_methods = ( diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 6e40c42fb2d..9632b12c414 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -567,7 +567,7 @@ class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel): layout = self.layout rd = context.scene.render - scene = context.scene + # scene = context.scene layout.active = rd.use_motion_blur @@ -580,7 +580,7 @@ class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel): layout = self.layout rd = context.scene.render - scene = context.scene + # scene = context.scene ob = context.object cob = ob.cycles @@ -982,7 +982,7 @@ class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel): layout = self.layout mat = context.material - cmat = mat.cycles + # cmat = mat.cycles panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume') @@ -1209,7 +1209,6 @@ class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel): @classmethod def poll(cls, context): - scene = context.scene psys = context.particle_system return CyclesButtonsPanel.poll(context) and psys and psys.settings.type == 'HAIR' @@ -1284,7 +1283,7 @@ class CyclesRender_PT_bake(CyclesButtonsPanel, Panel): box.prop(cbk, "normal_space", text="Space") row = box.row(align=True) - row.label(text = "Swizzle:") + row.label(text="Swizzle:") row.prop(cbk, "normal_r", text="") row.prop(cbk, "normal_g", text="") row.prop(cbk, "normal_b", text="") diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py index 6f9509e7d99..eaeec703ff5 100644 --- a/intern/cycles/blender/addon/version_update.py +++ b/intern/cycles/blender/addon/version_update.py @@ -28,17 +28,32 @@ def do_versions(self): if not bpy.data.is_saved: return + # Clamp Direct/Indirect separation in 270 + if bpy.data.version <= (2, 70, 0): + for scene in bpy.data.scenes: + cscene = scene.cycles + sample_clamp = cscene.get("sample_clamp", False) + if (sample_clamp and + not cscene.is_property_set("sample_clamp_direct") and + not cscene.is_property_set("sample_clamp_indirect")): + + cscene.sample_clamp_direct = sample_clamp + cscene.sample_clamp_indirect = sample_clamp + + # Change of Volume Bounces in 271 if bpy.data.version <= (2, 71, 0): for scene in bpy.data.scenes: cscene = scene.cycles if not cscene.is_property_set("volume_bounces"): cscene.volume_bounces = 1 - for scene in bpy.data.scenes: - cscene = scene.cycles - if (cscene.get("no_caustics", False) and - not cscene.is_property_set("caustics_reflective") and - not cscene.is_property_set("caustics_refractive")): + # Caustics Reflective/Refractive separation in 272 + if bpy.data.version <= (2, 72, 0): + for scene in bpy.data.scenes: + cscene = scene.cycles + if (cscene.get("no_caustics", False) and + not cscene.is_property_set("caustics_reflective") and + not cscene.is_property_set("caustics_refractive")): - cscene.caustics_reflective = False - cscene.caustics_refractive = False + cscene.caustics_reflective = False + cscene.caustics_refractive = False diff --git a/intern/cycles/blender/blender_logging.cpp b/intern/cycles/blender/blender_logging.cpp new file mode 100644 index 00000000000..d3f1accf099 --- /dev/null +++ b/intern/cycles/blender/blender_logging.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include "CCL_api.h" + +#include <stdio.h> + +#include "util_logging.h" + +#ifdef _MSC_VER +# define snprintf _snprintf +#endif + +void CCL_init_logging(const char *argv0) +{ +#ifdef WITH_CYCLES_LOGGING + /* Make it so FATAL messages are always print into console. */ + char severity_fatal[32]; + snprintf(severity_fatal, sizeof(severity_fatal), "%d", + google::GLOG_FATAL); + + google::InitGoogleLogging(argv0); + google::SetCommandLineOption("logtostderr", "1"); + google::SetCommandLineOption("v", "0"); + google::SetCommandLineOption("stderrthreshold", severity_fatal); + google::SetCommandLineOption("minloglevel", severity_fatal); +#else + (void) argv0; +#endif +} + +void CCL_start_debug_logging(void) +{ +#ifdef WITH_CYCLES_LOGGING + google::SetCommandLineOption("logtostderr", "1"); + google::SetCommandLineOption("v", "2"); + google::SetCommandLineOption("stderrthreshold", "1"); + google::SetCommandLineOption("minloglevel", "0"); +#endif +} + +void CCL_logging_verbosity_set(int verbosity) +{ +#ifdef WITH_CYCLES_LOGGING + char val[10]; + snprintf(val, sizeof(val), "%d", verbosity); + + google::SetCommandLineOption("v", val); +#else + (void) verbosity; +#endif +} diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 4ff3d89f9f1..0610c3f6579 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -261,6 +261,14 @@ static PassType get_pass_type(BL::RenderPass b_pass) case BL::RenderPass::type_SPECULAR: case BL::RenderPass::type_REFLECTION: return PASS_NONE; +#ifdef WITH_CYCLES_DEBUG + case BL::RenderPass::type_DEBUG: + { + if(b_pass.debug_type() == BL::RenderPass::debug_type_BVH_TRAVERSAL_STEPS) + return PASS_BVH_TRAVERSAL_STEPS; + break; + } +#endif } return PASS_NONE; @@ -423,6 +431,9 @@ void BlenderSession::render() /* add passes */ vector<Pass> passes; Pass::add(PASS_COMBINED, passes); +#ifdef WITH_CYCLES_DEBUG + Pass::add(PASS_BVH_TRAVERSAL_STEPS, passes); +#endif if(session_params.device.advanced_shading) { diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 7752c1ce1bd..33c7bf5f859 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -53,13 +53,13 @@ void BlenderSync::find_shader(BL::ID id, vector<uint>& used_shaders, int default static BL::NodeSocket get_node_output(BL::Node b_node, const string& name) { BL::Node::outputs_iterator b_out; - + for(b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out) if(b_out->name() == name) return *b_out; - + assert(0); - + return *b_out; } @@ -229,7 +229,11 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::ShaderNodeMixRGB b_mix_node(b_node); MixNode *mix = new MixNode(); mix->type = MixNode::type_enum[b_mix_node.blend_type()]; - mix->use_clamp = b_mix_node.use_clamp(); + /* Tag if it's Mix */ + if(b_mix_node.blend_type() == 0) + mix->special_type = SHADER_SPECIAL_TYPE_MIX_RGB; + + mix->use_clamp = b_mix_node.use_clamp(); node = mix; } else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) { @@ -260,7 +264,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::ShaderNodeMath b_math_node(b_node); MathNode *math = new MathNode(); math->type = MathNode::type_enum[b_math_node.operation()]; - math->use_clamp = b_math_node.use_clamp(); + math->use_clamp = b_math_node.use_clamp(); node = math; } else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) { @@ -280,7 +284,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen else if (b_node.is_a(&RNA_ShaderNodeNormal)) { BL::Node::outputs_iterator out_it; b_node.outputs.begin(out_it); - + NormalNode *norm = new NormalNode(); norm->direction = get_node_output_vector(b_node, "Normal"); node = norm; @@ -288,9 +292,9 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen else if (b_node.is_a(&RNA_ShaderNodeMapping)) { BL::ShaderNodeMapping b_mapping_node(b_node); MappingNode *mapping = new MappingNode(); - + get_tex_mapping(&mapping->tex_mapping, b_mapping_node); - + node = mapping; } else if (b_node.is_a(&RNA_ShaderNodeFresnel)) { @@ -496,7 +500,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen /* create script node */ BL::ShaderNodeScript b_script_node(b_node); OSLScriptNode *script_node = new OSLScriptNode(); - + /* Generate inputs/outputs from node sockets * * Note: the node sockets are generated from OSL parameters, @@ -505,38 +509,38 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen * Note 2: ShaderInput/ShaderOutput store shallow string copies only! * Socket names must be stored in the extra lists instead. */ BL::Node::inputs_iterator b_input; - + for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) { script_node->input_names.push_back(ustring(b_input->name())); ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(*b_input)); set_default_value(input, b_node, *b_input, b_data, b_ntree); } - + BL::Node::outputs_iterator b_output; - + for (b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) { script_node->output_names.push_back(ustring(b_output->name())); script_node->add_output(script_node->output_names.back().c_str(), convert_socket_type(*b_output)); } - + /* load bytecode or filepath */ OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager; string bytecode_hash = b_script_node.bytecode_hash(); - + if(!bytecode_hash.empty()) { /* loaded bytecode if not already done */ if(!manager->shader_test_loaded(bytecode_hash)) manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode()); - + script_node->bytecode_hash = bytecode_hash; } else { /* set filepath */ script_node->filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath()); } - + node = script_node; } #endif @@ -728,7 +732,7 @@ static bool node_use_modified_socket_name(ShaderNode *node) { if (node->special_type == SHADER_SPECIAL_TYPE_SCRIPT) return false; - + return true; } @@ -740,57 +744,57 @@ static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::Node b_node, B BL::Node::inputs_iterator b_input; bool found = false; int counter = 0, total = 0; - + for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { if (b_input->name() == name) { if (!found) counter++; total++; } - + if(b_input->ptr.data == b_socket.ptr.data) found = true; } - + /* rename if needed */ if (name == "Shader") name = "Closure"; - + if (total > 1) name = string_printf("%s%d", name.c_str(), counter); } - + return node->input(name.c_str()); } static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket) { string name = b_socket.name(); - + if (node_use_modified_socket_name(node)) { BL::Node::outputs_iterator b_output; bool found = false; int counter = 0, total = 0; - + for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { if (b_output->name() == name) { if (!found) counter++; total++; } - + if(b_output->ptr.data == b_socket.ptr.data) found = true; } - + /* rename if needed */ if (name == "Shader") name = "Closure"; - + if (total > 1) name = string_printf("%s%d", name.c_str(), counter); } - + return node->output(name.c_str()); } @@ -801,7 +805,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha BL::ShaderNodeTree::nodes_iterator b_node; PtrInputMap input_map; PtrOutputMap output_map; - + BL::Node::inputs_iterator b_input; BL::Node::outputs_iterator b_output; @@ -831,10 +835,10 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha BL::Node::internal_links_iterator b_link; for (b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) { ProxyNode *proxy = new ProxyNode(convert_socket_type(b_link->to_socket())); - + input_map[b_link->from_socket().ptr.data] = proxy->inputs[0]; output_map[b_link->to_socket().ptr.data] = proxy->outputs[0]; - + graph->add(proxy); } } @@ -846,7 +850,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha else b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(*b_node)).node_tree()); ProxyMap group_proxy_input_map, group_proxy_output_map; - + /* Add a proxy node for each socket * Do this even if the node group has no internal tree, * so that links have something to connect to and assert won't fail. @@ -854,21 +858,21 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_input)); graph->add(proxy); - + /* register the proxy node for internal binding */ group_proxy_input_map[b_input->identifier()] = proxy; - + input_map[b_input->ptr.data] = proxy->inputs[0]; - + set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree); } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_output)); graph->add(proxy); - + /* register the proxy node for internal binding */ group_proxy_output_map[b_output->identifier()] = proxy; - + output_map[b_output->ptr.data] = proxy->outputs[0]; } @@ -881,7 +885,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier()); if (proxy_it != proxy_input_map.end()) { ProxyNode *proxy = proxy_it->second; - + output_map[b_output->ptr.data] = proxy->outputs[0]; } } @@ -895,9 +899,9 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier()); if (proxy_it != proxy_output_map.end()) { ProxyNode *proxy = proxy_it->second; - + input_map[b_input->ptr.data] = proxy->inputs[0]; - + set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree); } } @@ -914,7 +918,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha else { node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node)); } - + if(node) { /* map node sockets for linking */ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { @@ -924,7 +928,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha continue; } input_map[b_input->ptr.data] = input; - + set_default_value(input, *b_node, *b_input, b_data, b_ntree); } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { @@ -949,7 +953,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha ShaderOutput *output = 0; ShaderInput *input = 0; - + PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data); if (output_it != output_map.end()) output = output_it->second; @@ -981,7 +985,7 @@ void BlenderSync::sync_materials(bool update_all) for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) { Shader *shader; - + /* test if we need to sync */ if(shader_map.sync(&shader, *b_mat) || update_all) { ShaderGraph *graph = new ShaderGraph(); @@ -1036,7 +1040,7 @@ void BlenderSync::sync_world(bool update_all) BL::ShaderNodeTree b_ntree(b_world.node_tree()); add_nodes(scene, b_data, b_scene, graph, b_ntree); - + /* volume */ PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume"); @@ -1109,7 +1113,7 @@ void BlenderSync::sync_lamps(bool update_all) for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp) { Shader *shader; - + /* test if we need to sync */ if(shader_map.sync(&shader, *b_lamp) || update_all) { ShaderGraph *graph = new ShaderGraph(); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 4623764d210..c9b8a5b726b 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -17,6 +17,11 @@ #include <stdlib.h> #include <string.h> +/* So ImathMath is included before our kernel_cpu_compat. */ +#ifdef WITH_OSL +# include <OSL/oslexec.h> +#endif + #include "device.h" #include "device_intern.h" diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 5de2efab8be..44be7779891 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -202,6 +202,10 @@ public: /* compute cubin name */ int major, minor; cuDeviceComputeCapability(&major, &minor, cuDevId); + + /* workaround to make sm_52 cards work, until we bundle kernel */ + if(major == 5 && minor == 2) + minor = 0; /* attempt to use kernel provided with blender */ string cubin; @@ -274,6 +278,10 @@ public: if(experimental) command += " -D__KERNEL_CUDA_EXPERIMENTAL__"; +#ifdef WITH_CYCLES_DEBUG + command += " -D__KERNEL_DEBUG__"; +#endif + printf("%s\n", command.c_str()); if(system(command.c_str()) == -1) { diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h index 8eee6a2c79e..07a6eb36a3c 100644 --- a/intern/cycles/device/device_memory.h +++ b/intern/cycles/device/device_memory.h @@ -260,6 +260,11 @@ public: return data.size(); } + T* get_data() + { + return &data[0]; + } + private: array<T> data; }; diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index d950d084cd4..58b2bcafb82 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -102,7 +102,11 @@ static string opencl_kernel_build_options(const string& platform, const string * if(opencl_kernel_use_debug()) build_options += "-D__KERNEL_OPENCL_DEBUG__ "; - + +#ifdef WITH_CYCLES_DEBUG + build_options += "-D__KERNEL_DEBUG__ "; +#endif + return build_options; } diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 8857f86890c..c521e1383a4 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -24,6 +24,7 @@ set(SRC_HEADERS kernel_compat_cpu.h kernel_compat_cuda.h kernel_compat_opencl.h + kernel_debug.h kernel_differential.h kernel_emission.h kernel_film.h @@ -61,7 +62,6 @@ set(SRC_CLOSURE_HEADERS closure/bsdf_transparent.h closure/bsdf_util.h closure/bsdf_ashikhmin_shirley.h - closure/bsdf_westin.h closure/bsdf_hair.h closure/bssrdf.h closure/emissive.h @@ -116,6 +116,7 @@ set(SRC_GEOM_HEADERS geom/geom_bvh_shadow.h geom/geom_bvh_subsurface.h geom/geom_bvh_traversal.h + geom/geom_bvh_volume.h geom/geom_curve.h geom/geom_motion_curve.h geom/geom_motion_triangle.h @@ -169,6 +170,12 @@ if(WITH_CYCLES_CUDA_BINARIES) set(cuda_cubin kernel_${arch}.cubin) endif() + if(WITH_CYCLES_DEBUG) + set(cuda_debug_flags "-D__KERNEL_DEBUG__") + else() + set(cuda_debug_flags "") + endif() + set(cuda_version_flags "-D__KERNEL_CUDA_VERSION__=${CUDA_VERSION}") set(cuda_math_flags "--use_fast_math") @@ -184,6 +191,7 @@ if(WITH_CYCLES_CUDA_BINARIES) ${cuda_version_flags} ${cuda_math_flags} ${cuda_extra_flags} + ${cuda_debug_flags} -I${CMAKE_CURRENT_SOURCE_DIR}/../util -I${CMAKE_CURRENT_SOURCE_DIR}/svm -DCCL_NAMESPACE_BEGIN= @@ -196,6 +204,7 @@ if(WITH_CYCLES_CUDA_BINARIES) list(APPEND cuda_cubins ${cuda_cubin}) unset(cuda_extra_flags) + unset(cuda_debug_flags) endmacro() foreach(arch ${CYCLES_CUDA_BINARIES_ARCH}) diff --git a/intern/cycles/kernel/SConscript b/intern/cycles/kernel/SConscript index 5a9e57c5342..c0d969e24ae 100644 --- a/intern/cycles/kernel/SConscript +++ b/intern/cycles/kernel/SConscript @@ -79,6 +79,9 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']: nvcc_flags += " -DCCL_NAMESPACE_BEGIN= -DCCL_NAMESPACE_END= -DNVCC" nvcc_flags += " -I \"%s\" -I \"%s\" -I \"%s\" -I \"%s\"" % (util_dir, svm_dir, geom_dir, closure_dir) + if env['WITH_BF_CYCLES_DEBUG']: + nvcc_flags += " -D__KERNEL_DEBUG__" + # dependencies dependencies = ['kernel.cu'] + kernel.Glob('*.h') + kernel.Glob('../util/*.h') + kernel.Glob('svm/*.h') + kernel.Glob('geom/*.h') + kernel.Glob('closure/*.h') last_cubin_file = None diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 9961071c2ac..7d4783b0f3c 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -24,7 +24,6 @@ #include "../closure/bsdf_refraction.h" #include "../closure/bsdf_transparent.h" #include "../closure/bsdf_ashikhmin_shirley.h" -#include "../closure/bsdf_westin.h" #include "../closure/bsdf_toon.h" #include "../closure/bsdf_hair.h" #ifdef __SUBSURFACE__ @@ -109,14 +108,6 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader label = bsdf_glossy_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; - case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - label = bsdf_westin_backscatter_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; - case CLOSURE_BSDF_WESTIN_SHEEN_ID: - label = bsdf_westin_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; case CLOSURE_BSDF_HAIR_REFLECTION_ID: label = bsdf_hair_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); @@ -199,12 +190,6 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade case CLOSURE_BSDF_GLOSSY_TOON_ID: eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf); break; - case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - eval = bsdf_westin_backscatter_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_WESTIN_SHEEN_ID: - eval = bsdf_westin_sheen_eval_reflect(sc, sd->I, omega_in, pdf); - break; case CLOSURE_BSDF_HAIR_REFLECTION_ID: eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf); break; @@ -267,12 +252,6 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade case CLOSURE_BSDF_GLOSSY_TOON_ID: eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf); break; - case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - eval = bsdf_westin_backscatter_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_WESTIN_SHEEN_ID: - eval = bsdf_westin_sheen_eval_transmit(sc, sd->I, omega_in, pdf); - break; case CLOSURE_BSDF_HAIR_REFLECTION_ID: eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf); break; @@ -353,12 +332,6 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness) case CLOSURE_BSDF_GLOSSY_TOON_ID: bsdf_glossy_toon_blur(sc, roughness); break; - case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - bsdf_westin_backscatter_blur(sc, roughness); - break; - case CLOSURE_BSDF_WESTIN_SHEEN_ID: - bsdf_westin_sheen_blur(sc, roughness); - break; case CLOSURE_BSDF_HAIR_REFLECTION_ID: case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: bsdf_hair_reflection_blur(sc, roughness); diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index a0c59e6cbc0..2079d26e5ad 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -35,139 +35,38 @@ CCL_NAMESPACE_BEGIN -/* Approximate erf and erfinv implementations +/* Approximate erf and erfinv implementations. + * Implementation comes straight from Wikipedia: * - * Adapted from code (C) Copyright John Maddock 2006. - * Use, modification and distribution are subject to the - * Boost Software License, Version 1.0. (See accompanying file - * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ - -ccl_device float approx_erff_impl(float z) -{ - float result; - - if(z < 0.5f) { - if(z < 1e-10f) { - if(z == 0) { - result = 0; - } - else { - float c = 0.0033791670f; - result = z * 1.125f + z * c; - } - } - else { - float Y = 1.044948577f; - - float zz = z * z; - float num = (((-0.007727583f * zz) + -0.050999073f)*zz + -0.338165134f)*zz + 0.083430589f; - float denom = (((0.000370900f * zz) + 0.008585719f)*zz + 0.087522260f)*zz + 0.455004033f; - result = z * (Y + num / denom); - } - } - else if(z < 2.5f) { - if(z < 1.5f) { - float Y = 0.4059357643f; - float fz = z - 0.5f; - - float num = (((0.088890036f * fz) + 0.191003695f)*fz + 0.178114665f)*fz + -0.098090592f; - float denom = (((0.123850974f * fz) + 0.578052804f)*fz + 1.426280048f)*fz + 1.847590709f; - - result = Y + num / denom; - result *= expf(-z * z) / z; - } - else { - float Y = 0.506728172f; - float fz = z - 1.5f; - float num = (((0.017567943f * fz) + 0.043948189f)*fz + 0.038654037f)*fz + -0.024350047f; - float denom = (((0.325732924f * fz) + 0.982403709f)*fz + 1.539914949f)*fz + 1; - - result = Y + num / denom; - result *= expf(-z * z) / z; - } - - result = 1 - result; - } - else { - result = 1; - } - - return result; -} + * http://en.wikipedia.org/wiki/Error_function + * + * Some constants are baked into the code. + */ -ccl_device float approx_erff(float z) +ccl_device_inline float approx_erff(float x) { float s = 1.0f; - - if(z < 0.0f) { + if(x < 0.0f) { s = -1.0f; - z = -z; - } - - return s * approx_erff_impl(z); -} - -ccl_device float approx_erfinvf_impl(float p, float q) -{ - float result = 0; - - if(p <= 0.5f) { - float Y = 0.089131474f; - float g = p * (p + 10); - float num = (((-0.012692614f * p) + 0.033480662f)*p + -0.008368748f)*p + -0.000508781f; - float denom = (((1.562215583f * p) + -1.565745582f)*p + -0.970005043f)*p + 1.0f; - float r = num / denom; - result = g * Y + g * r; + x = -x; } - else if(q >= 0.25f) { - float Y = 2.249481201f; - float g = sqrtf(-2 * logf(q)); - float xs = q - 0.25f; - float num = (((17.644729840f * xs) + 8.370503283f)*xs + 0.105264680f)*xs + -0.202433508f; - float denom = (((-28.660818049f * xs) + 3.971343795f)*xs + 6.242641248f)*xs + 1.0f; - float r = num / denom; - result = g / (Y + r); + /* Such a clamp doesn't give much distortion to the output value + * and gives quite a few of the speedup. + */ + if(x > 3.0f) { + return s; } - else { - float x = sqrtf(-logf(q)); - - if(x < 3) { - float Y = 0.807220458f; - float xs = x - 1.125f; - float num = (((0.387079738f * xs) + 0.117030156f)*xs + -0.163794047f)*xs + -0.131102781f; - float denom = (((4.778465929f * xs) + 5.381683457f)*xs + 3.466254072f)*xs + 1.0f; - float R = num / denom; - result = Y * x + R * x; - } - else { - float Y = 0.939955711f; - float xs = x - 3; - float num = (((0.009508047f * xs) + 0.018557330f)*xs + -0.002224265f)*xs + -0.035035378f; - float denom = (((0.220091105f * xs) + 0.762059164f)*xs + 1.365334981f)*xs + 1.0f; - float R = num / denom; - result = Y * x + R * x; - } - } - - return result; + float t = 1.0f / (1.0f + 0.47047f*x); + return s * (1.0f - + t*(0.3480242f + t*(-0.0958798f + t*0.7478556f)) * expf(-x*x)); } -ccl_device float approx_erfinvf(float z) +ccl_device_inline float approx_erfinvf(float x) { - float p, q, s; - - if(z < 0) { - p = -z; - q = 1 - p; - s = -1; - } - else { - p = z; - q = 1 - z; - s = 1; - } - - return s * approx_erfinvf_impl(p, q); + float ln1_x2 = logf(1.0f - x*x); + float term = 4.546884979448f + ln1_x2 * 0.5f; + return copysignf(1.0f, x) * + sqrtf(sqrtf(term*term - ln1_x2 * 7.142230224076f) - term); } /* Beckmann and GGX microfacet importance sampling from: diff --git a/intern/cycles/kernel/closure/bsdf_westin.h b/intern/cycles/kernel/closure/bsdf_westin.h deleted file mode 100644 index 9dc1c00bb3d..00000000000 --- a/intern/cycles/kernel/closure/bsdf_westin.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __BSDF_WESTIN_H__ -#define __BSDF_WESTIN_H__ - -CCL_NAMESPACE_BEGIN - -/* WESTIN BACKSCATTER */ - -ccl_device int bsdf_westin_backscatter_setup(ShaderClosure *sc) -{ - float roughness = sc->data0; - roughness = clamp(roughness, 1e-5f, 1.0f); - float m_invroughness = 1.0f/roughness; - - sc->type = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID; - sc->data0 = m_invroughness; - - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; -} - -ccl_device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness) -{ - float m_invroughness = sc->data0; - m_invroughness = min(1.0f/roughness, m_invroughness); - sc->data0 = m_invroughness; -} - -ccl_device float3 bsdf_westin_backscatter_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) -{ - float m_invroughness = sc->data0; - float3 N = sc->N; - - // pdf is implicitly 0 (no indirect sampling) - float cosNO = dot(N, I); - float cosNI = dot(N, omega_in); - if(cosNO > 0 && cosNI > 0) { - float cosine = dot(I, omega_in); - *pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0; - *pdf *= 0.5f * M_1_PI_F; - return make_float3 (*pdf, *pdf, *pdf); - } - return make_float3 (0, 0, 0); -} - -ccl_device float3 bsdf_westin_backscatter_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) -{ - return make_float3(0.0f, 0.0f, 0.0f); -} - -ccl_device int bsdf_westin_backscatter_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) -{ - float m_invroughness = sc->data0; - float3 N = sc->N; - - float cosNO = dot(N, I); - if(cosNO > 0) { -#ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = dIdx; - *domega_in_dy = dIdy; -#endif - float3 T, B; - make_orthonormals (I, &T, &B); - float phi = M_2PI_F * randu; - float cosTheta = powf(randv, 1 / (m_invroughness + 1)); - float sinTheta2 = 1 - cosTheta * cosTheta; - float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; - *omega_in = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - (cosTheta) * I; - if(dot(Ng, *omega_in) > 0) { - // common terms for pdf and eval - float cosNI = dot(N, *omega_in); - // make sure the direction we chose is still in the right hemisphere - if(cosNI > 0) - { - *pdf = 0.5f * M_1_PI_F * powf(cosTheta, m_invroughness); - *pdf = (m_invroughness + 1) * (*pdf); - *eval = make_float3(*pdf, *pdf, *pdf); - } - } - } - return LABEL_REFLECT|LABEL_GLOSSY; -} - -/* WESTIN SHEEN */ - -ccl_device int bsdf_westin_sheen_setup(ShaderClosure *sc) -{ - /* float edginess = sc->data0; */ - sc->type = CLOSURE_BSDF_WESTIN_SHEEN_ID; - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; -} - -ccl_device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness) -{ -} - -ccl_device float3 bsdf_westin_sheen_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) -{ - float m_edginess = sc->data0; - float3 N = sc->N; - - // pdf is implicitly 0 (no indirect sampling) - float cosNO = dot(N, I); - float cosNI = dot(N, omega_in); - if(cosNO > 0 && cosNI > 0) { - float sinNO2 = 1 - cosNO * cosNO; - *pdf = cosNI * M_1_PI_F; - float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * (*pdf) : 0; - return make_float3 (westin, westin, westin); - } - return make_float3 (0, 0, 0); -} - -ccl_device float3 bsdf_westin_sheen_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) -{ - return make_float3(0.0f, 0.0f, 0.0f); -} - -ccl_device int bsdf_westin_sheen_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) -{ - float m_edginess = sc->data0; - float3 N = sc->N; - - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere(N, randu, randv, omega_in, pdf); - if(dot(Ng, *omega_in) > 0) { - // TODO: account for sheen when sampling - float cosNO = dot(N, I); - float sinNO2 = 1 - cosNO * cosNO; - float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * (*pdf) : 0; - *eval = make_float3(westin, westin, westin); -#ifdef __RAY_DIFFERENTIALS__ - // TODO: find a better approximation for the diffuse bounce - *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; - *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; -#endif - } - else { - pdf = 0; - } - return LABEL_REFLECT|LABEL_DIFFUSE; -} - -CCL_NAMESPACE_END - -#endif /* __BSDF_WESTIN_H__ */ - diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/geom/geom_bvh.h index dd7c25d581d..c5336e086b7 100644 --- a/intern/cycles/kernel/geom/geom_bvh.h +++ b/intern/cycles/kernel/geom/geom_bvh.h @@ -28,6 +28,13 @@ CCL_NAMESPACE_BEGIN +/* Don't inline intersect functions on GPU, this is faster */ +#ifdef __KERNEL_GPU__ +#define ccl_device_intersect ccl_device_noinline +#else +#define ccl_device_intersect ccl_device_inline +#endif + /* BVH intersection function variations */ #define BVH_INSTANCING 1 @@ -35,6 +42,8 @@ CCL_NAMESPACE_BEGIN #define BVH_HAIR 4 #define BVH_HAIR_MINIMUM_WIDTH 8 +/* Regular BVH traversal */ + #define BVH_FUNCTION_NAME bvh_intersect #define BVH_FUNCTION_FEATURES 0 #include "geom_bvh_traversal.h" @@ -63,6 +72,8 @@ CCL_NAMESPACE_BEGIN #include "geom_bvh_traversal.h" #endif +/* Subsurface scattering BVH traversal */ + #if defined(__SUBSURFACE__) #define BVH_FUNCTION_NAME bvh_intersect_subsurface #define BVH_FUNCTION_FEATURES 0 @@ -93,47 +104,72 @@ CCL_NAMESPACE_BEGIN #include "geom_bvh_subsurface.h" #endif +/* Record all BVH intersection for shadows */ + #if defined(__SHADOW_RECORD_ALL__) #define BVH_FUNCTION_NAME bvh_intersect_shadow_all #define BVH_FUNCTION_FEATURES 0 #include "geom_bvh_shadow.h" #endif -#if defined(__SUBSURFACE__) && defined(__INSTANCING__) +#if defined(__SHADOW_RECORD_ALL__) && defined(__INSTANCING__) #define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing #define BVH_FUNCTION_FEATURES BVH_INSTANCING #include "geom_bvh_shadow.h" #endif -#if defined(__SUBSURFACE__) && defined(__HAIR__) +#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__) #define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR #include "geom_bvh_shadow.h" #endif -#if defined(__SUBSURFACE__) && defined(__OBJECT_MOTION__) +#if defined(__SHADOW_RECORD_ALL__) && defined(__OBJECT_MOTION__) #define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION #include "geom_bvh_shadow.h" #endif -#if defined(__SUBSURFACE__) && defined(__HAIR__) && defined(__OBJECT_MOTION__) +#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__) && defined(__OBJECT_MOTION__) #define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion #define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION #include "geom_bvh_shadow.h" #endif -/* to work around titan bug when using arrays instead of textures */ -#if !defined(__KERNEL_CUDA__) || defined(__KERNEL_CUDA_TEX_STORAGE__) -ccl_device_inline -#else -ccl_device_noinline +/* Camera inside Volume BVH intersection */ + +#if defined(__VOLUME__) +#define BVH_FUNCTION_NAME bvh_intersect_volume +#define BVH_FUNCTION_FEATURES 0 +#include "geom_bvh_volume.h" #endif -#ifdef __HAIR__ -bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect, uint *lcg_state, float difl, float extmax) -#else -bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) + +#if defined(__VOLUME__) && defined(__INSTANCING__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_instancing +#define BVH_FUNCTION_FEATURES BVH_INSTANCING +#include "geom_bvh_volume.h" +#endif + +#if defined(__VOLUME__) && defined(__HAIR__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_hair +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH +#include "geom_bvh_volume.h" +#endif + +#if defined(__VOLUME__) && defined(__OBJECT_MOTION__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_motion +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION +#include "geom_bvh_volume.h" +#endif + +#if defined(__VOLUME__) && defined(__HAIR__) && defined(__OBJECT_MOTION__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_hair_motion +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION +#include "geom_bvh_volume.h" #endif + +ccl_device_intersect bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect, + uint *lcg_state, float difl, float extmax) { #ifdef __OBJECT_MOTION__ if(kernel_data.bvh.have_motion) { @@ -170,14 +206,8 @@ bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, I #endif /* __KERNEL_CPU__ */ } -/* to work around titan bug when using arrays instead of textures */ #ifdef __SUBSURFACE__ -#if !defined(__KERNEL_CUDA__) || defined(__KERNEL_CUDA_TEX_STORAGE__) -ccl_device_inline -#else -ccl_device_noinline -#endif -uint scene_intersect_subsurface(KernelGlobals *kg, const Ray *ray, Intersection *isect, int subsurface_object, uint *lcg_state, int max_hits) +ccl_device_intersect uint scene_intersect_subsurface(KernelGlobals *kg, const Ray *ray, Intersection *isect, int subsurface_object, uint *lcg_state, int max_hits) { #ifdef __OBJECT_MOTION__ if(kernel_data.bvh.have_motion) { @@ -215,14 +245,8 @@ uint scene_intersect_subsurface(KernelGlobals *kg, const Ray *ray, Intersection } #endif -/* to work around titan bug when using arrays instead of textures */ #ifdef __SHADOW_RECORD_ALL__ -#if !defined(__KERNEL_CUDA__) || defined(__KERNEL_CUDA_TEX_STORAGE__) -ccl_device_inline -#else -ccl_device_noinline -#endif -uint scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection *isect, uint max_hits, uint *num_hits) +ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection *isect, uint max_hits, uint *num_hits) { #ifdef __OBJECT_MOTION__ if(kernel_data.bvh.have_motion) { @@ -240,20 +264,50 @@ uint scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection return bvh_intersect_shadow_all_hair(kg, ray, isect, max_hits, num_hits); #endif /* __HAIR__ */ -#ifdef __KERNEL_CPU__ - #ifdef __INSTANCING__ if(kernel_data.bvh.have_instancing) return bvh_intersect_shadow_all_instancing(kg, ray, isect, max_hits, num_hits); #endif /* __INSTANCING__ */ return bvh_intersect_shadow_all(kg, ray, isect, max_hits, num_hits); +} +#endif + +#ifdef __VOLUME__ +ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg, + const Ray *ray, + Intersection *isect) +{ +#ifdef __OBJECT_MOTION__ + if(kernel_data.bvh.have_motion) { +#ifdef __HAIR__ + if(kernel_data.bvh.have_curves) + return bvh_intersect_volume_hair_motion(kg, ray, isect); +#endif /* __HAIR__ */ + + return bvh_intersect_volume_motion(kg, ray, isect); + } +#endif /* __OBJECT_MOTION__ */ + +#ifdef __HAIR__ + if(kernel_data.bvh.have_curves) + return bvh_intersect_volume_hair(kg, ray, isect); +#endif /* __HAIR__ */ + +#ifdef __KERNEL_CPU__ + +#ifdef __INSTANCING__ + if(kernel_data.bvh.have_instancing) + return bvh_intersect_volume_instancing(kg, ray, isect); +#endif /* __INSTANCING__ */ + + return bvh_intersect_volume(kg, ray, isect); #else /* __KERNEL_CPU__ */ #ifdef __INSTANCING__ - return bvh_intersect_shadow_all_instancing(kg, ray, isect, max_hits, num_hits); + return bvh_intersect_volume_instancing(kg, ray, isect); #else - return bvh_intersect_shadow_all(kg, ray, isect, max_hits, num_hits); + return bvh_intersect_volume(kg, ray, isect); #endif /* __INSTANCING__ */ #endif /* __KERNEL_CPU__ */ diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h index 1f6e4942fab..aee4097d77e 100644 --- a/intern/cycles/kernel/geom/geom_bvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h @@ -252,7 +252,7 @@ ccl_device bool BVH_FUNCTION_NAME if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE) #endif { - shader = __float_as_int(kernel_tex_fetch(__tri_shader, prim)); + shader = kernel_tex_fetch(__tri_shader, prim); } #ifdef __HAIR__ else { diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h index e39228c33de..eed54a4d00d 100644 --- a/intern/cycles/kernel/geom/geom_bvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h @@ -68,6 +68,10 @@ ccl_device bool BVH_FUNCTION_NAME isect->u = 0.0f; isect->v = 0.0f; +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps = 0; +#endif + #if defined(__KERNEL_SSE2__) const shuffle_swap_t shuf_identity = shuffle_swap_identity(); const shuffle_swap_t shuf_swap = shuffle_swap_swap(); @@ -226,6 +230,10 @@ ccl_device bool BVH_FUNCTION_NAME --stackPtr; } } + +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; +#endif } /* if node is leaf, fetch triangle list */ @@ -274,6 +282,10 @@ ccl_device bool BVH_FUNCTION_NAME } } +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; +#endif + /* shadow ray early termination */ #if defined(__KERNEL_SSE2__) if(hit) { diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h new file mode 100644 index 00000000000..aac0a18647a --- /dev/null +++ b/intern/cycles/kernel/geom/geom_bvh_volume.h @@ -0,0 +1,322 @@ +/* + * Adapted from code Copyright 2009-2010 NVIDIA Corporation, + * and code copyright 2009-2012 Intel Corporation + * + * Modifications Copyright 2011-2014, Blender Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This is a template BVH traversal function for volumes, where + * various features can be enabled/disabled. This way we can compile optimized + * versions for each case without new features slowing things down. + * + * BVH_INSTANCING: object instancing + * BVH_HAIR: hair curve rendering + * BVH_MOTION: motion blur rendering + * + */ + +#define FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0) + +ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg, + const Ray *ray, + Intersection *isect) +{ + /* todo: + * - test if pushing distance on the stack helps (for non shadow rays) + * - separate version for shadow rays + * - likely and unlikely for if() statements + * - test restrict attribute for pointers + */ + + /* traversal stack in CUDA thread-local memory */ + int traversalStack[BVH_STACK_SIZE]; + traversalStack[0] = ENTRYPOINT_SENTINEL; + + /* traversal variables in registers */ + int stackPtr = 0; + int nodeAddr = kernel_data.bvh.root; + + /* ray parameters in registers */ + float3 P = ray->P; + float3 dir = bvh_clamp_direction(ray->D); + float3 idir = bvh_inverse_direction(dir); + int object = OBJECT_NONE; + + const uint visibility = PATH_RAY_ALL_VISIBILITY; + +#if FEATURE(BVH_MOTION) + Transform ob_tfm; +#endif + + isect->t = ray->t; + isect->object = OBJECT_NONE; + isect->prim = PRIM_NONE; + isect->u = 0.0f; + isect->v = 0.0f; + +#if defined(__KERNEL_SSE2__) + const shuffle_swap_t shuf_identity = shuffle_swap_identity(); + const shuffle_swap_t shuf_swap = shuffle_swap_swap(); + + const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000)); + ssef Psplat[3], idirsplat[3]; + shuffle_swap_t shufflexyz[3]; + + Psplat[0] = ssef(P.x); + Psplat[1] = ssef(P.y); + Psplat[2] = ssef(P.z); + + ssef tsplat(0.0f, 0.0f, -isect->t, -isect->t); + + gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); +#endif + + /* traversal loop */ + do { + do { + /* traverse internal nodes */ + while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { + bool traverseChild0, traverseChild1; + int nodeAddrChild1; + +#if !defined(__KERNEL_SSE2__) + /* Intersect two child bounding boxes, non-SSE version */ + float t = isect->t; + + /* fetch node data */ + float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0); + float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1); + float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2); + float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3); + + /* intersect ray against child nodes */ + NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x; + NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x; + NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y; + NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y; + NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z; + NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z; + NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f); + NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t); + + NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x; + NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x; + NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y; + NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y; + NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z; + NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z; + NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f); + NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t); + + /* decide which nodes to traverse next */ +#ifdef __VISIBILITY_FLAG__ + /* this visibility test gives a 5% performance hit, how to solve? */ + traverseChild0 = (c0max >= c0min) && (__float_as_uint(cnodes.z) & visibility); + traverseChild1 = (c1max >= c1min) && (__float_as_uint(cnodes.w) & visibility); +#else + traverseChild0 = (c0max >= c0min); + traverseChild1 = (c1max >= c1min); +#endif + +#else // __KERNEL_SSE2__ + /* Intersect two child bounding boxes, SSE3 version adapted from Embree */ + + /* fetch node data */ + const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE; + const float4 cnodes = ((float4*)bvh_nodes)[3]; + + /* intersect ray against child nodes */ + const ssef tminmaxx = (shuffle_swap(bvh_nodes[0], shufflexyz[0]) - Psplat[0]) * idirsplat[0]; + const ssef tminmaxy = (shuffle_swap(bvh_nodes[1], shufflexyz[1]) - Psplat[1]) * idirsplat[1]; + const ssef tminmaxz = (shuffle_swap(bvh_nodes[2], shufflexyz[2]) - Psplat[2]) * idirsplat[2]; + + /* calculate { c0min, c1min, -c0max, -c1max} */ + ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat)); + const ssef tminmax = minmax ^ pn; + + const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax); + + /* decide which nodes to traverse next */ +#ifdef __VISIBILITY_FLAG__ + /* this visibility test gives a 5% performance hit, how to solve? */ + traverseChild0 = (movemask(lrhit) & 1) && (__float_as_uint(cnodes.z) & visibility); + traverseChild1 = (movemask(lrhit) & 2) && (__float_as_uint(cnodes.w) & visibility); +#else + traverseChild0 = (movemask(lrhit) & 1); + traverseChild1 = (movemask(lrhit) & 2); +#endif +#endif // __KERNEL_SSE2__ + + nodeAddr = __float_as_int(cnodes.x); + nodeAddrChild1 = __float_as_int(cnodes.y); + + if(traverseChild0 && traverseChild1) { + /* both children were intersected, push the farther one */ +#if !defined(__KERNEL_SSE2__) + bool closestChild1 = (c1min < c0min); +#else + bool closestChild1 = tminmax[1] < tminmax[0]; +#endif + + if(closestChild1) { + int tmp = nodeAddr; + nodeAddr = nodeAddrChild1; + nodeAddrChild1 = tmp; + } + + ++stackPtr; + traversalStack[stackPtr] = nodeAddrChild1; + } + else { + /* one child was intersected */ + if(traverseChild1) { + nodeAddr = nodeAddrChild1; + } + else if(!traverseChild0) { + /* neither child was intersected */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + } + } + + /* if node is leaf, fetch triangle list */ + if(nodeAddr < 0) { + float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1)); + int primAddr = __float_as_int(leaf.x); + +#if FEATURE(BVH_INSTANCING) + if(primAddr >= 0) { +#endif + int primAddr2 = __float_as_int(leaf.y); + + /* pop */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + + /* primitive intersection */ + for(; primAddr < primAddr2; primAddr++) { + /* only primitives from volume object */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + + /* intersect ray against primitive */ + uint type = kernel_tex_fetch(__prim_type, primAddr); + + switch(type & PRIMITIVE_ALL) { + case PRIMITIVE_TRIANGLE: { + triangle_intersect(kg, isect, P, dir, visibility, object, primAddr); + break; + } +#if FEATURE(BVH_MOTION) + case PRIMITIVE_MOTION_TRIANGLE: { + motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr); + break; + } +#endif +#if FEATURE(BVH_HAIR) + case PRIMITIVE_CURVE: + case PRIMITIVE_MOTION_CURVE: { + if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) + bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); + else + bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); + break; + } +#endif + default: { + break; + } + } + } + } +#if FEATURE(BVH_INSTANCING) + else { + /* instance push */ + object = kernel_tex_fetch(__prim_object, -primAddr-1); + int object_flag = kernel_tex_fetch(__object_flag, object); + + if(object_flag & SD_OBJECT_HAS_VOLUME) { + +#if FEATURE(BVH_MOTION) + bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm); +#else + bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t); +#endif + +#if defined(__KERNEL_SSE2__) + Psplat[0] = ssef(P.x); + Psplat[1] = ssef(P.y); + Psplat[2] = ssef(P.z); + + tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); + + gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); +#endif + + ++stackPtr; + traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; + + nodeAddr = kernel_tex_fetch(__object_node, object); + } + else { + /* pop */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + } + } +#endif + } while(nodeAddr != ENTRYPOINT_SENTINEL); + +#if FEATURE(BVH_INSTANCING) + if(stackPtr >= 0) { + kernel_assert(object != OBJECT_NONE); + + /* instance pop */ +#if FEATURE(BVH_MOTION) + bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm); +#else + bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t); +#endif + +#if defined(__KERNEL_SSE2__) + Psplat[0] = ssef(P.x); + Psplat[1] = ssef(P.y); + Psplat[2] = ssef(P.z); + + tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); + + gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); +#endif + + object = OBJECT_NONE; + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } +#endif + } while(nodeAddr != ENTRYPOINT_SENTINEL); + + return (isect->prim != PRIM_NONE); +} + +#undef FEATURE +#undef BVH_FUNCTION_NAME +#undef BVH_FUNCTION_FEATURES + diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h index 7409aa0d014..b275b89a8a4 100644 --- a/intern/cycles/kernel/geom/geom_motion_triangle.h +++ b/intern/cycles/kernel/geom/geom_motion_triangle.h @@ -233,7 +233,7 @@ ccl_device_inline float3 motion_triangle_refine_subsurface(KernelGlobals *kg, Sh ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, bool subsurface) { /* get shader */ - sd->shader = __float_as_int(kernel_tex_fetch(__tri_shader, sd->prim)); + sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); /* get motion info */ int numsteps, numverts; diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h index 41e9d183a96..3d3a5e72485 100644 --- a/intern/cycles/kernel/geom/geom_triangle.h +++ b/intern/cycles/kernel/geom/geom_triangle.h @@ -157,7 +157,7 @@ ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int object, int *Ng = normalize(cross(v1 - v0, v2 - v0)); /* shader`*/ - *shader = __float_as_int(kernel_tex_fetch(__tri_shader, prim)); + *shader = kernel_tex_fetch(__tri_shader, prim); } /* Triangle vertex locations */ diff --git a/intern/cycles/kernel/kernel.cu b/intern/cycles/kernel/kernel.cu index d5b5293664c..9ed4592f604 100644 --- a/intern/cycles/kernel/kernel.cu +++ b/intern/cycles/kernel/kernel.cu @@ -52,8 +52,8 @@ #define CUDA_KERNEL_MAX_REGISTERS 63 #define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63 -/* 5.0 */ -#elif __CUDA_ARCH__ == 500 +/* 5.0 and 5.2 */ +#elif __CUDA_ARCH__ == 500 || __CUDA_ARCH__ == 520 #define CUDA_MULTIPRESSOR_MAX_REGISTERS 65536 #define CUDA_MULTIPROCESSOR_MAX_BLOCKS 32 #define CUDA_BLOCK_MAX_THREADS 1024 diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index dfbb49db7e6..a1ec080e3d3 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -33,7 +33,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian path_radiance_init(&L_sample, kernel_data.film.use_light_pass); /* init path state */ - path_state_init(kg, &state, &rng, sample); + path_state_init(kg, &state, &rng, sample, NULL); /* evaluate surface shader */ float rbsdf = path_state_rng_1D(kg, &rng, &state, PRNG_BSDF); @@ -96,7 +96,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian /* sample subsurface scattering */ if((is_combined || is_sss_sample) && (sd->flag & SD_BSSRDF)) { /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */ - kernel_branched_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, throughput); + kernel_branched_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, throughput); } #endif diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index c2aab93c87b..25531843993 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -25,6 +25,13 @@ #include "util_half.h" #include "util_types.h" +/* On 64bit linux single precision exponent is really slow comparing to the + * double precision version, even with float<->double conversion involved. + */ +#if !defined(__KERNEL_GPU__) && defined(__linux__) && defined(__x86_64__) +# define expf(x) ((float)exp((double)x)) +#endif + CCL_NAMESPACE_BEGIN /* Assertions inside the kernel only work for the CPU device, so we wrap it in diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h index 9e58ebff599..78b3fd012dd 100644 --- a/intern/cycles/kernel/kernel_compat_opencl.h +++ b/intern/cycles/kernel/kernel_compat_opencl.h @@ -24,14 +24,6 @@ #define CCL_NAMESPACE_BEGIN #define CCL_NAMESPACE_END -#ifdef __KERNEL_OPENCL_AMD__ -#define __CL_NO_FLOAT3__ -#endif - -#ifdef __CL_NO_FLOAT3__ -#define float3 float4 -#endif - #ifdef __CL_NOINLINE__ #define ccl_noinline __attribute__((noinline)) #else @@ -73,11 +65,7 @@ #endif #define make_float2(x, y) ((float2)(x, y)) -#ifdef __CL_NO_FLOAT3__ -#define make_float3(x, y, z) ((float4)(x, y, z, 0.0f)) -#else #define make_float3(x, y, z) ((float3)(x, y, z)) -#endif #define make_float4(x, y, z, w) ((float4)(x, y, z, w)) #define make_int2(x, y) ((int2)(x, y)) #define make_int3(x, y, z) ((int3)(x, y, z)) diff --git a/intern/cycles/kernel/kernel_debug.h b/intern/cycles/kernel/kernel_debug.h new file mode 100644 index 00000000000..bf1bc0e9db8 --- /dev/null +++ b/intern/cycles/kernel/kernel_debug.h @@ -0,0 +1,38 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +CCL_NAMESPACE_BEGIN + +ccl_device_inline void debug_data_init(DebugData *debug_data) +{ + debug_data->num_bvh_traversal_steps = 0; +} + +ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg, + ccl_global float *buffer, + PathState *state, + DebugData *debug_data, + int sample) +{ + int flag = kernel_data.film.pass_flag; + if(flag & PASS_BVH_TRAVERSAL_STEPS) { + kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversal_steps, + sample, + debug_data->num_bvh_traversal_steps); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 515854b6e9c..c03229f0a3a 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -45,6 +45,10 @@ #include "kernel_path_surface.h" #include "kernel_path_volume.h" +#ifdef __KERNEL_DEBUG__ +#include "kernel_debug.h" +#endif + CCL_NAMESPACE_BEGIN ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, @@ -55,11 +59,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, /* intersect scene */ Intersection isect; uint visibility = path_state_ray_visibility(kg, &state); -#ifdef __HAIR__ bool hit = scene_intersect(kg, &ray, visibility, &isect, NULL, 0.0f, 0.0f); -#else - bool hit = scene_intersect(kg, &ray, visibility, &isect); -#endif #ifdef __LAMP_MIS__ if(kernel_data.integrator.use_lamp_mis && !(state.flag & PATH_RAY_CAMERA)) { @@ -363,6 +363,30 @@ ccl_device void kernel_branched_path_ao(KernelGlobals *kg, ShaderData *sd, PathR } #ifdef __SUBSURFACE__ + +#ifdef __VOLUME__ +ccl_device void kernel_path_subsurface_update_volume_stack(KernelGlobals *kg, + Ray *ray, + VolumeStack *stack) +{ + kernel_assert(kernel_data.integrator.use_volumes); + + Ray volume_ray = *ray; + Intersection isect; + + while(scene_intersect_volume(kg, &volume_ray, &isect)) + { + ShaderData sd; + shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0); + kernel_volume_stack_enter_exit(kg, &sd, stack); + + /* Move ray forward. */ + volume_ray.P = ray_offset(sd.P, -sd.Ng); + volume_ray.t -= sd.ray_length; + } +} +#endif + ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, Ray *ray, float3 *throughput) { float bssrdf_probability; @@ -379,6 +403,11 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd float bssrdf_u, bssrdf_v; path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v); int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false); +#ifdef __VOLUME__ + Ray volume_ray = *ray; + bool need_update_volume_stack = kernel_data.integrator.use_volumes && + sd->flag & SD_OBJECT_INTERSECTS_VOLUME; +#endif /* compute lighting with the BSDF closure */ for(int hit = 0; hit < num_hits; hit++) { @@ -396,6 +425,22 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd hit_state.ray_t = 0.0f; #endif +#ifdef __VOLUME__ + if(need_update_volume_stack) { + /* Setup ray from previous surface point to the new one. */ + volume_ray.D = normalize_len(hit_ray.P - volume_ray.P, + &volume_ray.t); + + kernel_path_subsurface_update_volume_stack( + kg, + &volume_ray, + hit_state.volume_stack); + + /* Move volume ray forward. */ + volume_ray.P = hit_ray.P; + } +#endif + kernel_path_indirect(kg, rng, hit_ray, tp, state->num_samples, hit_state, L); /* for render passes, sum and reset indirect light pass variables @@ -420,7 +465,12 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, path_radiance_init(&L, kernel_data.film.use_light_pass); PathState state; - path_state_init(kg, &state, rng, sample); + path_state_init(kg, &state, rng, sample, &ray); + +#ifdef __KERNEL_DEBUG__ + DebugData debug_data; + debug_data_init(&debug_data); +#endif /* path iteration */ for(;;) { @@ -445,7 +495,13 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, bool hit = scene_intersect(kg, &ray, visibility, &isect, &lcg_state, difl, extmax); #else - bool hit = scene_intersect(kg, &ray, visibility, &isect); + bool hit = scene_intersect(kg, &ray, visibility, &isect, NULL, 0.0f, 0.0f); +#endif + +#ifdef __KERNEL_DEBUG__ + if(state.flag & PATH_RAY_CAMERA) { + debug_data.num_bvh_traversal_steps += isect.num_traversal_steps; + } #endif #ifdef __LAMP_MIS__ @@ -668,6 +724,10 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, kernel_write_light_passes(kg, buffer, &L, sample); +#ifdef __KERNEL_DEBUG__ + kernel_write_debug_passes(kg, buffer, &state, &debug_data, sample); +#endif + return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent); } @@ -722,7 +782,13 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba } #ifdef __SUBSURFACE__ -ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, float3 throughput) +ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, + ShaderData *sd, + PathRadiance *L, + PathState *state, + RNG *rng, + Ray *ray, + float3 throughput) { for(int i = 0; i< sd->num_closure; i++) { ShaderClosure *sc = &sd->closure[i]; @@ -745,6 +811,11 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, Shade float bssrdf_u, bssrdf_v; path_branched_rng_2D(kg, &bssrdf_rng, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v); int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, true); +#ifdef __VOLUME__ + Ray volume_ray = *ray; + bool need_update_volume_stack = kernel_data.integrator.use_volumes && + sd->flag & SD_OBJECT_INTERSECTS_VOLUME; +#endif /* compute lighting with the BSDF closure */ for(int hit = 0; hit < num_hits; hit++) { @@ -752,6 +823,23 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, Shade path_state_branch(&hit_state, j, num_samples); +#ifdef __VOLUME__ + if(need_update_volume_stack) { + /* Setup ray from previous surface point to the new one. */ + float3 P = ray_offset(bssrdf_sd[hit].P, -bssrdf_sd[hit].Ng); + volume_ray.D = normalize_len(P - volume_ray.P, + &volume_ray.t); + + kernel_path_subsurface_update_volume_stack( + kg, + &volume_ray, + hit_state.volume_stack); + + /* Move volume ray forward. */ + volume_ray.P = P; + } +#endif + #if defined(__EMISSION__) && defined(__BRANCHED_PATH__) /* direct light */ if(kernel_data.integrator.use_direct_light) { @@ -783,7 +871,12 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in path_radiance_init(&L, kernel_data.film.use_light_pass); PathState state; - path_state_init(kg, &state, rng, sample); + path_state_init(kg, &state, rng, sample, &ray); + +#ifdef __KERNEL_DEBUG__ + DebugData debug_data; + debug_data_init(&debug_data); +#endif for(;;) { /* intersect scene */ @@ -807,7 +900,13 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in bool hit = scene_intersect(kg, &ray, visibility, &isect, &lcg_state, difl, extmax); #else - bool hit = scene_intersect(kg, &ray, visibility, &isect); + bool hit = scene_intersect(kg, &ray, visibility, &isect, NULL, 0.0f, 0.0f); +#endif + +#ifdef __KERNEL_DEBUG__ + if(state.flag & PATH_RAY_CAMERA) { + debug_data.num_bvh_traversal_steps += isect.num_traversal_steps; + } #endif #ifdef __VOLUME__ @@ -1016,7 +1115,8 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in #ifdef __SUBSURFACE__ /* bssrdf scatter to a different location on the same object */ if(sd.flag & SD_BSSRDF) { - kernel_branched_path_subsurface_scatter(kg, &sd, &L, &state, rng, throughput); + kernel_branched_path_subsurface_scatter(kg, &sd, &L, &state, + rng, &ray, throughput); } #endif @@ -1064,6 +1164,10 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in kernel_write_light_passes(kg, buffer, &L, sample); +#ifdef __KERNEL_DEBUG__ + kernel_write_debug_passes(kg, buffer, &state, &debug_data, sample); +#endif + return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent); } diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index 43e75885849..f29168642a4 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -16,7 +16,7 @@ CCL_NAMESPACE_BEGIN -ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG *rng, int sample) +ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG *rng, int sample, Ray *ray) { state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP; @@ -41,7 +41,7 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG if(kernel_data.integrator.use_volumes) { /* initialize volume stack with volume we are inside of */ - kernel_volume_stack_init(kg, state->volume_stack); + kernel_volume_stack_init(kg, ray, state->volume_stack); /* seed RNG for cases where we can't use stratified samples */ state->rng_congruential = lcg_init(*rng + sample*0x51633e2d); } diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index fc61f1a9c2c..db08c328d7e 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -87,7 +87,7 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, if(sd->type & PRIMITIVE_TRIANGLE) { /* static triangle */ float3 Ng = triangle_normal(kg, sd); - sd->shader = __float_as_int(kernel_tex_fetch(__tri_shader, sd->prim)); + sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); /* vectors */ sd->P = triangle_refine(kg, sd, isect, ray); @@ -166,7 +166,7 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat /* fetch triangle data */ if(sd->type == PRIMITIVE_TRIANGLE) { float3 Ng = triangle_normal(kg, sd); - sd->shader = __float_as_int(kernel_tex_fetch(__tri_shader, sd->prim)); + sd->shader = kernel_tex_fetch(__tri_shader, sd->prim); /* static triangle */ sd->P = triangle_refine_subsurface(kg, sd, isect, ray); @@ -798,8 +798,8 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, #ifdef __SVM__ svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, path_flag); #else - sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f); - sd->closure.N = sd->N; + sd->closure->weight = make_float3(0.8f, 0.8f, 0.8f); + sd->closure->N = sd->N; sd->flag |= bsdf_diffuse_setup(&sd->closure); #endif } @@ -1026,7 +1026,7 @@ ccl_device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect #ifdef __HAIR__ if(kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) { #endif - shader = __float_as_int(kernel_tex_fetch(__tri_shader, prim)); + shader = kernel_tex_fetch(__tri_shader, prim); #ifdef __HAIR__ } else { diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h index 439e8bbd585..61954282c28 100644 --- a/intern/cycles/kernel/kernel_shadow.h +++ b/intern/cycles/kernel/kernel_shadow.h @@ -168,11 +168,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray * } else { Intersection isect; -#ifdef __HAIR__ blocked = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect, NULL, 0.0f, 0.0f); -#else - blocked = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect); -#endif } #ifdef __VOLUME__ @@ -185,6 +181,8 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray * return blocked; } +#undef STACK_MAX_HITS + #else /* Shadow function to compute how much light is blocked, GPU variation. @@ -203,11 +201,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray * return false; Intersection isect; -#ifdef __HAIR__ bool blocked = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect, NULL, 0.0f, 0.0f); -#else - bool blocked = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect); -#endif #ifdef __TRANSPARENT_SHADOWS__ if(blocked && kernel_data.integrator.transparent_shadows) { @@ -223,11 +217,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray * if(bounce >= kernel_data.integrator.transparent_max_bounce) return true; -#ifdef __HAIR__ if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, &isect, NULL, 0.0f, 0.0f)) -#else - if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, &isect)) -#endif { #ifdef __VOLUME__ diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index f60ed8ccd07..ef46b2f707f 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -36,7 +36,7 @@ KERNEL_TEX(float4, texture_float4, __objects) KERNEL_TEX(float4, texture_float4, __objects_vector) /* triangles */ -KERNEL_TEX(float, texture_float, __tri_shader) +KERNEL_TEX(uint, texture_uint, __tri_shader) KERNEL_TEX(float4, texture_float4, __tri_vnormal) KERNEL_TEX(float4, texture_float4, __tri_vindex) KERNEL_TEX(float4, texture_float4, __tri_verts) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 1f01622e349..e5cd23c0925 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -157,6 +157,10 @@ CCL_NAMESPACE_BEGIN #define __HAIR__ #endif +#ifdef WITH_CYCLES_DEBUG +# define __KERNEL_DEBUG__ +#endif + /* Random Numbers */ typedef uint RNG; @@ -313,6 +317,9 @@ typedef enum PassType { PASS_SUBSURFACE_INDIRECT = 8388608, PASS_SUBSURFACE_COLOR = 16777216, PASS_LIGHT = 33554432, /* no real pass, used to force use_light_pass */ +#ifdef __KERNEL_DEBUG__ + PASS_BVH_TRAVERSAL_STEPS = 67108864, +#endif } PassType; #define PASS_ALL (~0) @@ -453,6 +460,10 @@ typedef struct Intersection { int prim; int object; int type; + +#ifdef __KERNEL_DEBUG__ + int num_traversal_steps; +#endif } Intersection; /* Primitives */ @@ -530,7 +541,7 @@ typedef enum AttributeStandard { /* TODO(sergey): This is rather nasty bug happening in here, which * could be simply a compilers bug for which we can't find a generic - * platform indipendent workaround. Also even if it's a compiler + * platform independent workaround. Also even if it's a compiler * issue, it's not so simple to upgrade the compiler in the release * environment for linux and doing it so closer to the release is * rather a risky business. @@ -615,8 +626,12 @@ enum ShaderDataFlag { SD_OBJECT_MOTION = 1048576, /* has object motion blur */ SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */ SD_NEGATIVE_SCALE_APPLIED = 4194304, /* vertices have negative scale applied */ + SD_OBJECT_HAS_VOLUME = 8388608, /* object has a volume shader */ + SD_OBJECT_INTERSECTS_VOLUME = 16777216, /* object intersects AABB of an object with volume shader */ - SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED) + SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED| + SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME| + SD_OBJECT_INTERSECTS_VOLUME) }; struct KernelGlobals; @@ -784,7 +799,7 @@ typedef struct KernelCamera { /* anamorphic lens bokeh */ float inv_aperture_ratio; - int pad1; + int is_inside_volume; int pad2; /* more matrices */ @@ -846,6 +861,11 @@ typedef struct KernelFilm { float mist_start; float mist_inv_depth; float mist_falloff; + +#ifdef __KERNEL_DEBUG__ + int pass_bvh_traversal_steps; + int pass_pad3, pass_pad4, pass_pad5; +#endif } KernelFilm; typedef struct KernelBackground { @@ -972,6 +992,14 @@ typedef struct KernelData { KernelTables tables; } KernelData; +#ifdef __KERNEL_DEBUG__ +typedef struct DebugData { + // Total number of BVH node travesal steps and primitives intersections + // for the camera rays. + int num_bvh_traversal_steps; +} DebugData; +#endif + CCL_NAMESPACE_END #endif /* __KERNEL_TYPES_H__ */ diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index ea02ede10cd..93cb4c120ea 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -954,17 +954,88 @@ ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg, bool heterogeneou * This is an array of object/shared ID's that the current segment of the path * is inside of. */ -ccl_device void kernel_volume_stack_init(KernelGlobals *kg, VolumeStack *stack) +ccl_device void kernel_volume_stack_init(KernelGlobals *kg, + Ray *ray, + VolumeStack *stack) { - /* todo: this assumes camera is always in air, need to detect when it isn't */ - if(kernel_data.background.volume_shader == SHADER_NONE) { - stack[0].shader = SHADER_NONE; + /* NULL ray happens in the baker, does it need proper initializetion of + * camera in volume? + */ + if(!kernel_data.cam.is_inside_volume || ray == NULL) { + /* Camera is guaranteed to be in the air, only take background volume + * into account in this case. + */ + if(kernel_data.background.volume_shader != SHADER_NONE) { + stack[0].shader = kernel_data.background.volume_shader; + stack[0].object = PRIM_NONE; + stack[1].shader = SHADER_NONE; + } + else { + stack[0].shader = SHADER_NONE; + } + return; } - else { + + Ray volume_ray = *ray; + volume_ray.t = FLT_MAX; + + int stack_index = 0, enclosed_index = 0; + int enclosed_volumes[VOLUME_STACK_SIZE]; + + while(stack_index < VOLUME_STACK_SIZE - 1 && + enclosed_index < VOLUME_STACK_SIZE - 1) + { + Intersection isect; + if(!scene_intersect_volume(kg, &volume_ray, &isect)) { + break; + } + + ShaderData sd; + shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0); + if(sd.flag & SD_HAS_VOLUME) { + if(sd.flag & SD_BACKFACING) { + /* If ray exited the volume and never entered to that volume + * it means that camera is inside such a volume. + */ + bool is_enclosed = false; + for(int i = 0; i < enclosed_index; ++i) { + if(enclosed_volumes[i] == sd.object) { + is_enclosed = true; + break; + } + } + if(is_enclosed == false) { + stack[stack_index].object = sd.object; + stack[stack_index].shader = sd.shader; + ++stack_index; + } + } + else { + /* If ray from camera enters the volume, this volume shouldn't + * be added to the stak on exit. + */ + enclosed_volumes[enclosed_index++] = sd.object; + } + } + + /* Move ray forward. */ + volume_ray.P = ray_offset(sd.P, -sd.Ng); + } + /* stack_index of 0 means quick checks outside of the kernel gave false + * positive, nothing to worry about, just we've wasted quite a few of + * ticks just to come into conclusion that camera is in the air. + * + * In this case we're doing the same above -- check whether background has + * volume. + */ + if(stack_index == 0 && kernel_data.background.volume_shader == SHADER_NONE) { stack[0].shader = kernel_data.background.volume_shader; stack[0].object = PRIM_NONE; stack[1].shader = SHADER_NONE; } + else { + stack[stack_index].shader = SHADER_NONE; + } } ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg, ShaderData *sd, VolumeStack *stack) @@ -1013,4 +1084,3 @@ ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg, ShaderData *sd } CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/SConscript b/intern/cycles/kernel/osl/SConscript index 4685bb7753e..d721edbaf6e 100644 --- a/intern/cycles/kernel/osl/SConscript +++ b/intern/cycles/kernel/osl/SConscript @@ -43,6 +43,9 @@ defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {') defs.append('CCL_NAMESPACE_END=}') defs.append('WITH_OSL') +if env['WITH_BF_CYCLES_DEBUG']: + defs.append('WITH_CYCLES_DEBUG') + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): cxxflags.append('-DBOOST_NO_RTTI -DBOOST_NO_TYPEID /fp:fast'.split()) incs.append(env['BF_PTHREADS_INC']) diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index d7789edcfff..cc9942b024e 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -54,7 +54,6 @@ #include "closure/bsdf_refraction.h" #include "closure/bsdf_transparent.h" #include "closure/bsdf_ashikhmin_shirley.h" -#include "closure/bsdf_westin.h" #include "closure/bsdf_toon.h" #include "closure/bsdf_hair.h" #include "closure/volume.h" @@ -87,16 +86,6 @@ BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, refraction, LABEL_SINGULAR) CLOSURE_FLOAT_PARAM(RefractionClosure, sc.data0), BSDF_CLOSURE_CLASS_END(Refraction, refraction) -BSDF_CLOSURE_CLASS_BEGIN(WestinBackscatter, westin_backscatter, westin_backscatter, LABEL_GLOSSY) - CLOSURE_FLOAT3_PARAM(WestinBackscatterClosure, sc.N), - CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, sc.data0), -BSDF_CLOSURE_CLASS_END(WestinBackscatter, westin_backscatter) - -BSDF_CLOSURE_CLASS_BEGIN(WestinSheen, westin_sheen, westin_sheen, LABEL_DIFFUSE) - CLOSURE_FLOAT3_PARAM(WestinSheenClosure, sc.N), - CLOSURE_FLOAT_PARAM(WestinSheenClosure, sc.data0), -BSDF_CLOSURE_CLASS_END(WestinSheen, westin_sheen) - BSDF_CLOSURE_CLASS_BEGIN(Transparent, transparent, transparent, LABEL_SINGULAR) BSDF_CLOSURE_CLASS_END(Transparent, transparent) @@ -244,10 +233,6 @@ void OSLShader::register_closures(OSLShadingSystem *ss_) bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare); register_closure(ss, "glossy_toon", id++, bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare); - register_closure(ss, "westin_backscatter", id++, - bsdf_westin_backscatter_params(), bsdf_westin_backscatter_prepare); - register_closure(ss, "westin_sheen", id++, - bsdf_westin_sheen_params(), bsdf_westin_sheen_prepare); register_closure(ss, "emission", id++, closure_emission_params(), closure_emission_prepare); diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index 58d215295dc..5e833d738d8 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -48,8 +48,6 @@ OSL::ClosureParam *closure_holdout_params(); OSL::ClosureParam *closure_ambient_occlusion_params(); OSL::ClosureParam *closure_bsdf_diffuse_ramp_params(); OSL::ClosureParam *closure_bsdf_phong_ramp_params(); -OSL::ClosureParam *closure_westin_backscatter_params(); -OSL::ClosureParam *closure_westin_sheen_params(); OSL::ClosureParam *closure_bssrdf_cubic_params(); OSL::ClosureParam *closure_bssrdf_gaussian_params(); OSL::ClosureParam *closure_henyey_greenstein_volume_params(); @@ -60,8 +58,6 @@ void closure_holdout_prepare(OSL::RendererServices *, int id, void *data); void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data); void closure_bsdf_diffuse_ramp_prepare(OSL::RendererServices *, int id, void *data); void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data); -void closure_westin_backscatter_prepare(OSL::RendererServices *, int id, void *data); -void closure_westin_sheen_prepare(OSL::RendererServices *, int id, void *data); void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data); void closure_bssrdf_gaussian_prepare(OSL::RendererServices *, int id, void *data); void closure_henyey_greenstein_volume_prepare(OSL::RendererServices *, int id, void *data); diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 5a658d8244a..9c3134e41c9 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -20,7 +20,6 @@ #ifdef WITH_OSL #include <OSL/oslexec.h> -#include <cmath> #include "util_map.h" #include "util_param.h" diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 38cb5061346..1475e5a0a62 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -1047,11 +1047,7 @@ bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg, tracedata->sd.osl_globals = sd->osl_globals; /* raytrace */ -#ifdef __HAIR__ return scene_intersect(sd->osl_globals, &ray, PATH_RAY_ALL_VISIBILITY, &tracedata->isect, NULL, 0.0f, 0.0f); -#else - return scene_intersect(sd->osl_globals, &ray, PATH_RAY_ALL_VISIBILITY, &tracedata->isect); -#endif } diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 48498116874..ca0c2cc4415 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -14,6 +14,8 @@ * limitations under the License */ +#include <OSL/oslexec.h> + #include "kernel_compat_cpu.h" #include "kernel_montecarlo.h" #include "kernel_types.h" @@ -34,7 +36,6 @@ #include "attribute.h" -#include <OSL/oslexec.h> CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/kernel/shaders/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl index 70a6a6ea7ce..c9fb3542aef 100644 --- a/intern/cycles/kernel/shaders/node_brick_texture.osl +++ b/intern/cycles/kernel/shaders/node_brick_texture.osl @@ -93,6 +93,6 @@ shader node_brick_texture( Col[2] = facm * (Color1[2]) + tint * Color2[2]; } - Color = (Fac == 1.0) ? Mortar: Col; + Color = (Fac == 1.0) ? Mortar : Col; } diff --git a/intern/cycles/kernel/shaders/node_fresnel.h b/intern/cycles/kernel/shaders/node_fresnel.h index 9f10ba8023e..d192c5d02de 100644 --- a/intern/cycles/kernel/shaders/node_fresnel.h +++ b/intern/cycles/kernel/shaders/node_fresnel.h @@ -36,14 +36,14 @@ float fresnel_dielectric_cos(float cosi, float eta) color fresnel_conductor(float cosi, color eta, color k) { - color cosi2 = color(cosi*cosi); + color cosi2 = color(cosi * cosi); color one = color(1, 1, 1); color tmp_f = eta * eta + k * k; color tmp = tmp_f * cosi2; color Rparl2 = (tmp - (2.0 * eta * cosi) + one) / - (tmp + (2.0 * eta * cosi) + one); + (tmp + (2.0 * eta * cosi) + one); color Rperp2 = (tmp_f - (2.0 * eta * cosi) + cosi2) / - (tmp_f + (2.0 * eta * cosi) + cosi2); + (tmp_f + (2.0 * eta * cosi) + cosi2); return (Rparl2 + Rperp2) * 0.5; } diff --git a/intern/cycles/kernel/shaders/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl index 7bef2051865..cd68f07b21e 100644 --- a/intern/cycles/kernel/shaders/node_geometry.osl +++ b/intern/cycles/kernel/shaders/node_geometry.osl @@ -49,7 +49,7 @@ shader node_geometry( /* try to create spherical tangent from generated coordinates */ if (getattribute("geom:generated", generated)) { - normal data = normal(-(generated[1]-0.5), (generated[0]-0.5), 0.0); + normal data = normal(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0); vector T = transform("object", "world", data); Tangent = cross(Normal, normalize(cross(T, Normal))); } diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl index 7238a1e8862..18b5fb4b31f 100644 --- a/intern/cycles/kernel/shaders/node_image_texture.osl +++ b/intern/cycles/kernel/shaders/node_image_texture.osl @@ -113,6 +113,10 @@ shader node_image_texture( weight[2] = ((2.0 - limit) * Nob[2] + (limit - 1.0)) / (2.0 * limit - 1.0); } } + else { + /* Desperate mode, no valid choice anyway, fallback to one side.*/ + weight[0] = 1.0; + } Color = color(0.0, 0.0, 0.0); Alpha = 0.0; diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl index 60762539002..a32c3d4b1b8 100644 --- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl +++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl @@ -35,14 +35,14 @@ float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float int i; for (i = 0; i < (int)octaves; i++) { - value += safe_noise(p, 0) * pwr; + value += safe_noise(p, "signed") * pwr; pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); if (rmd != 0.0) - value += rmd * safe_noise(p, 0) * pwr; + value += rmd * safe_noise(p, "signed") * pwr; return value; } @@ -63,14 +63,14 @@ float noise_musgrave_multi_fractal(point p, string basis, float H, float lacunar int i; for (i = 0; i < (int)octaves; i++) { - value *= (pwr * safe_noise(p, 0) + 1.0); + value *= (pwr * safe_noise(p, "signed") + 1.0); pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); if (rmd != 0.0) - value *= (rmd * pwr * safe_noise(p, 0) + 1.0); /* correct? */ + value *= (rmd * pwr * safe_noise(p, "signed") + 1.0); /* correct? */ return value; } @@ -91,11 +91,11 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna int i; /* first unscaled octave of function; later octaves are scaled */ - value = offset + safe_noise(p, 0); + value = offset + safe_noise(p, "signed"); p *= lacunarity; for (i = 1; i < (int)octaves; i++) { - increment = (safe_noise(p, 0) + offset) * pwr * value; + increment = (safe_noise(p, "signed") + offset) * pwr * value; value += increment; pwr *= pwHL; p *= lacunarity; @@ -103,7 +103,7 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna rmd = octaves - floor(octaves); if (rmd != 0.0) { - increment = (safe_noise(p, 0) + offset) * pwr * value; + increment = (safe_noise(p, "signed") + offset) * pwr * value; value += rmd * increment; } @@ -126,7 +126,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float pwr = pwHL; int i; - result = safe_noise(p, 0) + offset; + result = safe_noise(p, "signed") + offset; weight = gain * result; p *= lacunarity; @@ -134,7 +134,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, if (weight > 1.0) weight = 1.0; - signal = (safe_noise(p, 0) + offset) * pwr; + signal = (safe_noise(p, "signed") + offset) * pwr; pwr *= pwHL; result += weight * signal; weight *= gain * signal; @@ -143,7 +143,7 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, rmd = octaves - floor(octaves); if (rmd != 0.0) - result += rmd * ((safe_noise(p, 0) + offset) * pwr); + result += rmd * ((safe_noise(p, "signed") + offset) * pwr); return result; } @@ -164,7 +164,7 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float pwr = pwHL; int i; - signal = offset - fabs(safe_noise(p, 0)); + signal = offset - fabs(safe_noise(p, "signed")); signal *= signal; result = signal; weight = 1.0; @@ -172,7 +172,7 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, for (i = 1; i < (int)octaves; i++) { p *= lacunarity; weight = clamp(signal * gain, 0.0, 1.0); - signal = offset - fabs(safe_noise(p, 0)); + signal = offset - fabs(safe_noise(p, "signed")); signal *= signal; signal *= weight; result += signal * pwr; diff --git a/intern/cycles/kernel/shaders/node_texture.h b/intern/cycles/kernel/shaders/node_texture.h index de51559f297..2710eed414a 100644 --- a/intern/cycles/kernel/shaders/node_texture.h +++ b/intern/cycles/kernel/shaders/node_texture.h @@ -153,12 +153,12 @@ float voronoi_CrS(point p) { return 2.0 * voronoi_Cr(p) - 1.0; } /* Noise Bases */ -float safe_noise(point p, int type) +float safe_noise(point p, string type) { float f = 0.0; /* Perlin noise in range -1..1 */ - if (type == 0) + if (type == "signed") f = noise("perlin", p); /* Perlin noise in range 0..1 */ @@ -175,7 +175,7 @@ float safe_noise(point p, int type) float noise_basis(point p, string basis) { if (basis == "Perlin") - return safe_noise(p, 1); + return safe_noise(p, "unsigned"); if (basis == "Voronoi F1") return voronoi_F1S(p); if (basis == "Voronoi F2") diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index f8e5fd510ee..1ff8f363b49 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -476,8 +476,6 @@ closure color diffuse_ramp(normal N, color colors[8]) BUILTIN; closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN; closure color diffuse_toon(normal N, float size, float smooth) BUILTIN; closure color glossy_toon(normal N, float size, float smooth) BUILTIN; -closure color westin_backscatter(normal N, float roughness) BUILTIN; -closure color westin_sheen(normal N, float edginess) BUILTIN; closure color translucent(normal N) BUILTIN; closure color reflection(normal N) BUILTIN; closure color refraction(normal N, float eta) BUILTIN; diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index a7abeda18e5..8a256c9bda5 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -435,6 +435,10 @@ ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float weight.z = ((2.0f - limit)*N.z + (limit - 1.0f))/(2.0f*limit - 1.0f); } } + else { + /* Desperate mode, no valid choice anyway, fallback to one side.*/ + weight.x = 1.0f; + } /* now fetch textures */ uint co_offset, out_offset, alpha_offset, srgb; diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h index 869341c81f4..c77c2a1c482 100644 --- a/intern/cycles/kernel/svm/svm_noise.h +++ b/intern/cycles/kernel/svm/svm_noise.h @@ -290,40 +290,6 @@ ccl_device_noinline float perlin(float x, float y, float z) } #endif -#if 0 // unused -ccl_device_noinline float perlin_periodic(float x, float y, float z, float3 pperiod) -{ - int X; float fx = floorfrac(x, &X); - int Y; float fy = floorfrac(y, &Y); - int Z; float fz = floorfrac(z, &Z); - - int3 p; - - p.x = max(quick_floor(pperiod.x), 1); - p.y = max(quick_floor(pperiod.y), 1); - p.z = max(quick_floor(pperiod.z), 1); - - float u = fade(fx); - float v = fade(fy); - float w = fade(fz); - - float result; - - result = nerp (w, nerp (v, nerp (u, grad (phash (X , Y , Z , p), fx , fy , fz ), - grad (phash (X+1, Y , Z , p), fx-1.0f, fy , fz )), - nerp (u, grad (phash (X , Y+1, Z , p), fx , fy-1.0f, fz ), - grad (phash (X+1, Y+1, Z , p), fx-1.0f, fy-1.0f, fz ))), - nerp (v, nerp (u, grad (phash (X , Y , Z+1, p), fx , fy , fz-1.0f ), - grad (phash (X+1, Y , Z+1, p), fx-1.0f, fy , fz-1.0f )), - nerp (u, grad (phash (X , Y+1, Z+1, p), fx , fy-1.0f, fz-1.0f ), - grad (phash (X+1, Y+1, Z+1, p), fx-1.0f, fy-1.0f, fz-1.0f )))); - float r = scale3(result); - - /* can happen for big coordinates, things even out to 0.0 then anyway */ - return (isfinite(r))? r: 0.0f; -} -#endif - /* perlin noise in range 0..1 */ ccl_device float noise(float3 p) { @@ -367,20 +333,5 @@ ccl_device ssef cellnoise_color(const ssef& p) } #endif -#if 0 // unused -/* periodic perlin noise in range 0..1 */ -ccl_device float pnoise(float3 p, float3 pperiod) -{ - float r = perlin_periodic(p.x, p.y, p.z, pperiod); - return 0.5f*r + 0.5f; -} - -/* periodic perlin noise in range -1..1 */ -ccl_device float psnoise(float3 p, float3 pperiod) -{ - return perlin_periodic(p.x, p.y, p.z, pperiod); -} -#endif - CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 103f562ed60..fbe669c1fab 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -348,7 +348,6 @@ typedef enum ClosureType { /* Diffuse */ CLOSURE_BSDF_DIFFUSE_ID, CLOSURE_BSDF_OREN_NAYAR_ID, - CLOSURE_BSDF_WESTIN_SHEEN_ID, CLOSURE_BSDF_DIFFUSE_RAMP_ID, CLOSURE_BSDF_DIFFUSE_TOON_ID, @@ -362,7 +361,6 @@ typedef enum ClosureType { CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID, CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID, CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, - CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, CLOSURE_BSDF_PHONG_RAMP_ID, CLOSURE_BSDF_GLOSSY_TOON_ID, CLOSURE_BSDF_HAIR_REFLECTION_ID, diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index fc65922fc87..756e16b38b5 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -190,6 +190,14 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int pixels[0] = clamp(f*scale_exposure, 0.0f, 1.0f); } } +#ifdef WITH_CYCLES_DEBUG + else if(type == PASS_BVH_TRAVERSAL_STEPS) { + for(int i = 0; i < size; i++, in += pass_stride, pixels++) { + float f = *in; + pixels[0] = f; + } + } +#endif else { for(int i = 0; i < size; i++, in += pass_stride, pixels++) { float f = *in; diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index bb0fec759a9..110adb4d036 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -15,10 +15,13 @@ */ #include "camera.h" +#include "mesh.h" +#include "object.h" #include "scene.h" #include "device.h" +#include "util_foreach.h" #include "util_vector.h" CCL_NAMESPACE_BEGIN @@ -270,6 +273,20 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) need_device_update = false; previous_need_motion = need_motion; + + /* Camera in volume. */ + kcam->is_inside_volume = 0; + BoundBox viewplane_boundbox = viewplane_bounds_get(); + for(size_t i = 0; i < scene->objects.size(); ++i) { + Object *object = scene->objects[i]; + if(object->mesh->has_volume && + viewplane_boundbox.intersects(object->bounds)) + { + /* TODO(sergey): Consider adding more grained check. */ + kcam->is_inside_volume = 1; + break; + } + } } void Camera::device_free(Device *device, DeviceScene *dscene) @@ -313,5 +330,62 @@ void Camera::tag_update() need_update = true; } +float3 Camera::transform_raster_to_world(float raster_x, float raster_y) +{ + float3 D, P; + if(type == CAMERA_PERSPECTIVE) { + D = transform_perspective(&rastertocamera, + make_float3(raster_x, raster_y, 0.0f)); + P = make_float3(0.0f, 0.0f, 0.0f); + /* TODO(sergey): Aperture support? */ + P = transform_point(&cameratoworld, P); + D = normalize(transform_direction(&cameratoworld, D)); + /* TODO(sergey): Clipping is conditional in kernel, and hence it could + * be mistakes in here, currently leading to wrong camera-in-volume + * detection. + */ + P += nearclip * D; + } + else if (type == CAMERA_ORTHOGRAPHIC) { + D = make_float3(0.0f, 0.0f, 1.0f); + /* TODO(sergey): Aperture support? */ + P = transform_perspective(&rastertocamera, + make_float3(raster_x, raster_y, 0.0f)); + P = transform_point(&cameratoworld, P); + D = normalize(transform_direction(&cameratoworld, D)); + } + else { + assert(!"unsupported camera type"); + } + return P; +} + +BoundBox Camera::viewplane_bounds_get() +{ + /* TODO(sergey): This is all rather stupid, but is there a way to perform + * checks we need in a more clear and smart fasion? + */ + BoundBox bounds = BoundBox::empty; + + if(type == CAMERA_PANORAMA) { + bounds.grow(make_float3(cameratoworld.w.x, + cameratoworld.w.y, + cameratoworld.w.z)); + } + else { + bounds.grow(transform_raster_to_world(0.0f, 0.0f)); + bounds.grow(transform_raster_to_world(0.0f, (float)height)); + bounds.grow(transform_raster_to_world((float)width, (float)height)); + bounds.grow(transform_raster_to_world((float)width, 0.0f)); + if(type == CAMERA_PERSPECTIVE) { + /* Center point has the most distancei in local Z axis, + * use it to construct bounding box/ + */ + bounds.grow(transform_raster_to_world(0.5f*width, 0.5f*height)); + } + } + return bounds; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 50889968a90..788ae7b9bb6 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -116,6 +116,9 @@ public: bool modified(const Camera& cam); bool motion_modified(const Camera& cam); void tag_update(); + + BoundBox viewplane_bounds_get(); + float3 transform_raster_to_world(float raster_x, float raster_y); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 09973e8bc86..19f959d4ea1 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -146,6 +146,12 @@ void Pass::add(PassType type, vector<Pass>& passes) case PASS_LIGHT: /* ignores */ break; +#ifdef WITH_CYCLES_DEBUG + case PASS_BVH_TRAVERSAL_STEPS: + pass.components = 1; + pass.exposure = false; + break; +#endif } passes.push_back(pass); @@ -388,6 +394,13 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) case PASS_LIGHT: kfilm->use_light_pass = 1; break; + +#ifdef WITH_CYCLES_DEBUG + case PASS_BVH_TRAVERSAL_STEPS: + kfilm->pass_bvh_traversal_steps = kfilm->pass_stride; + break; +#endif + case PASS_NONE: break; } diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 0ff904d06e7..45b08832fea 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -320,20 +320,20 @@ void ShaderGraph::remove_unneeded_nodes() { vector<bool> removed(num_node_ids, false); bool any_node_removed = false; - + /* find and unlink proxy nodes */ foreach(ShaderNode *node, nodes) { if(node->special_type == SHADER_SPECIAL_TYPE_PROXY) { ProxyNode *proxy = static_cast<ProxyNode*>(node); ShaderInput *input = proxy->inputs[0]; ShaderOutput *output = proxy->outputs[0]; - + /* temp. copy of the output links list. * output->links is modified when we disconnect! */ vector<ShaderInput*> links(output->links); ShaderOutput *from = input->link; - + /* bypass the proxy node */ if(from) { disconnect(input); @@ -391,6 +391,8 @@ void ShaderGraph::remove_unneeded_nodes() if(output) connect(output, input); } + removed[mix->id] = true; + any_node_removed = true; } /* remove unused mix closure input when factor is 0.0 or 1.0 */ @@ -400,7 +402,7 @@ void ShaderGraph::remove_unneeded_nodes() if(mix->inputs[0]->value.x == 0.0f) { ShaderOutput *output = mix->inputs[1]->link; vector<ShaderInput*> inputs = mix->outputs[0]->links; - + foreach(ShaderInput *sock, mix->inputs) if(sock->link) disconnect(sock); @@ -410,6 +412,8 @@ void ShaderGraph::remove_unneeded_nodes() if(output) connect(output, input); } + removed[mix->id] = true; + any_node_removed = true; } /* factor 1.0 */ else if(mix->inputs[0]->value.x == 1.0f) { @@ -425,13 +429,57 @@ void ShaderGraph::remove_unneeded_nodes() if(output) connect(output, input); } + removed[mix->id] = true; + any_node_removed = true; + } + } + } + else if(node->special_type == SHADER_SPECIAL_TYPE_MIX_RGB) { + MixNode *mix = static_cast<MixNode*>(node); + + /* remove unused Mix RGB inputs when factor is 0.0 or 1.0 */ + /* check for color links and make sure factor link is disconnected */ + if(mix->outputs[0]->links.size() && mix->inputs[1]->link && mix->inputs[2]->link && !mix->inputs[0]->link) { + /* factor 0.0 */ + if(mix->inputs[0]->value.x == 0.0f) { + ShaderOutput *output = mix->inputs[1]->link; + vector<ShaderInput*> inputs = mix->outputs[0]->links; + + foreach(ShaderInput *sock, mix->inputs) + if(sock->link) + disconnect(sock); + + foreach(ShaderInput *input, inputs) { + disconnect(input); + if(output) + connect(output, input); + } + removed[mix->id] = true; + any_node_removed = true; + } + /* factor 1.0 */ + else if(mix->inputs[0]->value.x == 1.0f) { + ShaderOutput *output = mix->inputs[2]->link; + vector<ShaderInput*> inputs = mix->outputs[0]->links; + + foreach(ShaderInput *sock, mix->inputs) + if(sock->link) + disconnect(sock); + + foreach(ShaderInput *input, inputs) { + disconnect(input); + if(output) + connect(output, input); + } + removed[mix->id] = true; + any_node_removed = true; } } } } /* remove nodes */ - if (any_node_removed) { + if(any_node_removed) { list<ShaderNode*> newnodes; foreach(ShaderNode *node, nodes) { @@ -787,5 +835,47 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight } } +void ShaderGraph::dump_graph(const char *filename) +{ + FILE *fd = fopen(filename, "w"); + + if(fd == NULL) { + printf("Error opening file for dumping the graph: %s\n", filename); + return; + } + + fprintf(fd, "digraph dependencygraph {\n"); + fprintf(fd, "ranksep=1.5\n"); + fprintf(fd, "splines=false\n"); + + foreach(ShaderNode *node, nodes) { + fprintf(fd, "// NODE: %p\n", node); + fprintf(fd, + "\"%p\" [shape=record,label=\"%s\"]\n", + node, + node->name.c_str()); + } + + foreach(ShaderNode *node, nodes) { + foreach(ShaderOutput *output, node->outputs) { + foreach(ShaderInput *input, output->links) { + fprintf(fd, + "// CONNECTION: %p->%p (%s:%s)\n", + output, + input, + output->name, input->name); + fprintf(fd, + "\"%p\":s -> \"%p\":n [label=\"%s:%s\"]\n", + output->parent, + input->parent, + output->name, input->name); + } + } + } + + fprintf(fd, "}\n"); + fclose(fd); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 89a066195d6..7b95703d3aa 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -76,6 +76,7 @@ enum ShaderNodeSpecialType { SHADER_SPECIAL_TYPE_NONE, SHADER_SPECIAL_TYPE_PROXY, SHADER_SPECIAL_TYPE_MIX_CLOSURE, + SHADER_SPECIAL_TYPE_MIX_RGB, /* Only Mix subtype */ SHADER_SPECIAL_TYPE_AUTOCONVERT, SHADER_SPECIAL_TYPE_GEOMETRY, SHADER_SPECIAL_TYPE_SCRIPT @@ -249,6 +250,8 @@ public: void remove_unneeded_nodes(); void finalize(bool do_bump = false, bool do_osl = false); + void dump_graph(const char *filename); + protected: typedef pair<ShaderNode* const, ShaderNode*> NodePair; diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 076cc3d8b63..eb2c3333c44 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -176,6 +176,10 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani img->frame = frame; img->need_load = true; } + if(img->use_alpha != use_alpha) { + img->use_alpha = use_alpha; + img->need_load = true; + } img->users++; return slot; } @@ -219,6 +223,10 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani img->frame = frame; img->need_load = true; } + if(img->use_alpha != use_alpha) { + img->use_alpha = use_alpha; + img->need_load = true; + } img->users++; return slot+tex_image_byte_start; } diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 8299cd02fef..42103396b53 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -378,12 +378,12 @@ void Mesh::add_vertex_normals() } } -void Mesh::pack_normals(Scene *scene, float *tri_shader, float4 *vnormal) +void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal) { Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL); float3 *vN = attr_vN->data_float3(); - int shader_id = 0; + uint shader_id = 0; uint last_shader = -1; bool last_smooth = false; @@ -401,7 +401,7 @@ void Mesh::pack_normals(Scene *scene, float *tri_shader, float4 *vnormal) shader_id = scene->shader_manager->get_shader_id(last_shader, this, last_smooth); } - tri_shader[i] = __int_as_float(shader_id); + tri_shader[i] = shader_id; } size_t verts_size = verts.size(); @@ -936,7 +936,7 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene /* normals */ progress.set_status("Updating Mesh", "Computing normals"); - float *tri_shader = dscene->tri_shader.resize(tri_size); + uint *tri_shader = dscene->tri_shader.resize(tri_size); float4 *vnormal = dscene->tri_vnormal.resize(vert_size); float4 *tri_verts = dscene->tri_verts.resize(vert_size); float4 *tri_vindex = dscene->tri_vindex.resize(tri_size); @@ -1032,11 +1032,16 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen if(!need_update) return; - /* update normals */ + /* update normals and flags */ foreach(Mesh *mesh, scene->meshes) { - foreach(uint shader, mesh->used_shaders) + mesh->has_volume = false; + foreach(uint shader, mesh->used_shaders) { if(scene->shaders[shader]->need_update_attributes) mesh->need_update = true; + if(scene->shaders[shader]->has_volume) { + mesh->has_volume = true; + } + } if(mesh->need_update) { mesh->add_face_normals(); @@ -1104,6 +1109,8 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen bool motion_blur = false; #endif + /* update obejcts */ + vector<Object *> volume_objects; foreach(Object *object, scene->objects) object->compute_bounds(motion_blur); diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index d45905611fa..7e34b761faf 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -79,6 +79,8 @@ public: vector<uint> shader; vector<bool> smooth; + bool has_volume; /* Set in the device_update(). */ + vector<float4> curve_keys; /* co + radius */ vector<Curve> curves; @@ -123,7 +125,7 @@ public: void add_face_normals(); void add_vertex_normals(); - void pack_normals(Scene *scene, float *shader, float4 *vnormal); + void pack_normals(Scene *scene, uint *shader, float4 *vnormal); void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset); void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset); void compute_bvh(SceneParams *params, Progress *progress, int n, int total); diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 1f148d34ea6..46ddab235d9 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -75,8 +75,14 @@ void Object::compute_bounds(bool motion_blur) bounds.grow(mbounds.transformed(&ttfm)); } } - else - bounds = mbounds.transformed(&tfm); + else { + if(mesh->transform_applied) { + bounds = mbounds; + } + else { + bounds = mbounds.transformed(&tfm); + } + } } void Object::apply_transform(bool apply_to_motion) @@ -372,8 +378,6 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc device_free(device, dscene); - need_update = false; - if(scene->objects.size() == 0) return; @@ -392,6 +396,46 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc progress.set_status("Updating Objects", "Applying Static Transformations"); apply_static_transforms(dscene, scene, object_flag, progress); } +} + +void ObjectManager::device_update_flags(Device *device, DeviceScene *dscene, + Scene *scene, Progress& progress) +{ + if(!need_update) + return; + + need_update = false; + + if(scene->objects.size() == 0) + return; + + /* object info flag */ + uint *object_flag = dscene->object_flag.get_data(); + + vector<Object *> volume_objects; + foreach(Object *object, scene->objects) { + if(object->mesh->has_volume) { + volume_objects.push_back(object); + } + } + + int object_index = 0; + foreach(Object *object, scene->objects) { + if(object->mesh->has_volume) { + object_flag[object_index] |= SD_OBJECT_HAS_VOLUME; + } + + foreach(Object *volume_object, volume_objects) { + if(object == volume_object) { + continue; + } + if(object->bounds.intersects(volume_object->bounds)) { + object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME; + break; + } + } + ++object_index; + } /* allocate object flag */ device->tex_alloc("__object_flag", dscene->object_flag); diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 677526b715f..2c69b83a2e9 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -76,6 +76,7 @@ public: void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress); + void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); void tag_update(Scene *scene); diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 796007b64a8..6c3f98bc9b0 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -165,13 +165,18 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel()) return; - progress.set_status("Updating Camera"); - camera->device_update(device, &dscene, this); + progress.set_status("Updating Objects"); + object_manager->device_update(device, &dscene, this, progress); if(progress.get_cancel()) return; - progress.set_status("Updating Objects"); - object_manager->device_update(device, &dscene, this, progress); + progress.set_status("Updating Meshes"); + mesh_manager->device_update(device, &dscene, this, progress); + + if(progress.get_cancel()) return; + + progress.set_status("Updating Objects Flags"); + object_manager->device_update_flags(device, &dscene, this, progress); if(progress.get_cancel()) return; @@ -185,8 +190,9 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel()) return; - progress.set_status("Updating Meshes"); - mesh_manager->device_update(device, &dscene, this, progress); + /* TODO(sergey): Make sure camera is not needed above. */ + progress.set_status("Updating Camera"); + camera->device_update(device, &dscene, this); if(progress.get_cancel()) return; diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index e5c7444c92d..5d205225d97 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -69,7 +69,7 @@ public: device_vector<uint> prim_object; /* mesh */ - device_vector<float> tri_shader; + device_vector<uint> tri_shader; device_vector<float4> tri_vnormal; device_vector<float4> tri_vindex; device_vector<float4> tri_verts; diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 0ed6d2ddf01..368496fd188 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -17,6 +17,10 @@ #ifndef __SHADER_H__ #define __SHADER_H__ +#ifdef WITH_OSL +# include <OSL/oslexec.h> +#endif + #include "attribute.h" #include "kernel_types.h" @@ -25,10 +29,6 @@ #include "util_string.h" #include "util_types.h" -#ifdef WITH_OSL -#include <OSL/oslexec.h> -#endif - CCL_NAMESPACE_BEGIN class Device; diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index d6094a4fa0a..e37d8e5f8a1 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -200,8 +200,8 @@ list<Tile>::iterator TileManager::next_background_tile(int device, TileOrder til switch (tile_order) { case TILE_CENTER: - distx = centx - (cur_tile.x + cur_tile.w); - disty = centy - (cur_tile.y + cur_tile.h); + distx = centx - (cur_tile.x + (cur_tile.w / 2)); + disty = centy - (cur_tile.y + (cur_tile.h / 2)); distx = (int64_t)sqrt((double)(distx * distx + disty * disty)); break; case TILE_RIGHT_TO_LEFT: diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index 7b3301e8abe..842d5efac79 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -11,6 +11,7 @@ set(INC_SYS set(SRC util_cache.cpp util_dynlib.cpp + util_logging.cpp util_md5.cpp util_path.cpp util_string.cpp @@ -40,6 +41,7 @@ set(SRC_HEADERS util_hash.h util_image.h util_list.h + util_logging.h util_map.h util_math.h util_md5.h diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h index 369082af60a..a71e0399619 100644 --- a/intern/cycles/util/util_boundbox.h +++ b/intern/cycles/util/util_boundbox.h @@ -167,6 +167,15 @@ public: return result; } + + __forceinline bool intersects(const BoundBox& other) + { + float3 center_diff = center() - other.center(), + total_size = (size() + other.size()) * 0.5f; + return fabsf(center_diff.x) <= total_size.x && + fabsf(center_diff.y) <= total_size.y && + fabsf(center_diff.z) <= total_size.z; + } }; __forceinline BoundBox merge(const BoundBox& bbox, const float3& pt) diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h index 48e9e2d025f..53b3d72de67 100644 --- a/intern/cycles/util/util_color.h +++ b/intern/cycles/util/util_color.h @@ -170,7 +170,7 @@ ccl_device float3 color_srgb_to_scene_linear(float3 c) #ifdef __KERNEL_SSE2__ /* * Calculate initial guess for arg^exp based on float representation - * This method gives a constant bias, which can be easily compensated by multiplicating with bias_coeff. + * This method gives a constant bias, which can be easily compensated by multiplication with bias_coeff. * Gives better results for exponents near 1 (e. g. 4/5). * exp = exponent, encoded as uint32_t * e2coeff = 2^(127/exponent - 127) * bias_coeff^(1/exponent), encoded as uint32_t diff --git a/intern/cycles/util/util_logging.cpp b/intern/cycles/util/util_logging.cpp new file mode 100644 index 00000000000..0722f16cf45 --- /dev/null +++ b/intern/cycles/util/util_logging.cpp @@ -0,0 +1,33 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include <util_logging.h> + +#include "util_math.h" + +CCL_NAMESPACE_BEGIN + +std::ostream& operator <<(std::ostream &os, + const float3 &value) +{ + os << "(" << value.x + << ", " << value.y + << ", " << value.z + << ")"; + return os; +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_logging.h b/intern/cycles/util/util_logging.h new file mode 100644 index 00000000000..991789e7460 --- /dev/null +++ b/intern/cycles/util/util_logging.h @@ -0,0 +1,53 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __UTIL_LOGGING_H__ +#define __UTIL_LOGGING_H__ + +#if defined(WITH_CYCLES_LOGGING) && !defined(__KERNEL_GPU__) +# include <glog/logging.h> +#else +# include <iostream> +#endif + +CCL_NAMESPACE_BEGIN + +#if !defined(WITH_CYCLES_LOGGING) || defined(__KERNEL_GPU__) +class StubStream : public std::ostream { + public: + StubStream() : std::ostream(NULL) { } +}; + +class LogMessageVoidify { +public: + LogMessageVoidify() { } + void operator&(::std::ostream&) { } +}; + +# define LOG_SUPPRESS() (true) ? (void) 0 : LogMessageVoidify() & StubStream() +# define LOG(severity) LOG_SUPPRESS() +# define VLOG(severity) LOG_SUPPRESS() + +#endif + +class float3; + +std::ostream& operator <<(std::ostream &os, + const float3 &value); + +CCL_NAMESPACE_END + +#endif /* __UTIL_LOGGING_H__ */ diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index d7d80e2cffd..2a199e591bf 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -33,14 +33,17 @@ #ifndef __KERNEL_GPU__ -#define ccl_device static inline +# ifdef NDEBUG +# define ccl_device static inline +# else +# define ccl_device static +# endif #define ccl_device_noinline static #define ccl_global #define ccl_constant #define __KERNEL_WITH_SSE_ALIGN__ #if defined(_WIN32) && !defined(FREE_WINDOWS) - #define ccl_device_inline static __forceinline #define ccl_align(...) __declspec(align(__VA_ARGS__)) #ifdef __KERNEL_64_BIT__ @@ -50,7 +53,11 @@ #define ccl_try_align(...) /* not support for function arguments (error C2719) */ #endif #define ccl_may_alias -#define ccl_always_inline __forceinline +# ifdef NDEBUG +# define ccl_always_inline __forceinline +# else +# define ccl_always_inline +# endif #define ccl_maybe_unused #else diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index a2e26574530..236002e9744 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -530,7 +530,8 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( //Ensures window top left is inside this available rect left = left > contentRect.origin.x ? left : contentRect.origin.x; - bottom = bottom > contentRect.origin.y ? bottom : contentRect.origin.y; + // Add contentRect.origin.y to respect docksize + bottom = bottom > contentRect.origin.y ? bottom + contentRect.origin.y : contentRect.origin.y; window = new GHOST_WindowCocoa (this, title, left, bottom, width, height, state, type, stereoVisual, numOfAASamples); @@ -703,7 +704,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) // For some reason NSApp is swallowing the key up events when modifier // key is pressed, even if there seems to be no apparent reason to do // so, as a workaround we always handle these up events. - if ([event type] == NSKeyUp && (([event modifierFlags] & NSCommandKeyMask) || ([event modifierFlags] & NSAlternateKeyMask))) + if ([event type] == NSKeyUp && ([event modifierFlags] & (NSCommandKeyMask | NSAlternateKeyMask))) handleKeyEvent(event); [NSApp sendEvent:event]; diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index 40f406d0ae2..be0a8aadf84 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -72,6 +72,7 @@ void *aligned_malloc(size_t size, size_t alignment) * they work natively with SSE types with no further work. */ assert(alignment == 16); + (void)alignment; return malloc(size); #elif defined(__FreeBSD__) || defined(__NetBSD__) void *result; diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h index 523d1786b97..7da74f7cc4c 100644 --- a/intern/guardedalloc/intern/mallocn_intern.h +++ b/intern/guardedalloc/intern/mallocn_intern.h @@ -103,6 +103,13 @@ # include <stdlib.h> #endif +/* visual studio 2012 does not define inline for C */ +#ifdef _MSC_VER +# define MEM_INLINE static __inline +#else +# define MEM_INLINE static inline +#endif + #define IS_POW2(a) (((a) & ((a) - 1)) == 0) /* Extra padding which needs to be applied on MemHead to make it aligned. */ diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.c b/intern/guardedalloc/intern/mallocn_lockfree_impl.c index ffb23702601..c0f6aeeaa9d 100644 --- a/intern/guardedalloc/intern/mallocn_lockfree_impl.c +++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.c @@ -70,6 +70,23 @@ enum { #define MEMHEAD_IS_MMAP(memhead) ((memhead)->len & (size_t) MEMHEAD_MMAP_FLAG) #define MEMHEAD_IS_ALIGNED(memhead) ((memhead)->len & (size_t) MEMHEAD_ALIGN_FLAG) +/* Uncomment this to have proper peak counter. */ +//#define USE_ATOMIC_MAX + +MEM_INLINE void update_maximum(size_t *maximum_value, size_t value) +{ +#ifdef USE_ATOMIC_MAX + size_t prev_value = *maximum_value; + while (prev_value < value) { + if (atomic_cas_z(maximum_value, prev_value, value) != prev_value) { + break; + } + } +#else + *maximum_value = value > *maximum_value ? value : *maximum_value; +#endif +} + #ifdef __GNUC__ __attribute__ ((format(printf, 1, 2))) #endif @@ -264,9 +281,7 @@ void *MEM_lockfree_callocN(size_t len, const char *str) memh->len = len; atomic_add_u(&totblock, 1); atomic_add_z(&mem_in_use, len); - - /* TODO(sergey): Not strictly speaking thread-safe. */ - peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem; + update_maximum(&peak_mem, mem_in_use); return PTR_FROM_MEMHEAD(memh); } @@ -291,9 +306,7 @@ void *MEM_lockfree_mallocN(size_t len, const char *str) memh->len = len; atomic_add_u(&totblock, 1); atomic_add_z(&mem_in_use, len); - - /* TODO(sergey): Not strictly speaking thread-safe. */ - peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem; + update_maximum(&peak_mem, mem_in_use); return PTR_FROM_MEMHEAD(memh); } @@ -342,9 +355,7 @@ void *MEM_lockfree_mallocN_aligned(size_t len, size_t alignment, const char *str memh->alignment = (short) alignment; atomic_add_u(&totblock, 1); atomic_add_z(&mem_in_use, len); - - /* TODO(sergey): Not strictly speaking thread-safe. */ - peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem; + update_maximum(&peak_mem, mem_in_use); return PTR_FROM_MEMHEAD(memh); } @@ -381,9 +392,8 @@ void *MEM_lockfree_mapallocN(size_t len, const char *str) atomic_add_z(&mem_in_use, len); atomic_add_z(&mmap_in_use, len); - /* TODO(sergey): Not strictly speaking thread-safe. */ - peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem; - peak_mem = mmap_in_use > peak_mem ? mmap_in_use : peak_mem; + update_maximum(&peak_mem, mem_in_use); + update_maximum(&peak_mem, mmap_in_use); return PTR_FROM_MEMHEAD(memh); } diff --git a/intern/opennl/extern/ONL_opennl.h b/intern/opennl/extern/ONL_opennl.h index 721da202c13..c89a4aaf1f4 100644 --- a/intern/opennl/extern/ONL_opennl.h +++ b/intern/opennl/extern/ONL_opennl.h @@ -100,11 +100,11 @@ NLContext nlGetCurrent(void); /* State get/set */ -void nlSolverParameterf(NLenum pname, NLfloat param); +void nlSolverParameterf(NLenum pname, NLdouble param); void nlSolverParameteri(NLenum pname, NLint param); void nlGetBooleanv(NLenum pname, NLboolean* params); -void nlGetFloatv(NLenum pname, NLfloat* params); +void nlGetFloatv(NLenum pname, NLdouble* params); void nlGetIntergerv(NLenum pname, NLint* params); void nlEnable(NLenum pname); @@ -113,8 +113,8 @@ NLboolean nlIsEnabled(NLenum pname); /* Variables */ -void nlSetVariable(NLuint rhsindex, NLuint index, NLfloat value); -NLfloat nlGetVariable(NLuint rhsindex, NLuint index); +void nlSetVariable(NLuint rhsindex, NLuint index, NLdouble value); +NLdouble nlGetVariable(NLuint rhsindex, NLuint index); void nlLockVariable(NLuint index); void nlUnlockVariable(NLuint index); NLboolean nlVariableIsLocked(NLuint index); @@ -126,13 +126,9 @@ void nlEnd(NLenum primitive); /* Setting elements in matrix/vector */ -void nlMatrixAdd(NLuint row, NLuint col, NLfloat value); -void nlRightHandSideAdd(NLuint rhsindex, NLuint index, NLfloat value); -void nlRightHandSideSet(NLuint rhsindex, NLuint index, NLfloat value); - -/* Multiply */ - -void nlMatrixMultiply(NLfloat *x, NLfloat *y); +void nlMatrixAdd(NLuint row, NLuint col, NLdouble value); +void nlRightHandSideAdd(NLuint rhsindex, NLuint index, NLdouble value); +void nlRightHandSideSet(NLuint rhsindex, NLuint index, NLdouble value); /* Solve */ diff --git a/intern/opennl/intern/opennl.c b/intern/opennl/intern/opennl.c index f9c63e9ecf6..8cf4bf1327b 100644 --- a/intern/opennl/intern/opennl.c +++ b/intern/opennl/intern/opennl.c @@ -69,7 +69,7 @@ static void __nl_assertion_failed(char* cond, char* file, int line) { } static void __nl_range_assertion_failed( - float x, float min_val, float max_val, char* file, int line + double x, double min_val, double max_val, char* file, int line ) { fprintf( stderr, @@ -151,7 +151,7 @@ static void __nl_should_not_have_reached(char* file, int line) { typedef struct { NLuint index; - NLfloat value; + NLdouble value; } __NLCoeff; typedef struct { @@ -183,7 +183,7 @@ static void __nlRowColumnGrow(__NLRowColumn* c) { } } -static void __nlRowColumnAdd(__NLRowColumn* c, NLint index, NLfloat value) { +static void __nlRowColumnAdd(__NLRowColumn* c, NLint index, NLdouble value) { NLuint i; for(i=0; i<c->size; i++) { if(c->coeff[i].index == (NLuint)index) { @@ -200,7 +200,7 @@ static void __nlRowColumnAdd(__NLRowColumn* c, NLint index, NLfloat value) { } /* Does not check whether the index already exists */ -static void __nlRowColumnAppend(__NLRowColumn* c, NLint index, NLfloat value) { +static void __nlRowColumnAppend(__NLRowColumn* c, NLint index, NLdouble value) { if(c->size == c->capacity) { __nlRowColumnGrow(c); } @@ -229,7 +229,7 @@ typedef struct { NLenum storage; __NLRowColumn* row; __NLRowColumn* column; - NLfloat* diag; + NLdouble* diag; } __NLSparseMatrix; @@ -259,7 +259,7 @@ static void __nlSparseMatrixConstruct( } M->diag_size = MIN(m,n); - M->diag = __NL_NEW_ARRAY(NLfloat, M->diag_size); + M->diag = __NL_NEW_ARRAY(NLdouble, M->diag_size); } static void __nlSparseMatrixDestroy(__NLSparseMatrix* M) { @@ -283,7 +283,7 @@ static void __nlSparseMatrixDestroy(__NLSparseMatrix* M) { } static void __nlSparseMatrixAdd( - __NLSparseMatrix* M, NLuint i, NLuint j, NLfloat value + __NLSparseMatrix* M, NLuint i, NLuint j, NLdouble value ) { __nl_parano_range_assert(i, 0, M->m - 1); __nl_parano_range_assert(j, 0, M->n - 1); @@ -313,7 +313,7 @@ static void __nlSparseMatrixClear( __NLSparseMatrix* M) { __nlRowColumnClear(&(M->column[i])); } } - __NL_CLEAR_ARRAY(NLfloat, M->diag, M->diag_size); + __NL_CLEAR_ARRAY(NLdouble, M->diag, M->diag_size); } /* Returns the number of non-zero coefficients */ @@ -338,7 +338,7 @@ static NLuint __nlSparseMatrixNNZ( __NLSparseMatrix* M) { /* SparseMatrix x Vector routines, internal helper routines */ static void __nlSparseMatrix_mult_rows_symmetric( - __NLSparseMatrix* A, NLfloat* x, NLfloat* y + __NLSparseMatrix* A, NLdouble* x, NLdouble* y ) { NLuint m = A->m; NLuint i,ij; @@ -358,7 +358,7 @@ static void __nlSparseMatrix_mult_rows_symmetric( } static void __nlSparseMatrix_mult_rows( - __NLSparseMatrix* A, NLfloat* x, NLfloat* y + __NLSparseMatrix* A, NLdouble* x, NLdouble* y ) { NLuint m = A->m; NLuint i,ij; @@ -375,7 +375,7 @@ static void __nlSparseMatrix_mult_rows( } static void __nlSparseMatrix_mult_cols_symmetric( - __NLSparseMatrix* A, NLfloat* x, NLfloat* y + __NLSparseMatrix* A, NLdouble* x, NLdouble* y ) { NLuint n = A->n; NLuint j,ii; @@ -395,13 +395,13 @@ static void __nlSparseMatrix_mult_cols_symmetric( } static void __nlSparseMatrix_mult_cols( - __NLSparseMatrix* A, NLfloat* x, NLfloat* y + __NLSparseMatrix* A, NLdouble* x, NLdouble* y ) { NLuint n = A->n; NLuint j,ii; __NLRowColumn* Cj = NULL; __NLCoeff* c = NULL; - __NL_CLEAR_ARRAY(NLfloat, y, A->m); + __NL_CLEAR_ARRAY(NLdouble, y, A->m); for(j=0; j<n; j++) { Cj = &(A->column[j]); for(ii=0; ii<Cj->size; ii++) { @@ -414,7 +414,7 @@ static void __nlSparseMatrix_mult_cols( /************************************************************************************/ /* SparseMatrix x Vector routines, main driver routine */ -static void __nlSparseMatrixMult(__NLSparseMatrix* A, NLfloat* x, NLfloat* y) { +static void __nlSparseMatrixMult(__NLSparseMatrix* A, NLdouble* x, NLdouble* y) { if(A->storage & __NL_ROWS) { if(A->storage & __NL_SYMMETRIC) { __nlSparseMatrix_mult_rows_symmetric(A, x, y); @@ -440,7 +440,7 @@ static void __nlSparseMatrix_square( NLuint i, j0, j1; __NLRowColumn *Ri = NULL; __NLCoeff *c0 = NULL, *c1 = NULL; - float value; + double value; __nlSparseMatrixConstruct(AtA, n, n, A->storage); @@ -460,7 +460,7 @@ static void __nlSparseMatrix_square( } static void __nlSparseMatrix_transpose_mult_rows( - __NLSparseMatrix* A, NLfloat* x, NLfloat* y + __NLSparseMatrix* A, NLdouble* x, NLdouble* y ) { NLuint m = A->m; NLuint n = A->n; @@ -468,7 +468,7 @@ static void __nlSparseMatrix_transpose_mult_rows( __NLRowColumn* Ri = NULL; __NLCoeff* c = NULL; - __NL_CLEAR_ARRAY(NLfloat, y, n); + __NL_CLEAR_ARRAY(NLdouble, y, n); for(i=0; i<m; i++) { Ri = &(A->row[i]); @@ -482,10 +482,10 @@ static void __nlSparseMatrix_transpose_mult_rows( /************************************************************************************/ /* NLContext data structure */ -typedef void(*__NLMatrixFunc)(float* x, float* y); +typedef void(*__NLMatrixFunc)(double* x, double* y); typedef struct { - NLfloat value[4]; + NLdouble value[4]; NLboolean locked; NLuint index; __NLRowColumn *a; @@ -503,11 +503,11 @@ typedef struct { NLuint n; NLuint m; __NLVariable* variable; - NLfloat* b; - NLfloat* Mtb; + NLdouble* b; + NLdouble* Mtb; __NLSparseMatrix M; __NLSparseMatrix MtM; - NLfloat* x; + NLdouble* x; NLuint nb_variables; NLuint nb_rows; NLboolean least_squares; @@ -520,7 +520,7 @@ typedef struct { NLboolean alloc_x; NLboolean alloc_b; NLboolean alloc_Mtb; - NLfloat error; + NLdouble error; __NLMatrixFunc matrix_vector_prod; struct __NLSuperLUContext { @@ -533,7 +533,7 @@ typedef struct { static __NLContext* __nlCurrentContext = NULL; -static void __nlMatrixVectorProd_default(NLfloat* x, NLfloat* y) { +static void __nlMatrixVectorProd_default(NLdouble* x, NLdouble* y) { __nlSparseMatrixMult(&(__nlCurrentContext->M), x, y); } @@ -611,7 +611,7 @@ static void __nlTransition(NLenum from_state, NLenum to_state) { /************************************************************************************/ /* Get/Set parameters */ -void nlSolverParameterf(NLenum pname, NLfloat param) { +void nlSolverParameterf(NLenum pname, NLdouble param) { __nlCheckState(__NL_STATE_INITIAL); switch(pname) { case NL_NB_VARIABLES: { @@ -677,22 +677,22 @@ void nlGetBooleanv(NLenum pname, NLboolean* params) { } } -void nlGetFloatv(NLenum pname, NLfloat* params) { +void nlGetFloatv(NLenum pname, NLdouble* params) { switch(pname) { case NL_NB_VARIABLES: { - *params = (NLfloat)(__nlCurrentContext->nb_variables); + *params = (NLdouble)(__nlCurrentContext->nb_variables); } break; case NL_NB_ROWS: { - *params = (NLfloat)(__nlCurrentContext->nb_rows); + *params = (NLdouble)(__nlCurrentContext->nb_rows); } break; case NL_LEAST_SQUARES: { - *params = (NLfloat)(__nlCurrentContext->least_squares); + *params = (NLdouble)(__nlCurrentContext->least_squares); } break; case NL_SYMMETRIC: { - *params = (NLfloat)(__nlCurrentContext->symmetric); + *params = (NLdouble)(__nlCurrentContext->symmetric); } break; case NL_ERROR: { - *params = (NLfloat)(__nlCurrentContext->error); + *params = (NLdouble)(__nlCurrentContext->error); } break; default: { __nl_assert_not_reached; @@ -751,13 +751,13 @@ NLboolean nlIsEnabled(NLenum pname) { /************************************************************************************/ /* Get/Set Lock/Unlock variables */ -void nlSetVariable(NLuint rhsindex, NLuint index, NLfloat value) { +void nlSetVariable(NLuint rhsindex, NLuint index, NLdouble value) { __nlCheckState(__NL_STATE_SYSTEM); __nl_parano_range_assert(index, 0, __nlCurrentContext->nb_variables - 1); __nlCurrentContext->variable[index].value[rhsindex] = value; } -NLfloat nlGetVariable(NLuint rhsindex, NLuint index) { +NLdouble nlGetVariable(NLuint rhsindex, NLuint index) { __nl_assert(__nlCurrentContext->state != __NL_STATE_INITIAL); __nl_parano_range_assert(index, 0, __nlCurrentContext->nb_variables - 1); return __nlCurrentContext->variable[index].value[rhsindex]; @@ -870,15 +870,15 @@ static void __nlBeginMatrix() { __nlSparseMatrixConstruct(&context->M, m, n, storage); context->alloc_M = NL_TRUE; - context->b = __NL_NEW_ARRAY(NLfloat, m*context->nb_rhs); + context->b = __NL_NEW_ARRAY(NLdouble, m*context->nb_rhs); context->alloc_b = NL_TRUE; - context->x = __NL_NEW_ARRAY(NLfloat, n*context->nb_rhs); + context->x = __NL_NEW_ARRAY(NLdouble, n*context->nb_rhs); context->alloc_x = NL_TRUE; } else { /* need to recompute b only, A is not constructed anymore */ - __NL_CLEAR_ARRAY(NLfloat, context->b, context->m*context->nb_rhs); + __NL_CLEAR_ARRAY(NLdouble, context->b, context->m*context->nb_rhs); } __nlVariablesToVector(); @@ -888,7 +888,7 @@ static void __nlEndMatrixRHS(NLuint rhs) { __NLContext *context = __nlCurrentContext; __NLVariable *variable; __NLRowColumn *a; - NLfloat *b, *Mtb; + NLdouble *b, *Mtb; NLuint i, j; b = context->b + context->m*rhs; @@ -922,7 +922,7 @@ static void __nlEndMatrix() { context->alloc_MtM = NL_TRUE; context->Mtb = - __NL_NEW_ARRAY(NLfloat, context->n*context->nb_rhs); + __NL_NEW_ARRAY(NLdouble, context->n*context->nb_rhs); context->alloc_Mtb = NL_TRUE; } } @@ -931,7 +931,7 @@ static void __nlEndMatrix() { __nlEndMatrixRHS(i); } -void nlMatrixAdd(NLuint row, NLuint col, NLfloat value) +void nlMatrixAdd(NLuint row, NLuint col, NLdouble value) { __NLContext *context = __nlCurrentContext; @@ -960,10 +960,10 @@ void nlMatrixAdd(NLuint row, NLuint col, NLfloat value) } } -void nlRightHandSideAdd(NLuint rhsindex, NLuint index, NLfloat value) +void nlRightHandSideAdd(NLuint rhsindex, NLuint index, NLdouble value) { __NLContext *context = __nlCurrentContext; - NLfloat* b = context->b; + NLdouble* b = context->b; __nlCheckState(__NL_STATE_MATRIX); @@ -981,10 +981,10 @@ void nlRightHandSideAdd(NLuint rhsindex, NLuint index, NLfloat value) } } -void nlRightHandSideSet(NLuint rhsindex, NLuint index, NLfloat value) +void nlRightHandSideSet(NLuint rhsindex, NLuint index, NLdouble value) { __NLContext *context = __nlCurrentContext; - NLfloat* b = context->b; + NLdouble* b = context->b; __nlCheckState(__NL_STATE_MATRIX); @@ -1047,8 +1047,8 @@ static NLboolean __nlFactorize_SUPERLU(__NLContext *context, NLint *permutation) /* Compressed Row Storage matrix representation */ NLint *xa = __NL_NEW_ARRAY(NLint, n+1); - NLfloat *rhs = __NL_NEW_ARRAY(NLfloat, n); - NLfloat *a = __NL_NEW_ARRAY(NLfloat, nnz); + NLdouble *rhs = __NL_NEW_ARRAY(NLdouble, n); + NLdouble *a = __NL_NEW_ARRAY(NLdouble, nnz); NLint *asub = __NL_NEW_ARRAY(NLint, nnz); NLint *etree = __NL_NEW_ARRAY(NLint, n); @@ -1083,7 +1083,7 @@ static NLboolean __nlFactorize_SUPERLU(__NLContext *context, NLint *permutation) sCreate_CompCol_Matrix( &At, n, n, nnz, a, asub, xa, SLU_NC, /* Colum wise, no supernode */ - SLU_S, /* floats */ + SLU_S, /* doubles */ SLU_GE /* general storage */ ); @@ -1136,8 +1136,8 @@ static NLboolean __nlFactorize_SUPERLU(__NLContext *context, NLint *permutation) static NLboolean __nlInvert_SUPERLU(__NLContext *context) { /* OpenNL Context */ - NLfloat* b = (context->least_squares)? context->Mtb: context->b; - NLfloat* x = context->x; + NLdouble* b = (context->least_squares)? context->Mtb: context->b; + NLdouble* x = context->x; NLuint n = context->n, j; /* SuperLU variables */ @@ -1149,7 +1149,7 @@ static NLboolean __nlInvert_SUPERLU(__NLContext *context) { sCreate_Dense_Matrix( &B, n, 1, b, n, SLU_DN, /* Fortran-type column-wise storage */ - SLU_S, /* floats */ + SLU_S, /* doubles */ SLU_GE /* general */ ); @@ -1184,12 +1184,12 @@ void nlPrintMatrix(void) { __NLContext *context = __nlCurrentContext; __NLSparseMatrix* M = &(context->M); __NLSparseMatrix* MtM = &(context->MtM); - float *b = context->b; + double *b = context->b; NLuint i, jj, k; NLuint m = context->m; NLuint n = context->n; __NLRowColumn* Ri = NULL; - float *value = malloc(sizeof(*value)*(n+m)); + double *value = malloc(sizeof(*value)*(n+m)); printf("A:\n"); for(i=0; i<m; i++) { diff --git a/intern/opennl/superlu/scolumn_bmod.c b/intern/opennl/superlu/scolumn_bmod.c index 3d4f5968778..9854115b894 100644 --- a/intern/opennl/superlu/scolumn_bmod.c +++ b/intern/opennl/superlu/scolumn_bmod.c @@ -29,9 +29,9 @@ /* * Function prototypes */ -void susolve(int, int, float*, float*); -void slsolve(int, int, float*, float*); -void smatvec(int, int, int, float*, float*, float*); +void susolve(int, int, double*, double*); +void slsolve(int, int, double*, double*); +void smatvec(int, int, int, double*, double*, double*); @@ -42,8 +42,8 @@ int scolumn_bmod ( const int jcol, /* in */ const int nseg, /* in */ - float *dense, /* in */ - float *tempv, /* working array */ + double *dense, /* in */ + double *tempv, /* working array */ int *segrep, /* in */ int *repfnz, /* in */ int fpanelc, /* in -- first column in the current panel */ @@ -67,7 +67,7 @@ scolumn_bmod ( #ifdef USE_VENDOR_BLAS int incx = 1, incy = 1; - float alpha, beta; + double alpha, beta; #endif /* krep = representative of current k-th supernode @@ -78,7 +78,7 @@ scolumn_bmod ( * kfnz = first nonz in the k-th supernodal segment * no_zeros = no of leading zeros in a supernodal U-segment */ - float ukj, ukj1, ukj2; + double ukj, ukj1, ukj2; int luptr, luptr1, luptr2; int fsupc, nsupc, nsupr, segsze; int nrow; /* No of rows in the matrix of matrix-vector */ @@ -91,14 +91,14 @@ scolumn_bmod ( panel and the first column of the current snode. */ int *xsup, *supno; int *lsub, *xlsub; - float *lusup; + double *lusup; int *xlusup; int nzlumax; - float *tempv1; - float zero = 0.0; + double *tempv1; + double zero = 0.0; #ifdef USE_VENDOR_BLAS - float one = 1.0; - float none = -1.0; + double one = 1.0; + double none = -1.0; #endif int mem_error; flops_t *ops = stat->ops; diff --git a/intern/opennl/superlu/scopy_to_ucol.c b/intern/opennl/superlu/scopy_to_ucol.c index 14904533e3a..4cf7d64a349 100644 --- a/intern/opennl/superlu/scopy_to_ucol.c +++ b/intern/opennl/superlu/scopy_to_ucol.c @@ -33,7 +33,7 @@ scopy_to_ucol( int *segrep, /* in */ int *repfnz, /* in */ int *perm_r, /* in */ - float *dense, /* modified - reset to zero on return */ + double *dense, /* modified - reset to zero on return */ GlobalLU_t *Glu /* modified */ ) { @@ -47,11 +47,11 @@ scopy_to_ucol( int new_next, mem_error; int *xsup, *supno; int *lsub, *xlsub; - float *ucol; + double *ucol; int *usub, *xusub; int nzumax; - float zero = 0.0; + double zero = 0.0; xsup = Glu->xsup; supno = Glu->supno; diff --git a/intern/opennl/superlu/sgssv.c b/intern/opennl/superlu/sgssv.c index a653764304a..b2a9848e597 100644 --- a/intern/opennl/superlu/sgssv.c +++ b/intern/opennl/superlu/sgssv.c @@ -119,7 +119,7 @@ sgssv(superlu_options_t *options, SuperMatrix *A, int *perm_c, int *perm_r, * On exit, the solution matrix if info = 0; * * stat (output) SuperLUStat_t* - * Record the statistics on runtime and floating-point operation count. + * Record the statistics on runtime and doubleing-point operation count. * See util.h for the definition of 'SuperLUStat_t'. * * info (output) int* diff --git a/intern/opennl/superlu/sgstrf.c b/intern/opennl/superlu/sgstrf.c index 335f21165ca..78b1ba21865 100644 --- a/intern/opennl/superlu/sgstrf.c +++ b/intern/opennl/superlu/sgstrf.c @@ -56,7 +56,7 @@ sgstrf (superlu_options_t *options, SuperMatrix *A, * (A->nrow, A->ncol). The type of A can be: * Stype = SLU_NCP; Dtype = SLU_S; Mtype = SLU_GE. * - * drop_tol (input) float (NOT IMPLEMENTED) + * drop_tol (input) double (NOT IMPLEMENTED) * Drop tolerance parameter. At step j of the Gaussian elimination, * if abs(A_ij)/(max_i abs(A_ij)) < drop_tol, drop entry A_ij. * 0 <= drop_tol <= 1. The default value of drop_tol is 0. @@ -119,7 +119,7 @@ sgstrf (superlu_options_t *options, SuperMatrix *A, * Dtype = SLU_S, Mtype = SLU_TRU. * * stat (output) SuperLUStat_t* - * Record the statistics on runtime and floating-point operation count. + * Record the statistics on runtime and doubleing-point operation count. * See util.h for the definition of 'SuperLUStat_t'. * * info (output) int* @@ -189,14 +189,14 @@ sgstrf (superlu_options_t *options, SuperMatrix *A, used when options->Fact == SamePattern_SameRowPerm */ int *iperm_c; /* inverse of perm_c */ int *iwork; - float *swork; + double *swork; int *segrep, *repfnz, *parent, *xplore; int *panel_lsub; /* dense[]/panel_lsub[] pair forms a w-wide SPA */ int *xprune; int *marker; - float *dense, *tempv; + double *dense, *tempv; int *relax_end; - float *a; + double *a; int *asub; int *xa_begin, *xa_end; int *xsup, *supno; diff --git a/intern/opennl/superlu/sgstrs.c b/intern/opennl/superlu/sgstrs.c index 0ed59df228e..5387e319d99 100644 --- a/intern/opennl/superlu/sgstrs.c +++ b/intern/opennl/superlu/sgstrs.c @@ -28,10 +28,10 @@ /* * Function prototypes */ -void susolve(int, int, float*, float*); -void slsolve(int, int, float*, float*); -void smatvec(int, int, int, float*, float*, float*); -void sprint_soln(int , float *); +void susolve(int, int, double*, double*); +void slsolve(int, int, double*, double*); +void smatvec(int, int, int, double*, double*, double*); +void sprint_soln(int , double *); void sgstrs (trans_t trans, SuperMatrix *L, SuperMatrix *U, @@ -82,7 +82,7 @@ sgstrs (trans_t trans, SuperMatrix *L, SuperMatrix *U, * On exit, the solution matrix if info = 0; * * stat (output) SuperLUStat_t* - * Record the statistics on runtime and floating-point operation count. + * Record the statistics on runtime and doubleing-point operation count. * See util.h for the definition of 'SuperLUStat_t'. * * info (output) int* @@ -94,17 +94,17 @@ sgstrs (trans_t trans, SuperMatrix *L, SuperMatrix *U, _fcd ftcs1, ftcs2, ftcs3, ftcs4; #endif #ifdef USE_VENDOR_BLAS - float alpha = 1.0, beta = 1.0; - float *work_col; + double alpha = 1.0, beta = 1.0; + double *work_col; #endif DNformat *Bstore; - float *Bmat; + double *Bmat; SCformat *Lstore; NCformat *Ustore; - float *Lval, *Uval; + double *Lval, *Uval; int fsupc, nrow, nsupr, nsupc, luptr, istart, irow; int i, j, k, iptr, jcol, n, ldb, nrhs; - float *work, *rhs_work, *soln; + double *work, *rhs_work, *soln; flops_t solve_ops; void sprint_soln(); @@ -130,9 +130,9 @@ sgstrs (trans_t trans, SuperMatrix *L, SuperMatrix *U, } n = L->nrow; - work = floatCalloc(n * nrhs); + work = doubleCalloc(n * nrhs); if ( !work ) ABORT("Malloc fails for local work[]."); - soln = floatMalloc(n); + soln = doubleMalloc(n); if ( !soln ) ABORT("Malloc fails for local soln[]."); Bmat = Bstore->nzval; @@ -325,7 +325,7 @@ sgstrs (trans_t trans, SuperMatrix *L, SuperMatrix *U, * Diagnostic print of the solution vector */ void -sprint_soln(int n, float *soln) +sprint_soln(int n, double *soln) { int i; diff --git a/intern/opennl/superlu/smemory.c b/intern/opennl/superlu/smemory.c index 7a2821a4068..a76f60a1758 100644 --- a/intern/opennl/superlu/smemory.c +++ b/intern/opennl/superlu/smemory.c @@ -24,8 +24,8 @@ /* Internal prototypes */ void *sexpand (int *, MemType,int, int, GlobalLU_t *); -int sLUWorkInit (int, int, int, int **, float **, LU_space_t); -void copy_mem_float (int, void *, void *); +int sLUWorkInit (int, int, int, int **, double **, LU_space_t); +void copy_mem_double (int, void *, void *); void sStackCompress (GlobalLU_t *); void sSetupSpace (void *, int, LU_space_t *); void *suser_malloc (int, int); @@ -59,7 +59,7 @@ static int no_expand; #define NotDoubleAlign(addr) ( (intptr_t)addr & 7 ) #define DoubleAlign(addr) ( ((intptr_t)addr + 7) & ~7L ) #define TempSpace(m, w) ( (2*w + 4 + NO_MARKER) * m * sizeof(int) + \ - (w + 1) * m * sizeof(float) ) + (w + 1) * m * sizeof(double) ) #define Reduce(alpha) ((alpha + 1) / 2) /* i.e. (alpha-1)/2 + 1 */ @@ -119,9 +119,9 @@ void suser_free(int bytes, int which_end) /* * mem_usage consists of the following fields: - * - for_lu (float) + * - for_lu (double) * The amount of space used in bytes for the L\U data structures. - * - total_needed (float) + * - total_needed (double) * The amount of space needed in bytes to perform factorization. * - expansions (int) * Number of memory expansions during the LU factorization. @@ -136,17 +136,17 @@ int sQuerySpace(SuperMatrix *L, SuperMatrix *U, mem_usage_t *mem_usage) Ustore = U->Store; n = L->ncol; iword = sizeof(int); - dword = sizeof(float); + dword = sizeof(double); /* For LU factors */ - mem_usage->for_lu = (float)( (4*n + 3) * iword + Lstore->nzval_colptr[n] * + mem_usage->for_lu = (double)( (4*n + 3) * iword + Lstore->nzval_colptr[n] * dword + Lstore->rowind_colptr[n] * iword ); - mem_usage->for_lu += (float)( (n + 1) * iword + + mem_usage->for_lu += (double)( (n + 1) * iword + Ustore->colptr[n] * (dword + iword) ); /* Working storage to support factorization */ mem_usage->total_needed = mem_usage->for_lu + - (float)( (2 * panel_size + 4 + NO_MARKER) * n * iword + + (double)( (2 * panel_size + 4 + NO_MARKER) * n * iword + (panel_size + 1) * n * dword ); mem_usage->expansions = --no_expand; @@ -165,16 +165,16 @@ int sQuerySpace(SuperMatrix *L, SuperMatrix *U, mem_usage_t *mem_usage) int sLUMemInit(fact_t fact, void *work, int lwork, int m, int n, int annz, int panel_size, SuperMatrix *L, SuperMatrix *U, GlobalLU_t *Glu, - int **iwork, float **dwork) + int **iwork, double **dwork) { int info, iword, dword; SCformat *Lstore; NCformat *Ustore; int *xsup, *supno; int *lsub, *xlsub; - float *lusup; + double *lusup; int *xlusup; - float *ucol; + double *ucol; int *usub, *xusub; int nzlmax, nzumax, nzlumax; int FILL = sp_ienv(6); @@ -182,7 +182,7 @@ sLUMemInit(fact_t fact, void *work, int lwork, int m, int n, int annz, Glu->n = n; no_expand = 0; iword = sizeof(int); - dword = sizeof(float); + dword = sizeof(double); if ( !expanders ) expanders = (ExpHeader*)SUPERLU_MALLOC(NO_MEMTYPE * sizeof(ExpHeader)); @@ -220,8 +220,8 @@ sLUMemInit(fact_t fact, void *work, int lwork, int m, int n, int annz, xusub = (int *)suser_malloc((n+1) * iword, HEAD); } - lusup = (float *) sexpand( &nzlumax, LUSUP, 0, 0, Glu ); - ucol = (float *) sexpand( &nzumax, UCOL, 0, 0, Glu ); + lusup = (double *) sexpand( &nzlumax, LUSUP, 0, 0, Glu ); + ucol = (double *) sexpand( &nzumax, UCOL, 0, 0, Glu ); lsub = (int *) sexpand( &nzlmax, LSUB, 0, 0, Glu ); usub = (int *) sexpand( &nzumax, USUB, 0, 1, Glu ); @@ -241,8 +241,8 @@ sLUMemInit(fact_t fact, void *work, int lwork, int m, int n, int annz, printf("Not enough memory to perform factorization.\n"); return (smemory_usage(nzlmax, nzumax, nzlumax, n) + n); } - lusup = (float *) sexpand( &nzlumax, LUSUP, 0, 0, Glu ); - ucol = (float *) sexpand( &nzumax, UCOL, 0, 0, Glu ); + lusup = (double *) sexpand( &nzlumax, LUSUP, 0, 0, Glu ); + ucol = (double *) sexpand( &nzumax, UCOL, 0, 0, Glu ); lsub = (int *) sexpand( &nzlmax, LSUB, 0, 0, Glu ); usub = (int *) sexpand( &nzumax, USUB, 0, 1, Glu ); } @@ -307,16 +307,16 @@ sLUMemInit(fact_t fact, void *work, int lwork, int m, int n, int annz, returns the number of bytes allocated so far when failure occurred. */ int sLUWorkInit(int m, int n, int panel_size, int **iworkptr, - float **dworkptr, LU_space_t MemModel) + double **dworkptr, LU_space_t MemModel) { int isize, dsize, extra; - float *old_ptr; + double *old_ptr; int maxsuper = sp_ienv(3), rowblk = sp_ienv(4); isize = ( (2 * panel_size + 3 + NO_MARKER ) * m + n ) * sizeof(int); dsize = (m * panel_size + - NUM_TEMPV(m,panel_size,maxsuper,rowblk)) * sizeof(float); + NUM_TEMPV(m,panel_size,maxsuper,rowblk)) * sizeof(double); if ( MemModel == SYSTEM ) *iworkptr = (int *) intCalloc(isize/sizeof(int)); @@ -328,13 +328,13 @@ sLUWorkInit(int m, int n, int panel_size, int **iworkptr, } if ( MemModel == SYSTEM ) - *dworkptr = (float *) SUPERLU_MALLOC(dsize); + *dworkptr = (double *) SUPERLU_MALLOC(dsize); else { - *dworkptr = (float *) suser_malloc(dsize, TAIL); + *dworkptr = (double *) suser_malloc(dsize, TAIL); if ( NotDoubleAlign(*dworkptr) ) { old_ptr = *dworkptr; - *dworkptr = (float*) DoubleAlign(*dworkptr); - *dworkptr = (float*) ((double*)*dworkptr - 1); + *dworkptr = (double*) DoubleAlign(*dworkptr); + *dworkptr = (double*) ((double*)*dworkptr - 1); extra = (char*)old_ptr - (char*)*dworkptr; #ifdef DEBUG printf("sLUWorkInit: not aligned, extra %d\n", extra); @@ -356,10 +356,10 @@ sLUWorkInit(int m, int n, int panel_size, int **iworkptr, * Set up pointers for real working arrays. */ void -sSetRWork(int m, int panel_size, float *dworkptr, - float **dense, float **tempv) +sSetRWork(int m, int panel_size, double *dworkptr, + double **dense, double **tempv) { - float zero = 0.0; + double zero = 0.0; int maxsuper = sp_ienv(3), rowblk = sp_ienv(4); @@ -372,7 +372,7 @@ sSetRWork(int m, int panel_size, float *dworkptr, /* * Free the working storage used by factor routines. */ -void sLUWorkFree(int *iwork, float *dwork, GlobalLU_t *Glu) +void sLUWorkFree(int *iwork, double *dwork, GlobalLU_t *Glu) { if ( Glu->MemModel == SYSTEM ) { SUPERLU_FREE (iwork); @@ -421,11 +421,11 @@ sLUMemXpand(int jcol, switch ( mem_type ) { case LUSUP: - Glu->lusup = (float *) new_mem; + Glu->lusup = (double *) new_mem; Glu->nzlumax = *maxlen; break; case UCOL: - Glu->ucol = (float *) new_mem; + Glu->ucol = (double *) new_mem; Glu->nzumax = *maxlen; break; case LSUB: @@ -445,11 +445,11 @@ sLUMemXpand(int jcol, void -copy_mem_float(int howmany, void *old, void *new) +copy_mem_double(int howmany, void *old, void *new) { register int i; - float *dold = old; - float *dnew = new; + double *dold = old; + double *dnew = new; for (i = 0; i < howmany; i++) dnew[i] = dold[i]; } @@ -466,8 +466,8 @@ void GlobalLU_t *Glu /* modified - global LU data structures */ ) { - float EXPAND = 1.5; - float alpha; + double EXPAND = 1.5; + double alpha; void *new_mem, *old_mem; int new_len, tries, lword, extra, bytes_to_copy; @@ -480,7 +480,7 @@ void } if ( type == LSUB || type == USUB ) lword = sizeof(int); - else lword = sizeof(float); + else lword = sizeof(double); if ( Glu->MemModel == SYSTEM ) { new_mem = (void *) SUPERLU_MALLOC(new_len * lword); @@ -501,7 +501,7 @@ void if ( type == LSUB || type == USUB ) { copy_mem_int(len_to_copy, expanders[type].mem, new_mem); } else { - copy_mem_float(len_to_copy, expanders[type].mem, new_mem); + copy_mem_double(len_to_copy, expanders[type].mem, new_mem); } SUPERLU_FREE (expanders[type].mem); } @@ -585,12 +585,12 @@ sStackCompress(GlobalLU_t *Glu) register int iword, dword, ndim; char *last, *fragment; int *ifrom, *ito; - float *dfrom, *dto; + double *dfrom, *dto; int *xlsub, *lsub, *xusub, *usub, *xlusup; - float *ucol, *lusup; + double *ucol, *lusup; iword = sizeof(int); - dword = sizeof(float); + dword = sizeof(double); ndim = Glu->n; xlsub = Glu->xlsub; @@ -602,8 +602,8 @@ sStackCompress(GlobalLU_t *Glu) lusup = Glu->lusup; dfrom = ucol; - dto = (float *)((char*)lusup + xlusup[ndim] * dword); - copy_mem_float(xusub[ndim], dfrom, dto); + dto = (double *)((char*)lusup + xlusup[ndim] * dword); + copy_mem_double(xusub[ndim], dfrom, dto); ucol = dto; ifrom = lsub; @@ -637,32 +637,32 @@ sStackCompress(GlobalLU_t *Glu) * Allocate storage for original matrix A */ void -sallocateA(int n, int nnz, float **a, int **asub, int **xa) +sallocateA(int n, int nnz, double **a, int **asub, int **xa) { - *a = (float *) floatMalloc(nnz); + *a = (double *) doubleMalloc(nnz); *asub = (int *) intMalloc(nnz); *xa = (int *) intMalloc(n+1); } -float *floatMalloc(int n) +double *doubleMalloc(int n) { - float *buf; - buf = (float *) SUPERLU_MALLOC(n * sizeof(float)); + double *buf; + buf = (double *) SUPERLU_MALLOC(n * sizeof(double)); if ( !buf ) { - ABORT("SUPERLU_MALLOC failed for buf in floatMalloc()\n"); + ABORT("SUPERLU_MALLOC failed for buf in doubleMalloc()\n"); } return (buf); } -float *floatCalloc(int n) +double *doubleCalloc(int n) { - float *buf; + double *buf; register int i; - float zero = 0.0; - buf = (float *) SUPERLU_MALLOC(n * sizeof(float)); + double zero = 0.0; + buf = (double *) SUPERLU_MALLOC(n * sizeof(double)); if ( !buf ) { - ABORT("SUPERLU_MALLOC failed for buf in floatCalloc()\n"); + ABORT("SUPERLU_MALLOC failed for buf in doubleCalloc()\n"); } for (i = 0; i < n; ++i) buf[i] = zero; return (buf); @@ -675,7 +675,7 @@ int smemory_usage(const int nzlmax, const int nzumax, register int iword, dword; iword = sizeof(int); - dword = sizeof(float); + dword = sizeof(double); return (10 * n * iword + nzlmax * iword + nzumax * (iword + dword) + nzlumax * dword); diff --git a/intern/opennl/superlu/smyblas2.c b/intern/opennl/superlu/smyblas2.c index 79f6a11bb6a..11e3b4b4761 100644 --- a/intern/opennl/superlu/smyblas2.c +++ b/intern/opennl/superlu/smyblas2.c @@ -25,17 +25,17 @@ */ /* local prototypes*/ -void slsolve ( int, int, float *, float *); -void susolve ( int, int, float *, float *); -void smatvec ( int, int, int, float *, float *, float *); +void slsolve ( int, int, double *, double *); +void susolve ( int, int, double *, double *); +void smatvec ( int, int, int, double *, double *, double *); -void slsolve ( int ldm, int ncol, float *M, float *rhs ) +void slsolve ( int ldm, int ncol, double *M, double *rhs ) { int k; - float x0, x1, x2, x3, x4, x5, x6, x7; - float *M0; - register float *Mki0, *Mki1, *Mki2, *Mki3, *Mki4, *Mki5, *Mki6, *Mki7; + double x0, x1, x2, x3, x4, x5, x6, x7; + double *M0; + register double *Mki0, *Mki1, *Mki2, *Mki3, *Mki4, *Mki5, *Mki6, *Mki7; register int firstcol = 0; M0 = &M[0]; @@ -131,10 +131,10 @@ void susolve ( ldm, ncol, M, rhs ) int ldm; /* in */ int ncol; /* in */ -float *M; /* in */ -float *rhs; /* modified */ +double *M; /* in */ +double *rhs; /* modified */ { - float xj; + double xj; int jcol, j, irow; jcol = ncol - 1; @@ -162,14 +162,14 @@ void smatvec ( ldm, nrow, ncol, M, vec, Mxvec ) int ldm; /* in -- leading dimension of M */ int nrow; /* in */ int ncol; /* in */ -float *M; /* in */ -float *vec; /* in */ -float *Mxvec; /* in/out */ +double *M; /* in */ +double *vec; /* in */ +double *Mxvec; /* in/out */ { - float vi0, vi1, vi2, vi3, vi4, vi5, vi6, vi7; - float *M0; - register float *Mki0, *Mki1, *Mki2, *Mki3, *Mki4, *Mki5, *Mki6, *Mki7; + double vi0, vi1, vi2, vi3, vi4, vi5, vi6, vi7; + double *M0; + register double *Mki0, *Mki1, *Mki2, *Mki3, *Mki4, *Mki5, *Mki6, *Mki7; register int firstcol = 0; int k; diff --git a/intern/opennl/superlu/spanel_bmod.c b/intern/opennl/superlu/spanel_bmod.c index c9c17ea861d..5f150e640fd 100644 --- a/intern/opennl/superlu/spanel_bmod.c +++ b/intern/opennl/superlu/spanel_bmod.c @@ -29,8 +29,8 @@ /* * Function prototypes */ -void slsolve(int, int, float *, float *); -void smatvec(int, int, int, float *, float *, float *); +void slsolve(int, int, double *, double *); +void smatvec(int, int, int, double *, double *, double *); extern void scheck_tempv(); void @@ -39,8 +39,8 @@ spanel_bmod ( const int w, /* in */ const int jcol, /* in */ const int nseg, /* in */ - float *dense, /* out, of size n by w */ - float *tempv, /* working array */ + double *dense, /* out, of size n by w */ + double *tempv, /* working array */ int *segrep, /* in */ int *repfnz, /* in, of size n by w */ GlobalLU_t *Glu, /* modified */ @@ -71,13 +71,13 @@ spanel_bmod ( ftcs3 = _cptofcd("U", strlen("U")); #endif int incx = 1, incy = 1; - float alpha, beta; + double alpha, beta; #endif register int k, ksub; int fsupc, nsupc, nsupr, nrow; int krep, krep_ind; - float ukj, ukj1, ukj2; + double ukj, ukj1, ukj2; int luptr, luptr1, luptr2; int segsze; int block_nrow; /* no of rows in a block row */ @@ -87,13 +87,13 @@ spanel_bmod ( register int jj; /* Index through each column in the panel */ int *xsup, *supno; int *lsub, *xlsub; - float *lusup; + double *lusup; int *xlusup; int *repfnz_col; /* repfnz[] for a column in the panel */ - float *dense_col; /* dense[] for a column in the panel */ - float *tempv1; /* Used in 1-D update */ - float *TriTmp, *MatvecTmp; /* used in 2-D update */ - float zero = 0.0; + double *dense_col; /* dense[] for a column in the panel */ + double *tempv1; /* Used in 1-D update */ + double *TriTmp, *MatvecTmp; /* used in 2-D update */ + double zero = 0.0; register int ldaTmp; register int r_ind, r_hi; static int first = 1, maxsuper, rowblk, colblk; diff --git a/intern/opennl/superlu/spanel_dfs.c b/intern/opennl/superlu/spanel_dfs.c index e49adf635b2..80e6814dde9 100644 --- a/intern/opennl/superlu/spanel_dfs.c +++ b/intern/opennl/superlu/spanel_dfs.c @@ -34,7 +34,7 @@ spanel_dfs ( SuperMatrix *A, /* in - original matrix */ int *perm_r, /* in */ int *nseg, /* out */ - float *dense, /* out */ + double *dense, /* out */ int *panel_lsub, /* out */ int *segrep, /* out */ int *repfnz, /* out */ @@ -74,7 +74,7 @@ spanel_dfs ( * */ NCPformat *Astore; - float *a; + double *a; int *asub; int *xa_begin, *xa_end; int krep, chperm, chmark, chrep, oldrep, kchild, myfnz; @@ -84,7 +84,7 @@ spanel_dfs ( int *marker1; /* marker1[jj] >= jcol if vertex jj was visited by a previous column within this panel. */ int *repfnz_col; /* start of each column in the panel */ - float *dense_col; /* start of each column in the panel */ + double *dense_col; /* start of each column in the panel */ int nextl_col; /* next available position in panel_lsub[*,jj] */ int *xsup, *supno; int *lsub, *xlsub; diff --git a/intern/opennl/superlu/spivotL.c b/intern/opennl/superlu/spivotL.c index 3d5174e0b90..1a0302d0101 100644 --- a/intern/opennl/superlu/spivotL.c +++ b/intern/opennl/superlu/spivotL.c @@ -31,7 +31,7 @@ int spivotL( const int jcol, /* in */ - const float u, /* in - diagonal pivoting threshold */ + const double u, /* in - diagonal pivoting threshold */ int *usepr, /* re-use the pivot sequence given by perm_r/iperm_r */ int *perm_r, /* may be modified */ int *iperm_r, /* in - inverse of perm_r */ @@ -67,14 +67,14 @@ spivotL( int nsupr; /* no of rows in the supernode */ int lptr; /* points to the starting subscript of the supernode */ int pivptr, old_pivptr, diag, diagind; - float pivmax, rtemp, thresh; - float temp; - float *lu_sup_ptr; - float *lu_col_ptr; + double pivmax, rtemp, thresh; + double temp; + double *lu_sup_ptr; + double *lu_col_ptr; int *lsub_ptr; int isub, icol, k, itemp; int *lsub, *xlsub; - float *lusup; + double *lusup; int *xlusup; flops_t *ops = stat->ops; diff --git a/intern/opennl/superlu/spruneL.c b/intern/opennl/superlu/spruneL.c index e6603f1d42a..3cf29658596 100644 --- a/intern/opennl/superlu/spruneL.c +++ b/intern/opennl/superlu/spruneL.c @@ -45,13 +45,13 @@ spruneL( * contains the current pivot row "pivrow" * */ - float utemp; + double utemp; int jsupno, irep, irep1, kmin, kmax, krow, movnum; int i, ktemp, minloc, maxloc; int do_prune; /* logical variable */ int *xsup, *supno; int *lsub, *xlsub; - float *lusup; + double *lusup; int *xlusup; xsup = Glu->xsup; diff --git a/intern/opennl/superlu/ssnode_bmod.c b/intern/opennl/superlu/ssnode_bmod.c index 21b236feedd..9533373f212 100644 --- a/intern/opennl/superlu/ssnode_bmod.c +++ b/intern/opennl/superlu/ssnode_bmod.c @@ -24,8 +24,8 @@ #include "ssp_defs.h" -void slsolve(int, int, float*, float*); -void smatvec(int, int, int, float*, float*, float*); +void slsolve(int, int, double*, double*); +void smatvec(int, int, int, double*, double*, double*); /* * Performs numeric block updates within the relaxed snode. @@ -34,8 +34,8 @@ int ssnode_bmod ( const int jcol, /* in */ const int fsupc, /* in */ - float *dense, /* in */ - float *tempv, /* working array */ + double *dense, /* in */ + double *tempv, /* working array */ GlobalLU_t *Glu, /* modified */ SuperLUStat_t *stat /* output */ ) @@ -47,14 +47,14 @@ ssnode_bmod ( ftcs3 = _cptofcd("U", strlen("U")); #endif int incx = 1, incy = 1; - float alpha = -1.0, beta = 1.0; + double alpha = -1.0, beta = 1.0; #endif int luptr, nsupc, nsupr, nrow; int isub, irow, i, iptr; register int ufirst, nextlu; int *lsub, *xlsub; - float *lusup; + double *lusup; int *xlusup; flops_t *ops = stat->ops; diff --git a/intern/opennl/superlu/ssp_blas2.c b/intern/opennl/superlu/ssp_blas2.c index d8889cd4b9d..9215d48dc09 100644 --- a/intern/opennl/superlu/ssp_blas2.c +++ b/intern/opennl/superlu/ssp_blas2.c @@ -19,14 +19,14 @@ /* * Function prototypes */ -void susolve(int, int, float*, float*); -void slsolve(int, int, float*, float*); -void smatvec(int, int, int, float*, float*, float*); -int strsv_(char*, char*, char*, int*, float*, int*, float*, int*); +void susolve(int, int, double*, double*); +void slsolve(int, int, double*, double*); +void smatvec(int, int, int, double*, double*, double*); +int strsv_(char*, char*, char*, int*, double*, int*, double*, int*); int sp_strsv(char *uplo, char *trans, char *diag, SuperMatrix *L, - SuperMatrix *U, float *x, SuperLUStat_t *stat, int *info) + SuperMatrix *U, double *x, SuperLUStat_t *stat, int *info) { /* * Purpose @@ -71,7 +71,7 @@ sp_strsv(char *uplo, char *trans, char *diag, SuperMatrix *L, * The factor U from the factorization Pr*A*Pc=L*U. * U has types: Stype = NC, Dtype = SLU_S, Mtype = TRU. * - * x - (input/output) float* + * x - (input/output) double* * Before entry, the incremented array X must contain the n * element right-hand side vector b. On exit, X is overwritten * with the solution vector x. @@ -87,12 +87,12 @@ sp_strsv(char *uplo, char *trans, char *diag, SuperMatrix *L, #endif SCformat *Lstore; NCformat *Ustore; - float *Lval, *Uval; + double *Lval, *Uval; int incx = 1; int nrow; int fsupc, nsupr, nsupc, luptr, istart, irow; int i, k, iptr, jcol; - float *work; + double *work; flops_t solve_ops; /* Test the input parameters */ @@ -115,7 +115,7 @@ sp_strsv(char *uplo, char *trans, char *diag, SuperMatrix *L, Uval = Ustore->nzval; solve_ops = 0; - if ( !(work = floatCalloc(L->nrow)) ) + if ( !(work = doubleCalloc(L->nrow)) ) ABORT("Malloc fails for work in sp_strsv()."); if ( lsame_(trans, "N") ) { /* Form x := inv(A)*x. */ @@ -306,8 +306,8 @@ sp_strsv(char *uplo, char *trans, char *diag, SuperMatrix *L, int -sp_sgemv(char *trans, float alpha, SuperMatrix *A, float *x, - int incx, float beta, float *y, int incy) +sp_sgemv(char *trans, double alpha, SuperMatrix *A, double *x, + int incx, double beta, double *y, int incy) { /* Purpose ======= @@ -327,7 +327,7 @@ sp_sgemv(char *trans, float alpha, SuperMatrix *A, float *x, TRANS = 'T' or 't' y := alpha*A'*x + beta*y. TRANS = 'C' or 'c' y := alpha*A'*x + beta*y. - ALPHA - (input) float + ALPHA - (input) double On entry, ALPHA specifies the scalar alpha. A - (input) SuperMatrix* @@ -336,7 +336,7 @@ sp_sgemv(char *trans, float alpha, SuperMatrix *A, float *x, Stype = NC or NCP; Dtype = SLU_S; Mtype = GE. In the future, more general A can be handled. - X - (input) float*, array of DIMENSION at least + X - (input) double*, array of DIMENSION at least ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' and at least ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. @@ -347,11 +347,11 @@ sp_sgemv(char *trans, float alpha, SuperMatrix *A, float *x, On entry, INCX specifies the increment for the elements of X. INCX must not be zero. - BETA - (input) float + BETA - (input) double On entry, BETA specifies the scalar beta. When BETA is supplied as zero then Y need not be set on input. - Y - (output) float*, array of DIMENSION at least + Y - (output) double*, array of DIMENSION at least ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' and at least ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. @@ -368,9 +368,9 @@ sp_sgemv(char *trans, float alpha, SuperMatrix *A, float *x, /* Local variables */ NCformat *Astore; - float *Aval; + double *Aval; int info; - float temp; + double temp; int lenx, leny, i, j, irow; int iy, jx, jy, kx, ky; int notran; diff --git a/intern/opennl/superlu/ssp_blas3.c b/intern/opennl/superlu/ssp_blas3.c index 789635ceec4..aeb51b0c1ca 100644 --- a/intern/opennl/superlu/ssp_blas3.c +++ b/intern/opennl/superlu/ssp_blas3.c @@ -20,8 +20,8 @@ int sp_sgemm(char *transa, int n, - float alpha, SuperMatrix *A, float *b, int ldb, - float beta, float *c, int ldc) + double alpha, SuperMatrix *A, double *b, int ldb, + double beta, double *c, int ldc) { /* Purpose ======= @@ -74,7 +74,7 @@ sp_sgemm(char *transa, int n, be at least zero. Unchanged on exit. - ALPHA - (input) float + ALPHA - (input) double On entry, ALPHA specifies the scalar alpha. A - (input) SuperMatrix* @@ -96,7 +96,7 @@ sp_sgemm(char *transa, int n, in the calling (sub) program. LDB must be at least max( 1, n ). Unchanged on exit. - BETA - (input) float + BETA - (input) double On entry, BETA specifies the scalar beta. When BETA is supplied as zero then C need not be set on input. diff --git a/intern/opennl/superlu/ssp_defs.h b/intern/opennl/superlu/ssp_defs.h index 118e3f16eb1..5110fc5ad69 100644 --- a/intern/opennl/superlu/ssp_defs.h +++ b/intern/opennl/superlu/ssp_defs.h @@ -88,9 +88,9 @@ typedef struct { int *supno; int *lsub; /* compressed L subscripts */ int *xlsub; - float *lusup; /* L supernodes */ + double *lusup; /* L supernodes */ int *xlusup; - float *ucol; /* U columns */ + double *ucol; /* U columns */ int *usub; int *xusub; int nzlmax; /* current max size of lsub */ @@ -101,8 +101,8 @@ typedef struct { } GlobalLU_t; typedef struct { - float for_lu; - float total_needed; + double for_lu; + double total_needed; int expansions; } mem_usage_t; @@ -116,61 +116,61 @@ sgssv(superlu_options_t *, SuperMatrix *, int *, int *, SuperMatrix *, SuperMatrix *, SuperMatrix *, SuperLUStat_t *, int *); extern void sgssvx(superlu_options_t *, SuperMatrix *, int *, int *, int *, - char *, float *, float *, SuperMatrix *, SuperMatrix *, + char *, double *, double *, SuperMatrix *, SuperMatrix *, void *, int, SuperMatrix *, SuperMatrix *, - float *, float *, float *, float *, + double *, double *, double *, double *, mem_usage_t *, SuperLUStat_t *, int *); /* Supernodal LU factor related */ extern void -sCreate_CompCol_Matrix(SuperMatrix *, int, int, int, float *, +sCreate_CompCol_Matrix(SuperMatrix *, int, int, int, double *, int *, int *, Stype_t, Dtype_t, Mtype_t); extern void -sCreate_CompRow_Matrix(SuperMatrix *, int, int, int, float *, +sCreate_CompRow_Matrix(SuperMatrix *, int, int, int, double *, int *, int *, Stype_t, Dtype_t, Mtype_t); extern void sCopy_CompCol_Matrix(SuperMatrix *, SuperMatrix *); extern void -sCreate_Dense_Matrix(SuperMatrix *, int, int, float *, int, +sCreate_Dense_Matrix(SuperMatrix *, int, int, double *, int, Stype_t, Dtype_t, Mtype_t); extern void -sCreate_SuperNode_Matrix(SuperMatrix *, int, int, int, float *, +sCreate_SuperNode_Matrix(SuperMatrix *, int, int, int, double *, int *, int *, int *, int *, int *, Stype_t, Dtype_t, Mtype_t); extern void -sCopy_Dense_Matrix(int, int, float *, int, float *, int); +sCopy_Dense_Matrix(int, int, double *, int, double *, int); extern void countnz (const int, int *, int *, int *, GlobalLU_t *); extern void fixupL (const int, const int *, GlobalLU_t *); -extern void sallocateA (int, int, float **, int **, int **); +extern void sallocateA (int, int, double **, int **, int **); extern void sgstrf (superlu_options_t*, SuperMatrix*, int, int, int*, void *, int, int *, int *, SuperMatrix *, SuperMatrix *, SuperLUStat_t*, int *); extern int ssnode_dfs (const int, const int, const int *, const int *, const int *, int *, int *, GlobalLU_t *); -extern int ssnode_bmod (const int, const int, float *, - float *, GlobalLU_t *, SuperLUStat_t*); +extern int ssnode_bmod (const int, const int, double *, + double *, GlobalLU_t *, SuperLUStat_t*); extern void spanel_dfs (const int, const int, const int, SuperMatrix *, - int *, int *, float *, int *, int *, int *, + int *, int *, double *, int *, int *, int *, int *, int *, int *, int *, GlobalLU_t *); extern void spanel_bmod (const int, const int, const int, const int, - float *, float *, int *, int *, + double *, double *, int *, int *, GlobalLU_t *, SuperLUStat_t*); extern int scolumn_dfs (const int, const int, int *, int *, int *, int *, int *, int *, int *, int *, int *, GlobalLU_t *); -extern int scolumn_bmod (const int, const int, float *, - float *, int *, int *, int, +extern int scolumn_bmod (const int, const int, double *, + double *, int *, int *, int, GlobalLU_t *, SuperLUStat_t*); extern int scopy_to_ucol (int, int, int *, int *, int *, - float *, GlobalLU_t *); -extern int spivotL (const int, const float, int *, int *, + double *, GlobalLU_t *); +extern int spivotL (const int, const double, int *, int *, int *, int *, int *, GlobalLU_t *, SuperLUStat_t*); extern void spruneL (const int, const int *, const int, const int, const int *, const int *, int *, GlobalLU_t *); -extern void sreadmt (int *, int *, int *, float **, int **, int **); -extern void sGenXtrue (int, int, float *, int); -extern void sFillRHS (trans_t, int, float *, int, SuperMatrix *, +extern void sreadmt (int *, int *, int *, double **, int **, int **); +extern void sGenXtrue (int, int, double *, int); +extern void sFillRHS (trans_t, int, double *, int, SuperMatrix *, SuperMatrix *); extern void sgstrs (trans_t, SuperMatrix *, SuperMatrix *, int *, int *, SuperMatrix *, SuperLUStat_t*, int *); @@ -178,56 +178,56 @@ extern void sgstrs (trans_t, SuperMatrix *, SuperMatrix *, int *, int *, /* Driver related */ -extern void sgsequ (SuperMatrix *, float *, float *, float *, - float *, float *, int *); -extern void slaqgs (SuperMatrix *, float *, float *, float, - float, float, char *); +extern void sgsequ (SuperMatrix *, double *, double *, double *, + double *, double *, int *); +extern void slaqgs (SuperMatrix *, double *, double *, double, + double, double, char *); extern void sgscon (char *, SuperMatrix *, SuperMatrix *, - float, float *, SuperLUStat_t*, int *); -extern float sPivotGrowth(int, SuperMatrix *, int *, + double, double *, SuperLUStat_t*, int *); +extern double sPivotGrowth(int, SuperMatrix *, int *, SuperMatrix *, SuperMatrix *); extern void sgsrfs (trans_t, SuperMatrix *, SuperMatrix *, - SuperMatrix *, int *, int *, char *, float *, - float *, SuperMatrix *, SuperMatrix *, - float *, float *, SuperLUStat_t*, int *); + SuperMatrix *, int *, int *, char *, double *, + double *, SuperMatrix *, SuperMatrix *, + double *, double *, SuperLUStat_t*, int *); extern int sp_strsv (char *, char *, char *, SuperMatrix *, - SuperMatrix *, float *, SuperLUStat_t*, int *); -extern int sp_sgemv (char *, float, SuperMatrix *, float *, - int, float, float *, int); + SuperMatrix *, double *, SuperLUStat_t*, int *); +extern int sp_sgemv (char *, double, SuperMatrix *, double *, + int, double, double *, int); -extern int sp_sgemm (char *, int, float, - SuperMatrix *, float *, int, float, - float *, int); +extern int sp_sgemm (char *, int, double, + SuperMatrix *, double *, int, double, + double *, int); /* Memory-related */ extern int sLUMemInit (fact_t, void *, int, int, int, int, int, SuperMatrix *, SuperMatrix *, - GlobalLU_t *, int **, float **); -extern void sSetRWork (int, int, float *, float **, float **); -extern void sLUWorkFree (int *, float *, GlobalLU_t *); + GlobalLU_t *, int **, double **); +extern void sSetRWork (int, int, double *, double **, double **); +extern void sLUWorkFree (int *, double *, GlobalLU_t *); extern int sLUMemXpand (int, int, MemType, int *, GlobalLU_t *); -extern float *floatMalloc(int); -extern float *floatCalloc(int); +extern double *doubleMalloc(int); +extern double *doubleCalloc(int); extern int smemory_usage(const int, const int, const int, const int); extern int sQuerySpace (SuperMatrix *, SuperMatrix *, mem_usage_t *); /* Auxiliary routines */ -extern void sreadhb(int *, int *, int *, float **, int **, int **); -extern void sCompRow_to_CompCol(int, int, int, float*, int*, int*, - float **, int **, int **); -extern void sfill (float *, int, float); -extern void sinf_norm_error (int, SuperMatrix *, float *); +extern void sreadhb(int *, int *, int *, double **, int **, int **); +extern void sCompRow_to_CompCol(int, int, int, double*, int*, int*, + double **, int **, int **); +extern void sfill (double *, int, double); +extern void sinf_norm_error (int, SuperMatrix *, double *); extern void PrintPerf (SuperMatrix *, SuperMatrix *, mem_usage_t *, - float, float, float *, float *, char *); + double, double, double *, double *, char *); /* Routines for debugging */ extern void sPrint_CompCol_Matrix(char *, SuperMatrix *); extern void sPrint_SuperNode_Matrix(char *, SuperMatrix *); extern void sPrint_Dense_Matrix(char *, SuperMatrix *); extern void print_lu_col(char *, int, int, int *, GlobalLU_t *); -extern void check_tempv(int, float *); +extern void check_tempv(int, double *); extern int print_int_vec(char *what, int n, int *vec); extern int sp_symetree(int *acolst, int *acolend, int *arow, int n, int *parent); diff --git a/intern/opennl/superlu/strsv.c b/intern/opennl/superlu/strsv.c index da904ba3e9d..a34f5fb38a1 100644 --- a/intern/opennl/superlu/strsv.c +++ b/intern/opennl/superlu/strsv.c @@ -1,17 +1,17 @@ /** \file opennl/superlu/strsv.c * \ingroup opennl */ -int strsv_(char *, char *, char *, int *, float *, int *, float *, int *); +int strsv_(char *, char *, char *, int *, double *, int *, double *, int *); /* Subroutine */ int strsv_(char *uplo, char *trans, char *diag, int *n, - float *a, int *lda, float *x, int *incx) + double *a, int *lda, double *x, int *incx) { /* Local variables */ static int info; - static float temp; + static double temp; static int i, j; extern int lsame_(char *, char *); static int ix, jx, kx; diff --git a/intern/opennl/superlu/sutil.c b/intern/opennl/superlu/sutil.c index a77e87b9c65..52728e47f56 100644 --- a/intern/opennl/superlu/sutil.c +++ b/intern/opennl/superlu/sutil.c @@ -27,15 +27,15 @@ /* prototypes */ void sprint_lu_col(char *msg, int jcol, int pivrow, int *xprune, GlobalLU_t *Glu); -void scheck_tempv(int n, float *tempv); -void sPrintPerf(SuperMatrix *, SuperMatrix *, mem_usage_t *,float , float , - float *, float *, char *, SuperLUStat_t *); -int print_float_vec(char *what, int n, float *vec); +void scheck_tempv(int n, double *tempv); +void sPrintPerf(SuperMatrix *, SuperMatrix *, mem_usage_t *,double , double , + double *, double *, char *, SuperLUStat_t *); +int print_double_vec(char *what, int n, double *vec); /* ********** */ void sCreate_CompCol_Matrix(SuperMatrix *A, int m, int n, int nnz, - float *nzval, int *rowind, int *colptr, + double *nzval, int *rowind, int *colptr, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { NCformat *Astore; @@ -56,7 +56,7 @@ sCreate_CompCol_Matrix(SuperMatrix *A, int m, int n, int nnz, void sCreate_CompRow_Matrix(SuperMatrix *A, int m, int n, int nnz, - float *nzval, int *colind, int *rowptr, + double *nzval, int *colind, int *rowptr, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { NRformat *Astore; @@ -91,14 +91,14 @@ sCopy_CompCol_Matrix(SuperMatrix *A, SuperMatrix *B) Bstore = (NCformat *) B->Store; Bstore->nnz = nnz = Astore->nnz; for (i = 0; i < nnz; ++i) - ((float *)Bstore->nzval)[i] = ((float *)Astore->nzval)[i]; + ((double *)Bstore->nzval)[i] = ((double *)Astore->nzval)[i]; for (i = 0; i < nnz; ++i) Bstore->rowind[i] = Astore->rowind[i]; for (i = 0; i <= ncol; ++i) Bstore->colptr[i] = Astore->colptr[i]; } void -sCreate_Dense_Matrix(SuperMatrix *X, int m, int n, float *x, int ldx, +sCreate_Dense_Matrix(SuperMatrix *X, int m, int n, double *x, int ldx, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { DNformat *Xstore; @@ -112,12 +112,12 @@ sCreate_Dense_Matrix(SuperMatrix *X, int m, int n, float *x, int ldx, if ( !(X->Store) ) ABORT("SUPERLU_MALLOC fails for X->Store"); Xstore = (DNformat *) X->Store; Xstore->lda = ldx; - Xstore->nzval = (float *) x; + Xstore->nzval = (double *) x; } void -sCopy_Dense_Matrix(int M, int N, float *X, int ldx, - float *Y, int ldy) +sCopy_Dense_Matrix(int M, int N, double *X, int ldx, + double *Y, int ldy) { /* * @@ -135,7 +135,7 @@ sCopy_Dense_Matrix(int M, int N, float *X, int ldx, void sCreate_SuperNode_Matrix(SuperMatrix *L, int m, int n, int nnz, - float *nzval, int *nzval_colptr, int *rowind, + double *nzval, int *nzval_colptr, int *rowind, int *rowind_colptr, int *col_to_sup, int *sup_to_col, Stype_t stype, Dtype_t dtype, Mtype_t mtype) { @@ -166,14 +166,14 @@ sCreate_SuperNode_Matrix(SuperMatrix *L, int m, int n, int nnz, */ void sCompRow_to_CompCol(int m, int n, int nnz, - float *a, int *colind, int *rowptr, - float **at, int **rowind, int **colptr) + double *a, int *colind, int *rowptr, + double **at, int **rowind, int **colptr) { register int i, j, col, relpos; int *marker; /* Allocate storage for another copy of the matrix. */ - *at = (float *) floatMalloc(nnz); + *at = (double *) doubleMalloc(nnz); *rowind = (int *) intMalloc(nnz); *colptr = (int *) intMalloc(n+1); marker = (int *) intCalloc(n); @@ -207,13 +207,13 @@ sPrint_CompCol_Matrix(char *what, SuperMatrix *A) { NCformat *Astore; register int i,n; - float *dp; + double *dp; printf("\nCompCol matrix %s:\n", what); printf("Stype %d, Dtype %d, Mtype %d\n", A->Stype,A->Dtype,A->Mtype); n = A->ncol; Astore = (NCformat *) A->Store; - dp = (float *) Astore->nzval; + dp = (double *) Astore->nzval; printf("nrow %d, ncol %d, nnz %d\n", A->nrow,A->ncol,Astore->nnz); printf("nzval: "); for (i = 0; i < Astore->colptr[n]; ++i) printf("%f ", dp[i]); @@ -230,14 +230,14 @@ sPrint_SuperNode_Matrix(char *what, SuperMatrix *A) { SCformat *Astore; register int i, j, k, c, d, n, nsup; - float *dp; + double *dp; int *col_to_sup, *sup_to_col, *rowind, *rowind_colptr; printf("\nSuperNode matrix %s:\n", what); printf("Stype %d, Dtype %d, Mtype %d\n", A->Stype,A->Dtype,A->Mtype); n = A->ncol; Astore = (SCformat *) A->Store; - dp = (float *) Astore->nzval; + dp = (double *) Astore->nzval; col_to_sup = Astore->col_to_sup; sup_to_col = Astore->sup_to_col; rowind_colptr = Astore->rowind_colptr; @@ -279,12 +279,12 @@ sPrint_Dense_Matrix(char *what, SuperMatrix *A) { DNformat *Astore; register int i; - float *dp; + double *dp; printf("\nDense matrix %s:\n", what); printf("Stype %d, Dtype %d, Mtype %d\n", A->Stype,A->Dtype,A->Mtype); Astore = (DNformat *) A->Store; - dp = (float *) Astore->nzval; + dp = (double *) Astore->nzval; printf("nrow %d, ncol %d, lda %d\n", A->nrow,A->ncol,Astore->lda); printf("\nnzval: "); for (i = 0; i < A->nrow; ++i) printf("%f ", dp[i]); @@ -301,9 +301,9 @@ sprint_lu_col(char *msg, int jcol, int pivrow, int *xprune, GlobalLU_t *Glu) int i, k, fsupc; int *xsup, *supno; int *xlsub, *lsub; - float *lusup; + double *lusup; int *xlusup; - float *ucol; + double *ucol; int *usub, *xusub; xsup = Glu->xsup; @@ -339,7 +339,7 @@ sprint_lu_col(char *msg, int jcol, int pivrow, int *xprune, GlobalLU_t *Glu) * Check whether tempv[] == 0. This should be true before and after * calling any numeric routines, i.e., "panel_bmod" and "column_bmod". */ -void scheck_tempv(int n, float *tempv) +void scheck_tempv(int n, double *tempv) { int i; @@ -354,12 +354,12 @@ void scheck_tempv(int n, float *tempv) void -sGenXtrue(int n, int nrhs, float *x, int ldx) +sGenXtrue(int n, int nrhs, double *x, int ldx) { int i, j; for (j = 0; j < nrhs; ++j) for (i = 0; i < n; ++i) { - x[i + j*ldx] = 1.0;/* + (float)(i+1.)/n;*/ + x[i + j*ldx] = 1.0;/* + (double)(i+1.)/n;*/ } } @@ -367,13 +367,13 @@ sGenXtrue(int n, int nrhs, float *x, int ldx) * Let rhs[i] = sum of i-th row of A, so the solution vector is all 1's */ void -sFillRHS(trans_t trans, int nrhs, float *x, int ldx, +sFillRHS(trans_t trans, int nrhs, double *x, int ldx, SuperMatrix *A, SuperMatrix *B) { DNformat *Bstore; - float *rhs; - float one = 1.0; - float zero = 0.0; + double *rhs; + double one = 1.0; + double zero = 0.0; int ldc; char transc[1]; @@ -390,10 +390,10 @@ sFillRHS(trans_t trans, int nrhs, float *x, int ldx, } /* - * Fills a float precision array with a given value. + * Fills a double precision array with a given value. */ void -sfill(float *a, int alen, float dval) +sfill(double *a, int alen, double dval) { register int i; for (i = 0; i < alen; i++) a[i] = dval; @@ -404,11 +404,11 @@ sfill(float *a, int alen, float dval) /* * Check the inf-norm of the error vector */ -void sinf_norm_error(int nrhs, SuperMatrix *X, float *xtrue) +void sinf_norm_error(int nrhs, SuperMatrix *X, double *xtrue) { DNformat *Xstore; - float err, xnorm; - float *Xmat, *soln_work; + double err, xnorm; + double *Xmat, *soln_work; int i, j; Xstore = X->Store; @@ -431,8 +431,8 @@ void sinf_norm_error(int nrhs, SuperMatrix *X, float *xtrue) /* Print performance of the code. */ void sPrintPerf(SuperMatrix *L, SuperMatrix *U, mem_usage_t *mem_usage, - float rpg, float rcond, float *ferr, - float *berr, char *equed, SuperLUStat_t *stat) + double rpg, double rcond, double *ferr, + double *berr, char *equed, SuperLUStat_t *stat) { SCformat *Lstore; NCformat *Ustore; @@ -475,7 +475,7 @@ sPrintPerf(SuperMatrix *L, SuperMatrix *U, mem_usage_t *mem_usage, -int print_float_vec(char *what, int n, float *vec) +int print_double_vec(char *what, int n, double *vec) { int i; printf("%s: n %d\n", what, n); diff --git a/intern/opennl/superlu/util.c b/intern/opennl/superlu/util.c index 7339bbc623a..96f404d886b 100644 --- a/intern/opennl/superlu/util.c +++ b/intern/opennl/superlu/util.c @@ -28,8 +28,8 @@ /* prototypes */ flops_t LUFactFlops(SuperLUStat_t *stat); flops_t LUSolveFlops(SuperLUStat_t *stat); -float SpaSize(int n, int np, float sum_npw); -float DenseSize(int n, float sum_nw); +double SpaSize(int n, int np, double sum_npw); +double DenseSize(int n, double sum_nw); /* * Global statistics variale @@ -332,27 +332,27 @@ void super_stats(int nsuper, int *xsup) for (i = 0; i <= nsuper; i++) { isize = xsup[i+1] - xsup[i]; - whichb = (float) isize / max_sup_size * NBUCKS; + whichb = (double) isize / max_sup_size * NBUCKS; if (whichb >= NBUCKS) whichb = NBUCKS - 1; bucket[whichb]++; } printf("\tHistogram of supernode sizes:\n"); for (i = 0; i < NBUCKS; i++) { - bl = (float) i * max_sup_size / NBUCKS; - bh = (float) (i+1) * max_sup_size / NBUCKS; + bl = (double) i * max_sup_size / NBUCKS; + bh = (double) (i+1) * max_sup_size / NBUCKS; printf("\tsnode: %d-%d\t\t%d\n", bl+1, bh, bucket[i]); } } -float SpaSize(int n, int np, float sum_npw) +double SpaSize(int n, int np, double sum_npw) { return (sum_npw*8 + np*8 + n*4)/1024.; } -float DenseSize(int n, float sum_nw) +double DenseSize(int n, double sum_nw) { return (sum_nw*8 + n*8)/1024.;; } diff --git a/intern/opennl/superlu/util.h b/intern/opennl/superlu/util.h index c4c478cec2b..da9a8dbe4e3 100644 --- a/intern/opennl/superlu/util.h +++ b/intern/opennl/superlu/util.h @@ -97,7 +97,7 @@ typedef enum { RCOND, /* estimate reciprocal condition number */ SOLVE, /* forward and back solves */ REFINE, /* perform iterative refinement */ - SLU_FLOAT, /* time spent in floating-point operations */ + SLU_FLOAT, /* time spent in doubleing-point operations */ TRSV, /* fraction of FACT spent in xTRSV */ GEMV, /* fraction of FACT spent in xGEMV */ FERR, /* estimate error bounds after iterative refinement */ @@ -108,7 +108,7 @@ typedef enum { /*********************************************************************** * Type definitions ***********************************************************************/ -typedef float flops_t; +typedef double flops_t; typedef unsigned char Logical; /* diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index 4a1e2cd1d9a..f7dc50431c7 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -28399,26 +28399,9 @@ </dc:publisher> <dc:coverage /> <cc:license - rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /> - <dc:description>This content is under CC Attribution-NonCommercial ShareAlike licence 3.0 as long as it's used for Blender 3D GUI. Any other uses are not allowed.</dc:description> + rdf:resource="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html" /> + <dc:description>GNU General Public License, version 2 or later.</dc:description> </cc:Work> - <cc:License - rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"> - <cc:permits - rdf:resource="http://creativecommons.org/ns#Reproduction" /> - <cc:permits - rdf:resource="http://creativecommons.org/ns#Distribution" /> - <cc:requires - rdf:resource="http://creativecommons.org/ns#Notice" /> - <cc:requires - rdf:resource="http://creativecommons.org/ns#Attribution" /> - <cc:prohibits - rdf:resource="http://creativecommons.org/ns#CommercialUse" /> - <cc:permits - rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> - <cc:requires - rdf:resource="http://creativecommons.org/ns#ShareAlike" /> - </cc:License> </rdf:RDF> </metadata> <g diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject 919eb683bd2c5a2e626bcdb78f5fd5c048a70fd +Subproject 841b1b9f494b6f980da4e244bbd86ecb8a8ac0b diff --git a/release/datafiles/prvicons.svg b/release/datafiles/prvicons.svg index 4e7bac725bd..e0894ff2dc8 100644 --- a/release/datafiles/prvicons.svg +++ b/release/datafiles/prvicons.svg @@ -17956,26 +17956,9 @@ </dc:publisher> <dc:coverage /> <cc:license - rdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" /> - <dc:description>This content is under CC Attribution-NonCommercial ShareAlike licence 3.0 as long as it's used for Blender 3D GUI. Any other uses are not allowed.</dc:description> + rdf:resource="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html" /> + <dc:description>GNU General Public License, version 2 or later.</dc:description> </cc:Work> - <cc:License - rdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/"> - <cc:permits - rdf:resource="http://creativecommons.org/ns#Reproduction" /> - <cc:permits - rdf:resource="http://creativecommons.org/ns#Distribution" /> - <cc:requires - rdf:resource="http://creativecommons.org/ns#Notice" /> - <cc:requires - rdf:resource="http://creativecommons.org/ns#Attribution" /> - <cc:prohibits - rdf:resource="http://creativecommons.org/ns#CommercialUse" /> - <cc:permits - rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> - <cc:requires - rdf:resource="http://creativecommons.org/ns#ShareAlike" /> - </cc:License> </rdf:RDF> </metadata> <g diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png Binary files differindex 451273728f2..76bb67b7263 100644 --- a/release/datafiles/splash.png +++ b/release/datafiles/splash.png diff --git a/release/datafiles/splash_2x.png b/release/datafiles/splash_2x.png Binary files differindex 758178be298..c0eaba50460 100644 --- a/release/datafiles/splash_2x.png +++ b/release/datafiles/splash_2x.png diff --git a/release/scripts/addons b/release/scripts/addons -Subproject 74393fe915b5dadbe3066a149ef1d16575d5912 +Subproject fd695c3a81b63db072311e8516e0dbb8d447404 diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib -Subproject 88931a09a925a86701779a4b700508eff9fdc6b +Subproject 8f33ffcebed445755d3453b8f486306bcf2b142 diff --git a/release/scripts/freestyle/modules/freestyle/__init__.py b/release/scripts/freestyle/modules/freestyle/__init__.py index 5874488f684..d2795f65b6a 100644 --- a/release/scripts/freestyle/modules/freestyle/__init__.py +++ b/release/scripts/freestyle/modules/freestyle/__init__.py @@ -17,8 +17,21 @@ # ##### END GPL LICENSE BLOCK ##### """ -Top-level module containing all Freestyle stylization constructs +This module provides data types of view map components (0D and 1D +elements), base classes for defining line stylization rules +(predicates, functions, chaining iterators, and stroke shaders), as +well as helper functions for style module writing. + +Submodules: + +* :mod:`freestyle.types` +* :mod:`freestyle.predicates` +* :mod:`freestyle.functions` +* :mod:`freestyle.chainingiterators` +* :mod:`freestyle.shaders` +* :mod:`freestyle.utils` """ + # module members from . import chainingiterators, functions, predicates, shaders, types, utils diff --git a/release/scripts/freestyle/modules/freestyle/chainingiterators.py b/release/scripts/freestyle/modules/freestyle/chainingiterators.py index 8d144bf17fd..52f22b3e8be 100644 --- a/release/scripts/freestyle/modules/freestyle/chainingiterators.py +++ b/release/scripts/freestyle/modules/freestyle/chainingiterators.py @@ -17,10 +17,10 @@ # ##### END GPL LICENSE BLOCK ##### """ -Chaining iterators used for the chaining operation to construct long -strokes by concatenating feature edges according to selected chaining -rules. Also intended to be a collection of examples for defining -chaining iterators in Python +This module contains chaining iterators used for the chaining +operation to construct long strokes by concatenating feature edges +according to selected chaining rules. The module is also intended to +be a collection of examples for defining chaining iterators in Python. """ __all__ = ( @@ -82,12 +82,11 @@ def nature_in_preceding(nature, index): class pyChainSilhouetteIterator(ChainingIterator): - """Natural chaining iterator - - Follows the edges of the same nature following the topology of - objects, with decreasing priority for silhouettes, then borders, - then suggestive contours, then all other edge types. A ViewEdge - is only chained once. + """ + Natural chaining iterator that follows the edges of the same nature + following the topology of objects, with decreasing priority for + silhouettes, then borders, then suggestive contours, then all other edge + types. A ViewEdge is only chained once. """ def __init__(self, stayInSelection=True): ChainingIterator.__init__(self, stayInSelection, True, None, True) @@ -121,16 +120,20 @@ class pyChainSilhouetteIterator(ChainingIterator): class pyChainSilhouetteGenericIterator(ChainingIterator): - """Natural chaining iterator + """ + Natural chaining iterator that follows the edges of the same nature + following the topology of objects, with decreasing priority for + silhouettes, then borders, then suggestive contours, then all other + edge types. - Follows the edges of the same nature following the topology of - objects, with decreasing priority for silhouettes, then borders, - then suggestive contours, then all other edge types. + .. method:: __init__(self, stayInSelection=True, stayInUnvisited=True) - :arg stayInSelection: True if it is allowed to go out of the selection - :type stayInSelection: bool - :arg stayInUnvisited: May the same ViewEdge be chained twice - :type stayInUnvisited: bool + Builds a pyChainSilhouetteGenericIterator object. + + :arg stayInSelection: True if it is allowed to go out of the selection + :type stayInSelection: bool + :arg stayInUnvisited: May the same ViewEdge be chained twice + :type stayInUnvisited: bool """ def __init__(self, stayInSelection=True, stayInUnvisited=True): @@ -209,14 +212,18 @@ class pyExternalContourChainingIterator(ChainingIterator): class pySketchyChainSilhouetteIterator(ChainingIterator): - """Natural chaining iterator with a sketchy multiple touch + """ + Natural chaining iterator with a sketchy multiple touch. It chains the + same ViewEdge multiple times to achieve a sketchy effect. + + .. method:: __init__(self, nRounds=3,stayInSelection=True) - Chains the same ViewEdge multiple times to achieve a sketchy effect. + Builds a pySketchyChainSilhouetteIterator object. - :arg rounds: Number of times every Viewedge is chained. - :type rounds: int - :arg stayInSelection: if False, edges outside of the selection can be chained. - :type stayInSelection: bool + :arg nRounds: Number of times every Viewedge is chained. + :type nRounds: int + :arg stayInSelection: if False, edges outside of the selection can be chained. + :type stayInSelection: bool """ def __init__(self, nRounds=3,stayInSelection=True): @@ -267,10 +274,10 @@ class pySketchyChainSilhouetteIterator(ChainingIterator): class pySketchyChainingIterator(ChainingIterator): - """Chaining iterator designed for sketchy style - - It chaines the same ViewEdge several times in order to produce - multiple strokes per ViewEdge. + """ + Chaining iterator designed for sketchy style. It chaines the same + ViewEdge several times in order to produce multiple strokes per + ViewEdge. """ def __init__(self, nRounds=3, stayInSelection=True): ChainingIterator.__init__(self, stayInSelection, False, None, True) @@ -306,11 +313,16 @@ class pySketchyChainingIterator(ChainingIterator): class pyFillOcclusionsRelativeChainingIterator(ChainingIterator): - """Chaining iterator that fills small occlusions + """ + Chaining iterator that fills small occlusions + + .. method:: __init__(self, percent) + + Builds a pyFillOcclusionsRelativeChainingIterator object. - :arg percent: The maximul length of the occluded part, expressed - in a percentage of the total chain length. - :type percent: float + :arg percent: The maximul length of the occluded part, expressed + in a percentage of the total chain length. + :type percent: float """ def __init__(self, percent): @@ -374,10 +386,15 @@ class pyFillOcclusionsRelativeChainingIterator(ChainingIterator): class pyFillOcclusionsAbsoluteChainingIterator(ChainingIterator): - """Chaining iterator that fills small occlusions + """ + Chaining iterator that fills small occlusions + + .. method:: __init__(self, length) + + Builds a pyFillOcclusionsAbsoluteChainingIterator object. - :arg size: The maximum length of the occluded part in pixels. - :type size: int + :arg length: The maximum length of the occluded part in pixels. + :type length: int """ def __init__(self, length): ChainingIterator.__init__(self, False, True, None, True) @@ -429,12 +446,19 @@ class pyFillOcclusionsAbsoluteChainingIterator(ChainingIterator): class pyFillOcclusionsAbsoluteAndRelativeChainingIterator(ChainingIterator): - """Chaining iterator that fills small occlusions regardless of the - selection + """ + Chaining iterator that fills small occlusions regardless of the + selection. + + .. method:: __init__(self, percent, l) + + Builds a pyFillOcclusionsAbsoluteAndRelativeChainingIterator object. - :arg percent: The maximul length of the occluded part as a - percentage of the total chain length. - :type percent: float + :arg percent: The maximul length of the occluded part as a + percentage of the total chain length. + :type percent: float + :arg l: Absolute length. + :type l: float """ def __init__(self, percent, l): ChainingIterator.__init__(self, False, True, None, True) @@ -492,12 +516,19 @@ class pyFillOcclusionsAbsoluteAndRelativeChainingIterator(ChainingIterator): class pyFillQi0AbsoluteAndRelativeChainingIterator(ChainingIterator): - """Chaining iterator that fills small occlusions regardless of the - selection + """ + Chaining iterator that fills small occlusions regardless of the + selection. + + .. method:: __init__(self, percent, l) + + Builds a pyFillQi0AbsoluteAndRelativeChainingIterator object. - :arg percent: The maximul length of the occluded part as a - percentage of the total chain length. - :type percent: float + :arg percent: The maximul length of the occluded part as a + percentage of the total chain length. + :type percent: float + :arg l: Absolute length. + :type l: float """ def __init__(self, percent, l): ChainingIterator.__init__(self, False, True, None, True) @@ -554,15 +585,18 @@ class pyFillQi0AbsoluteAndRelativeChainingIterator(ChainingIterator): class pyNoIdChainSilhouetteIterator(ChainingIterator): - """Natural chaining iterator + """ + Natural chaining iterator that follows the edges of the same nature + following the topology of objects, with decreasing priority for + silhouettes, then borders, then suggestive contours, then all other edge + types. It won't chain the same ViewEdge twice. + + .. method:: __init__(self, stayInSelection=True) - Follows the edges of the same nature following the topology of - objects, with decreasing priority for silhouettes, then borders, - then suggestive contours, then all other edge types. It won't - chain the same ViewEdge twice. + Builds a pyNoIdChainSilhouetteIterator object. - :arg stayInSelection: True if it is allowed to go out of the selection - :type stayInSelection: bool + :arg stayInSelection: True if it is allowed to go out of the selection + :type stayInSelection: bool """ def __init__(self, stayInSelection=True): diff --git a/release/scripts/freestyle/modules/freestyle/functions.py b/release/scripts/freestyle/modules/freestyle/functions.py index 674c1f01864..48d9b2e2b39 100644 --- a/release/scripts/freestyle/modules/freestyle/functions.py +++ b/release/scripts/freestyle/modules/freestyle/functions.py @@ -17,11 +17,99 @@ # ##### END GPL LICENSE BLOCK ##### """ -Functions operating on vertices (0D elements) and polylines (1D -elements). Also intended to be a collection of examples for predicate -definition in Python. +This module contains functions operating on vertices (0D elements) and +polylines (1D elements). The module is also intended to be a +collection of examples for function definition in Python. + +User-defined functions inherit one of the following base classes, +depending on the object type (0D or 1D) to operate on and the return +value type: + +- :class:`freestyle.types.UnaryFunction0DDouble` +- :class:`freestyle.types.UnaryFunction0DEdgeNature` +- :class:`freestyle.types.UnaryFunction0DFloat` +- :class:`freestyle.types.UnaryFunction0DId` +- :class:`freestyle.types.UnaryFunction0DMaterial` +- :class:`freestyle.types.UnaryFunction0DUnsigned` +- :class:`freestyle.types.UnaryFunction0DVec2f` +- :class:`freestyle.types.UnaryFunction0DVec3f` +- :class:`freestyle.types.UnaryFunction0DVectorViewShape` +- :class:`freestyle.types.UnaryFunction0DViewShape` +- :class:`freestyle.types.UnaryFunction1DDouble` +- :class:`freestyle.types.UnaryFunction1DEdgeNature` +- :class:`freestyle.types.UnaryFunction1DFloat` +- :class:`freestyle.types.UnaryFunction1DUnsigned` +- :class:`freestyle.types.UnaryFunction1DVec2f` +- :class:`freestyle.types.UnaryFunction1DVec3f` +- :class:`freestyle.types.UnaryFunction1DVectorViewShape` +- :class:`freestyle.types.UnaryFunction1DVoid` """ +__all__ = ( + "ChainingTimeStampF1D", + "Curvature2DAngleF0D", + "Curvature2DAngleF1D", + "CurveMaterialF0D", + "CurveNatureF0D", + "CurveNatureF1D", + "DensityF0D", + "DensityF1D", + "GetCompleteViewMapDensityF1D", + "GetCurvilinearAbscissaF0D", + "GetDirectionalViewMapDensityF1D", + "GetOccludeeF0D", + "GetOccludeeF1D", + "GetOccludersF0D", + "GetOccludersF1D", + "GetParameterF0D", + "GetProjectedXF0D", + "GetProjectedXF1D", + "GetProjectedYF0D", + "GetProjectedYF1D", + "GetProjectedZF0D", + "GetProjectedZF1D", + "GetShapeF0D", + "GetShapeF1D", + "GetSteerableViewMapDensityF1D", + "GetViewMapGradientNormF0D", + "GetViewMapGradientNormF1D", + "GetXF0D", + "GetXF1D", + "GetYF0D", + "GetYF1D", + "GetZF0D", + "GetZF1D", + "IncrementChainingTimeStampF1D", + "LocalAverageDepthF0D", + "LocalAverageDepthF1D", + "MaterialF0D", + "Normal2DF0D", + "Normal2DF1D", + "Orientation2DF1D", + "Orientation3DF1D", + "QuantitativeInvisibilityF0D", + "QuantitativeInvisibilityF1D", + "ReadCompleteViewMapPixelF0D", + "ReadMapPixelF0D", + "ReadSteerableViewMapPixelF0D", + "ShapeIdF0D", + "TimeStampF1D", + "VertexOrientation2DF0D", + "VertexOrientation3DF0D", + "ZDiscontinuityF0D", + "ZDiscontinuityF1D", + "pyCurvilinearLengthF0D", + "pyDensityAnisotropyF0D", + "pyDensityAnisotropyF1D", + "pyGetInverseProjectedZF1D", + "pyGetSquareInverseProjectedZF1D", + "pyInverseCurvature2DAngleF0D", + "pyViewMapGradientNormF0D", + "pyViewMapGradientNormF1D", + "pyViewMapGradientVectorF0D", + ) + + # module members from _freestyle import ( ChainingTimeStampF1D, @@ -149,10 +237,15 @@ class pyDensityAnisotropyF0D(UnaryFunction0DDouble): class pyViewMapGradientVectorF0D(UnaryFunction0DVec2f): - """Returns the gradient vector for a pixel. + """ + Returns the gradient vector for a pixel. + + .. method:: __init__(self, level) + + Builds a pyViewMapGradientVectorF0D object. - :arg level: the level at which to compute the gradient - :type level: int + :arg level: the level at which to compute the gradient + :type level: int """ def __init__(self, level): UnaryFunction0DVec2f.__init__(self) diff --git a/release/scripts/freestyle/modules/freestyle/predicates.py b/release/scripts/freestyle/modules/freestyle/predicates.py index 344b89d869c..54656e450d9 100644 --- a/release/scripts/freestyle/modules/freestyle/predicates.py +++ b/release/scripts/freestyle/modules/freestyle/predicates.py @@ -17,11 +17,86 @@ # ##### END GPL LICENSE BLOCK ##### """ -Predicates operating on vertices (0D elements) and polylines (1D -elements). Also intended to be a collection of examples for predicate -definition in Python +This module contains predicates operating on vertices (0D elements) +and polylines (1D elements). It is also intended to be a collection +of examples for predicate definition in Python. + +User-defined predicates inherit one of the following base classes, +depending on the object type (0D or 1D) to operate on and the arity +(unary or binary): + +- :class:`freestyle.types.BinaryPredicate0D` +- :class:`freestyle.types.BinaryPredicate1D` +- :class:`freestyle.types.UnaryPredicate0D` +- :class:`freestyle.types.UnaryPredicate1D` """ +__all__ = ( + "AndBP1D", + "AndUP1D", + "ContourUP1D", + "DensityLowerThanUP1D", + "EqualToChainingTimeStampUP1D", + "EqualToTimeStampUP1D", + "ExternalContourUP1D", + "FalseBP1D", + "FalseUP0D", + "FalseUP1D", + "Length2DBP1D", + "NotBP1D", + "NotUP1D", + "ObjectNamesUP1D", + "OrBP1D", + "OrUP1D", + "QuantitativeInvisibilityRangeUP1D", + "QuantitativeInvisibilityUP1D", + "SameShapeIdBP1D", + "ShapeUP1D", + "TrueBP1D", + "TrueUP0D", + "TrueUP1D", + "ViewMapGradientNormBP1D", + "WithinImageBoundaryUP1D", + "pyBackTVertexUP0D", + "pyClosedCurveUP1D", + "pyDensityFunctorUP1D", + "pyDensityUP1D", + "pyDensityVariableSigmaUP1D", + "pyHighDensityAnisotropyUP1D", + "pyHighDirectionalViewMapDensityUP1D", + "pyHighSteerableViewMapDensityUP1D", + "pyHighViewMapDensityUP1D", + "pyHighViewMapGradientNormUP1D", + "pyHigherCurvature2DAngleUP0D", + "pyHigherLengthUP1D", + "pyHigherNumberOfTurnsUP1D", + "pyIsInOccludersListUP1D", + "pyIsOccludedByIdListUP1D", + "pyIsOccludedByItselfUP1D", + "pyIsOccludedByUP1D", + "pyLengthBP1D", + "pyLowDirectionalViewMapDensityUP1D", + "pyLowSteerableViewMapDensityUP1D", + "pyNFirstUP1D", + "pyNatureBP1D", + "pyNatureUP1D", + "pyParameterUP0D", + "pyParameterUP0DGoodOne", + "pyProjectedXBP1D", + "pyProjectedYBP1D", + "pyShapeIdListUP1D", + "pyShapeIdUP1D", + "pyShuffleBP1D", + "pySilhouetteFirstBP1D", + "pyUEqualsUP0D", + "pyVertexNatureUP0D", + "pyViewMapGradientNormBP1D", + "pyZBP1D", + "pyZDiscontinuityBP1D", + "pyZSmallerUP1D", + ) + + # module members from _freestyle import ( ContourUP1D, @@ -62,6 +137,8 @@ from freestyle.functions import ( GetCurvilinearAbscissaF0D, GetDirectionalViewMapDensityF1D, GetOccludersF1D, + GetProjectedXF1D, + GetProjectedYF1D, GetProjectedZF1D, GetShapeF1D, GetSteerableViewMapDensityF1D, @@ -511,7 +588,7 @@ class NotBP1D(BinaryPredicate1D): self._predicate = predicate def __call__(self, i1, i2): - return (not self._precicate(i1, i2)) + return (not self._predicate(i1, i2)) class pyZBP1D(BinaryPredicate1D): @@ -523,6 +600,24 @@ class pyZBP1D(BinaryPredicate1D): return (self.func(i1) > self.func(i2)) +class pyProjectedXBP1D(BinaryPredicate1D): + def __init__(self, iType=IntegrationType.MEAN): + BinaryPredicate1D.__init__(self) + self.func = GetProjectedXF1D(iType) + + def __call__(self, i1, i2): + return (self.func(i1) > self.func(i2)) + + +class pyProjectedYBP1D(BinaryPredicate1D): + def __init__(self, iType=IntegrationType.MEAN): + BinaryPredicate1D.__init__(self) + self.func = GetProjectedYF1D(iType) + + def __call__(self, i1, i2): + return (self.func(i1) > self.func(i2)) + + class pyZDiscontinuityBP1D(BinaryPredicate1D): def __init__(self, iType=IntegrationType.MEAN): BinaryPredicate1D.__init__(self) diff --git a/release/scripts/freestyle/modules/freestyle/shaders.py b/release/scripts/freestyle/modules/freestyle/shaders.py index 502d9b69a97..508df7feca0 100644 --- a/release/scripts/freestyle/modules/freestyle/shaders.py +++ b/release/scripts/freestyle/modules/freestyle/shaders.py @@ -22,10 +22,80 @@ # Purpose : Stroke shaders to be used for creation of stylized strokes """ -Stroke shaders used for creation of stylized strokes. Also intended -to be a collection of examples for shader definition in Python. +This module contains stroke shaders used for creation of stylized +strokes. It is also intended to be a collection of examples for +shader definition in Python. + +User-defined stroke shaders inherit the +:class:`freestyle.types.StrokeShader` class. """ +__all__ = ( + "BackboneStretcherShader", + "BezierCurveShader", + "BlenderTextureShader", + "CalligraphicShader", + "ColorNoiseShader", + "ColorVariationPatternShader", + "ConstantColorShader", + "ConstantThicknessShader", + "ConstrainedIncreasingThicknessShader", + "GuidingLinesShader", + "IncreasingColorShader", + "IncreasingThicknessShader", + "PolygonalizationShader", + "RoundCapShader", + "SamplingShader", + "SmoothingShader", + "SpatialNoiseShader", + "SquareCapShader", + "StrokeTextureShader", + "StrokeTextureStepShader", + "TextureAssignerShader", + "ThicknessNoiseShader", + "ThicknessVariationPatternShader", + "TipRemoverShader", + "fstreamShader", + "py2DCurvatureColorShader", + "pyBackboneStretcherNoCuspShader", + "pyBackboneStretcherShader", + "pyBluePrintCirclesShader", + "pyBluePrintDirectedSquaresShader", + "pyBluePrintEllipsesShader", + "pyBluePrintSquaresShader", + "pyConstantColorShader", + "pyConstantThicknessShader", + "pyConstrainedIncreasingThicknessShader", + "pyDecreasingThicknessShader", + "pyDepthDiscontinuityThicknessShader", + "pyDiffusion2Shader", + "pyFXSVaryingThicknessWithDensityShader", + "pyGuidingLineShader", + "pyHLRShader", + "pyImportance2DThicknessShader", + "pyImportance3DThicknessShader", + "pyIncreasingColorShader", + "pyIncreasingThicknessShader", + "pyInterpolateColorShader", + "pyLengthDependingBackboneStretcherShader", + "pyMaterialColorShader", + "pyModulateAlphaShader", + "pyNonLinearVaryingThicknessShader", + "pyPerlinNoise1DShader", + "pyPerlinNoise2DShader", + "pyRandomColorShader", + "pySLERPThicknessShader", + "pySamplingShader", + "pySinusDisplacementShader", + "pyTVertexRemoverShader", + "pyTVertexThickenerShader", + "pyTimeColorShader", + "pyTipRemoverShader", + "pyZDependingThicknessShader", + "streamShader", + ) + + # module members from _freestyle import ( BackboneStretcherShader, @@ -671,10 +741,8 @@ class pyTipRemoverShader(StrokeShader): @staticmethod def check_vertex(v, length): - """ - Returns True if the given strokevertex is less than self._l away - from the stroke's tip and therefore should be removed. - """ + # Returns True if the given strokevertex is less than self._l away + # from the stroke's tip and therefore should be removed. return (v.curvilinear_abscissa < length or v.stroke_length-v.curvilinear_abscissa < length) def shade(self, stroke): diff --git a/release/scripts/freestyle/modules/freestyle/types.py b/release/scripts/freestyle/modules/freestyle/types.py index 8f596fd275c..22f80f41dfc 100644 --- a/release/scripts/freestyle/modules/freestyle/types.py +++ b/release/scripts/freestyle/modules/freestyle/types.py @@ -17,9 +17,96 @@ # ##### END GPL LICENSE BLOCK ##### """ -Submodule containing all Freestyle types. +This module contains core classes of the Freestyle Python API, +including data types of view map components (0D and 1D elements), base +classes for user-defined line stylization rules (predicates, +functions, chaining iterators, and stroke shaders), and operators. + +Class hierarchy: + +- :class:`BBox` +- :class:`BinaryPredicate0D` +- :class:`BinaryPredicate1D` +- :class:`Id` +- :class:`Interface0D` + + - :class:`CurvePoint` + + - :class:`StrokeVertex` + + - :class:`SVertex` + - :class:`ViewVertex` + + - :class:`NonTVertex` + - :class:`TVertex` + +- :class:`Interface1D` + + - :class:`Curve` + + - :class:`Chain` + + - :class:`FEdge` + + - :class:`FEdgeSharp` + - :class:`FEdgeSmooth` + + - :class:`Stroke` + - :class:`ViewEdge` + +- :class:`Iterator` + + - :class:`AdjacencyIterator` + - :class:`CurvePointIterator` + - :class:`Interface0DIterator` + - :class:`SVertexIterator` + - :class:`StrokeVertexIterator` + - :class:`ViewEdgeIterator` + + - :class:`ChainingIterator` + + - :class:`orientedViewEdgeIterator` + +- :class:`Material` +- :class:`Noise` +- :class:`Operators` +- :class:`SShape` +- :class:`StrokeAttribute` +- :class:`StrokeShader` +- :class:`UnaryFunction0D` + + - :class:`UnaryFunction0DDouble` + - :class:`UnaryFunction0DEdgeNature` + - :class:`UnaryFunction0DFloat` + - :class:`UnaryFunction0DId` + - :class:`UnaryFunction0DMaterial` + - :class:`UnaryFunction0DUnsigned` + - :class:`UnaryFunction0DVec2f` + - :class:`UnaryFunction0DVec3f` + - :class:`UnaryFunction0DVectorViewShape` + - :class:`UnaryFunction0DViewShape` + +- :class:`UnaryFunction1D` + + - :class:`UnaryFunction1DDouble` + - :class:`UnaryFunction1DEdgeNature` + - :class:`UnaryFunction1DFloat` + - :class:`UnaryFunction1DUnsigned` + - :class:`UnaryFunction1DVec2f` + - :class:`UnaryFunction1DVec3f` + - :class:`UnaryFunction1DVectorViewShape` + - :class:`UnaryFunction1DVoid` + +- :class:`UnaryPredicate0D` +- :class:`UnaryPredicate1D` +- :class:`ViewMap` +- :class:`ViewShape` +- :class:`IntegrationType` +- :class:`MediumType` +- :class:`Nature` """ + # module members from _freestyle import ( AdjacencyIterator, diff --git a/release/scripts/freestyle/modules/freestyle/utils.py b/release/scripts/freestyle/modules/freestyle/utils.py index e6dca93b777..e0679a53954 100644 --- a/release/scripts/freestyle/modules/freestyle/utils.py +++ b/release/scripts/freestyle/modules/freestyle/utils.py @@ -17,9 +17,33 @@ # ##### END GPL LICENSE BLOCK ##### """ -Helper functions used for Freestyle style module writing. +This module contains helper functions used for Freestyle style module +writing. """ +__all__ = ( + "ContextFunctions", + "bound", + "bounding_box", + "find_matching_vertex", + "getCurrentScene", + "get_chain_length", + "get_test_stroke", + "integrate", + "iter_distance_along_stroke", + "iter_distance_from_camera", + "iter_distance_from_object", + "iter_material_value", + "iter_t2d_along_stroke", + "pairwise", + "phase_to_direction", + "rgb_to_bw", + "stroke_curvature", + "stroke_normal", + "tripplewise", + ) + + # module members from _freestyle import ( ContextFunctions, @@ -27,13 +51,13 @@ from _freestyle import ( integrate, ) +# constructs for helper functions in Python from freestyle.types import ( Interface0DIterator, Stroke, StrokeVertexIterator, ) - from mathutils import Vector from functools import lru_cache, namedtuple from math import cos, sin, pi diff --git a/release/scripts/freestyle/modules/parameter_editor.py b/release/scripts/freestyle/modules/parameter_editor.py index ebd09bd0181..9ac5c665f1e 100644 --- a/release/scripts/freestyle/modules/parameter_editor.py +++ b/release/scripts/freestyle/modules/parameter_editor.py @@ -62,7 +62,10 @@ from freestyle.predicates import ( TrueBP1D, TrueUP1D, WithinImageBoundaryUP1D, + pyNFirstUP1D, pyNatureUP1D, + pyProjectedXBP1D, + pyProjectedYBP1D, pyZBP1D, ) from freestyle.shaders import ( @@ -1006,11 +1009,6 @@ def process(layer_name, lineset_name): Operators.sequential_split(SplitPatternStartingUP0D(controller), SplitPatternStoppingUP0D(controller), sampling) - # select chains - if linestyle.use_length_min or linestyle.use_length_max: - length_min = linestyle.length_min if linestyle.use_length_min else None - length_max = linestyle.length_max if linestyle.use_length_max else None - Operators.select(LengthThresholdUP1D(length_min, length_max)) # sort selected chains if linestyle.use_sorting: integration = integration_types.get(linestyle.integration_type, IntegrationType.MEAN) @@ -1018,9 +1016,20 @@ def process(layer_name, lineset_name): bpred = pyZBP1D(integration) elif linestyle.sort_key == '2D_LENGTH': bpred = Length2DBP1D() + elif linestyle.sort_key == 'PROJECTED_X': + bpred = pyProjectedXBP1D(integration) + elif linestyle.sort_key == 'PROJECTED_Y': + bpred = pyProjectedYBP1D(integration) if linestyle.sort_order == 'REVERSE': bpred = NotBP1D(bpred) Operators.sort(bpred) + # select chains + if linestyle.use_length_min or linestyle.use_length_max: + length_min = linestyle.length_min if linestyle.use_length_min else None + length_max = linestyle.length_max if linestyle.use_length_max else None + Operators.select(LengthThresholdUP1D(length_min, length_max)) + if linestyle.use_chain_count: + Operators.select(pyNFirstUP1D(linestyle.chain_count)) # prepare a list of stroke shaders shaders_list = [] for m in linestyle.geometry_modifiers: diff --git a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py index ad2a70b84e8..8874ecceb77 100644 --- a/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py +++ b/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py @@ -343,10 +343,10 @@ def dump_rna_messages(msgs, reports, settings, verbose=False): process_msg(msgs, default_context, cls.__doc__, msgsrc, reports, check_ctxt_rna_tip, settings) # Panels' "tabs" system. - if hasattr(bl_rna, 'bl_category') and bl_rna.bl_category: + if hasattr(bl_rna, 'bl_category') and bl_rna.bl_category: process_msg(msgs, default_context, bl_rna.bl_category, msgsrc, reports, check_ctxt_rna, settings) - if hasattr(bl_rna, 'bl_label') and bl_rna.bl_label: + if hasattr(bl_rna, 'bl_label') and bl_rna.bl_label: process_msg(msgs, msgctxt, bl_rna.bl_label, msgsrc, reports, check_ctxt_rna, settings) walk_properties(cls) diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py index 85977642bbb..911e1764698 100644 --- a/release/scripts/modules/bl_i18n_utils/utils.py +++ b/release/scripts/modules/bl_i18n_utils/utils.py @@ -1343,7 +1343,7 @@ class I18n: #key = self.settings.PO_HEADER_KEY #for uid, trans in self.trans.items(): #if key not in trans.msgs: - #trans.msgs[key] + #trans.msgs[key] self.unescape() def write(self, kind, langs=set()): diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py index ad555a417d7..b25024fca9b 100644 --- a/release/scripts/modules/bpy_extras/view3d_utils.py +++ b/release/scripts/modules/bpy_extras/view3d_utils.py @@ -54,9 +54,13 @@ def region_2d_to_vector_3d(region, rv3d, coord): w = out.dot(persinv[3].xyz) + persinv[3][3] - return ((persinv * out) / w) - viewinv.translation + view_vector = ((persinv * out) / w) - viewinv.translation else: - return viewinv.col[2].xyz.normalized() + view_vector = -viewinv.col[2].xyz + + view_vector.normalize() + + return view_vector def region_2d_to_origin_3d(region, rv3d, coord): diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index bc2e9368b71..e19766310ec 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -694,7 +694,7 @@ class _GenericUI: draw_funcs = cls._dyn_ui_initialize() try: draw_funcs.remove(draw_func) - except: + except ValueError: pass diff --git a/release/scripts/modules/console/complete_namespace.py b/release/scripts/modules/console/complete_namespace.py index 74406d5e002..992bb72aa08 100644 --- a/release/scripts/modules/console/complete_namespace.py +++ b/release/scripts/modules/console/complete_namespace.py @@ -186,7 +186,7 @@ def complete(word, namespace, private=True): except Exception: return [] # ignore basic types - if type(obj) in (bool, float, int, str): + if type(obj) in {bool, float, int, str}: return [] # an extra char '[', '(' or '.' will be added if hasattr(obj, '__getitem__') and not is_struct_seq(obj): diff --git a/release/scripts/modules/rna_xml.py b/release/scripts/modules/rna_xml.py index 9776993b74b..41f890de51f 100644 --- a/release/scripts/modules/rna_xml.py +++ b/release/scripts/modules/rna_xml.py @@ -92,7 +92,6 @@ def rna2xml(fw=print_ln, bpy.types.Sequence, ) - def number_to_str(val, val_type): if val_type == int: return "%d" % val @@ -245,13 +244,13 @@ def xml2rna(root_xml, ): def rna2xml_node(xml_node, value): -# print("evaluating:", xml_node.nodeName) + # print("evaluating:", xml_node.nodeName) # --------------------------------------------------------------------- # Simple attributes for attr in xml_node.attributes.keys(): -# print(" ", attr) + # print(" ", attr) subvalue = getattr(value, attr, Ellipsis) if subvalue is Ellipsis: diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml index 152e944a7ba..0d377f9af68 100644 --- a/release/scripts/presets/interface_theme/back_to_black.xml +++ b/release/scripts/presets/interface_theme/back_to_black.xml @@ -156,7 +156,7 @@ <ThemeWidgetColors outline="#0a0a0a" inner="#191919e6" inner_sel="#8c8c8cff" - item="#2d2d2de6" + item="#33406be6" text="#a0a0a0" text_sel="#ffffff" show_shaded="TRUE" @@ -286,6 +286,7 @@ editmesh_active="#ff020080" normal="#22dddd" vertex_normal="#2361dd" + split_normal="#dd23dd" bone_solid="#c8c8c8" bone_pose="#50c8ff" bone_pose_active="#8cffff" @@ -310,7 +311,7 @@ tab_active="#212947" tab_inactive="#000000" tab_back="#060606ff" - tab_outline="#3a3a3a"> + tab_outline="#000000"> <gradients> <ThemeGradientColors show_grad="TRUE" gradient="#0a0a0a" diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml index 9cb3276b103..ef452aff353 100644 --- a/release/scripts/presets/interface_theme/blender_24x.xml +++ b/release/scripts/presets/interface_theme/blender_24x.xml @@ -153,11 +153,11 @@ </ThemeWidgetColors> </wcol_menu_back> <wcol_pie_menu> - <ThemeWidgetColors outline="#0a0a0a" - inner="#191919e6" - inner_sel="#8c8c8cff" - item="#2d2d2de6" - text="#a0a0a0" + <ThemeWidgetColors outline="#262626" + inner="#b4b4b42e" + inner_sel="#646464b4" + item="#b4b4b4ff" + text="#000000" text_sel="#ffffff" show_shaded="TRUE" shadetop="10" @@ -237,7 +237,7 @@ </ThemeUserInterface> </user_interface> <view_3d> - <ThemeView3D grid="#5c5c5c" + <ThemeView3D grid="#4c4c4c" wire="#000000" wire_edit="#000000" lamp="#00000028" @@ -245,23 +245,23 @@ camera="#000000" view_overlay="#000000" empty="#000000" - object_selected="#ff88ff" - object_active="#ffbbff" - object_grouped="#104010" + object_selected="#f15800" + object_active="#ffaa40" + object_grouped="#083008" object_grouped_active="#55bb55" transform="#ffffff" - vertex="#ff70ff" - vertex_select="#ffff70" - vertex_size="2" + vertex="#000000" + vertex_select="#ff8500" + vertex_size="3" vertex_unreferenced="#000000" - edge_select="#cece38" - edge_seam="#e69632" - edge_sharp="#ff2020" + edge_select="#ffa000" + edge_seam="#db2512" + edge_sharp="#00abc0" edge_crease="#cc0099" edge_facesel="#4b4b4b" freestyle_edge_mark="#7fff7f" - face="#0032961e" - face_select="#c864c83c" + face="#00000000" + face_select="#ff85003c" face_dot="#ff8a30" facedot_size="4" freestyle_face_mark="#7fff7f33" @@ -286,6 +286,7 @@ editmesh_active="#ffffff80" normal="#22dddd" vertex_normal="#2361dd" + split_normal="#dd23dd" bone_solid="#c8c8c8" bone_pose="#50c8ff" bone_pose_active="#8cffff" @@ -293,7 +294,7 @@ outline_width="1" bundle_solid="#c8c8c8" camera_path="#000000" - skin_root="#000000" + skin_root="#b44d4d" paint_curve_handle="#7fff7f7f" paint_curve_pivot="#ff7f7f7f"> <space> @@ -314,7 +315,7 @@ <gradients> <ThemeGradientColors show_grad="FALSE" gradient="#000000" - high_gradient="#757575"> + high_gradient="#7e7e7e"> </ThemeGradientColors> </gradients> <panelcolors> @@ -749,8 +750,8 @@ wire_select="#ffffff" selected_text="#7f7070" node_backdrop="#9b9b9ba0" - converter_node="#686a75" - color_node="#6c696f" + converter_node="#c6bfbf" + color_node="#457b95" group_node="#69756e" group_socket_node="#dfca35" frame_node="#9a9b9ba0" @@ -760,12 +761,12 @@ input_node="#646464" output_node="#646464" filter_node="#6c696f" - vector_node="#6c696f" - texture_node="#6c696f" - shader_node="#6c696f" + vector_node="#6f578c" + texture_node="#8395bf" + shader_node="#4f9370" script_node="#6c696f" pattern_node="#6c696f" - layout_node="#6c696f"> + layout_node="#6e6f69"> <space> <ThemeSpaceGeneric back="#757575" title="#000000" @@ -983,7 +984,7 @@ handle_sel_auto_clamped="#000000" handle_vertex="#000000" handle_vertex_select="#ffff00" - handle_vertex_size="4"> + handle_vertex_size="5"> <space> <ThemeSpaceGeneric back="#757575" title="#000000" diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml index 2d213d0ed70..9b9804b5511 100644 --- a/release/scripts/presets/interface_theme/elsyiun.xml +++ b/release/scripts/presets/interface_theme/elsyiun.xml @@ -154,9 +154,9 @@ </wcol_menu_back> <wcol_pie_menu> <ThemeWidgetColors outline="#0a0a0a" - inner="#191919e6" + inner="#414141e6" inner_sel="#8c8c8cff" - item="#2d2d2de6" + item="#b67e3ee6" text="#a0a0a0" text_sel="#ffffff" show_shaded="TRUE" @@ -286,6 +286,7 @@ editmesh_active="#ffffff80" normal="#22dddd" vertex_normal="#2361dd" + split_normal="#dd23dd" bone_solid="#c8c8c8" bone_pose="#50c8ff" bone_pose_active="#8cffff" @@ -305,9 +306,9 @@ header_text_hi="#ffffff" button="#3b3b3b57" button_title="#979797" - button_text="#979797" + button_text="#c5c5c5" button_text_hi="#ffffff" - tab_active="#464646" + tab_active="#b67e3e" tab_inactive="#393939" tab_back="#404040ff" tab_outline="#323232"> diff --git a/release/scripts/presets/interface_theme/hexagon.xml b/release/scripts/presets/interface_theme/hexagon.xml index d2221bc9935..6f24d989e79 100644 --- a/release/scripts/presets/interface_theme/hexagon.xml +++ b/release/scripts/presets/interface_theme/hexagon.xml @@ -154,11 +154,11 @@ </wcol_menu_back> <wcol_pie_menu> <ThemeWidgetColors outline="#0a0a0a" - inner="#191919e6" + inner="#5a5e6ae6" inner_sel="#8c8c8cff" - item="#2d2d2de6" - text="#a0a0a0" - text_sel="#ffffff" + item="#8f92a1e6" + text="#d6d6d6" + text_sel="#000000" show_shaded="TRUE" shadetop="10" shadedown="-10"> @@ -286,6 +286,7 @@ editmesh_active="#00e8ff80" normal="#00ffff" vertex_normal="#2361dd" + split_normal="#dd23dd" bone_solid="#c8c8c8" bone_pose="#50c8ff" bone_pose_active="#8cffff" diff --git a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml index 06d29a97745..e702e25bc86 100644 --- a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml +++ b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml @@ -156,7 +156,7 @@ <ThemeWidgetColors outline="#0a0a0a" inner="#191919e6" inner_sel="#8c8c8cff" - item="#2d2d2de6" + item="#6a3859e6" text="#a0a0a0" text_sel="#ffffff" show_shaded="TRUE" @@ -286,6 +286,7 @@ editmesh_active="#ffffff80" normal="#19b6ee" vertex_normal="#19b6ee" + split_normal="#dd23dd" bone_solid="#c8c8c8" bone_pose="#50c8ff" bone_pose_active="#8cffff" diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py index 4f6863a590c..e44fce63acd 100644 --- a/release/scripts/startup/bl_operators/__init__.py +++ b/release/scripts/startup/bl_operators/__init__.py @@ -9,7 +9,7 @@ # 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. diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py index 42ab99ed399..756b75b8d03 100644 --- a/release/scripts/startup/bl_operators/anim.py +++ b/release/scripts/startup/bl_operators/anim.py @@ -306,7 +306,8 @@ class UpdateAnimatedTransformConstraint(Operator): paths = from_paths | to_paths def update_cb(base, class_name, old_path, fcurve, options): - print(options) + # print(options) + def handle_deg2rad(fcurve): if fcurve is not None: if hasattr(fcurve, "keyframes"): diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py index 0508c32ca03..4ce300ecce2 100644 --- a/release/scripts/startup/bl_operators/clip.py +++ b/release/scripts/startup/bl_operators/clip.py @@ -780,9 +780,9 @@ class CLIP_OT_setup_tracking_scene(Operator): def _getPlaneVertices(half_size, z): return [(-half_size, -half_size, z), - (-half_size, half_size, z), + (half_size, -half_size, z), (half_size, half_size, z), - (half_size, -half_size, z)] + (-half_size, half_size, z)] def _createGround(self, scene): vertices = self._getPlaneVertices(4.0, 0.0) diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py index 32688299b76..06dc82d2b77 100644 --- a/release/scripts/startup/bl_operators/object_quick_effects.py +++ b/release/scripts/startup/bl_operators/object_quick_effects.py @@ -289,8 +289,8 @@ def obj_bb_minmax(obj, min_co, max_co): max_co[0] = max(bb_vec[0], max_co[0]) max_co[1] = max(bb_vec[1], max_co[1]) max_co[2] = max(bb_vec[2], max_co[2]) - - + + def grid_location(x, y): return (x * 200, y * 150) @@ -387,94 +387,96 @@ class QuickSmoke(Operator): links.new(node_add_shader_1.outputs["Shader"], node_out.inputs["Volume"]) - # Smoke - - # Add shader 2 - node_add_shader_2 = nodes.new(type='ShaderNodeAddShader') - node_add_shader_2.location = grid_location(4, 2) - links.new(node_add_shader_2.outputs["Shader"], - node_add_shader_1.inputs[0]) - - # Volume scatter - node_scatter = nodes.new(type='ShaderNodeVolumeScatter') - node_scatter.location = grid_location(3, 3) - links.new(node_scatter.outputs["Volume"], - node_add_shader_2.inputs[0]) - - # Volume absorption - node_absorption = nodes.new(type='ShaderNodeVolumeAbsorption') - node_absorption.location = grid_location(3, 2) - links.new(node_absorption.outputs["Volume"], - node_add_shader_2.inputs[1]) - - # Density Multiplier - node_densmult = nodes.new(type='ShaderNodeMath') - node_densmult.location = grid_location(2, 2) - node_densmult.operation = 'MULTIPLY' - node_densmult.inputs[1].default_value = 5.0 - links.new(node_densmult.outputs["Value"], - node_scatter.inputs["Density"]) - links.new(node_densmult.outputs["Value"], - node_absorption.inputs["Density"]) - - # Attribute "density" - node_attrib_density = nodes.new(type='ShaderNodeAttribute') - node_attrib_density.attribute_name = "density" - node_attrib_density.location = grid_location(1, 2) - links.new(node_attrib_density.outputs["Fac"], - node_densmult.inputs[0]) - - # Attribute "color" - node_attrib_color = nodes.new(type='ShaderNodeAttribute') - node_attrib_color.attribute_name = "color" - node_attrib_color.location = grid_location(2, 3) - links.new(node_attrib_color.outputs["Color"], - node_scatter.inputs["Color"]) - links.new(node_attrib_color.outputs["Color"], - node_absorption.inputs["Color"]) - - # Fire - - # Emission - node_emission = nodes.new(type='ShaderNodeEmission') - node_emission.inputs["Color"].default_value = (0.8, 0.1, 0.01, 1.0) - node_emission.location = grid_location(4, 1) - links.new(node_emission.outputs["Emission"], - node_add_shader_1.inputs[1]) - - # Flame strength multiplier - node_flame_strength_mult = nodes.new(type='ShaderNodeMath') - node_flame_strength_mult.location = grid_location(3, 1) - node_flame_strength_mult.operation = 'MULTIPLY' - node_flame_strength_mult.inputs[1].default_value = 2.5 - links.new(node_flame_strength_mult.outputs["Value"], - node_emission.inputs["Strength"]) - - # Color ramp Flame - node_flame_ramp = nodes.new(type='ShaderNodeValToRGB') - node_flame_ramp.location = grid_location(1, 1) - ramp = node_flame_ramp.color_ramp - ramp.interpolation = 'EASE' - - # orange - elem = ramp.elements.new(0.5) - elem.color = (1.0, 0.128, 0.0, 1.0) - - # yellow - elem = ramp.elements.new(0.9) - elem.color = (0.9, 0.6, 0.1, 1.0) - - links.new(node_flame_ramp.outputs["Color"], - node_emission.inputs["Color"]) - - # Attribute "flame" - node_attrib_flame = nodes.new(type='ShaderNodeAttribute') - node_attrib_flame.attribute_name = "flame" - node_attrib_flame.location = grid_location(0, 1) - links.new(node_attrib_flame.outputs["Fac"], - node_flame_ramp.inputs["Fac"]) - links.new(node_attrib_flame.outputs["Fac"], - node_flame_strength_mult.inputs[0]) + if self.style in {'SMOKE', 'BOTH'}: + # Smoke + + # Add shader 2 + node_add_shader_2 = nodes.new(type='ShaderNodeAddShader') + node_add_shader_2.location = grid_location(4, 2) + links.new(node_add_shader_2.outputs["Shader"], + node_add_shader_1.inputs[0]) + + # Volume scatter + node_scatter = nodes.new(type='ShaderNodeVolumeScatter') + node_scatter.location = grid_location(3, 3) + links.new(node_scatter.outputs["Volume"], + node_add_shader_2.inputs[0]) + + # Volume absorption + node_absorption = nodes.new(type='ShaderNodeVolumeAbsorption') + node_absorption.location = grid_location(3, 2) + links.new(node_absorption.outputs["Volume"], + node_add_shader_2.inputs[1]) + + # Density Multiplier + node_densmult = nodes.new(type='ShaderNodeMath') + node_densmult.location = grid_location(2, 2) + node_densmult.operation = 'MULTIPLY' + node_densmult.inputs[1].default_value = 5.0 + links.new(node_densmult.outputs["Value"], + node_scatter.inputs["Density"]) + links.new(node_densmult.outputs["Value"], + node_absorption.inputs["Density"]) + + # Attribute "density" + node_attrib_density = nodes.new(type='ShaderNodeAttribute') + node_attrib_density.attribute_name = "density" + node_attrib_density.location = grid_location(1, 2) + links.new(node_attrib_density.outputs["Fac"], + node_densmult.inputs[0]) + + # Attribute "color" + node_attrib_color = nodes.new(type='ShaderNodeAttribute') + node_attrib_color.attribute_name = "color" + node_attrib_color.location = grid_location(2, 3) + links.new(node_attrib_color.outputs["Color"], + node_scatter.inputs["Color"]) + links.new(node_attrib_color.outputs["Color"], + node_absorption.inputs["Color"]) + + if self.style in {'FIRE', 'BOTH'}: + # Fire + + # Emission + node_emission = nodes.new(type='ShaderNodeEmission') + node_emission.inputs["Color"].default_value = (0.8, 0.1, 0.01, 1.0) + node_emission.location = grid_location(4, 1) + links.new(node_emission.outputs["Emission"], + node_add_shader_1.inputs[1]) + + # Flame strength multiplier + node_flame_strength_mult = nodes.new(type='ShaderNodeMath') + node_flame_strength_mult.location = grid_location(3, 1) + node_flame_strength_mult.operation = 'MULTIPLY' + node_flame_strength_mult.inputs[1].default_value = 2.5 + links.new(node_flame_strength_mult.outputs["Value"], + node_emission.inputs["Strength"]) + + # Color ramp Flame + node_flame_ramp = nodes.new(type='ShaderNodeValToRGB') + node_flame_ramp.location = grid_location(1, 1) + ramp = node_flame_ramp.color_ramp + ramp.interpolation = 'EASE' + + # orange + elem = ramp.elements.new(0.5) + elem.color = (1.0, 0.128, 0.0, 1.0) + + # yellow + elem = ramp.elements.new(0.9) + elem.color = (0.9, 0.6, 0.1, 1.0) + + links.new(node_flame_ramp.outputs["Color"], + node_emission.inputs["Color"]) + + # Attribute "flame" + node_attrib_flame = nodes.new(type='ShaderNodeAttribute') + node_attrib_flame.attribute_name = "flame" + node_attrib_flame.location = grid_location(0, 1) + links.new(node_attrib_flame.outputs["Fac"], + node_flame_ramp.inputs["Fac"]) + links.new(node_attrib_flame.outputs["Fac"], + node_flame_strength_mult.inputs[0]) # Blender Internal else: diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 5c3f94a8739..8d04cb132e6 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1934,7 +1934,6 @@ class WM_OT_addon_install(Operator): try: os.makedirs(path_addons, exist_ok=True) except: - import traceback traceback.print_exc() # Check if we are installing from a target path, diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py index 58818e90440..6abd6f448f5 100644 --- a/release/scripts/startup/bl_ui/properties_freestyle.py +++ b/release/scripts/startup/bl_ui/properties_freestyle.py @@ -122,7 +122,9 @@ class RENDERLAYER_PT_freestyle(RenderLayerFreestyleButtonsPanel, Panel): layout.active = rl.use_freestyle + row = layout.row() layout.prop(freestyle, "mode", text="Control mode") + layout.prop(freestyle, "use_view_map_cache", text="View Map Cache") layout.label(text="Edge Detection Options:") split = layout.split() @@ -579,6 +581,20 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, sub.prop(linestyle, "split_dash3", text="D3") sub.prop(linestyle, "split_gap3", text="G3") + ## Sorting + layout.prop(linestyle, "use_sorting", text="Sorting:") + col = layout.column() + col.active = linestyle.use_sorting + row = col.row(align=True) + row.prop(linestyle, "sort_key", text="") + sub = row.row() + sub.active = linestyle.sort_key in {'DISTANCE_FROM_CAMERA', + 'PROJECTED_X', + 'PROJECTED_Y'} + sub.prop(linestyle, "integration_type", text="") + row = col.row(align=True) + row.prop(linestyle, "sort_order", expand=True) + ## Selection layout.label(text="Selection:") split = layout.split(align=True) @@ -589,25 +605,18 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, sub = row.row() sub.active = linestyle.use_length_min sub.prop(linestyle, "length_min") - # Second column - col = split.column() row = col.row(align=True) row.prop(linestyle, "use_length_max", text="") sub = row.row() sub.active = linestyle.use_length_max sub.prop(linestyle, "length_max") - - ## Sorting - layout.prop(linestyle, "use_sorting", text="Sorting:") - col = layout.column() - col.active = linestyle.use_sorting + # Second column + col = split.column() row = col.row(align=True) - row.prop(linestyle, "sort_key", text="") + row.prop(linestyle, "use_chain_count", text="") sub = row.row() - sub.active = linestyle.sort_key in {'DISTANCE_FROM_CAMERA'} - sub.prop(linestyle, "integration_type", text="") - row = col.row(align=True) - row.prop(linestyle, "sort_order", expand=True) + sub.active = linestyle.use_chain_count + sub.prop(linestyle, "chain_count") ## Caps layout.label(text="Caps:") diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 5dd1f94747c..4789d119192 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -47,4 +47,3 @@ class GreasePencilPanel(): col.label(text="Measure:") col.operator("view3d.ruler") - diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index e6d6a3952ea..25367a58a54 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -151,6 +151,7 @@ class OBJECT_PT_relations(ObjectButtonsPanel, Panel): sub.prop_search(ob, "parent_bone", parent.data, "bones", text="") sub.active = (parent is not None) + class GROUP_MT_specials(Menu): bl_label = "Group Specials" diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 5c758b6568b..f1042856e4c 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -36,7 +36,10 @@ class UnifiedPaintPanel(): elif context.weight_paint_object: return toolsettings.weight_paint elif context.image_paint_object: - return toolsettings.image_paint + if (toolsettings.image_paint and toolsettings.image_paint.detect_data()): + return toolsettings.image_paint + + return None elif context.particle_edit_object: return toolsettings.particle_edit @@ -170,7 +173,7 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal mat = ob.active_material if mat: - col.label("Clone Slot") + col.label("Source Clone Slot") col.template_list("TEXTURE_UL_texpaintslots", "", mat, "texture_paint_images", mat, "paint_clone_slot", rows=2) @@ -179,18 +182,14 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal mesh = ob.data clone_text = mesh.uv_texture_clone.name if mesh.uv_texture_clone else "" - col.label("Image") + col.label("Source Clone Image") col.template_ID(settings, "clone_image") - col.label("UV Map") + col.label("Source Clone UV Map") col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False) - - else: col.prop(brush, "clone_image", text="Image") col.prop(brush, "clone_alpha", text="Alpha") - - col.separator() if capabilities.has_radius: diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 13aad4c3888..3382633af60 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -260,7 +260,7 @@ class CLIP_PT_tools_marker(CLIP_PT_tracking_panel, Panel): def draw(self, context): layout = self.layout - sc = context.space_data + # sc = context.space_data # clip = sc.clip col = layout.column(align=True) diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 8fd0ded17f7..927e517ef21 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -154,6 +154,7 @@ class IMAGE_MT_brush(Menu): ups = context.tool_settings.unified_paint_settings layout.prop(ups, "use_unified_size", text="Unified Size") layout.prop(ups, "use_unified_strength", text="Unified Strength") + layout.prop(ups, "use_unified_color", text="Unified Color") layout.separator() # brush tool @@ -1014,11 +1015,13 @@ class IMAGE_UV_sculpt(Panel, ImagePaintPanel): col = layout.column() col.prop(toolsettings, "uv_sculpt_lock_borders") col.prop(toolsettings, "uv_sculpt_all_islands") - col.prop(toolsettings, "uv_sculpt_tool") + col.prop(toolsettings, "uv_sculpt_tool") if toolsettings.uv_sculpt_tool == 'RELAX': col.prop(toolsettings, "uv_relax_method") + col.prop(uvsculpt, "show_brush") + class IMAGE_PT_tools_mask(MASK_PT_tools, Panel): bl_space_type = 'IMAGE_EDITOR' diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index e8914a3e9b0..24e8d2e4a53 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -200,7 +200,7 @@ class NODE_MT_select(Menu): layout.separator() - layout.operator("node.select_same_type") + layout.operator("node.select_grouped") layout.operator("node.select_same_type_step").prev = True layout.operator("node.select_same_type_step").prev = False diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index bbb1e41beb1..ce00d4eb8e7 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -215,7 +215,7 @@ class SEQUENCER_MT_select(Menu): op = layout.operator("sequencer.select", text="All strips to the Right") op.left_right = 'RIGHT' op.linked_time = True - + layout.separator() layout.operator("sequencer.select_handles", text="Surrounding Handles").side = 'BOTH' layout.operator("sequencer.select_handles", text="Left Handle").side = 'LEFT' @@ -259,6 +259,7 @@ class SEQUENCER_MT_frame(Menu): layout.operator("anim.previewrange_clear") layout.operator("anim.previewrange_set") + class SEQUENCER_MT_add(Menu): bl_label = "Add" @@ -607,7 +608,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): col = layout.column(align=True) if strip.type == 'SPEED': col.prop(strip, "multiply_speed") - elif strip.type in {'CROSS', 'GAMMA_CROSS', 'WIPE', 'ALPHA_OVER','ALPHA_UNDER','OVER_DROP'}: + elif strip.type in {'CROSS', 'GAMMA_CROSS', 'WIPE', 'ALPHA_OVER', 'ALPHA_UNDER', 'OVER_DROP'}: col.prop(strip, "use_default_fade", "Default fade") if not strip.use_default_fade: col.prop(strip, "effect_fader", text="Effect fader") diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 999e41e17f7..dc18dd73abc 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -383,6 +383,11 @@ class USERPREF_PT_system(Panel): col = colsplit.column() col.label(text="General:") col.prop(system, "dpi") + col.label("Virtual Pixel Mode:") + col.prop(system, "virtual_pixel_mode", text="") + + col.separator() + col.prop(system, "frame_server_port") col.prop(system, "scrollback", text="Console Scrollback") @@ -424,7 +429,6 @@ class USERPREF_PT_system(Panel): col.prop(system, "use_gpu_mipmap") col.prop(system, "use_16bit_textures") - if system.is_occlusion_query_supported(): col.separator() col.label(text="Selection") diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 61d359ebdac..2249d2b04b8 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -608,6 +608,19 @@ class VIEW3D_MT_select_particle(Menu): layout.operator("particle.select_tips", text="Tips") +class VIEW3D_MT_edit_mesh_select_similar(Menu): + bl_label = "Select Similar" + + def draw(self, context): + layout = self.layout + + layout.operator_enum("mesh.select_similar", "type") + + layout.separator() + + layout.operator("mesh.select_similar_region", text="Face Regions") + + class VIEW3D_MT_select_edit_mesh(Menu): bl_label = "Select" @@ -647,7 +660,7 @@ class VIEW3D_MT_select_edit_mesh(Menu): layout.separator() # other ... - layout.operator_menu_enum("mesh.select_similar", "type", text="Similar") + layout.menu("VIEW3D_MT_edit_mesh_select_similar") layout.operator("mesh.select_ungrouped", text="Ungrouped Verts") layout.separator() @@ -1424,6 +1437,8 @@ class VIEW3D_MT_brush(Menu): ups = context.tool_settings.unified_paint_settings layout.prop(ups, "use_unified_size", text="Unified Size") layout.prop(ups, "use_unified_strength", text="Unified Strength") + if context.image_paint_object or context.vertex_paint_object: + layout.prop(ups, "use_unified_color", text="Unified Color") layout.separator() # brush paint modes @@ -2198,7 +2213,6 @@ class VIEW3D_MT_edit_mesh_edges(Menu): layout = self.layout with_freestyle = bpy.app.build_options.freestyle - scene = context.scene layout.operator_context = 'INVOKE_REGION_WIN' @@ -2254,7 +2268,6 @@ class VIEW3D_MT_edit_mesh_faces(Menu): layout = self.layout with_freestyle = bpy.app.build_options.freestyle - scene = context.scene layout.operator_context = 'INVOKE_REGION_WIN' @@ -2951,7 +2964,7 @@ class VIEW3D_PT_view3d_meshdisplay(Panel): sub = row.row(align=True) sub.active = mesh.show_normal_vertex or mesh.show_normal_face or mesh.show_normal_loop - sub.prop(context.scene.tool_settings, "normal_size", text="Size") + sub.prop(scene.tool_settings, "normal_size", text="Size") col.separator() split = layout.split() diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 6b0c5b1e993..213bfd9d808 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -775,6 +775,65 @@ class View3DPaintPanel(UnifiedPaintPanel): bl_space_type = 'VIEW_3D' bl_region_type = 'TOOLS' +class VIEW3D_PT_imapaint_tools_missing(Panel, View3DPaintPanel): + bl_category = "Tools" + bl_label = "Missing Data" + + @classmethod + def poll(cls, context): + toolsettings = context.tool_settings.image_paint + return context.image_paint_object and not toolsettings.detect_data() + + def draw(self, context): + layout = self.layout + toolsettings = context.tool_settings.image_paint + + col = layout.column() + col.label("Missing Data", icon='ERROR') + if toolsettings.missing_uvs: + col.separator() + col.label("Missing UVs", icon='INFO') + col.label("Unwrap the mesh in edit mode or generate a simple UVs") + col.operator("mesh.uv_texture_add", text="Add Simple UVs") + + if toolsettings.mode == 'MATERIAL': + if toolsettings.missing_materials: + col.separator() + col.label("Missing Materials", icon='INFO') + col.label("Add a material and paint slot below") + col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot") + + elif toolsettings.missing_texture: + ob = context.active_object + mat = ob.active_material + + col.separator() + if mat: + col.label("Missing Texture Slots", icon='INFO') + col.label("Add a paint slot below") + col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot") + else: + col.label("Missing Materials", icon='INFO') + col.label("Add a material and paint slot below") + col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot") + + + elif toolsettings.mode == 'IMAGE': + if toolsettings.missing_texture: + col.separator() + col.label("Missing Canvas", icon='INFO') + col.label("Add or assign a canvas image below") + col.label("Canvas Image") + col.template_ID(toolsettings, "canvas") + col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS' + + if toolsettings.missing_stencil: + col.separator() + col.label("Missing Stencil", icon='INFO') + col.label("Add or assign a stencil image below") + col.label("Stencil Image") + col.template_ID(toolsettings, "stencil_image") + col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL' class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel): bl_category = "Tools" @@ -844,14 +903,15 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel): self.prop_unified_size(row, context, brush, "use_pressure_size") # strength, use_strength_pressure, and use_strength_attenuation - if capabilities.has_strength: - col.separator() - row = col.row(align=True) + col.separator() + row = col.row(align=True) - if capabilities.has_space_attenuation: - row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True) + if capabilities.has_space_attenuation: + row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True) + + self.prop_unified_strength(row, context, brush, "strength", text="Strength") - self.prop_unified_strength(row, context, brush, "strength", text="Strength") + if capabilities.has_strength_pressure: self.prop_unified_strength(row, context, brush, "use_pressure_strength") # auto_smooth_factor and use_inverse_smooth_pressure @@ -1005,6 +1065,17 @@ class TEXTURE_UL_texpaintslots(UIList): layout.alignment = 'CENTER' layout.label(text="") +class VIEW3D_MT_tools_projectpaint_uvlayer(Menu): + bl_label = "Clone Layer" + + def draw(self, context): + layout = self.layout + + for i, tex in enumerate(context.active_object.data.uv_textures): + props = layout.operator("wm.context_set_int", text=tex.name, translate=False) + props.data_path = "active_object.data.uv_textures.active_index" + props.value = i + class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel): bl_context = "imagepaint" @@ -1027,7 +1098,7 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel): col = layout.column() col.label("Painting Mode") - col.prop(settings, "mode", text = "") + col.prop(settings, "mode", text="") col.separator() if settings.mode == 'MATERIAL': @@ -1058,16 +1129,21 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel): col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="") elif settings.mode == 'IMAGE': + mesh = ob.data + uv_text = mesh.uv_textures.active.name if mesh.uv_textures.active else "" + col.label("Canvas Image") col.template_ID(settings, "canvas") + col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS' + col.label("UV Map") + col.menu("VIEW3D_MT_tools_projectpaint_uvlayer", text=uv_text, translate=False) col.separator() col.operator("image.save_dirty", text="Save All Images") - class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel): bl_context = "imagepaint" - bl_label = "Stencil" + bl_label = "Mask" bl_category = "Slots" @classmethod @@ -1095,9 +1171,10 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel): col.label("UV Map") col.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False) - col.label("Image") - row = col.row(align=True) - row.template_ID(ipaint, "stencil_image") + col.label("Stencil Image") + col.template_ID(ipaint, "stencil_image") + col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL' + col.label("Visualization") row = col.row(align=True) @@ -1195,7 +1272,7 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel): brush_texture_settings(col, brush, context.sculpt_object) -class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel): +class VIEW3D_PT_tools_mask_texture(View3DPanel, View3DPaintPanel): bl_category = "Tools" bl_context = "imagepaint" bl_label = "Texture Mask" @@ -1203,8 +1280,8 @@ class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel): @classmethod def poll(cls, context): - brush = context.tool_settings.image_paint.brush - return (context.image_paint_object and brush) + settings = cls.paint_settings(context) + return (settings and settings.image_paint.brush and context.image_paint_object and brush) def draw(self, context): layout = self.layout @@ -1459,11 +1536,8 @@ class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel): @classmethod def poll(cls, context): - toolsettings = context.tool_settings - return ((context.sculpt_object and toolsettings.sculpt) or - (context.vertex_paint_object and toolsettings.vertex_paint) or - (context.weight_paint_object and toolsettings.weight_paint) or - (context.image_paint_object and toolsettings.image_paint)) + settings = cls.paint_settings(context) + return settings def draw(self, context): layout = self.layout diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 5dccda789e0..8c2476bd430 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -112,6 +112,20 @@ def line_style_shader_nodes_poll(context): snode.shader_type == 'LINESTYLE') +# only show nodes working in world node trees +def world_shader_nodes_poll(context): + snode = context.space_data + return (snode.tree_type == 'ShaderNodeTree' and + snode.shader_type == 'WORLD') + + +# only show nodes working in object node trees +def object_shader_nodes_poll(context): + snode = context.space_data + return (snode.tree_type == 'ShaderNodeTree' and + snode.shader_type == 'OBJECT') + + # All standard node categories currently used in nodes. shader_node_categories = [ @@ -180,30 +194,30 @@ shader_node_categories = [ NodeItem("NodeGroupInput", poll=group_input_output_item_poll), ]), ShaderNewNodeCategory("SH_NEW_OUTPUT", "Output", items=[ - NodeItem("ShaderNodeOutputMaterial"), - NodeItem("ShaderNodeOutputLamp"), - NodeItem("ShaderNodeOutputWorld"), + NodeItem("ShaderNodeOutputMaterial", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeOutputLamp", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeOutputWorld", poll=world_shader_nodes_poll), NodeItem("ShaderNodeOutputLineStyle", poll=line_style_shader_nodes_poll), NodeItem("NodeGroupOutput", poll=group_input_output_item_poll), ]), ShaderNewNodeCategory("SH_NEW_SHADER", "Shader", items=[ NodeItem("ShaderNodeMixShader"), NodeItem("ShaderNodeAddShader"), - NodeItem("ShaderNodeBsdfDiffuse"), - NodeItem("ShaderNodeBsdfGlossy"), - NodeItem("ShaderNodeBsdfTransparent"), - NodeItem("ShaderNodeBsdfRefraction"), - NodeItem("ShaderNodeBsdfGlass"), - NodeItem("ShaderNodeBsdfTranslucent"), - NodeItem("ShaderNodeBsdfAnisotropic"), - NodeItem("ShaderNodeBsdfVelvet"), - NodeItem("ShaderNodeBsdfToon"), - NodeItem("ShaderNodeSubsurfaceScattering"), - NodeItem("ShaderNodeEmission"), - NodeItem("ShaderNodeBsdfHair"), - NodeItem("ShaderNodeBackground"), - NodeItem("ShaderNodeAmbientOcclusion"), - NodeItem("ShaderNodeHoldout"), + NodeItem("ShaderNodeBsdfDiffuse", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeBsdfGlossy", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeBsdfTransparent", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeBsdfRefraction", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeBsdfGlass", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeBsdfTranslucent", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeBsdfAnisotropic", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeBsdfVelvet", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeBsdfToon", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeSubsurfaceScattering", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeEmission", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeBsdfHair", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeBackground", poll=world_shader_nodes_poll), + NodeItem("ShaderNodeAmbientOcclusion", poll=object_shader_nodes_poll), + NodeItem("ShaderNodeHoldout", poll=object_shader_nodes_poll), NodeItem("ShaderNodeVolumeAbsorption"), NodeItem("ShaderNodeVolumeScatter"), ]), diff --git a/release/scripts/templates_osl/fresnel_conductive.osl b/release/scripts/templates_osl/fresnel_conductive.osl index c197656eaee..6de0692bffe 100644 --- a/release/scripts/templates_osl/fresnel_conductive.osl +++ b/release/scripts/templates_osl/fresnel_conductive.osl @@ -16,14 +16,14 @@ color fresnel_conductor(float cosi, color eta, color k) { - color cosi2 = color(cosi*cosi); + color cosi2 = color(cosi * cosi); color one = color(1, 1, 1); color tmp_f = eta * eta + k * k; color tmp = tmp_f * cosi2; color Rparl2 = (tmp - (2.0 * eta * cosi) + one) / - (tmp + (2.0 * eta * cosi) + one); + (tmp + (2.0 * eta * cosi) + one); color Rperp2 = (tmp_f - (2.0 * eta * cosi) + cosi2) / - (tmp_f + (2.0 * eta * cosi) + cosi2); + (tmp_f + (2.0 * eta * cosi) + cosi2); return (Rparl2 + Rperp2) * 0.5; } diff --git a/release/scripts/templates_osl/westin_closure.osl b/release/scripts/templates_osl/westin_closure.osl deleted file mode 100644 index 8d90f3aa306..00000000000 --- a/release/scripts/templates_osl/westin_closure.osl +++ /dev/null @@ -1,12 +0,0 @@ - -shader node_westin_bsdf( - color Color = 0.8, - float Roughness = 0.5, - float Edginess = 0.2, - normal Normal = N, - output closure color Sheen = 0, - output closure color Backscatter = 0) -{ - Sheen = Color * westin_sheen(Normal, Roughness); - Backscatter = Color * westin_backscatter(Normal, Edginess); -}
\ No newline at end of file diff --git a/release/scripts/templates_py/batch_export.py b/release/scripts/templates_py/batch_export.py index 45d26f4b525..6c77c5d6a1a 100644 --- a/release/scripts/templates_py/batch_export.py +++ b/release/scripts/templates_py/batch_export.py @@ -9,6 +9,9 @@ basedir = os.path.dirname(bpy.data.filepath) if not basedir: raise Exception("Blend file is not saved") +scene = bpy.context.scene + +obj_active = scene.objects.active selection = bpy.context.selected_objects bpy.ops.object.select_all(action='DESELECT') @@ -17,6 +20,9 @@ for obj in selection: obj.select = True + # some exporters only use the active object + scene.objects.active = obj + name = bpy.path.clean_name(obj.name) fn = os.path.join(basedir, name) @@ -29,5 +35,8 @@ for obj in selection: print("written:", fn) + +scene.objects.active = obj_active + for obj in selection: obj.select = True diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py index 4d0355047f4..1aa13c90ca3 100644 --- a/release/scripts/templates_py/operator_modal_view3d_raycast.py +++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py @@ -1,9 +1,8 @@ import bpy -from mathutils import Vector from bpy_extras import view3d_utils -def main(context, event, ray_max=10000.0): +def main(context, event, ray_max=1000.0): """Run this function on left mouse, execute the ray cast""" # get the context arguments scene = context.scene @@ -14,6 +13,11 @@ def main(context, event, ray_max=10000.0): # get the ray from the viewport and mouse view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) + + if rv3d.view_perspective == 'ORTHO': + # move ortho origin back + ray_origin = ray_origin - (view_vector * (ray_max / 2.0)) + ray_target = ray_origin + (view_vector * ray_max) def visible_objects_and_duplis(): @@ -106,4 +110,3 @@ def unregister(): if __name__ == "__main__": register() - diff --git a/release/scripts/templates_py/script_stub.py b/release/scripts/templates_py/script_stub.py index 3f56749f3b3..5505ca64078 100644 --- a/release/scripts/templates_py/script_stub.py +++ b/release/scripts/templates_py/script_stub.py @@ -11,4 +11,3 @@ filepath = os.path.join(os.path.dirname(bpy.data.filepath), filename) global_namespace = {"__file__": filepath, "__name__": "__main__"} with open(filepath, 'rb') as file: exec(compile(file.read(), filepath, 'exec'), global_namespace) - diff --git a/release/scripts/templates_py/ui_pie_menu.py b/release/scripts/templates_py/ui_pie_menu.py index 87500b682d6..0c431ca50ff 100644 --- a/release/scripts/templates_py/ui_pie_menu.py +++ b/release/scripts/templates_py/ui_pie_menu.py @@ -29,4 +29,3 @@ if __name__ == "__main__": register() bpy.ops.wm.call_menu_pie(name="VIEW3D_PIE_template") - diff --git a/scons b/scons -Subproject 1ec93106c40fab0c339d09c7ed9897c85ddf3da +Subproject 625d446ae8996ff1b3d660c44e2827fc832cf12 diff --git a/source/blender/avi/intern/avi_rgb.c b/source/blender/avi/intern/avi_rgb.c index c6a78eccce2..632ecad61a6 100644 --- a/source/blender/avi/intern/avi_rgb.c +++ b/source/blender/avi/intern/avi_rgb.c @@ -123,13 +123,12 @@ void *avi_converter_to_avi_rgb(AviMovie *movie, int stream, unsigned char *buffe (void)stream; /* unused */ - *size = movie->header->Height * movie->header->Width * 3; - if (movie->header->Width % 2) *size += movie->header->Height; - - buf = MEM_mallocN(*size, "toavirgbbuf"); - rowstride = movie->header->Width * 3; - if (movie->header->Width % 2) rowstride++; + /* AVI files has uncompressed lines 4-byte aligned */ + rowstride = (rowstride + 3) & ~3; + + *size = movie->header->Height * rowstride; + buf = MEM_mallocN(*size, "toavirgbbuf"); for (y = 0; y < movie->header->Height; y++) { memcpy(&buf[y * rowstride], &buffer[((movie->header->Height - 1) - y) * movie->header->Width * 3], movie->header->Width * 3); diff --git a/source/blender/avi/intern/avi_rgb32.c b/source/blender/avi/intern/avi_rgb32.c index 5c7a4889d97..c9cbcb05bb8 100644 --- a/source/blender/avi/intern/avi_rgb32.c +++ b/source/blender/avi/intern/avi_rgb32.c @@ -74,8 +74,8 @@ void *avi_converter_to_rgb32(AviMovie *movie, int stream, unsigned char *buffer, (void)stream; /* unused */ - buf = MEM_mallocN(movie->header->Height * movie->header->Width * 4, "torgb32buf"); *size = movie->header->Height * movie->header->Width * 4; + buf = MEM_mallocN(*size, "torgb32buf"); memset(buf, 255, *size); diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 80d2750fe82..e79822daa4d 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -37,8 +37,10 @@ struct Main; struct AnimData; struct KeyingSet; struct KS_Path; +struct bContext; struct PointerRNA; +struct PropertyRNA; struct ReportList; struct bAction; struct bActionGroup; @@ -127,6 +129,9 @@ void BKE_animdata_separate_by_basepath(struct ID *srcID, struct ID *dstID, struc /* Move F-Curves from src to destination if it's path is based on basepath */ void action_move_fcurves_by_basepath(struct bAction *srcAct, struct bAction *dstAct, const char basepath[]); +char *BKE_animdata_driver_path_hack(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, + char *base_path); + /* ************************************* */ /* Batch AnimData API */ diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 46a0c36a5f2..6c8f90c60ae 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,8 +41,8 @@ extern "C" { /* these lines are grep'd, watch out for our not-so-awesome regex * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ -#define BLENDER_VERSION 271 -#define BLENDER_SUBVERSION 6 +#define BLENDER_VERSION 272 +#define BLENDER_SUBVERSION 1 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 5a1e173f0b3..9a6524cc9ab 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -310,7 +310,7 @@ void CustomData_set_layer_flag(struct CustomData *data, int type, int flag); void CustomData_bmesh_set_default(struct CustomData *data, void **block); void CustomData_bmesh_free_block(struct CustomData *data, void **block); -void CustomData_bmesh_free_block_data(struct CustomData *data, void **block); +void CustomData_bmesh_free_block_data(struct CustomData *data, void *block); /* copy custom data to/from layers as in mesh/derivedmesh, to editmesh * blocks of data. the CustomData's must not be compatible */ diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 0e86be9b97c..c377769b271 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -43,6 +43,7 @@ struct DriverVar; struct DriverTarget; struct FCM_EnvelopeData; +struct bContext; struct bAction; struct BezTriple; struct StructRNA; @@ -221,8 +222,12 @@ struct FCurve *id_data_find_fcurve(ID *id, void *data, struct StructRNA *type, c */ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName); -/* find an f-curve based on an rna property */ -struct FCurve *rna_get_fcurve(struct PointerRNA *ptr, struct PropertyRNA *prop, int rnaindex, struct bAction **action, bool *r_driven); +/* find an f-curve based on an rna property. */ +struct FCurve *rna_get_fcurve(struct PointerRNA *ptr, struct PropertyRNA *prop, int rnaindex, + struct bAction **action, bool *r_driven); +/* Same as above, but takes a context data, temp hack needed for complex paths like texture ones. */ +struct FCurve *rna_get_fcurve_context_ui(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, + int rnaindex, struct bAction **action, bool *r_driven); /* Binary search algorithm for finding where to 'insert' BezTriple with given frame number. * Returns the index to insert at (data already at that index will be offset if replace is 0) diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 1d37f9e64e1..500c2813a75 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -71,8 +71,8 @@ void id_clear_lib_data(struct Main *bmain, struct ID *id); struct ListBase *which_libbase(struct Main *mainlib, short type); -#define MAX_LIBARRAY 43 -int set_listbasepointers(struct Main *main, struct ListBase **lb); +#define MAX_LIBARRAY 35 +int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]); void BKE_libblock_free(struct Main *bmain, void *idv); void BKE_libblock_free_ex(struct Main *bmain, void *idv, bool do_id_user); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index a81da8c18af..b080ca37e67 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -50,6 +50,7 @@ struct PaintCurve; struct Palette; struct PaletteColor; struct PBVH; +struct ReportList; struct Scene; struct Sculpt; struct StrokeCache; @@ -100,7 +101,6 @@ void BKE_paint_set_overlay_override(enum OverlayFlags flag); void BKE_palette_free(struct Palette *palette); struct Palette *BKE_palette_add(struct Main *bmain, const char *name); struct PaletteColor *BKE_palette_color_add(struct Palette *palette); -void BKE_palette_color_delete(struct Palette *palette); bool BKE_palette_is_empty(const struct Palette *palette); void BKE_palette_color_remove(struct Palette *palette, struct PaletteColor *color); void BKE_palette_cleanup(struct Palette *palette); @@ -122,6 +122,9 @@ struct Palette *BKE_paint_palette(struct Paint *paint); void BKE_paint_palette_set(struct Paint *p, struct Palette *palette); void BKE_paint_curve_set(struct Brush *br, struct PaintCurve *pc); +void BKE_paint_data_warning(struct ReportList *reports, bool uvs, bool mat, bool tex, bool stencil); +bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil); + /* testing face select mode * Texture paint could be removed since selected faces are not used * however hiding faces is useful */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 9ff9991f5a6..81c03d8081b 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2602,8 +2602,6 @@ static void make_vertexcos__mapFunc(void *userData, int index, const float co[3] void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int totcos) { - float (*vertexcos)[3]; - if (dm->foreachMappedVert) { MappedUserData userData; memset(r_cos, 0, sizeof(*r_cos) * totcos); @@ -2615,7 +2613,7 @@ void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int else { int i; for (i = 0; i < totcos; i++) { - dm->getVertCo(dm, i, vertexcos[i]); + dm->getVertCo(dm, i, r_cos[i]); } } } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 5ee82bb5842..2fb832dc72d 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -51,18 +51,23 @@ #include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "DNA_texture_types.h" #include "DNA_world_types.h" #include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_nla.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_library.h" #include "BKE_report.h" +#include "BKE_texture.h" #include "RNA_access.h" @@ -551,6 +556,74 @@ void BKE_animdata_separate_by_basepath(ID *srcID, ID *dstID, ListBase *basepaths } } +/** + * Temporary wrapper for driver operators for buttons to make it easier to create + * such drivers by rerouting all paths through the active object instead so that + * they will get picked up by the dependency system. + * + * \param C Context pointer - for getting active data + * \param[in,out] ptr RNA pointer for property's datablock. May be modified as result of path remapping. + * \param prop RNA definition of property to add for + * \return MEM_alloc'd string representing the path to the property from the given #PointerRNA + */ +char *BKE_animdata_driver_path_hack(bContext *C, PointerRNA *ptr, PropertyRNA *prop, char *base_path) +{ + ID *id = (ID *)ptr->id.data; + ScrArea *sa = CTX_wm_area(C); + + /* get standard path which may be extended */ + char *basepath = base_path ? base_path : RNA_path_from_ID_to_property(ptr, prop); + char *path = basepath; /* in case no remapping is needed */ + + /* Remapping will only be performed in the Properties Editor, as only this + * restricts the subspace of options to the 'active' data (a manageable state) + */ + /* TODO: watch out for pinned context? */ + if ((sa) && (sa->spacetype == SPACE_BUTS)) { + Object *ob = CTX_data_active_object(C); + + if (ob && id) { + /* only id-types which can be remapped to go through objects should be considered */ + switch (GS(id->name)) { + case ID_TE: /* textures */ + { + Material *ma = give_current_material(ob, ob->actcol); + Tex *tex = give_current_material_texture(ma); + + /* assumes: texture will only be shown if it is active material's active texture it's ok */ + if ((ID *)tex == id) { + char name_esc_ma[(sizeof(ma->id.name) - 2) * 2]; + char name_esc_tex[(sizeof(tex->id.name) - 2) * 2]; + + BLI_strescape(name_esc_ma, ma->id.name + 2, sizeof(name_esc_ma)); + BLI_strescape(name_esc_tex, tex->id.name + 2, sizeof(name_esc_tex)); + + /* create new path */ + // TODO: use RNA path functions to construct step by step instead? + // FIXME: maybe this isn't even needed anymore... + path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", + name_esc_ma, name_esc_tex, basepath); + + /* free old one */ + if (basepath != base_path) + MEM_freeN(basepath); + } + break; + } + } + + /* fix RNA pointer, as we've now changed the ID root by changing the paths */ + if (basepath != path) { + /* rebase provided pointer so that it starts from object... */ + RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr); + } + } + } + + /* the path should now have been corrected for use */ + return path; +} + /* Path Validation -------------------------------------------- */ /* Check if a given RNA Path is valid, by tracing it from the given ID, and seeing if we can resolve it */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 16b5574709e..bb05b5de8a6 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -505,7 +505,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB invert_m3_m3(imat3, mat3); mul_m3_m3m3(mat3, result, imat3); /* the matrix transforming vec_roll to desired roll */ - roll1 = (float)atan2(mat3[2][0], mat3[2][2]); + roll1 = atan2f(mat3[2][0], mat3[2][2]); } } else { @@ -543,7 +543,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB invert_m3_m3(imat3, mat3); mul_m3_m3m3(mat3, imat3, result); /* the matrix transforming vec_roll to desired roll */ - roll2 = (float)atan2(mat3[2][0], mat3[2][2]); + roll2 = atan2f(mat3[2][0], mat3[2][2]); /* and only now negate handle */ mul_v3_fl(h2, -hlength2); diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 6ce3abe7a32..1402f62291f 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -232,7 +232,7 @@ void BKE_camera_params_from_object(CameraParams *params, Object *ob) /* lamp object */ Lamp *la = ob->data; float fac = cosf(la->spotsize * 0.5f); - float phi = acos(fac); + float phi = acosf(fac); params->lens = 16.0f * fac / sinf(phi); if (params->lens == 0.0f) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 08052127fbf..bfc70c91181 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -552,7 +552,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, MVert *mvert = cddm->mvert; MFace *mface = cddm->mface; const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL); - short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1; if (cddm->pbvh && cddm->pbvh_draw) { @@ -673,9 +673,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, { CDDerivedMesh *cddm = (CDDerivedMesh *) dm; MVert *mv = cddm->mvert; - MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE); + const MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE); const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL); - short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); MCol *mcol; int i, orig; @@ -940,7 +940,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, MFace *mf = cddm->mface; MCol *mcol; const float *nors = DM_get_tessface_data_layer(dm, CD_NORMAL); - short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); int colType, useColors = flag & DM_DRAW_USE_COLORS; int i, orig; @@ -1157,8 +1157,8 @@ static void cdDM_drawMappedFacesTex(DerivedMesh *dm, cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag); } -static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert, - short (*lnor)[3], int smoothnormal) +static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int vert, + const short (*lnor)[3], const bool smoothnormal) { const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; int b; @@ -1234,11 +1234,11 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, CDDerivedMesh *cddm = (CDDerivedMesh *) dm; GPUVertexAttribs gattribs; DMVertexAttribs attribs; - MVert *mvert = cddm->mvert; - MFace *mface = cddm->mface; + const MVert *mvert = cddm->mvert; + const MFace *mface = cddm->mface; /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ - float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); - short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + const float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); + const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); int a, b, matnr, new_matnr; bool do_draw; int orig; @@ -1277,8 +1277,8 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, glBegin(GL_QUADS); for (a = 0; a < dm->numTessFaceData; a++, mface++) { - const int smoothnormal = lnors || (mface->flag & ME_SMOOTH); - short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL; + const bool smoothnormal = lnors || (mface->flag & ME_SMOOTH); + const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL; new_matnr = mface->mat_nr + 1; if (new_matnr != matnr) { @@ -1323,13 +1323,11 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, glNormal3fv(nor); } } - - if (lnors) { - ln1 = &lnors[0][0]; - ln2 = &lnors[0][1]; - ln3 = &lnors[0][2]; - ln4 = &lnors[0][3]; - lnors++; + else if (lnors) { + ln1 = &lnors[a][0]; + ln2 = &lnors[a][1]; + ln3 = &lnors[a][2]; + ln4 = &lnors[a][3]; } cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, ln1, smoothnormal); @@ -1350,7 +1348,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int start = 0, numfaces = 0 /* , prevdraw = 0 */ /* UNUSED */, curface = 0; int i; - MFace *mf = mface; + const MFace *mf = mface; GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/ memset(&attribs, 0, sizeof(attribs)); @@ -1574,8 +1572,8 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, DMVertexAttribs attribs; MVert *mvert = cddm->mvert; MFace *mf = cddm->mface; - float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); - short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); + const float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); + const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); int a, matnr, new_matnr; int orig; @@ -1610,8 +1608,8 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, glBegin(GL_QUADS); for (a = 0; a < dm->numTessFaceData; a++, mf++) { - const int smoothnormal = lnors || (mf->flag & ME_SMOOTH); - short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL; + const bool smoothnormal = lnors || (mf->flag & ME_SMOOTH); + const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL; /* material */ new_matnr = mf->mat_nr + 1; @@ -1650,13 +1648,11 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, glNormal3fv(nor); } } - - if (lnors) { - ln1 = &lnors[0][0]; - ln2 = &lnors[0][1]; - ln3 = &lnors[0][2]; - ln4 = &lnors[0][3]; - lnors++; + else if (lnors) { + ln1 = &lnors[a][0]; + ln2 = &lnors[a][1]; + ln3 = &lnors[a][2]; + ln4 = &lnors[a][3]; } /* vertices */ @@ -2720,7 +2716,7 @@ static unsigned int poly_gset_hash_fn(const void *key) return pk->hash_sum; } -static int poly_gset_compare_fn(const void *k1, const void *k2) +static bool poly_gset_compare_fn(const void *k1, const void *k2) { const PolyKey *pk1 = k1; const PolyKey *pk2 = k2; @@ -3017,10 +3013,17 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int if (UNLIKELY(c == 0)) { continue; } + else if (UNLIKELY(c < 3)) { + STACK_DISCARD(oldl, c); + STACK_DISCARD(mloop, c); + continue; + } + mp_new = STACK_PUSH_RET_PTR(mpoly); *mp_new = *mp; mp_new->totloop = c; + BLI_assert(mp_new->totloop >= 3); mp_new->loopstart = STACK_SIZE(mloop) - c; STACK_PUSH(oldp, i); @@ -3091,7 +3094,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int MEM_freeN(oldv); MEM_freeN(olde); MEM_freeN(oldl); - MEM_freeN(oldp);; + MEM_freeN(oldp); BLI_edgehash_free(ehash, NULL); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 885f186faf3..aacf02555d4 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -228,7 +228,7 @@ void bvhtree_update_from_cloth(ClothModifierData *clmd, int moving) ClothVertex *verts = cloth->verts; MFace *mfaces; float co[12], co_moving[12]; - int ret = 0; + bool ret = false; if (!bvhtree) return; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index cedd9eae597..2f600935b1e 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -110,7 +110,7 @@ void bvhtree_update_from_mvert(BVHTree *bvhtree, MFace *faces, int numfaces, MVe int i; MFace *mfaces = faces; float co[12], co_moving[12]; - int ret = 0; + bool ret = false; if ( !bvhtree ) return; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index c6d07a959d1..a63e06c7cb8 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -577,14 +577,14 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr) /* store first and last handle for extrapolation, unit length */ cuma->ext_in[0] = bezt[0].vec[0][0] - bezt[0].vec[1][0]; cuma->ext_in[1] = bezt[0].vec[0][1] - bezt[0].vec[1][1]; - range = sqrt(cuma->ext_in[0] * cuma->ext_in[0] + cuma->ext_in[1] * cuma->ext_in[1]); + range = sqrtf(cuma->ext_in[0] * cuma->ext_in[0] + cuma->ext_in[1] * cuma->ext_in[1]); cuma->ext_in[0] /= range; cuma->ext_in[1] /= range; a = cuma->totpoint - 1; cuma->ext_out[0] = bezt[a].vec[1][0] - bezt[a].vec[2][0]; cuma->ext_out[1] = bezt[a].vec[1][1] - bezt[a].vec[2][1]; - range = sqrt(cuma->ext_out[0] * cuma->ext_out[0] + cuma->ext_out[1] * cuma->ext_out[1]); + range = sqrtf(cuma->ext_out[0] * cuma->ext_out[0] + cuma->ext_out[1] * cuma->ext_out[1]); cuma->ext_out[0] /= range; cuma->ext_out[1] /= range; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index d80529ee780..ee7bad773fa 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3592,7 +3592,7 @@ static void damptrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t cross_v3_v3v3(raxis, obvec, tarvec); rangle = dot_v3v3(obvec, tarvec); - rangle = acos(max_ff(-1.0f, min_ff(1.0f, rangle))); + rangle = acosf(max_ff(-1.0f, min_ff(1.0f, rangle))); /* construct rotation matrix from the axis-angle rotation found above * - this call takes care to make sure that the axis provided is a unit vector first diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index a06834f61b3..ca58035d638 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -2468,7 +2468,7 @@ static void make_bevel_list_2D(BevList *bl) /* first */ bevp = bl->bevpoints; - angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0; + angle = atan2f(bevp->dir[0], bevp->dir[1]) - (float)(M_PI / 2.0f); bevp->sina = sinf(angle); bevp->cosa = cosf(angle); vec_to_quat(bevp->quat, bevp->dir, 5, 1); @@ -2476,7 +2476,7 @@ static void make_bevel_list_2D(BevList *bl) /* last */ bevp = bl->bevpoints; bevp += (bl->nr - 1); - angle = atan2(bevp->dir[0], bevp->dir[1]) - M_PI / 2.0; + angle = atan2f(bevp->dir[0], bevp->dir[1]) - (float)(M_PI / 2.0f); bevp->sina = sinf(angle); bevp->cosa = cosf(angle); vec_to_quat(bevp->quat, bevp->dir, 5, 1); @@ -2590,7 +2590,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) if (nu->type == CU_POLY) { len = nu->pntsu; bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2"); - if (need_seglen) { + if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList2_seglen"); bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList2_segbevcount"); } @@ -2613,7 +2613,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) bevp->weight = bp->weight; bevp->split_tag = true; bp++; - if (seglen != NULL) { + if (seglen != NULL && len != 0) { *seglen = len_v3v3(bevp->vec, bp->vec); bevp++; bevp->offset = *seglen; @@ -2629,11 +2629,6 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) if ((nu->flagu & CU_NURB_CYCLIC) == 0) { bevlist_firstlast_direction_calc_from_bpoint(nu, bl); - if (seglen != NULL) { - *seglen = len_v3v3(bevp->vec, nu->bp->vec); - bl->bevpoints->offset = *seglen; - *segbevcount = 1; - } } } else if (nu->type == CU_BEZIER) { @@ -2641,7 +2636,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) len = segcount * resolu + 1; bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints"); - if (need_seglen) { + if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelBPoints_seglen"); bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelBPoints_segbevcount"); } @@ -2777,7 +2772,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) len = (resolu * segcount); bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3"); - if (need_seglen) { + if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { bl->seglen = MEM_mallocN(segcount * sizeof(float), "makeBevelList3_seglen"); bl->segbevcount = MEM_mallocN(segcount * sizeof(int), "makeBevelList3_segbevcount"); } diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index ab3cf5851e9..63eb3b397b0 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -2554,12 +2554,12 @@ void CustomData_bmesh_free_block(CustomData *data, void **block) /** * Same as #CustomData_bmesh_free_block but zero the memory rather then freeing. */ -void CustomData_bmesh_free_block_data(CustomData *data, void **block) +void CustomData_bmesh_free_block_data(CustomData *data, void *block) { const LayerTypeInfo *typeInfo; int i; - if (*block == NULL) + if (block == NULL) return; for (i = 0; i < data->totlayer; ++i) { @@ -2568,13 +2568,13 @@ void CustomData_bmesh_free_block_data(CustomData *data, void **block) if (typeInfo->free) { int offset = data->layers[i].offset; - typeInfo->free((char *)*block + offset, 1, typeInfo->size); + typeInfo->free((char *)block + offset, 1, typeInfo->size); } } } if (data->totsize) - memset(*block, 0, data->totsize); + memset(block, 0, data->totsize); } static void CustomData_bmesh_alloc_block(CustomData *data, void **block) diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 93bb4849718..44a0b93fc01 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -75,6 +75,7 @@ #include "BKE_mball.h" #include "BKE_modifier.h" #include "BKE_object.h" +#include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_scene.h" @@ -2509,6 +2510,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id) obt = sce->basact ? sce->basact->object : NULL; if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) { BKE_texpaint_slots_refresh_object(sce, obt); + BKE_paint_proj_mesh_data_check(sce, obt, NULL, NULL, NULL, NULL); GPU_drawobject_free(obt->derivedFinal); } } diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 24ee470eaa7..ced9da8d0b1 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -872,7 +872,7 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected case PFIELD_HARMONIC: mul_v3_fl(force, -strength * efd->falloff); copy_v3_v3(temp, point->vel); - mul_v3_fl(temp, -damp * 2.0f * (float)sqrt(fabs(strength)) * point->vel_to_sec); + mul_v3_fl(temp, -damp * 2.0f * sqrtf(fabsf(strength)) * point->vel_to_sec); add_v3_v3(force, temp); break; case PFIELD_CHARGE: diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 09c1dcf701d..e90a0891436 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -55,6 +55,7 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_constraint.h" +#include "BKE_context.h" #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_object.h" @@ -310,19 +311,35 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, bool *r_driven) { + return rna_get_fcurve_context_ui(NULL, ptr, prop, rnaindex, action, r_driven); +} + +FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, + bAction **action, bool *r_driven) +{ FCurve *fcu = NULL; + PointerRNA tptr = *ptr; *r_driven = false; /* there must be some RNA-pointer + property combon */ - if (prop && ptr->id.data && RNA_property_animateable(ptr, prop)) { - AnimData *adt = BKE_animdata_from_id(ptr->id.data); - char *path; + if (prop && tptr.id.data && RNA_property_animateable(&tptr, prop)) { + AnimData *adt = BKE_animdata_from_id(tptr.id.data); + int step = C ? 2 : 1; /* Always 1 in case we have no context (can't check in 'ancestors' of given RNA ptr). */ + char *path = NULL; - if (adt) { + if (!adt && C) { + path = BKE_animdata_driver_path_hack(C, &tptr, prop, NULL); + adt = BKE_animdata_from_id(tptr.id.data); + step--; + } + + while (adt && step--) { if ((adt->action && adt->action->curves.first) || (adt->drivers.first)) { /* XXX this function call can become a performance bottleneck */ - path = RNA_path_from_ID_to_property(ptr, prop); + if (step) { + path = RNA_path_from_ID_to_property(&tptr, prop); + } if (path) { /* animation takes priority over drivers */ @@ -337,13 +354,25 @@ FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction *r_driven = true; } - if (fcu && action) + if (fcu && action) { *action = adt->action; - - MEM_freeN(path); + break; + } + else if (step) { + char *tpath = BKE_animdata_driver_path_hack(C, &tptr, prop, path); + if (tpath && tpath != path) { + MEM_freeN(path); + path = tpath; + adt = BKE_animdata_from_id(tptr.id.data); + } + else { + adt = NULL; + } + } } } } + MEM_SAFE_FREE(path); } return fcu; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 805c1250c5d..5c673eeef3f 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -62,6 +62,7 @@ #include "DNA_meshdata_types.h" #include "BLI_blenlib.h" +#include "BLI_math_vector.h" #include "BLI_threads.h" #include "BLI_timecode.h" /* for stamp timecode format */ #include "BLI_utildefines.h" @@ -120,12 +121,12 @@ static unsigned int imagecache_hashhash(const void *key_v) return key->index; } -static int imagecache_hashcmp(const void *a_v, const void *b_v) +static bool imagecache_hashcmp(const void *a_v, const void *b_v) { const ImageCacheKey *a = (ImageCacheKey *) a_v; const ImageCacheKey *b = (ImageCacheKey *) b_v; - return a->index - b->index; + return (a->index != b->index); } static void imagecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags) @@ -365,6 +366,7 @@ Image *BKE_image_copy(Main *bmain, Image *ima) nima->gen_x = ima->gen_x; nima->gen_y = ima->gen_y; nima->gen_type = ima->gen_type; + copy_v4_v4(nima->gen_color, ima->gen_color); nima->animspeed = ima->animspeed; @@ -769,6 +771,7 @@ Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int hei ima->gen_type = gen_type; ima->gen_flag |= (floatbuf ? IMA_GEN_FLOAT : 0); ima->gen_depth = depth; + copy_v4_v4(ima->gen_color, color); ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, gen_type, color, &ima->colorspace_settings); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); @@ -2996,7 +2999,6 @@ BLI_INLINE bool image_quick_test(Image *ima, ImageUser *iuser) static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { ImBuf *ibuf = NULL; - float color[] = {0, 0, 0, 1}; int frame = 0, index = 0; if (lock_r) @@ -3041,7 +3043,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) if (ima->gen_y == 0) ima->gen_y = 1024; if (ima->gen_depth == 0) ima->gen_depth = 24; ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, ima->gen_depth, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, - color, &ima->colorspace_settings); + ima->gen_color, &ima->colorspace_settings); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); ima->ok = IMA_OK_LOADED; } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 4d80256426d..4cf9d52989f 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1236,7 +1236,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, sub_v3_v3v3(extent, X[s->kl], X[s->ij]); sub_v3_v3v3(vel, V[s->kl], V[s->ij]); dot = dot_v3v3(extent, extent); - length = sqrt(dot); + length = sqrtf(dot); s->flags &= ~CLOTH_SPRING_FLAG_NEEDED; diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 749e915e5ca..4a413850ec0 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -135,8 +135,7 @@ Lamp *localize_lamp(Lamp *la) Lamp *lan; int a; - lan = BKE_libblock_copy(&la->id); - BLI_remlink(&G.main->lamp, lan); + lan = BKE_libblock_copy_nolib(&la->id, false); for (a = 0; a < MAX_MTEX; a++) { if (lan->mtex[a]) { diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 515287de336..b49eee3ea22 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -620,6 +620,8 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a] = NULL; + BLI_assert(a + 1 == MAX_LIBARRAY); + return a; } diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 45695844101..5e17117a875 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -93,6 +93,7 @@ static void default_linestyle_settings(FreestyleLineStyle *linestyle) linestyle->min_length = 0.0f; linestyle->max_length = 10000.0f; linestyle->split_length = 100; + linestyle->chain_count = 10; linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA; linestyle->integration_type = LS_INTEGRATION_MEAN; linestyle->texstep = 1.0f; @@ -186,6 +187,7 @@ FreestyleLineStyle *BKE_linestyle_copy(FreestyleLineStyle *linestyle) new_linestyle->max_angle = linestyle->max_angle; new_linestyle->min_length = linestyle->min_length; new_linestyle->max_length = linestyle->max_length; + new_linestyle->chain_count = linestyle->chain_count; new_linestyle->split_dash1 = linestyle->split_dash1; new_linestyle->split_gap1 = linestyle->split_gap1; new_linestyle->split_dash2 = linestyle->split_dash2; diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 1c40446c217..83ad2f1b2d2 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1821,10 +1821,10 @@ void BKE_mask_layer_shape_unlink(MaskLayer *masklay, MaskLayerShape *masklay_sha BKE_mask_layer_shape_free(masklay_shape); } -static int mask_layer_shape_sort_cb(void *masklay_shape_a_ptr, void *masklay_shape_b_ptr) +static int mask_layer_shape_sort_cb(const void *masklay_shape_a_ptr, const void *masklay_shape_b_ptr) { - MaskLayerShape *masklay_shape_a = (MaskLayerShape *)masklay_shape_a_ptr; - MaskLayerShape *masklay_shape_b = (MaskLayerShape *)masklay_shape_b_ptr; + const MaskLayerShape *masklay_shape_a = masklay_shape_a_ptr; + const MaskLayerShape *masklay_shape_b = masklay_shape_b_ptr; if (masklay_shape_a->frame < masklay_shape_b->frame) return -1; else if (masklay_shape_a->frame > masklay_shape_b->frame) return 1; diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 35bf453c328..e28adb7c0e0 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -406,27 +406,14 @@ static unsigned int moviecache_hashhash(const void *keyv) return rval; } -static int moviecache_hashcmp(const void *av, const void *bv) +static bool moviecache_hashcmp(const void *av, const void *bv) { const MovieClipImBufCacheKey *a = (MovieClipImBufCacheKey *)av; const MovieClipImBufCacheKey *b = (MovieClipImBufCacheKey *)bv; - if (a->framenr < b->framenr) - return -1; - else if (a->framenr > b->framenr) - return 1; - - if (a->proxy < b->proxy) - return -1; - else if (a->proxy > b->proxy) - return 1; - - if (a->render_flag < b->render_flag) - return -1; - else if (a->render_flag > b->render_flag) - return 1; - - return 0; + return ((a->framenr != b->framenr) || + (a->proxy != b->proxy) || + (a->render_flag != b->render_flag)); } static void *moviecache_getprioritydata(void *key_v) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 0f86b551092..3a7bfb03e07 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2682,16 +2682,12 @@ static unsigned int node_instance_hash_key(const void *key) return ((const bNodeInstanceKey *)key)->value; } -static int node_instance_hash_key_cmp(const void *a, const void *b) +static bool node_instance_hash_key_cmp(const void *a, const void *b) { unsigned int value_a = ((const bNodeInstanceKey *)a)->value; unsigned int value_b = ((const bNodeInstanceKey *)b)->value; - if (value_a == value_b) - return 0; - else if (value_a < value_b) - return -1; - else - return 1; + + return (value_a != value_b); } bNodeInstanceHash *BKE_node_instance_hash_new(const char *info) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index b09016506e3..755ce91a8af 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1067,10 +1067,10 @@ void BKE_object_lod_add(Object *ob) BLI_addtail(&ob->lodlevels, lod); } -static int lod_cmp(void *a, void *b) +static int lod_cmp(const void *a, const void *b) { - LodLevel *loda = (LodLevel *)a; - LodLevel *lodb = (LodLevel *)b; + const LodLevel *loda = a; + const LodLevel *lodb = b; if (loda->distance < lodb->distance) return -1; return loda->distance > lodb->distance; @@ -3242,9 +3242,9 @@ bool BKE_boundbox_ray_hit_check( return result; } -static int pc_cmp(void *a, void *b) +static int pc_cmp(const void *a, const void *b) { - LinkData *ad = a, *bd = b; + const LinkData *ad = a, *bd = b; if (GET_INT_FROM_POINTER(ad->data) > GET_INT_FROM_POINTER(bd->data)) return 1; else return 0; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 4382d74f34e..d16575d80c8 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -315,8 +315,14 @@ void BKE_paint_curve_set(Brush *br, PaintCurve *pc) /* remove colour from palette. Must be certain color is inside the palette! */ void BKE_palette_color_remove(Palette *palette, PaletteColor *color) { - BLI_remlink(&palette->colors, color); - BLI_addhead(&palette->deleted, color); + if (color) { + int numcolors = BLI_countlist(&palette->colors); + if ((numcolors == palette->active_color + 1) && (numcolors != 1)) + palette->active_color--; + + BLI_remlink(&palette->colors, color); + BLI_addhead(&palette->deleted, color); + } } void BKE_palette_cleanup(Palette *palette) @@ -350,19 +356,6 @@ PaletteColor *BKE_palette_color_add(Palette *palette) return color; } -void BKE_palette_color_delete(struct Palette *palette) -{ - PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color); - - if (color) { - if ((color == palette->colors.last) && (palette->colors.last != palette->colors.first)) - palette->active_color--; - - BLI_remlink(&palette->colors, color); - BLI_addhead(&palette->deleted, color); - } -} - bool BKE_palette_is_empty(const struct Palette *palette) { @@ -493,7 +486,7 @@ void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_ sub_v2_v2v2(dpos, ups->last_rake, mouse_pos); if (len_squared_v2(dpos) >= r * r) { - ups->brush_rotation = atan2(dpos[0], dpos[1]); + ups->brush_rotation = atan2f(dpos[0], dpos[1]); interp_v2_v2v2(ups->last_rake, ups->last_rake, mouse_pos, u); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 27d346f65b9..530573d6e38 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -656,7 +656,7 @@ static float psys_render_projected_area(ParticleSystem *psys, const float center } /* screen space radius */ - radius = sqrt(area / (float)M_PI); + radius = sqrtf(area / (float)M_PI); /* make smaller using fallof once over screen edge */ *viewport = 1.0f; @@ -917,8 +917,8 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) elem->scalemax = (lambda + t < 1.0f) ? 1.0f / lambda : 1.0f / (1.0f - elem->t * elem->t / t); elem->scalemin = (lambda + t < 1.0f) ? 0.0f : elem->scalemax * (1.0f - elem->t / t); - elem->scalemin = sqrt(elem->scalemin); - elem->scalemax = sqrt(elem->scalemax); + elem->scalemin = sqrtf(elem->scalemin); + elem->scalemax = sqrtf(elem->scalemax); /* clamp scaling */ scaleclamp = (float)min_ii(elem->totchild, 10); @@ -939,8 +939,8 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) } elem->lambda = lambda; - elem->scalemin = sqrt(elem->scalemin); - elem->scalemax = sqrt(elem->scalemax); + elem->scalemin = sqrtf(elem->scalemin); + elem->scalemax = sqrtf(elem->scalemax); elem->curchild = 0; } @@ -1950,10 +1950,10 @@ static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float t = time * freq * (float)M_PI; if (smooth_start) { - dt = fabs(t); + dt = fabsf(t); /* smooth the beginning of kink */ CLAMP(dt, 0.f, (float)M_PI); - dt = sin(dt / 2.f); + dt = sinf(dt / 2.f); } if (type != PART_KINK_RADIAL) { @@ -2014,12 +2014,12 @@ static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float madd_v3_v3fl(result, proj, flat); } - madd_v3_v3fl(result, par_vec, -amplitude * (float)sin(t)); + madd_v3_v3fl(result, par_vec, -amplitude * sinf(t)); break; } case PART_KINK_WAVE: { - madd_v3_v3fl(result, kink, amplitude * (float)sin(t)); + madd_v3_v3fl(result, kink, amplitude * sinf(t)); if (flat > 0.f) { float proj[3]; @@ -2054,22 +2054,22 @@ static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float if (inp_y > 0.5f) { copy_v3_v3(state_co, y_vec); - mul_v3_fl(y_vec, amplitude * (float)cos(t)); - mul_v3_fl(z_vec, amplitude / 2.f * (float)sin(2.f * t)); + mul_v3_fl(y_vec, amplitude * cosf(t)); + mul_v3_fl(z_vec, amplitude / 2.f * sinf(2.f * t)); } else if (inp_z > 0.0f) { - mul_v3_v3fl(state_co, z_vec, (float)sin((float)M_PI / 3.f)); + mul_v3_v3fl(state_co, z_vec, sinf((float)M_PI / 3.f)); madd_v3_v3fl(state_co, y_vec, -0.5f); - mul_v3_fl(y_vec, -amplitude * (float)cos(t + (float)M_PI / 3.f)); - mul_v3_fl(z_vec, amplitude / 2.f * (float)cos(2.f * t + (float)M_PI / 6.f)); + mul_v3_fl(y_vec, -amplitude * cosf(t + (float)M_PI / 3.f)); + mul_v3_fl(z_vec, amplitude / 2.f * cosf(2.f * t + (float)M_PI / 6.f)); } else { - mul_v3_v3fl(state_co, z_vec, -(float)sin((float)M_PI / 3.f)); + mul_v3_v3fl(state_co, z_vec, -sinf((float)M_PI / 3.f)); madd_v3_v3fl(state_co, y_vec, -0.5f); - mul_v3_fl(y_vec, amplitude * (float)-sin(t + (float)M_PI / 6.f)); - mul_v3_fl(z_vec, amplitude / 2.f * (float)-sin(2.f * t + (float)M_PI / 3.f)); + mul_v3_fl(y_vec, amplitude * -sinf(t + (float)M_PI / 6.f)); + mul_v3_fl(z_vec, amplitude / 2.f * -sinf(2.f * t + (float)M_PI / 3.f)); } mul_v3_fl(state_co, amplitude); @@ -2271,8 +2271,11 @@ static void do_rough(float *loc, float mat[4][4], float t, float fac, float size float rough[3]; float rco[3]; - if (thres != 0.0f) - if ((float)fabs((float)(-1.5f + loc[0] + loc[1] + loc[2])) < 1.5f * thres) return; + if (thres != 0.0f) { + if (fabsf((float)(-1.5f + loc[0] + loc[1] + loc[2])) < 1.5f * thres) { + return; + } + } copy_v3_v3(rco, loc); mul_v3_fl(rco, t); @@ -4567,8 +4570,8 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa normalize_v3(nor); /* make sure that we get a proper side vector */ - if (fabs(dot_v3v3(nor, vec)) > 0.999999) { - if (fabs(dot_v3v3(nor, xvec)) > 0.999999) { + if (fabsf(dot_v3v3(nor, vec)) > 0.999999) { + if (fabsf(dot_v3v3(nor, xvec)) > 0.999999) { nor[0] = 0.0f; nor[1] = 1.0f; nor[2] = 0.0f; @@ -4676,12 +4679,12 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] copy_v3_v3(tvec, xvec); copy_v3_v3(tvec2, yvec); - mul_v3_fl(xvec, cos(bb->tilt * (float)M_PI)); - mul_v3_fl(tvec2, sin(bb->tilt * (float)M_PI)); + mul_v3_fl(xvec, cosf(bb->tilt * (float)M_PI)); + mul_v3_fl(tvec2, sinf(bb->tilt * (float)M_PI)); add_v3_v3(xvec, tvec2); - mul_v3_fl(yvec, cos(bb->tilt * (float)M_PI)); - mul_v3_fl(tvec, -sin(bb->tilt * (float)M_PI)); + mul_v3_fl(yvec, cosf(bb->tilt * (float)M_PI)); + mul_v3_fl(tvec, -sinf(bb->tilt * (float)M_PI)); add_v3_v3(yvec, tvec); mul_v3_fl(xvec, bb->size[0]); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 09e20c02691..155299b69c3 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -701,7 +701,7 @@ static void init_mv_jit(float *jit, int num, int seed2, float amount) rad1= (float)(1.0f/sqrtf((float)num)); rad2= (float)(1.0f/((float)num)); - rad3= (float)sqrt((float)num)/((float)num); + rad3= (float)sqrtf((float)num)/((float)num); rng = BLI_rng_new(31415926 + num + seed2); x= 0; diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 55653f41e75..1a0ddac03d7 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -823,15 +823,16 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, return any_subdivided; } -static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, - BMVert *v1, BMVert *v2, - GSet *deleted_verts, - BLI_Buffer *edge_loops, - BLI_Buffer *deleted_faces, - EdgeQueueContext *eq_ctx) +static void pbvh_bmesh_collapse_edge( + PBVH *bvh, BMEdge *e, + BMVert *v1, BMVert *v2, + GSet *deleted_verts, + BLI_Buffer *deleted_faces, + EdgeQueueContext *eq_ctx) { BMIter bm_iter; BMFace *f; + BMLoop *l_adj; BMVert *v_del, *v_conn; int i; float mask_v1 = BM_ELEM_CD_GET_FLOAT(v1, eq_ctx->cd_vert_mask_offset); @@ -846,15 +847,11 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, v_conn = v1; } - /* Get all faces adjacent to the edge */ - pbvh_bmesh_edge_loops(edge_loops, e); - /* Remove the merge vertex from the PBVH */ pbvh_bmesh_vert_remove(bvh, v_del, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset); /* Remove all faces adjacent to the edge */ - for (i = 0; i < edge_loops->count; i++) { - BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i); + while ((l_adj = e->l)) { BMFace *f_adj = l_adj->f; pbvh_bmesh_face_remove(bvh, f_adj, eq_ctx->cd_vert_node_offset, eq_ctx->cd_face_node_offset); @@ -973,10 +970,10 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BM_vert_kill(bvh->bm, v_del); } -static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, - PBVH *bvh, - BLI_Buffer *edge_loops, - BLI_Buffer *deleted_faces) +static bool pbvh_bmesh_collapse_short_edges( + EdgeQueueContext *eq_ctx, + PBVH *bvh, + BLI_Buffer *deleted_faces) { float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; GSet *deleted_verts; @@ -1020,7 +1017,7 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, any_collapsed = true; pbvh_bmesh_collapse_edge(bvh, e, v1, v2, - deleted_verts, edge_loops, + deleted_verts, deleted_faces, eq_ctx); } @@ -1214,7 +1211,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, const float center[3], float radius) { /* 2 is enough for edge faces - manifold edge */ - BLI_buffer_declare_static(BMFace *, edge_loops, BLI_BUFFER_NOP, 2); + BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2); BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32); const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK); const int cd_vert_node_offset = bvh->cd_vert_node_offset; @@ -1230,7 +1227,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, short_edge_queue_create(&eq_ctx, bvh, center, radius); modified |= !BLI_heap_is_empty(q.heap); - pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &edge_loops, + pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &deleted_faces); BLI_heap_free(q.heap, NULL); BLI_mempool_destroy(queue_pool); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 063a81e6efb..a6a7664ec61 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -85,11 +85,12 @@ #ifdef WITH_LZO #include "minilzo.h" -#else -/* used for non-lzo cases */ -#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3) +#define LZO_HEAP_ALLOC(var,size) \ + lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] #endif +#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3) + #ifdef WITH_LZMA #include "LzmaLib.h" #endif diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index eb98e381222..5bfd6e8a120 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -93,9 +93,6 @@ #include "bmesh.h" -//XXX #include "BIF_previewrender.h" -//XXX #include "BIF_editseq.h" - #ifdef WIN32 #else # include <sys/time.h> @@ -521,6 +518,9 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->r.preview_start_resolution = 64; + sce->r.line_thickness_mode = R_LINE_THICKNESS_ABSOLUTE; + sce->r.unit_line_thickness = 1.0f; + sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct"); sce->toolsettings->doublimit = 0.001; sce->toolsettings->uvcalc_margin = 0.001f; @@ -1991,14 +1991,13 @@ double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, doubl switch (unit_type) { case B_UNIT_LENGTH: return value * (double)unit->scale_length; - case B_UNIT_CAMERA: - return value * (double)unit->scale_length; case B_UNIT_AREA: return value * pow(unit->scale_length, 2); case B_UNIT_VOLUME: return value * pow(unit->scale_length, 3); case B_UNIT_MASS: return value * pow(unit->scale_length, 3); + case B_UNIT_CAMERA: /* *Do not* use scene's unit scale for camera focal lens! See T42026. */ default: return value; } diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index 97062f728c5..4268b33cb14 100644 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -69,58 +69,15 @@ static struct SeqPreprocessCache *preprocess_cache = NULL; static void preprocessed_cache_destruct(void); -static int seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b) +static bool seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b) { - if (a->preview_render_size < b->preview_render_size) { - return -1; - } - if (a->preview_render_size > b->preview_render_size) { - return 1; - } - - if (a->rectx < b->rectx) { - return -1; - } - if (a->rectx > b->rectx) { - return 1; - } - - if (a->recty < b->recty) { - return -1; - } - if (a->recty > b->recty) { - return 1; - } - - if (a->bmain < b->bmain) { - return -1; - } - if (a->bmain > b->bmain) { - return 1; - } - - if (a->scene < b->scene) { - return -1; - } - if (a->scene > b->scene) { - return 1; - } - - if (a->motion_blur_shutter < b->motion_blur_shutter) { - return -1; - } - if (a->motion_blur_shutter > b->motion_blur_shutter) { - return 1; - } - - if (a->motion_blur_samples < b->motion_blur_samples) { - return -1; - } - if (a->motion_blur_samples > b->motion_blur_samples) { - return 1; - } - - return 0; + return ((a->preview_render_size != b->preview_render_size) || + (a->rectx != b->rectx) || + (a->recty != b->recty) || + (a->bmain != b->bmain) || + (a->scene != b->scene) || + (a->motion_blur_shutter != b->motion_blur_shutter) || + (a->motion_blur_samples != b->motion_blur_samples)); } static unsigned int seq_hash_render_data(const SeqRenderData *a) @@ -148,33 +105,15 @@ static unsigned int seqcache_hashhash(const void *key_) return rval; } -static int seqcache_hashcmp(const void *a_, const void *b_) +static bool seqcache_hashcmp(const void *a_, const void *b_) { const SeqCacheKey *a = (SeqCacheKey *) a_; const SeqCacheKey *b = (SeqCacheKey *) b_; - if (a->seq < b->seq) { - return -1; - } - if (a->seq > b->seq) { - return 1; - } - - if (a->cfra < b->cfra) { - return -1; - } - if (a->cfra > b->cfra) { - return 1; - } - - if (a->type < b->type) { - return -1; - } - if (a->type > b->type) { - return 1; - } - - return seq_cmp_render_data(&a->context, &b->context); + return ((a->seq != b->seq) || + (a->cfra != b->cfra) || + (a->type != b->type) || + seq_cmp_render_data(&a->context, &b->context)); } void BKE_sequencer_cache_destruct(void) diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index a8e578eae0d..11a6cb7acc3 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -1322,7 +1322,7 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f if (angle == 0.0f) { b1 = posy; b2 = y; - hyp = fabs(y - posy); + hyp = fabsf(y - posy); } else { b1 = posy - (-angle) * posx; @@ -1745,8 +1745,8 @@ static void transform_image(int x, int y, ImBuf *ibuf1, ImBuf *out, float scale yo = y; /* Rotate */ - s = sin(rotate); - c = cos(rotate); + s = sinf(rotate); + c = cosf(rotate); for (yi = 0; yi < yo; yi++) { for (xi = 0; xi < xo; xi++) { diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 9c411142566..13575560669 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -2160,7 +2160,7 @@ static void sb_spring_force(Object *ob, int bpi, BodySpring *bs, float iks, floa // dfdx_spring(ia, ia, op, dir, bs->len, distance, -mpos); /* depending on my vel */ // dfdv_goal(ia, ia, mvel); // well that ignores geometie - if (bp2->goal < SOFTGOALSNAP) { /* ommit this bp when it snaps */ + if (bp2->goal < SOFTGOALSNAP) { /* omit this bp when it snaps */ /* depending on other pos */ // dfdx_spring(ia, ic, op, dir, bs->len, distance, mpos); /* depending on other vel */ @@ -2257,7 +2257,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo } /* naive ball self collision done */ - if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* ommit this bp when it snaps */ + if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* omit this bp when it snaps */ float auxvect[3]; float velgoal[3]; @@ -2652,7 +2652,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa } /* naive ball self collision done */ - if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* ommit this bp when it snaps */ + if (_final_goal(ob, bp) < SOFTGOALSNAP) { /* omit this bp when it snaps */ float auxvect[3]; float velgoal[3]; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 4cd85fb342e..8a272cd9d81 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -267,16 +267,79 @@ static void cleanup_textline(TextLine *tl) tl->len += txt_extended_ascii_as_utf8(&tl->line); } +/** + * used for load and reload (unlike txt_insert_buf) + * assumes all fields are empty + */ +static void text_from_buf(Text *text, const unsigned char *buffer, const int len) +{ + int i, llen; + + BLI_assert(BLI_listbase_is_empty(&text->lines)); + + text->nlines = 0; + llen = 0; + for (i = 0; i < len; i++) { + if (buffer[i] == '\n') { + TextLine *tmp; + + tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); + tmp->format = NULL; + + if (llen) memcpy(tmp->line, &buffer[i - llen], llen); + tmp->line[llen] = 0; + tmp->len = llen; + + cleanup_textline(tmp); + + BLI_addtail(&text->lines, tmp); + text->nlines++; + + llen = 0; + continue; + } + llen++; + } + + /* create new line in cases: + * - rest of line (if last line in file hasn't got \n terminator). + * in this case content of such line would be used to fill text line buffer + * - file is empty. in this case new line is needed to start editing from. + * - last characted in buffer is \n. in this case new line is needed to + * deal with newline at end of file. (see [#28087]) (sergey) */ + if (llen != 0 || text->nlines == 0 || buffer[len - 1] == '\n') { + TextLine *tmp; + + tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); + tmp->format = NULL; + + if (llen) memcpy(tmp->line, &buffer[i - llen], llen); + + tmp->line[llen] = 0; + tmp->len = llen; + + cleanup_textline(tmp); + + BLI_addtail(&text->lines, tmp); + text->nlines++; + } + + text->curl = text->sell = text->lines.first; + text->curc = text->selc = 0; +} + int BKE_text_reload(Text *text) { FILE *fp; - int i, llen, len; + int len; unsigned char *buffer; TextLine *tmp; char str[FILE_MAX]; - struct stat st; + BLI_stat_t st; - if (!text || !text->name) return 0; + if (!text->name) return 0; BLI_strncpy(str, text->name, FILE_MAX); BLI_path_abs(str, G.main->name); @@ -299,13 +362,12 @@ int BKE_text_reload(Text *text) /* clear undo buffer */ MEM_freeN(text->undo_buf); init_undo_text(text); - + fseek(fp, 0L, SEEK_END); len = ftell(fp); fseek(fp, 0L, SEEK_SET); - text->undo_pos = -1; - + buffer = MEM_mallocN(len, "text_buffer"); // under windows fread can return less then len bytes because // of CR stripping @@ -313,51 +375,11 @@ int BKE_text_reload(Text *text) fclose(fp); - stat(str, &st); + BLI_stat(str, &st); text->mtime = st.st_mtime; - - text->nlines = 0; - llen = 0; - for (i = 0; i < len; i++) { - if (buffer[i] == '\n') { - tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); - tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); - tmp->format = NULL; - - if (llen) memcpy(tmp->line, &buffer[i - llen], llen); - tmp->line[llen] = 0; - tmp->len = llen; - - cleanup_textline(tmp); - BLI_addtail(&text->lines, tmp); - text->nlines++; - - llen = 0; - continue; - } - llen++; - } + text_from_buf(text, buffer, len); - if (llen != 0 || text->nlines == 0) { - tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); - tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); - tmp->format = NULL; - - if (llen) memcpy(tmp->line, &buffer[i - llen], llen); - - tmp->line[llen] = 0; - tmp->len = llen; - - cleanup_textline(tmp); - - BLI_addtail(&text->lines, tmp); - text->nlines++; - } - - text->curl = text->sell = text->lines.first; - text->curc = text->selc = 0; - MEM_freeN(buffer); return 1; } @@ -365,12 +387,11 @@ int BKE_text_reload(Text *text) Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const bool is_internal) { FILE *fp; - int i, llen, len; + int len; unsigned char *buffer; - TextLine *tmp; Text *ta; char str[FILE_MAX]; - struct stat st; + BLI_stat_t st; BLI_strncpy(str, file, FILE_MAX); if (relpath) /* can be NULL (bg mode) */ @@ -388,10 +409,6 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE) == 0) ta->flags = TXT_TABSTOSPACES; - fseek(fp, 0L, SEEK_END); - len = ftell(fp); - fseek(fp, 0L, SEEK_SET); - if (is_internal == false) { ta->name = MEM_mallocN(strlen(file) + 1, "text_name"); strcpy(ta->name, file); @@ -400,7 +417,12 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const ta->flags |= TXT_ISMEM | TXT_ISDIRTY; } + /* clear undo buffer */ init_undo_text(ta); + + fseek(fp, 0L, SEEK_END); + len = ftell(fp); + fseek(fp, 0L, SEEK_SET); buffer = MEM_mallocN(len, "text_buffer"); // under windows fread can return less then len bytes because @@ -409,56 +431,10 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const fclose(fp); - stat(str, &st); + BLI_stat(str, &st); ta->mtime = st.st_mtime; - ta->nlines = 0; - llen = 0; - for (i = 0; i < len; i++) { - if (buffer[i] == '\n') { - tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); - tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); - tmp->format = NULL; - - if (llen) memcpy(tmp->line, &buffer[i - llen], llen); - tmp->line[llen] = 0; - tmp->len = llen; - - cleanup_textline(tmp); - - BLI_addtail(&ta->lines, tmp); - ta->nlines++; - - llen = 0; - continue; - } - llen++; - } - - /* create new line in cases: - * - rest of line (if last line in file hasn't got \n terminator). - * in this case content of such line would be used to fill text line buffer - * - file is empty. in this case new line is needed to start editing from. - * - last characted in buffer is \n. in this case new line is needed to - * deal with newline at end of file. (see [#28087]) (sergey) */ - if (llen != 0 || ta->nlines == 0 || buffer[len - 1] == '\n') { - tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); - tmp->line = (char *) MEM_mallocN(llen + 1, "textline_string"); - tmp->format = NULL; - - if (llen) memcpy(tmp->line, &buffer[i - llen], llen); - - tmp->line[llen] = 0; - tmp->len = llen; - - cleanup_textline(tmp); - - BLI_addtail(&ta->lines, tmp); - ta->nlines++; - } - - ta->curl = ta->sell = ta->lines.first; - ta->curc = ta->selc = 0; + text_from_buf(ta, buffer, len); MEM_freeN(buffer); @@ -671,7 +647,7 @@ int BKE_text_file_modified_check(Text *text) int result; char file[FILE_MAX]; - if (!text || !text->name) + if (!text->name) return 0; BLI_strncpy(file, text->name, FILE_MAX); @@ -700,7 +676,7 @@ void BKE_text_file_modified_ignore(Text *text) int result; char file[FILE_MAX]; - if (!text || !text->name) return; + if (!text->name) return; BLI_strncpy(file, text->name, FILE_MAX); BLI_path_abs(file, G.main->name); @@ -766,9 +742,7 @@ static TextLine *txt_new_linen(const char *str, int n) void txt_clean_text(Text *text) { TextLine **top, **bot; - - if (!text) return; - + if (!text->lines.first) { if (text->lines.last) text->lines.first = text->lines.last; else text->lines.first = text->lines.last = txt_new_line(NULL); @@ -907,8 +881,7 @@ void txt_move_up(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -930,8 +903,7 @@ void txt_move_down(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -953,8 +925,7 @@ void txt_move_left(Text *text, const bool sel) TextLine **linep; int *charp; int tabsize = 0, i = 0; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -998,8 +969,7 @@ void txt_move_right(Text *text, const bool sel) TextLine **linep; int *charp, i; bool do_tab = false; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -1040,8 +1010,7 @@ void txt_jump_left(Text *text, const bool sel, const bool use_init_step) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -1057,8 +1026,7 @@ void txt_jump_right(Text *text, const bool sel, const bool use_init_step) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; @@ -1074,8 +1042,7 @@ void txt_move_bol(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; @@ -1089,8 +1056,7 @@ void txt_move_eol(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; @@ -1104,8 +1070,7 @@ void txt_move_bof(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; @@ -1120,8 +1085,7 @@ void txt_move_eof(Text *text, const bool sel) { TextLine **linep; int *charp; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; @@ -1143,8 +1107,7 @@ void txt_move_to(Text *text, unsigned int line, unsigned int ch, const bool sel) TextLine **linep; int *charp; unsigned int i; - - if (!text) return; + if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; @@ -1181,7 +1144,6 @@ static void txt_curs_swap(Text *text) static void txt_pop_first(Text *text) { - if (txt_get_span(text->curl, text->sell) < 0 || (text->curl == text->sell && text->curc > text->selc)) { @@ -1210,7 +1172,6 @@ void txt_pop_sel(Text *text) void txt_order_cursors(Text *text, const bool reverse) { - if (!text) return; if (!text->curl) return; if (!text->sell) return; @@ -1240,8 +1201,7 @@ static void txt_delete_sel(Text *text) { TextLine *tmpl; char *buf; - - if (!text) return; + if (!text->curl) return; if (!text->sell) return; @@ -1277,8 +1237,6 @@ static void txt_delete_sel(Text *text) void txt_sel_all(Text *text) { - if (!text) return; - text->curl = text->lines.first; text->curc = 0; @@ -1301,7 +1259,6 @@ void txt_sel_clear(Text *text) void txt_sel_line(Text *text) { - if (!text) return; if (!text->curl) return; text->curc = 0; @@ -1319,8 +1276,7 @@ char *txt_to_buf(Text *text) TextLine *tmp, *linef, *linel; int charf, charl; char *buf; - - if (!text) return NULL; + if (!text->curl) return NULL; if (!text->sell) return NULL; if (!text->lines.first) return NULL; @@ -1382,7 +1338,7 @@ int txt_find_string(Text *text, const char *findstr, int wrap, int match_case) TextLine *tl, *startl; const char *s = NULL; - if (!text || !text->curl || !text->sell) return 0; + if (!text->curl || !text->sell) return 0; txt_order_cursors(text, false); @@ -1422,8 +1378,7 @@ char *txt_sel_to_buf(Text *text) int length = 0; TextLine *tmp, *linef, *linel; int charf, charl; - - if (!text) return NULL; + if (!text->curl) return NULL; if (!text->sell) return NULL; @@ -1504,7 +1459,6 @@ void txt_insert_buf(Text *text, const char *in_buffer) TextLine *add; char *buffer; - if (!text) return; if (!in_buffer) return; txt_delete_sel(text); @@ -2386,8 +2340,7 @@ void txt_split_curline(Text *text) { TextLine *ins; char *left, *right; - - if (!text) return; + if (!text->curl) return; txt_delete_sel(text); @@ -2429,7 +2382,6 @@ void txt_split_curline(Text *text) static void txt_delete_line(Text *text, TextLine *line) { - if (!text) return; if (!text->curl) return; BLI_remlink(&text->lines, line); @@ -2446,8 +2398,6 @@ static void txt_delete_line(Text *text, TextLine *line) static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb) { char *tmp, *s; - - if (!text) return; if (!linea || !lineb) return; @@ -2471,7 +2421,7 @@ void txt_duplicate_line(Text *text) { TextLine *textline; - if (!text || !text->curl) return; + if (!text->curl) return; if (text->curl == text->sell) { textline = txt_new_line(text->curl->line); @@ -2487,8 +2437,7 @@ void txt_duplicate_line(Text *text) void txt_delete_char(Text *text) { unsigned int c = '\n'; - - if (!text) return; + if (!text->curl) return; if (txt_has_sel(text)) { /* deleting a selection */ @@ -2531,7 +2480,6 @@ void txt_backspace_char(Text *text) { unsigned int c = '\n'; - if (!text) return; if (!text->curl) return; if (txt_has_sel(text)) { /* deleting a selection */ @@ -2595,8 +2543,7 @@ static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs) { char *tmp, ch[BLI_UTF8_MAX]; size_t add_len; - - if (!text) return 0; + if (!text->curl) return 0; if (add == '\n') { @@ -2655,8 +2602,7 @@ bool txt_replace_char(Text *text, unsigned int add) unsigned int del; size_t del_size = 0, add_size; char ch[BLI_UTF8_MAX]; - - if (!text) return 0; + if (!text->curl) return 0; /* If text is selected or we're at the end of the line just use txt_add_char */ @@ -2710,7 +2656,7 @@ void txt_indent(Text *text) /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; - if (ELEM(NULL, text, text->curl, text->sell)) { + if (ELEM(NULL, text->curl, text->sell)) { return; } @@ -2777,7 +2723,7 @@ void txt_unindent(Text *text) /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; - if (ELEM(NULL, text, text->curl, text->sell)) { + if (ELEM(NULL, text->curl, text->sell)) { return; } @@ -2830,8 +2776,7 @@ void txt_comment(Text *text) int len, num; char *tmp; char add = '#'; - - if (!text) return; + if (!text->curl) return; if (!text->sell) return; // Need to change this need to check if only one line is selected to more than one @@ -2878,8 +2823,7 @@ void txt_uncomment(Text *text) { int num = 0; char remove = '#'; - - if (!text) return; + if (!text->curl) return; if (!text->sell) return; @@ -2925,7 +2869,7 @@ void txt_move_lines(struct Text *text, const int direction) BLI_assert(ELEM(direction, TXT_MOVE_LINE_UP, TXT_MOVE_LINE_DOWN)); - if (!text || !text->curl || !text->sell) return; + if (!text->curl || !text->sell) return; txt_order_cursors(text, false); @@ -2958,6 +2902,7 @@ int txt_setcurr_tab_spaces(Text *text, int space) const char *comm = "#"; const char indent = (text->flags & TXT_TABSTOSPACES) ? ' ' : '\t'; static const char *back_words[] = {"return", "break", "continue", "pass", "yield", NULL}; + if (!text->curl) return 0; while (text->curl->line[i] == indent) { diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index b77cd744a18..40d9dc0d7e0 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -371,6 +371,9 @@ void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingO while (track) { MovieTrackingTrack *new_track = BKE_tracking_track_duplicate(track); + if (track->prev == NULL) { + tracking->act_track = new_track; + } BLI_addtail(tracksbase, new_track); BKE_tracking_track_unique_name(tracksbase, new_track); @@ -1789,13 +1792,19 @@ ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking * if (ibuf->rect_float) { if (undistort) { libmv_cameraIntrinsicsUndistortFloat(distortion->intrinsics, - ibuf->rect_float, resibuf->rect_float, - ibuf->x, ibuf->y, overscan, ibuf->channels); + ibuf->rect_float, + ibuf->x, ibuf->y, + overscan, + ibuf->channels, + resibuf->rect_float); } else { libmv_cameraIntrinsicsDistortFloat(distortion->intrinsics, - ibuf->rect_float, resibuf->rect_float, - ibuf->x, ibuf->y, overscan, ibuf->channels); + ibuf->rect_float, + ibuf->x, ibuf->y, + overscan, + ibuf->channels, + resibuf->rect_float); } if (ibuf->rect) @@ -1804,13 +1813,19 @@ ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking * else { if (undistort) { libmv_cameraIntrinsicsUndistortByte(distortion->intrinsics, - (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect, - ibuf->x, ibuf->y, overscan, ibuf->channels); + (unsigned char *)ibuf->rect, + ibuf->x, ibuf->y, + overscan, + ibuf->channels, + (unsigned char *)resibuf->rect); } else { libmv_cameraIntrinsicsDistortByte(distortion->intrinsics, - (unsigned char *)ibuf->rect, (unsigned char *)resibuf->rect, - ibuf->x, ibuf->y, overscan, ibuf->channels); + (unsigned char *)ibuf->rect, + ibuf->x, ibuf->y, + overscan, + ibuf->channels, + (unsigned char *)resibuf->rect); } } @@ -2017,14 +2032,14 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea } if (search_ibuf->rect_float) { - libmv_samplePlanarPatch(search_ibuf->rect_float, - search_ibuf->x, search_ibuf->y, 4, - src_pixel_x, src_pixel_y, - num_samples_x, num_samples_y, - mask, - pattern_ibuf->rect_float, - &warped_position_x, - &warped_position_y); + libmv_samplePlanarPatchFloat(search_ibuf->rect_float, + search_ibuf->x, search_ibuf->y, 4, + src_pixel_x, src_pixel_y, + num_samples_x, num_samples_y, + mask, + pattern_ibuf->rect_float, + &warped_position_x, + &warped_position_y); } else { libmv_samplePlanarPatchByte((unsigned char *) search_ibuf->rect, @@ -2185,10 +2200,10 @@ void BKE_tracking_disable_channels(ImBuf *ibuf, bool disable_red, bool disable_g /* ** Channels sort comparators ** */ -static int channels_alpha_sort(void *a, void *b) +static int channels_alpha_sort(const void *a, const void *b) { - MovieTrackingDopesheetChannel *channel_a = a; - MovieTrackingDopesheetChannel *channel_b = b; + const MovieTrackingDopesheetChannel *channel_a = a; + const MovieTrackingDopesheetChannel *channel_b = b; if (BLI_strcasecmp(channel_a->track->name, channel_b->track->name) > 0) return 1; @@ -2196,10 +2211,10 @@ static int channels_alpha_sort(void *a, void *b) return 0; } -static int channels_total_track_sort(void *a, void *b) +static int channels_total_track_sort(const void *a, const void *b) { - MovieTrackingDopesheetChannel *channel_a = a; - MovieTrackingDopesheetChannel *channel_b = b; + const MovieTrackingDopesheetChannel *channel_a = a; + const MovieTrackingDopesheetChannel *channel_b = b; if (channel_a->total_frames > channel_b->total_frames) return 1; @@ -2207,10 +2222,10 @@ static int channels_total_track_sort(void *a, void *b) return 0; } -static int channels_longest_segment_sort(void *a, void *b) +static int channels_longest_segment_sort(const void *a, const void *b) { - MovieTrackingDopesheetChannel *channel_a = a; - MovieTrackingDopesheetChannel *channel_b = b; + const MovieTrackingDopesheetChannel *channel_a = a; + const MovieTrackingDopesheetChannel *channel_b = b; if (channel_a->max_segment > channel_b->max_segment) return 1; @@ -2218,10 +2233,10 @@ static int channels_longest_segment_sort(void *a, void *b) return 0; } -static int channels_average_error_sort(void *a, void *b) +static int channels_average_error_sort(const void *a, const void *b) { - MovieTrackingDopesheetChannel *channel_a = a; - MovieTrackingDopesheetChannel *channel_b = b; + const MovieTrackingDopesheetChannel *channel_a = a; + const MovieTrackingDopesheetChannel *channel_b = b; if (channel_a->track->error > channel_b->track->error) return 1; @@ -2229,7 +2244,7 @@ static int channels_average_error_sort(void *a, void *b) return 0; } -static int channels_alpha_inverse_sort(void *a, void *b) +static int channels_alpha_inverse_sort(const void *a, const void *b) { if (channels_alpha_sort(a, b)) return 0; @@ -2237,7 +2252,7 @@ static int channels_alpha_inverse_sort(void *a, void *b) return 1; } -static int channels_total_track_inverse_sort(void *a, void *b) +static int channels_total_track_inverse_sort(const void *a, const void *b) { if (channels_total_track_sort(a, b)) return 0; @@ -2245,7 +2260,7 @@ static int channels_total_track_inverse_sort(void *a, void *b) return 1; } -static int channels_longest_segment_inverse_sort(void *a, void *b) +static int channels_longest_segment_inverse_sort(const void *a, const void *b) { if (channels_longest_segment_sort(a, b)) return 0; @@ -2253,10 +2268,10 @@ static int channels_longest_segment_inverse_sort(void *a, void *b) return 1; } -static int channels_average_error_inverse_sort(void *a, void *b) +static int channels_average_error_inverse_sort(const void *a, const void *b) { - MovieTrackingDopesheetChannel *channel_a = a; - MovieTrackingDopesheetChannel *channel_b = b; + const MovieTrackingDopesheetChannel *channel_a = a; + const MovieTrackingDopesheetChannel *channel_b = b; if (channel_a->track->error < channel_b->track->error) return 1; diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/treehash.c index a65bd28da97..866502c4ae1 100644 --- a/source/blender/blenkernel/intern/treehash.c +++ b/source/blender/blenkernel/intern/treehash.c @@ -91,7 +91,7 @@ static unsigned int tse_hash(const void *ptr) return hash.u_int; } -static int tse_cmp(const void *a, const void *b) +static bool tse_cmp(const void *a, const void *b) { const TreeStoreElem *tse_a = a; const TreeStoreElem *tse_b = b; diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h index 3a9d013f796..db33c5cec8b 100644 --- a/source/blender/blenlib/BLI_array.h +++ b/source/blender/blenlib/BLI_array.h @@ -84,26 +84,30 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, * * Allow for a large 'num' value when the new size is more than double * to allocate the exact sized array. */ -#define BLI_array_grow_items(arr, num) (( \ +#define BLI_array_reserve(arr, num) (void)( \ (((void *)(arr) == NULL) && \ ((void *)(_##arr##_static) != NULL) && \ /* don't add _##arr##_count below because it must be zero */ \ - (_bli_array_totalsize_static(arr) >= _##arr##_count + num)) ? \ + (_bli_array_totalsize_static(arr) >= _##arr##_count + (num))) ? \ /* we have an empty array and a static var big enough */ \ (void)(arr = (void *)_##arr##_static) \ : \ /* use existing static array or allocate */ \ - (LIKELY(_bli_array_totalsize(arr) >= _##arr##_count + num) ? \ + (LIKELY(_bli_array_totalsize(arr) >= _##arr##_count + (num)) ? \ (void)0 /* do nothing */ : \ _bli_array_grow_func((void **)&(arr), _##arr##_static, \ sizeof(*(arr)), _##arr##_count, num, \ "BLI_array." #arr)) \ - ), \ - /* increment the array count, all conditions above are accounted for. */ \ - (_##arr##_count += num)) + ) + /* returns length of array */ -#define BLI_array_grow_one(arr) BLI_array_grow_items(arr, 1) + +#define BLI_array_grow_items(arr, num) \ + (BLI_array_reserve(arr, num), (_##arr##_count += num)) + +#define BLI_array_grow_one(arr) \ + BLI_array_grow_items(arr, 1) /* appends an item to the array. */ @@ -120,9 +124,9 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, (&arr[_##arr##_count - 1]) \ ) -#define BLI_array_reserve(arr, num) \ - BLI_array_grow_items(arr, num), (void)(_##arr##_count -= (num)) - +/* appends (grows) & returns a pointer to the uninitialized memory */ +#define BLI_array_append_ret(arr) \ + (BLI_array_reserve(arr, 1), &arr[(_##arr##_count++)]) #define BLI_array_free(arr) \ if (arr && (char *)arr != _##arr##_static) { \ diff --git a/source/blender/blenlib/BLI_compiler_typecheck.h b/source/blender/blenlib/BLI_compiler_typecheck.h new file mode 100644 index 00000000000..551569b066d --- /dev/null +++ b/source/blender/blenlib/BLI_compiler_typecheck.h @@ -0,0 +1,379 @@ +/* + * ***** 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 ***** + */ + +#ifndef __BLI_COMPILER_TYPECHECK_H__ +#define __BLI_COMPILER_TYPECHECK_H__ + +/** \file BLI_compiler_typecheck.h + * \ingroup bli + * + * Type checking macros (often used to ensure valid use of macro args). + * These depend on compiler extensions and c11 in some cases. + */ + +/* Causes warning: + * incompatible types when assigning to type 'Foo' from type 'Bar' + * ... the compiler optimizes away the temp var */ +#ifdef __GNUC__ +#define CHECK_TYPE(var, type) { \ + typeof(var) *__tmp; \ + __tmp = (type *)NULL; \ + (void)__tmp; \ +} (void)0 + +#define CHECK_TYPE_PAIR(var_a, var_b) { \ + typeof(var_a) *__tmp; \ + __tmp = (typeof(var_b) *)NULL; \ + (void)__tmp; \ +} (void)0 + +#define CHECK_TYPE_PAIR_INLINE(var_a, var_b) ((void)({ \ + typeof(var_a) *__tmp; \ + __tmp = (typeof(var_b) *)NULL; \ + (void)__tmp; \ +})) + +#else +# define CHECK_TYPE(var, type) +# define CHECK_TYPE_PAIR(var_a, var_b) +# define CHECK_TYPE_PAIR_INLINE(var_a, var_b) (void)0 +#endif + +/* can be used in simple macros */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +# define CHECK_TYPE_INLINE(val, type) \ + (void)((void)(((type)0) != (0 ? (val) : ((type)0))), \ + _Generic((val), type: 0, const type: 0)) +#else +# define CHECK_TYPE_INLINE(val, type) \ + ((void)(((type)0) != (0 ? (val) : ((type)0)))) +#endif + +#define CHECK_TYPE_NONCONST(var) { \ + void *non_const = 0 ? (var) : NULL; \ + (void)non_const; \ +} (void)0 + +/** + * CHECK_TYPE_ANY: handy macro, eg: + * ``CHECK_TYPE_ANY(var, Foo *, Bar *, Baz *)`` + * + * excuse ridiculously long generated args. + * <pre> + * for i in range(63): + * args = [(chr(ord('a') + (c % 26)) + (chr(ord('0') + (c // 26)))) for c in range(i + 1)] + * print("#define _VA_CHECK_TYPE_ANY%d(v, %s) \\" % (i + 2, ", ".join(args))) + * print(" ((void)_Generic((v), %s))" % (": 0, ".join(args) + ": 0")) + * </pre> + */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) + +#define _VA_CHECK_TYPE_ANY2(v, a0) \ + ((void)_Generic((v), a0: 0)) +#define _VA_CHECK_TYPE_ANY3(v, a0, b0) \ + ((void)_Generic((v), a0: 0, b0: 0)) +#define _VA_CHECK_TYPE_ANY4(v, a0, b0, c0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0)) +#define _VA_CHECK_TYPE_ANY5(v, a0, b0, c0, d0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0)) +#define _VA_CHECK_TYPE_ANY6(v, a0, b0, c0, d0, e0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0)) +#define _VA_CHECK_TYPE_ANY7(v, a0, b0, c0, d0, e0, f0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0)) +#define _VA_CHECK_TYPE_ANY8(v, a0, b0, c0, d0, e0, f0, g0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0)) +#define _VA_CHECK_TYPE_ANY9(v, a0, b0, c0, d0, e0, f0, g0, h0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0)) +#define _VA_CHECK_TYPE_ANY10(v, a0, b0, c0, d0, e0, f0, g0, h0, i0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0)) +#define _VA_CHECK_TYPE_ANY11(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0)) +#define _VA_CHECK_TYPE_ANY12(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0)) +#define _VA_CHECK_TYPE_ANY13(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0)) +#define _VA_CHECK_TYPE_ANY14(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0)) +#define _VA_CHECK_TYPE_ANY15(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0)) +#define _VA_CHECK_TYPE_ANY16(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0)) +#define _VA_CHECK_TYPE_ANY17(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0)) +#define _VA_CHECK_TYPE_ANY18(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0)) +#define _VA_CHECK_TYPE_ANY19(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0)) +#define _VA_CHECK_TYPE_ANY20(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0)) +#define _VA_CHECK_TYPE_ANY21(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0)) +#define _VA_CHECK_TYPE_ANY22(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0)) +#define _VA_CHECK_TYPE_ANY23(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0)) +#define _VA_CHECK_TYPE_ANY24(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0)) +#define _VA_CHECK_TYPE_ANY25(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0)) +#define _VA_CHECK_TYPE_ANY26(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0)) +#define _VA_CHECK_TYPE_ANY27(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0)) +#define _VA_CHECK_TYPE_ANY28(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0)) +#define _VA_CHECK_TYPE_ANY29(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0)) +#define _VA_CHECK_TYPE_ANY30(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0)) +#define _VA_CHECK_TYPE_ANY31(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0)) +#define _VA_CHECK_TYPE_ANY32(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0)) +#define _VA_CHECK_TYPE_ANY33(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0)) +#define _VA_CHECK_TYPE_ANY34(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0)) +#define _VA_CHECK_TYPE_ANY35(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0)) +#define _VA_CHECK_TYPE_ANY36(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0)) +#define _VA_CHECK_TYPE_ANY37(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0)) +#define _VA_CHECK_TYPE_ANY38(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0)) +#define _VA_CHECK_TYPE_ANY39(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0)) +#define _VA_CHECK_TYPE_ANY40(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0)) +#define _VA_CHECK_TYPE_ANY41(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0)) +#define _VA_CHECK_TYPE_ANY42(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0)) +#define _VA_CHECK_TYPE_ANY43(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0)) +#define _VA_CHECK_TYPE_ANY44(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0)) +#define _VA_CHECK_TYPE_ANY45(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0)) +#define _VA_CHECK_TYPE_ANY46(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0)) +#define _VA_CHECK_TYPE_ANY47(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0)) +#define _VA_CHECK_TYPE_ANY48(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0)) +#define _VA_CHECK_TYPE_ANY49(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0)) +#define _VA_CHECK_TYPE_ANY50(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0)) +#define _VA_CHECK_TYPE_ANY51(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0)) +#define _VA_CHECK_TYPE_ANY52(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0)) +#define _VA_CHECK_TYPE_ANY53(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0)) +#define _VA_CHECK_TYPE_ANY54(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0)) +#define _VA_CHECK_TYPE_ANY55(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2, b2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0, b2: 0)) +#define _VA_CHECK_TYPE_ANY56(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2, b2, c2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0, b2: 0, c2: 0)) +#define _VA_CHECK_TYPE_ANY57(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2, b2, c2, d2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0, b2: 0, c2: 0, d2: 0)) +#define _VA_CHECK_TYPE_ANY58(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2, b2, c2, d2, e2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0, b2: 0, c2: 0, d2: 0, e2: 0)) +#define _VA_CHECK_TYPE_ANY59(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2, b2, c2, d2, e2, f2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0, b2: 0, c2: 0, d2: 0, e2: 0, f2: 0)) +#define _VA_CHECK_TYPE_ANY60(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2, b2, c2, d2, e2, f2, g2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0, b2: 0, c2: 0, d2: 0, e2: 0, f2: 0, g2: 0)) +#define _VA_CHECK_TYPE_ANY61(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0, b2: 0, c2: 0, d2: 0, e2: 0, f2: 0, g2: 0, h2: 0)) +#define _VA_CHECK_TYPE_ANY62(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0, b2: 0, c2: 0, d2: 0, e2: 0, f2: 0, g2: 0, h2: 0, i2: 0)) +#define _VA_CHECK_TYPE_ANY63(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2, j2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0, b2: 0, c2: 0, d2: 0, e2: 0, f2: 0, g2: 0, h2: 0, i2: 0, \ + j2: 0)) +#define _VA_CHECK_TYPE_ANY64(v, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, u0, \ + v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, w1, \ + x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2) \ + ((void)_Generic((v), a0: 0, b0: 0, c0: 0, d0: 0, e0: 0, f0: 0, g0: 0, h0: 0, i0: 0, j0: 0, k0: 0, l0: 0, m0: 0, \ + n0: 0, o0: 0, p0: 0, q0: 0, r0: 0, s0: 0, t0: 0, u0: 0, v0: 0, w0: 0, x0: 0, y0: 0, z0: 0, a1: 0, b1: 0, c1: 0, \ + d1: 0, e1: 0, f1: 0, g1: 0, h1: 0, i1: 0, j1: 0, k1: 0, l1: 0, m1: 0, n1: 0, o1: 0, p1: 0, q1: 0, r1: 0, s1: 0, \ + t1: 0, u1: 0, v1: 0, w1: 0, x1: 0, y1: 0, z1: 0, a2: 0, b2: 0, c2: 0, d2: 0, e2: 0, f2: 0, g2: 0, h2: 0, i2: 0, \ + j2: 0, k2: 0)) +# define CHECK_TYPE_ANY(...) VA_NARGS_CALL_OVERLOAD(_VA_CHECK_TYPE_ANY, __VA_ARGS__) +#else +# define CHECK_TYPE_ANY(...) (void)0 +#endif + +#endif /* __BLI_COMPILER_TYPECHECK_H__ */ diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index dd3f62cd6d3..af2605894e3 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -41,7 +41,7 @@ extern "C" { #endif typedef unsigned int (*GHashHashFP) (const void *key); -typedef int (*GHashCmpFP) (const void *a, const void *b); +typedef bool (*GHashCmpFP) (const void *a, const void *b); typedef void (*GHashKeyFreeFP) (void *key); typedef void (*GHashValFreeFP) (void *val); @@ -120,14 +120,14 @@ BLI_INLINE bool BLI_ghashIterator_done(GHashIterator *ghi) { return !ghi * \{ */ unsigned int BLI_ghashutil_ptrhash(const void *key); -int BLI_ghashutil_ptrcmp(const void *a, const void *b); +bool BLI_ghashutil_ptrcmp(const void *a, const void *b); unsigned int BLI_ghashutil_strhash_n(const char *key, size_t n); #define BLI_ghashutil_strhash(key) ( \ CHECK_TYPE_INLINE(key, char *), \ BLI_ghashutil_strhash_p(key)) unsigned int BLI_ghashutil_strhash_p(const void *key); -int BLI_ghashutil_strcmp(const void *a, const void *b); +bool BLI_ghashutil_strcmp(const void *a, const void *b); #define BLI_ghashutil_inthash(key) ( \ CHECK_TYPE_INLINE(&(key), int *), \ @@ -139,11 +139,11 @@ unsigned int BLI_ghashutil_uinthash(unsigned int key); unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]); #define BLI_ghashutil_inthash_v4_p \ ((GSetHashFP)BLI_ghashutil_uinthash_v4) -int BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b); +bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b); #define BLI_ghashutil_inthash_v4_cmp \ BLI_ghashutil_uinthash_v4_cmp unsigned int BLI_ghashutil_inthash_p(const void *ptr); -int BLI_ghashutil_intcmp(const void *a, const void *b); +bool BLI_ghashutil_intcmp(const void *a, const void *b); /** \} */ @@ -167,7 +167,7 @@ typedef struct GHashPair { GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second); unsigned int BLI_ghashutil_pairhash(const void *ptr); -int BLI_ghashutil_paircmp(const void *a, const void *b); +bool BLI_ghashutil_paircmp(const void *a, const void *b); void BLI_ghashutil_pairfree(void *ptr); diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 99a5fad397a..49d072ddfdc 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -89,7 +89,7 @@ void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoin void BLI_bvhtree_balance(BVHTree *tree); /* update: first update points/nodes, then call update_tree to refit the bounding volumes */ -int BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints); +bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints); void BLI_bvhtree_update_tree(BVHTree *tree); /* collision/overlap: check two trees if they overlap, alloc's *overlap with length of the int return value */ diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index 697ba863603..fb388977ddf 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -67,8 +67,8 @@ void *BLI_poptail(ListBase *listbase) ATTR_NONNULL(1); void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1); void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1); void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1); -void BLI_sortlist(struct ListBase *listbase, int (*cmp)(void *, void *)) ATTR_NONNULL(1, 2); -void BLI_sortlist_r(ListBase *listbase, void *thunk, int (*cmp)(void *, void *, void *)) ATTR_NONNULL(1, 3); +void BLI_sortlist(struct ListBase *listbase, int (*cmp)(const void *, const void *)) ATTR_NONNULL(1, 2); +void BLI_sortlist_r(ListBase *listbase, void *thunk, int (*cmp)(void *, const void *, const void *)) ATTR_NONNULL(1, 3); void BLI_freelist(struct ListBase *listbase) ATTR_NONNULL(1); int BLI_countlist(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1); diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 5f94f04e0a8..494bc4083ba 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -83,8 +83,8 @@ static const int NAN_INT = 0x7FC00000; # define NAN_FLT (*((float *)(&NAN_INT))) #endif -/* do not redefine functions from C99 or POSIX.1-2001 */ -#if !(defined(_ISOC99_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)) +/* do not redefine functions from C99, POSIX.1-2001 or MSVC12 (partial C99) */ +#if !(defined(_ISOC99_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || (defined(_MSC_VER) && _MSC_VER >= 1800)) #ifndef sqrtf #define sqrtf(a) ((float)sqrt(a)) @@ -138,7 +138,7 @@ static const int NAN_INT = 0x7FC00000; #define copysignf(a, b) ((float)copysign(a, b)) #endif -#endif /* C99 or POSIX.1-2001 */ +#endif /* C99, POSIX.1-2001 or MSVC12 (partial C99) */ #ifdef WIN32 # if defined(_MSC_VER) diff --git a/source/blender/blenlib/BLI_math_color_blend.h b/source/blender/blenlib/BLI_math_color_blend.h index 2535a31ccc4..d966676e19e 100644 --- a/source/blender/blenlib/BLI_math_color_blend.h +++ b/source/blender/blenlib/BLI_math_color_blend.h @@ -78,22 +78,22 @@ MINLINE void blend_color_darken_float(float dst[4], const float src1[4], const f MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], const float src2[4]); MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], const float src2[4]); -MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[2]); -MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[2]); +MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[4]); +MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[4]); MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t); diff --git a/source/blender/blenlib/BLI_stack.h b/source/blender/blenlib/BLI_stack.h index 1e0b29bc7e8..a8c4478c450 100644 --- a/source/blender/blenlib/BLI_stack.h +++ b/source/blender/blenlib/BLI_stack.h @@ -46,6 +46,9 @@ void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL(); void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) ATTR_NONNULL(); void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL(); +void *BLI_stack_peek(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BLI_stack_discard(BLI_Stack *stack) ATTR_NONNULL(); + size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/blenlib/BLI_stackdefines.h b/source/blender/blenlib/BLI_stackdefines.h index da9bf5ea04c..864a7704aa9 100644 --- a/source/blender/blenlib/BLI_stackdefines.h +++ b/source/blender/blenlib/BLI_stackdefines.h @@ -64,6 +64,13 @@ stack[_i] = stack[_##stack##_index]; \ } \ } (void)0 +#define STACK_DISCARD(stack, n) \ + { \ + const unsigned int _n = n; \ + BLI_assert(_##stack##_index >= _n); \ + (void)stack; \ + _##stack##_index -= _n; \ + } (void)0 #ifdef __GNUC__ #define STACK_SWAP(stack_a, stack_b) { \ SWAP(typeof(stack_a), stack_a, stack_b); \ diff --git a/source/blender/blenlib/BLI_strict_flags.h b/source/blender/blenlib/BLI_strict_flags.h index 1d595ff3bf3..964ee06469d 100644 --- a/source/blender/blenlib/BLI_strict_flags.h +++ b/source/blender/blenlib/BLI_strict_flags.h @@ -28,13 +28,15 @@ */ #ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ # pragma GCC diagnostic error "-Wsign-compare" # pragma GCC diagnostic error "-Wconversion" # endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 /* gcc4.8+ only (behavior changed to ignore globals)*/ +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 + /* gcc4.8+ only (behavior changed to ignore globals)*/ # pragma GCC diagnostic error "-Wshadow" + /* older gcc changed behavior with ternary */ +# pragma GCC diagnostic error "-Wsign-conversion" # endif /* pedantic gives too many issues, developers can define this for own use */ # ifdef WARN_PEDANTIC diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 683b3c4c438..a829cc60106 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -47,11 +47,15 @@ #define _VA_NARGS_RETURN_COUNT(\ _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, _10_, _11_, _12_, _13_, _14_, _15_, _16_, \ _17_, _18_, _19_, _20_, _21_, _22_, _23_, _24_, _25_, _26_, _27_, _28_, _29_, _30_, _31_, _32_, \ + _33_, _34_, _35_, _36_, _37_, _38_, _39_, _40_, _41_, _42_, _43_, _44_, _45_, _46_, _47_, _48_, \ + _49_, _50_, _51_, _52_, _53_, _54_, _55_, _56_, _57_, _58_, _59_, _60_, _61_, _62_, _63_, _64_, \ count, ...) count #define _VA_NARGS_EXPAND(args) _VA_NARGS_RETURN_COUNT args #define _VA_NARGS_COUNT_MAX32(...) _VA_NARGS_EXPAND((__VA_ARGS__, \ - 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, \ - 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) + 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, \ + 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, \ + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \ + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) #define _VA_NARGS_OVERLOAD_MACRO2(name, count) name##count #define _VA_NARGS_OVERLOAD_MACRO1(name, count) _VA_NARGS_OVERLOAD_MACRO2(name, count) #define _VA_NARGS_OVERLOAD_MACRO(name, count) _VA_NARGS_OVERLOAD_MACRO1(name, count) @@ -67,6 +71,9 @@ # define MAX2(x, y) (_TYPECHECK(x, y), (((x) > (y) ? (x) : (y)))) #endif +/* include after _VA_NARGS macro */ +#include "BLI_compiler_typecheck.h" + /* min/max */ #if defined(__GNUC__) || defined(__clang__) @@ -151,48 +158,6 @@ /* some math and copy defines */ -/* Causes warning: - * incompatible types when assigning to type 'Foo' from type 'Bar' - * ... the compiler optimizes away the temp var */ -#ifdef __GNUC__ -#define CHECK_TYPE(var, type) { \ - typeof(var) *__tmp; \ - __tmp = (type *)NULL; \ - (void)__tmp; \ -} (void)0 - -#define CHECK_TYPE_PAIR(var_a, var_b) { \ - typeof(var_a) *__tmp; \ - __tmp = (typeof(var_b) *)NULL; \ - (void)__tmp; \ -} (void)0 - -#define CHECK_TYPE_PAIR_INLINE(var_a, var_b) ((void)({ \ - typeof(var_a) *__tmp; \ - __tmp = (typeof(var_b) *)NULL; \ - (void)__tmp; \ -})) - -#else -# define CHECK_TYPE(var, type) -# define CHECK_TYPE_PAIR(var_a, var_b) -# define CHECK_TYPE_PAIR_INLINE(var_a, var_b) (void)0 -#endif - -/* can be used in simple macros */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) -# define CHECK_TYPE_INLINE(val, type) \ - (void)((void)(((type)0) != (0 ? (val) : ((type)0))), \ - _Generic((val), type: 0, const type: 0)) -#else -# define CHECK_TYPE_INLINE(val, type) \ - ((void)(((type)0) != (0 ? (val) : ((type)0)))) -#endif - -#define CHECK_TYPE_NONCONST(var) { \ - void *non_const = 0 ? (var) : NULL; \ - (void)non_const; \ -} (void)0 #define SWAP(type, a, b) { \ type sw_ap; \ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index dd02bcf22a9..9efa20da13e 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -118,6 +118,7 @@ set(SRC BLI_callbacks.h BLI_compiler_attrs.h BLI_compiler_compat.h + BLI_compiler_typecheck.h BLI_convexhull2d.h BLI_dial.h BLI_dlrbTree.h diff --git a/source/blender/blenlib/intern/BLI_args.c b/source/blender/blenlib/intern/BLI_args.c index 8bd35f651b7..49a3c466727 100644 --- a/source/blender/blenlib/intern/BLI_args.c +++ b/source/blender/blenlib/intern/BLI_args.c @@ -91,15 +91,17 @@ static unsigned int keyhash(const void *ptr) return case_strhash(k->arg); /* ^ BLI_ghashutil_inthash((void *)k->pass); */ } -static int keycmp(const void *a, const void *b) +static bool keycmp(const void *a, const void *b) { const bAKey *ka = a; const bAKey *kb = b; if (ka->pass == kb->pass || ka->pass == -1 || kb->pass == -1) { /* -1 is wildcard for pass */ - if (ka->case_str == 1 || kb->case_str == 1) - return BLI_strcasecmp(ka->arg, kb->arg); - else - return strcmp(ka->arg, kb->arg); + if (ka->case_str == 1 || kb->case_str == 1) { + return (BLI_strcasecmp(ka->arg, kb->arg) != 0); + } + else { + return (strcmp(ka->arg, kb->arg) != 0); + } } else { return BLI_ghashutil_intcmp((const void *)ka->pass, (const void *)kb->pass); diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 74d7fdc88cb..6747e5c4e7e 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -155,7 +155,7 @@ BLI_INLINE Entry *ghash_lookup_entry_ex(GHash *gh, const void *key, Entry *e; for (e = gh->buckets[hash]; e; e = e->next) { - if (UNLIKELY(gh->cmpfp(key, e->key) == 0)) { + if (UNLIKELY(gh->cmpfp(key, e->key) == false)) { return e; } } @@ -251,7 +251,7 @@ static Entry *ghash_remove_ex(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GH Entry *e_prev = NULL; for (e = gh->buckets[hash]; e; e = e->next) { - if (UNLIKELY(gh->cmpfp(key, e->key) == 0)) { + if (UNLIKELY(gh->cmpfp(key, e->key) == false)) { Entry *e_next = e->next; if (keyfreefp) keyfreefp(e->key); @@ -683,12 +683,9 @@ unsigned int BLI_ghashutil_ptrhash(const void *key) return (unsigned int)y; } #endif -int BLI_ghashutil_ptrcmp(const void *a, const void *b) +bool BLI_ghashutil_ptrcmp(const void *a, const void *b) { - if (a == b) - return 0; - else - return (a < b) ? -1 : 1; + return (a != b); } unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]) @@ -704,9 +701,9 @@ unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]) return hash; } -int BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b) +bool BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b) { - return memcmp(a, b, sizeof(unsigned int[4])); + return (memcmp(a, b, sizeof(unsigned int[4])) != 0); } unsigned int BLI_ghashutil_uinthash(unsigned int key) @@ -735,12 +732,9 @@ unsigned int BLI_ghashutil_inthash_p(const void *ptr) return (unsigned int)(key & 0xffffffff); } -int BLI_ghashutil_intcmp(const void *a, const void *b) +bool BLI_ghashutil_intcmp(const void *a, const void *b) { - if (a == b) - return 0; - else - return (a < b) ? -1 : 1; + return (a != b); } /** @@ -774,9 +768,9 @@ unsigned int BLI_ghashutil_strhash_p(const void *ptr) return h; } -int BLI_ghashutil_strcmp(const void *a, const void *b) +bool BLI_ghashutil_strcmp(const void *a, const void *b) { - return strcmp(a, b); + return (strcmp(a, b) != 0); } GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second) @@ -794,15 +788,13 @@ unsigned int BLI_ghashutil_pairhash(const void *ptr) return hash ^ BLI_ghashutil_ptrhash(pair->second); } -int BLI_ghashutil_paircmp(const void *a, const void *b) +bool BLI_ghashutil_paircmp(const void *a, const void *b) { const GHashPair *A = a; const GHashPair *B = b; - int cmp = BLI_ghashutil_ptrcmp(A->first, B->first); - if (cmp == 0) - return BLI_ghashutil_ptrcmp(A->second, B->second); - return cmp; + return (BLI_ghashutil_ptrcmp(A->first, B->first) || + BLI_ghashutil_ptrcmp(A->second, B->second)); } void BLI_ghashutil_pairfree(void *ptr) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index dbacb0f3451..d28215ee8ed 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -979,7 +979,7 @@ void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoin /* call before BLI_bvhtree_update_tree() */ -int BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints) +bool BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints) { BVHNode *node = NULL; axis_t axis_iter; diff --git a/source/blender/blenlib/intern/buffer.c b/source/blender/blenlib/intern/buffer.c index 4e570823319..9e96205a5e8 100644 --- a/source/blender/blenlib/intern/buffer.c +++ b/source/blender/blenlib/intern/buffer.c @@ -38,17 +38,14 @@ static void *buffer_alloc(BLI_Buffer *buffer, int len) static void *buffer_realloc(BLI_Buffer *buffer, int len) { - if (buffer->flag & BLI_BUFFER_USE_CALLOC) { - return MEM_recallocN(buffer->data, buffer->elem_size * len); - } - else { - return MEM_reallocN(buffer->data, buffer->elem_size * len); - } + return ((buffer->flag & BLI_BUFFER_USE_CALLOC) ? + MEM_recallocN_id : MEM_reallocN_id) + (buffer->data, buffer->elem_size * len, "BLI_Buffer.data"); } void BLI_buffer_resize(BLI_Buffer *buffer, int new_count) { - if (new_count > buffer->alloc_count) { + if (UNLIKELY(new_count > buffer->alloc_count)) { if (buffer->flag & BLI_BUFFER_USE_STATIC) { void *orig = buffer->data; @@ -65,12 +62,7 @@ void BLI_buffer_resize(BLI_Buffer *buffer, int new_count) buffer->alloc_count = new_count; } - if (buffer->data) { - buffer->data = buffer_realloc(buffer, buffer->alloc_count); - } - else { - buffer->data = buffer_alloc(buffer, buffer->alloc_count); - } + buffer->data = buffer_realloc(buffer, buffer->alloc_count); } } diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index abf15d57cf7..d9cf8971246 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -173,7 +173,7 @@ void BLI_freelinkN(ListBase *listbase, void *vlink) * (which should return 1 iff its first arg should come after its second arg). * This uses insertion sort, so NOT ok for large list. */ -void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *)) +void BLI_sortlist(ListBase *listbase, int (*cmp)(const void *, const void *)) { Link *current = NULL; Link *previous = NULL; @@ -195,7 +195,7 @@ void BLI_sortlist(ListBase *listbase, int (*cmp)(void *, void *)) } } -void BLI_sortlist_r(ListBase *listbase, void *thunk, int (*cmp)(void *, void *, void *)) +void BLI_sortlist_r(ListBase *listbase, void *thunk, int (*cmp)(void *, const void *, const void *)) { Link *current = NULL; Link *previous = NULL; diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c index 2522fe5f6c9..73a7259ddcd 100644 --- a/source/blender/blenlib/intern/math_color_blend_inline.c +++ b/source/blender/blenlib/intern/math_color_blend_inline.c @@ -781,7 +781,7 @@ MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], cons } } -MINLINE void blend_color_overlay_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -807,7 +807,7 @@ MINLINE void blend_color_overlay_float(float dst[3], const float src1[3], const } -MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[2]) +MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -832,7 +832,7 @@ MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], cons } } -MINLINE void blend_color_burn_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -850,7 +850,7 @@ MINLINE void blend_color_burn_float(float dst[3], const float src1[3], const flo } } -MINLINE void blend_color_linearburn_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -869,7 +869,7 @@ MINLINE void blend_color_linearburn_float(float dst[3], const float src1[3], con } -MINLINE void blend_color_dodge_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -887,7 +887,7 @@ MINLINE void blend_color_dodge_float(float dst[3], const float src1[3], const fl } } -MINLINE void blend_color_screen_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -905,7 +905,7 @@ MINLINE void blend_color_screen_float(float dst[3], const float src1[3], const f } } -MINLINE void blend_color_softlight_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -930,7 +930,7 @@ MINLINE void blend_color_softlight_float(float dst[3], const float src1[3], cons } } -MINLINE void blend_color_pinlight_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -956,7 +956,7 @@ MINLINE void blend_color_pinlight_float(float dst[3], const float src1[3], const } -MINLINE void blend_color_linearlight_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -982,7 +982,7 @@ MINLINE void blend_color_linearlight_float(float dst[3], const float src1[3], co } -MINLINE void blend_color_vividlight_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -1013,7 +1013,7 @@ MINLINE void blend_color_vividlight_float(float dst[3], const float src1[3], con } } -MINLINE void blend_color_difference_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -1031,7 +1031,7 @@ MINLINE void blend_color_difference_float(float dst[3], const float src1[3], con } -MINLINE void blend_color_exclusion_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -1050,7 +1050,7 @@ MINLINE void blend_color_exclusion_float(float dst[3], const float src1[3], cons } -MINLINE void blend_color_color_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -1078,7 +1078,7 @@ MINLINE void blend_color_color_float(float dst[3], const float src1[3], const fl } -MINLINE void blend_color_hue_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -1104,7 +1104,7 @@ MINLINE void blend_color_hue_float(float dst[3], const float src1[3], const floa } } -MINLINE void blend_color_saturation_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { @@ -1131,7 +1131,7 @@ MINLINE void blend_color_saturation_float(float dst[3], const float src1[3], con } } -MINLINE void blend_color_luminosity_float(float dst[3], const float src1[3], const float src2[3]) +MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[4]) { const float fac = src2[3]; if (fac != 0.0f && fac < 1.0f) { diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 17a1dcbf34d..496e5362cc4 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -160,6 +160,12 @@ float area_poly_v3(const float verts[][3], unsigned int nr) return normal_poly_v3(n, verts, nr) * 0.5f; } +/** + * Scalar cross product of a 2d polygon. + * + * - equivalent to ``area * 2`` + * - useful for checking polygon winding (a positive value is clockwise). + */ float cross_poly_v2(const float verts[][2], unsigned int nr) { unsigned int a; @@ -1786,7 +1792,10 @@ float closest_to_line_v2(float cp[2], const float p[2], const float l1[2], const return lambda; } -/* little sister we only need to know lambda */ +/** + * A simplified version of #closest_to_line_v3 + * we only need to return the ``lambda`` + */ float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3]) { float h[3], u[3]; @@ -3193,7 +3202,7 @@ void map_to_tube(float *r_u, float *r_v, const float x, const float y, const flo len = sqrtf(x * x + y * y); if (len > 0.0f) { - *r_u = (float)((1.0 - (atan2(x / len, y / len) / M_PI)) / 2.0); + *r_u = (1.0f - (atan2f(x / len, y / len) / (float)M_PI)) / 2.0f; } else { *r_v = *r_u = 0.0f; /* to avoid un-initialized variables */ diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 141f9201689..9a6515daf68 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -366,7 +366,7 @@ void mat3_to_quat_is_ok(float q[4], float wmat[3][3]) mul_m3_v3(matn, mat[0]); /* and align x-axes */ - angle = (float)(0.5 * atan2(mat[0][1], mat[0][0])); + angle = 0.5f * atan2f(mat[0][1], mat[0][0]); co = cosf(angle); si = sinf(angle); @@ -765,7 +765,7 @@ void tri_to_quat_ex(float quat[4], const float v1[3], const float v2[3], const f vec[2] = 0.0f; normalize_v3(vec); - angle = (float)(0.5 * atan2(vec[1], vec[0])); + angle = 0.5f * atan2f(vec[1], vec[0]); co = cosf(angle); si = sinf(angle); q2[0] = co; diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 5529433f6c9..da9d5bd3f49 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -957,6 +957,18 @@ MINLINE bool compare_v4v4(const float v1[4], const float v2[4], const float limi return false; } +/** + * <pre> + * + l1 + * | + * neg <- | -> pos + * | + * + l2 + * </pre> + * + * \return Positive value when 'pt' is left-of-line + * (looking from 'l1' -> 'l2'). + */ MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2]) { return (((l1[0] - pt[0]) * (l2[1] - pt[1])) - diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index a7fa443cfc4..d5af980e373 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -873,9 +873,12 @@ bool BLI_path_abs(char *path, const char *basepath) char tmp[FILE_MAX]; char base[FILE_MAX]; #ifdef WIN32 - char vol[3] = {'\0', '\0', '\0'}; - BLI_strncpy(vol, path, 3); + /* without this: "" --> "C:\" */ + if (*path == '\0') { + return wasrelative; + } + /* we are checking here if we have an absolute path that is not in the current * blend file as a lib main - we are basically checking for the case that a * UNIX root '/' is passed. diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c index a00d95a075f..16cf7ff960b 100644 --- a/source/blender/blenlib/intern/polyfill2d.c +++ b/source/blender/blenlib/intern/polyfill2d.c @@ -567,7 +567,7 @@ static void pf_triangulate(PolyFill *pf) #ifdef USE_CLIP_EVEN #ifdef USE_CLIP_SWEEP - pi_ear_init = reverse ? pi_next->next : pi_prev->prev; + pi_ear_init = reverse ? pi_prev->prev : pi_next->next; #else pi_ear_init = pi_next->next; #endif diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c index 828cb3a580b..9fc1db1f1e4 100644 --- a/source/blender/blenlib/intern/scanfill_utils.c +++ b/source/blender/blenlib/intern/scanfill_utils.c @@ -132,12 +132,12 @@ static ListBase *edge_isect_ls_add(GHash *isect_hash, ScanFillEdge *eed, ScanFil return e_ls; } -static int edge_isect_ls_sort_cb(void *thunk, void *def_a_ptr, void *def_b_ptr) +static int edge_isect_ls_sort_cb(void *thunk, const void *def_a_ptr, const void *def_b_ptr) { const float *co = thunk; - ScanFillIsect *i_a = (ScanFillIsect *)(((LinkData *)def_a_ptr)->data); - ScanFillIsect *i_b = (ScanFillIsect *)(((LinkData *)def_b_ptr)->data); + const ScanFillIsect *i_a = ((LinkData *)def_a_ptr)->data; + const ScanFillIsect *i_b = ((LinkData *)def_b_ptr)->data; const float a = len_squared_v2v2(co, i_a->co); const float b = len_squared_v2v2(co, i_b->co); diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c index 58029120de9..2d3a2f77a3e 100644 --- a/source/blender/blenlib/intern/stack.c +++ b/source/blender/blenlib/intern/stack.c @@ -48,8 +48,6 @@ ((void)0, (((char *)(_stack)->chunk_curr->data) + \ ((_stack)->elem_size * (_stack)->chunk_index))) -#define IS_POW2(a) (((a) & ((a) - 1)) == 0) - struct StackChunk { struct StackChunk *next; char data[0]; @@ -96,11 +94,6 @@ BLI_Stack *BLI_stack_new_ex(const size_t elem_size, const char *description, /* force init */ stack->chunk_index = stack->chunk_elem_max - 1; - /* ensure we have a correctly rounded size */ - BLI_assert((IS_POW2(stack->elem_size) == 0) || - (IS_POW2((stack->chunk_elem_max * stack->elem_size) + - (sizeof(struct StackChunk) + MEM_SIZE_OVERHEAD)))); - return stack; } @@ -182,6 +175,31 @@ void BLI_stack_pop(BLI_Stack *stack, void *dst) BLI_assert(BLI_stack_is_empty(stack) == false); memcpy(dst, CHUNK_LAST_ELEM(stack), stack->elem_size); + + BLI_stack_discard(stack); +} + +void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) +{ + BLI_assert(n <= BLI_stack_count(stack)); + + while (n--) { + BLI_stack_pop(stack, dst); + dst = (void *)((char *)dst + stack->elem_size); + } +} + +void *BLI_stack_peek(BLI_Stack *stack) +{ + BLI_assert(BLI_stack_is_empty(stack) == false); + + return CHUNK_LAST_ELEM(stack); +} + +void BLI_stack_discard(BLI_Stack *stack) +{ + BLI_assert(BLI_stack_is_empty(stack) == false); + #ifdef USE_TOTELEM stack->totelem--; #endif @@ -198,16 +216,6 @@ void BLI_stack_pop(BLI_Stack *stack, void *dst) } } -void BLI_stack_pop_n(BLI_Stack *stack, void *dst, unsigned int n) -{ - BLI_assert(n <= BLI_stack_count(stack)); - - while (n--) { - BLI_stack_pop(stack, dst); - dst = (void *)((char *)dst + stack->elem_size); - } -} - size_t BLI_stack_count(const BLI_Stack *stack) { #ifdef USE_TOTELEM diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8561903ce04..aea35963269 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1862,6 +1862,7 @@ static void direct_link_palette(FileData *fd, Palette *palette) { /* palette itself has been read */ link_list(fd, &palette->colors); + BLI_listbase_clear(&palette->deleted); } static void lib_link_paint_curve(FileData *UNUSED(fd), Main *main) @@ -6237,7 +6238,6 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) rv3d->depths = NULL; rv3d->gpuoffscreen = NULL; - rv3d->ri = NULL; rv3d->render_engine = NULL; rv3d->sms = NULL; rv3d->smooth_timer = NULL; @@ -8995,10 +8995,10 @@ static ID *append_named_part_ex(const bContext *C, Main *mainl, FileData *fd, co ob = (Object *)id; - /* link at active layer (view3d->lay if in context, else scene->lay */ + /* link at active layer (view3d if available in context, else scene one */ if ((flag & FILE_ACTIVELAY)) { View3D *v3d = CTX_wm_view3d(C); - ob->lay = v3d ? v3d->layact : scene->lay; + ob->lay = BKE_screen_view3d_layer_active(v3d, scene); } ob->mode = OB_MODE_OBJECT; diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 06d871c8db0..40b756a3f7c 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -89,9 +89,6 @@ #include "NOD_socket.h" -//XXX #include "BIF_butspace.h" // badlevel, for do_versions, patching event codes -//XXX #include "BIF_filelist.h" // badlevel too, where to move this? - elubie -//XXX #include "BIF_previewrender.h" // bedlelvel, for struct RenderInfo #include "BLO_readfile.h" #include "BLO_undofile.h" diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 8e760a9c9f6..d8da0a12b50 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -350,12 +350,19 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) for (br = main->brush.first; br; br = br->id.next) { br->fill_threshold = 0.2f; } - } - if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) { - Scene *scene; - for (scene = main->scene.first; scene; scene = scene->id.next) { - scene->r.preview_start_resolution = 64; + if (!DNA_struct_elem_find(fd->filesdna, "BevelModifierData", "int", "mat")) { + Object *ob; + for (ob = main->object.first; ob; ob = ob->id.next) { + ModifierData *md; + + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Bevel) { + BevelModifierData *bmd = (BevelModifierData *)md; + bmd->mat = -1; + } + } + } } } @@ -374,4 +381,28 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + if (!MAIN_VERSION_ATLEAST(main, 272, 0)) { + if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) { + Scene *scene; + for (scene = main->scene.first; scene; scene = scene->id.next) { + scene->r.preview_start_resolution = 64; + } + } + } + + if (!MAIN_VERSION_ATLEAST(main, 272, 1)) { + Brush *br; + for (br = main->brush.first; br; br = br->id.next) { + if ((br->ob_mode & OB_MODE_SCULPT) && ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK)) + br->alpha = 1.0f; + } + } + + if (!DNA_struct_elem_find(fd->filesdna, "Image", "float", "gen_color")) { + Image *image; + for (image = main->image.first; image != NULL; image = image->id.next) { + image->gen_color[3] = 1.0f; + } + } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 217d1f0821f..1afcac313a2 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -99,6 +99,7 @@ void BLO_update_defaults_startup_blend(Main *bmain) linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA; linestyle->integration_type = LS_INTEGRATION_MEAN; linestyle->texstep = 1.0; + linestyle->chain_count = 10; } { diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index a43e835f022..50d3ac30ddc 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -140,6 +140,8 @@ set(SRC tools/bmesh_intersect.h tools/bmesh_path.c tools/bmesh_path.h + tools/bmesh_region_match.c + tools/bmesh_region_match.h tools/bmesh_triangulate.c tools/bmesh_triangulate.h tools/bmesh_wireframe.c diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index 8b5250b7c1e..4efc6aa16f8 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -58,8 +58,8 @@ * * \subsection bm_loop The Loop * - * Loops define the boundary loop of a face. Each loop logically corresponds to an edge, - * which is defined by the loop and next loop's vertices. + * Each loop connects the face to one of its corner vertices, + * and also references an edge which connects this loop's vertex to the next loop's vertex. * * Loops store several handy pointers: * diff --git a/source/blender/bmesh/bmesh_tools.h b/source/blender/bmesh/bmesh_tools.h index baffeb774b6..f7f767f91bf 100644 --- a/source/blender/bmesh/bmesh_tools.h +++ b/source/blender/bmesh/bmesh_tools.h @@ -41,6 +41,7 @@ extern "C" { #include "tools/bmesh_edgenet.h" #include "tools/bmesh_edgesplit.h" #include "tools/bmesh_path.h" +#include "tools/bmesh_region_match.h" #include "tools/bmesh_triangulate.h" #ifdef __cplusplus diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index eef1e7bbb4f..e0348fea636 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -505,7 +505,7 @@ static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, return; } copy_v3_v3(target_vertex->no, source_vertex->no); - CustomData_bmesh_free_block_data(&target_mesh->vdata, &target_vertex->head.data); + CustomData_bmesh_free_block_data(&target_mesh->vdata, target_vertex->head.data); CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata, source_vertex->head.data, &target_vertex->head.data); } @@ -517,7 +517,7 @@ static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, BLI_assert(!"BMEdge: source and targer match"); return; } - CustomData_bmesh_free_block_data(&target_mesh->edata, &target_edge->head.data); + CustomData_bmesh_free_block_data(&target_mesh->edata, target_edge->head.data); CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata, source_edge->head.data, &target_edge->head.data); } @@ -529,7 +529,7 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, BLI_assert(!"BMLoop: source and targer match"); return; } - CustomData_bmesh_free_block_data(&target_mesh->ldata, &target_loop->head.data); + CustomData_bmesh_free_block_data(&target_mesh->ldata, target_loop->head.data); CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata, source_loop->head.data, &target_loop->head.data); } @@ -542,7 +542,7 @@ static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, return; } copy_v3_v3(target_face->no, source_face->no); - CustomData_bmesh_free_block_data(&target_mesh->pdata, &target_face->head.data); + CustomData_bmesh_free_block_data(&target_mesh->pdata, target_face->head.data); CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata, source_face->head.data, &target_face->head.data); target_face->mat_nr = source_face->mat_nr; diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 1f942dad048..eb7b9f78ef4 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1473,8 +1473,10 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) valence2 = bmesh_disk_count(tv); #endif + /* order of 'e_new' verts should match 'e' + * (so extruded faces don't flip) */ v_new = BM_vert_create(bm, tv->co, tv, BM_CREATE_NOP); - e_new = BM_edge_create(bm, v_new, tv, e, BM_CREATE_NOP); + e_new = BM_edge_create(bm, tv, v_new, e, BM_CREATE_NOP); bmesh_disk_edge_remove(e_new, tv); bmesh_disk_edge_remove(e_new, v_new); diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 306b6e74350..a32f28169f6 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -54,7 +54,7 @@ static void bm_data_interp_from_elem(CustomData *data_layer, BMElem *ele1, BMEle /* do nothing */ } else { - CustomData_bmesh_free_block_data(data_layer, &ele_dst->head.data); + CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data); CustomData_bmesh_copy_data(data_layer, data_layer, ele1->head.data, &ele_dst->head.data); } } @@ -63,7 +63,7 @@ static void bm_data_interp_from_elem(CustomData *data_layer, BMElem *ele1, BMEle /* do nothing */ } else { - CustomData_bmesh_free_block_data(data_layer, &ele_dst->head.data); + CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data); CustomData_bmesh_copy_data(data_layer, data_layer, ele2->head.data, &ele_dst->head.data); } } diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 91b9774634d..476878ad38c 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -338,50 +338,18 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const # define USE_IMMUTABLE_ASSERT #endif -void bmiter__vert_of_mesh_begin(struct BMIter__vert_of_mesh *iter) +void bmiter__elem_of_mesh_begin(struct BMIter__elem_of_mesh *iter) { #ifdef USE_IMMUTABLE_ASSERT - ((BMIter *)iter)->count = iter->bm->totvert; + ((BMIter *)iter)->count = BLI_mempool_count(iter->pooliter.pool); #endif - BLI_mempool_iternew(iter->bm->vpool, &iter->pooliter); + BLI_mempool_iternew(iter->pooliter.pool, &iter->pooliter); } -void *bmiter__vert_of_mesh_step(struct BMIter__vert_of_mesh *iter) +void *bmiter__elem_of_mesh_step(struct BMIter__elem_of_mesh *iter) { #ifdef USE_IMMUTABLE_ASSERT - BLI_assert(((BMIter *)iter)->count <= iter->bm->totvert); -#endif - return BLI_mempool_iterstep(&iter->pooliter); -} - -void bmiter__edge_of_mesh_begin(struct BMIter__edge_of_mesh *iter) -{ -#ifdef USE_IMMUTABLE_ASSERT - ((BMIter *)iter)->count = iter->bm->totedge; -#endif - BLI_mempool_iternew(iter->bm->epool, &iter->pooliter); -} - -void *bmiter__edge_of_mesh_step(struct BMIter__edge_of_mesh *iter) -{ -#ifdef USE_IMMUTABLE_ASSERT - BLI_assert(((BMIter *)iter)->count <= iter->bm->totedge); -#endif - return BLI_mempool_iterstep(&iter->pooliter); -} - -void bmiter__face_of_mesh_begin(struct BMIter__face_of_mesh *iter) -{ -#ifdef USE_IMMUTABLE_ASSERT - ((BMIter *)iter)->count = iter->bm->totface; -#endif - BLI_mempool_iternew(iter->bm->fpool, &iter->pooliter); -} - -void *bmiter__face_of_mesh_step(struct BMIter__face_of_mesh *iter) -{ -#ifdef USE_IMMUTABLE_ASSERT - BLI_assert(((BMIter *)iter)->count <= iter->bm->totface); + BLI_assert(((BMIter *)iter)->count <= BLI_mempool_count(iter->pooliter.pool)); #endif return BLI_mempool_iterstep(&iter->pooliter); } diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index fdf0f27f05f..44be7072e71 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -110,16 +110,7 @@ extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX]; for (ele = BM_iter_new(iter, NULL, itype, data), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++) /* iterator type structs */ -struct BMIter__vert_of_mesh { - BMesh *bm; - BLI_mempool_iter pooliter; -}; -struct BMIter__edge_of_mesh { - BMesh *bm; - BLI_mempool_iter pooliter; -}; -struct BMIter__face_of_mesh { - BMesh *bm; +struct BMIter__elem_of_mesh { BLI_mempool_iter pooliter; }; struct BMIter__edge_of_vert { @@ -173,9 +164,7 @@ typedef void *(*BMIter__step_cb) (void *); typedef struct BMIter { /* keep union first */ union { - struct BMIter__vert_of_mesh vert_of_mesh; - struct BMIter__edge_of_mesh edge_of_mesh; - struct BMIter__face_of_mesh face_of_mesh; + struct BMIter__elem_of_mesh elem_of_mesh; struct BMIter__edge_of_vert edge_of_vert; struct BMIter__face_of_vert face_of_vert; @@ -219,9 +208,7 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, c void bmiter__##name##_begin(struct BMIter__##name *iter); \ void *bmiter__##name##_step(struct BMIter__##name *iter) -BMITER_CB_DEF(vert_of_mesh); -BMITER_CB_DEF(edge_of_mesh); -BMITER_CB_DEF(face_of_mesh); +BMITER_CB_DEF(elem_of_mesh); BMITER_CB_DEF(edge_of_vert); BMITER_CB_DEF(face_of_vert); BMITER_CB_DEF(loop_of_vert); @@ -237,4 +224,12 @@ BMITER_CB_DEF(loop_of_face); #include "intern/bmesh_iterators_inline.h" +#define BM_ITER_CHECK_TYPE_DATA(data) \ + CHECK_TYPE_ANY(data, void *, BMFace *, BMEdge *, BMVert *, BMLoop *, BMElem *) + +#define BM_iter_new(iter, bm, itype, data) \ + (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_new(iter, bm, itype, data)) +#define BM_iter_init(iter, bm, itype, data) \ + (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_init(iter, bm, itype, data)) + #endif /* __BMESH_ITERATORS_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h index b9733d4702f..d3e18b97acb 100644 --- a/source/blender/bmesh/intern/bmesh_iterators_inline.h +++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h @@ -60,23 +60,23 @@ BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *da case BM_VERTS_OF_MESH: BLI_assert(bm != NULL); BLI_assert(data == NULL); - iter->begin = (BMIter__begin_cb)bmiter__vert_of_mesh_begin; - iter->step = (BMIter__step_cb)bmiter__vert_of_mesh_step; - iter->data.vert_of_mesh.bm = bm; + iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin; + iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step; + iter->data.elem_of_mesh.pooliter.pool = bm->vpool; break; case BM_EDGES_OF_MESH: BLI_assert(bm != NULL); BLI_assert(data == NULL); - iter->begin = (BMIter__begin_cb)bmiter__edge_of_mesh_begin; - iter->step = (BMIter__step_cb)bmiter__edge_of_mesh_step; - iter->data.edge_of_mesh.bm = bm; + iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin; + iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step; + iter->data.elem_of_mesh.pooliter.pool = bm->epool; break; case BM_FACES_OF_MESH: BLI_assert(bm != NULL); BLI_assert(data == NULL); - iter->begin = (BMIter__begin_cb)bmiter__face_of_mesh_begin; - iter->step = (BMIter__step_cb)bmiter__face_of_mesh_step; - iter->data.face_of_mesh.bm = bm; + iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin; + iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step; + iter->data.elem_of_mesh.pooliter.pool = bm->fpool; break; case BM_EDGES_OF_VERT: BLI_assert(data != NULL); diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 19e6f646564..ee35d8cd1d2 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -537,7 +537,7 @@ void BM_mesh_select_mode_set(BMesh *bm, int selectmode) * counts number of elements with flag enabled/disabled */ static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag, - const short respecthide, const bool test_for_enabled) + const bool respecthide, const bool test_for_enabled) { BMElem *ele; BMIter iter; diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 6e8591da0f3..72d25413f09 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -265,7 +265,8 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f_a, BMFace *f_b, BMEdge *e, const * * \param bm The bmesh * \param f the original face - * \param v1, v2 vertices which define the split edge, must be different + * \param l_a, l_b Loops of this face, their vertices define + * the split edge to be created (must be differ and not can't be adjacent in the face). * \param r_l pointer which will receive the BMLoop for the split edge in the new face * \param example Edge used for attributes of splitting edge, if non-NULL * \param nodouble Use an existing edge if found @@ -348,7 +349,7 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, * \param l_a, l_b vertices which define the split edge, must be different * \param cos Array of coordinates for intermediate points * \param n Length of \a cos (must be > 0) - * \param r_l pointer which will receive the BMLoop for the first split edge (from \a v1) in the new face + * \param r_l pointer which will receive the BMLoop for the first split edge (from \a l_a) in the new face * \param example Edge used for attributes of splitting edge, if non-NULL * * \return Pointer to the newly created face representing one side of the split diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index d8be55ce7c2..e2be90e7baf 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -104,6 +104,7 @@ static BMOpDefine bmo_smooth_vert_def = { "smooth_vert", /* slots_in */ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"factor", BMO_OP_SLOT_FLT}, /* smoothing factor */ {"mirror_clip_x", BMO_OP_SLOT_BOOL}, /* set vertices close to the x axis before the operation to 0 */ {"mirror_clip_y", BMO_OP_SLOT_BOOL}, /* set vertices close to the y axis before the operation to 0 */ {"mirror_clip_z", BMO_OP_SLOT_BOOL}, /* set vertices close to the z axis before the operation to 0 */ diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 9a1914b5596..a8e1acd9c71 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -666,49 +666,25 @@ static bool line_crosses_v2f(const float v1[2], const float v2[2], const float v */ bool BM_face_point_inside_test(BMFace *f, const float co[3]) { - int ax, ay; - float co2[2], cent[2] = {0.0f, 0.0f}, out[2] = {FLT_MAX * 0.5f, FLT_MAX * 0.5f}; + float axis_mat[3][3]; + float (*projverts)[2] = BLI_array_alloca(projverts, f->len); + + float co_2d[2]; BMLoop *l_iter; - BMLoop *l_first; - int crosses = 0; - float onepluseps = 1.0f + (float)FLT_EPSILON * 150.0f; + int i; if (is_zero_v3(f->no)) BM_face_normal_update(f); - - /* find best projection of face XY, XZ or YZ: barycentric weights of - * the 2d projected coords are the same and faster to compute - * - * this probably isn't all that accurate, but it has the advantage of - * being fast (especially compared to projecting into the face orientation) - */ - axis_dominant_v3(&ax, &ay, f->no); - - co2[0] = co[ax]; - co2[1] = co[ay]; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - cent[0] += l_iter->v->co[ax]; - cent[1] += l_iter->v->co[ay]; - } while ((l_iter = l_iter->next) != l_first); - - mul_v2_fl(cent, 1.0f / (float)f->len); - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - float v1[2], v2[2]; - - v1[0] = (l_iter->prev->v->co[ax] - cent[0]) * onepluseps + cent[0]; - v1[1] = (l_iter->prev->v->co[ay] - cent[1]) * onepluseps + cent[1]; - - v2[0] = (l_iter->v->co[ax] - cent[0]) * onepluseps + cent[0]; - v2[1] = (l_iter->v->co[ay] - cent[1]) * onepluseps + cent[1]; - - crosses += line_crosses_v2f(v1, v2, co2, out) != 0; - } while ((l_iter = l_iter->next) != l_first); - - return crosses % 2 != 0; + + axis_dominant_v3_to_m3(axis_mat, f->no); + + mul_v2_m3v3(co_2d, axis_mat, co); + + for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) { + mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); + } + + return isect_point_poly_v2(co_2d, (const float (*)[2])projverts, f->len, false); } /** diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 685e5443583..40e0356e14c 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -311,7 +311,7 @@ BMLoop *BM_vert_find_first_loop(BMVert *v) { BMEdge *e; - if (!v || !v->e) + if (!v->e) return NULL; e = bmesh_disk_faceedge_find_first(v->e, v); diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index d8313dab36f..3e8002c0192 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -108,6 +108,7 @@ bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) * - #bmesh_radial_append * - #bmesh_radial_loop_remove * - #bmesh_radial_facevert_count + * - #bmesh_radial_facevert_check * - #bmesh_radial_faceloop_find_first * - #bmesh_radial_faceloop_find_next * - #bmesh_radial_validate @@ -265,7 +266,7 @@ BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) { const BMEdge *e_find = e; do { - if (e_find->l && bmesh_radial_facevert_count(e_find->l, v)) { + if (e_find->l && bmesh_radial_facevert_check(e_find->l, v)) { return (BMEdge *)e_find; } } while ((e_find = bmesh_disk_edge_next(e_find, v)) != e); @@ -275,10 +276,10 @@ BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) { - BMEdge *e_find = NULL; + BMEdge *e_find; e_find = bmesh_disk_edge_next(e, v); do { - if (e_find->l && bmesh_radial_facevert_count(e_find->l, v)) { + if (e_find->l && bmesh_radial_facevert_check(e_find->l, v)) { return e_find; } } while ((e_find = bmesh_disk_edge_next(e_find, v)) != e); @@ -455,6 +456,24 @@ int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) return count; } +/** + * \brief RADIAL CHECK FACE VERT + * + * Quicker check for ``bmesh_radial_facevert_count(...) != 0`` + */ +bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) +{ + const BMLoop *l_iter; + l_iter = l; + do { + if (l_iter->v == v) { + return true; + } + } while ((l_iter = l_iter->radial_next) != l); + + return false; +} + /*****loop cycle functions, e.g. loops surrounding a face**** */ bool bmesh_loop_validate(BMFace *f) { diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h index d2ad655ae75..29868194bbf 100644 --- a/source/blender/bmesh/intern/bmesh_structure.h +++ b/source/blender/bmesh/intern/bmesh_structure.h @@ -61,6 +61,7 @@ void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e) ATTR_NONNULL(1); * just use member access l->radial_next, l->radial_prev now */ int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index fc507cdbd21..0d9ce4b2731 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -32,6 +32,7 @@ #include "BLI_rand.h" #include "BLI_array.h" #include "BLI_noise.h" +#include "BLI_stack.h" #include "BKE_customdata.h" @@ -766,8 +767,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BMOpSlot *einput; const SubDPattern *pat; SubDParams params; - SubDFaceData *facedata = NULL; - BLI_array_declare(facedata); + BLI_Stack *facedata; BMIter viter, fiter, liter; BMVert *v, **verts = NULL; BMEdge *edge; @@ -782,7 +782,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_declare(verts); float smooth, fractal, along_normal; bool use_sphere, use_single_edge, use_grid_fill, use_only_quads; - int cornertype, seed, i, j, matched, a, b, numcuts, totesel, smooth_falloff; + int cornertype, seed, i, j, a, b, numcuts, totesel, smooth_falloff; BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT); @@ -875,9 +875,12 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BM_EDGE, EDGE_PERCENT); + facedata = BLI_stack_new(sizeof(SubDFaceData), __func__); + BM_ITER_MESH (face, &fiter, bm, BM_FACES_OF_MESH) { BMEdge *e1 = NULL, *e2 = NULL; float vec1[3], vec2[3]; + bool matched = false; /* skip non-quads if requested */ if (use_only_quads && face->len != 4) @@ -891,8 +894,6 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_grow_items(edges, face->len); BLI_array_grow_items(verts, face->len); - matched = 0; - totesel = 0; BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, i) { edges[i] = l_new->e; @@ -930,12 +931,13 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } } if (matched) { - BLI_array_grow_one(facedata); - b = BLI_array_count(facedata) - 1; - facedata[b].pat = pat; - facedata[b].start = verts[i]; - facedata[b].face = face; - facedata[b].totedgesel = totesel; + SubDFaceData *fd; + + fd = BLI_stack_push_r(facedata); + fd->pat = pat; + fd->start = verts[i]; + fd->face = face; + fd->totedgesel = totesel; BMO_elem_flag_enable(bm, face, SUBD_SPLIT); break; } @@ -966,15 +968,15 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } } if (matched) { - BLI_array_grow_one(facedata); - j = BLI_array_count(facedata) - 1; + SubDFaceData *fd; BMO_elem_flag_enable(bm, face, SUBD_SPLIT); - facedata[j].pat = pat; - facedata[j].start = verts[a]; - facedata[j].face = face; - facedata[j].totedgesel = totesel; + fd = BLI_stack_push_r(facedata); + fd->pat = pat; + fd->start = verts[a]; + fd->face = face; + fd->totedgesel = totesel; break; } } @@ -982,16 +984,16 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } if (!matched && totesel) { - BLI_array_grow_one(facedata); - j = BLI_array_count(facedata) - 1; + SubDFaceData *fd; BMO_elem_flag_enable(bm, face, SUBD_SPLIT); /* must initialize all members here */ - facedata[j].start = NULL; - facedata[j].pat = NULL; - facedata[j].totedgesel = totesel; - facedata[j].face = face; + fd = BLI_stack_push_r(facedata); + fd->start = NULL; + fd->pat = NULL; + fd->totedgesel = totesel; + fd->face = face; } } @@ -1009,16 +1011,17 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) copy_v3_v3(v->co, co); } - i = 0; - for (i = 0; i < BLI_array_count(facedata); i++) { - face = facedata[i].face; + for (; !BLI_stack_is_empty(facedata); BLI_stack_discard(facedata)) { + SubDFaceData *fd = BLI_stack_peek(facedata); + + face = fd->face; /* figure out which pattern to use */ BLI_array_empty(verts); - pat = facedata[i].pat; + pat = fd->pat; - if (!pat && facedata[i].totedgesel == 2) { + if (!pat && fd->totedgesel == 2) { int vlen; /* ok, no pattern. we still may be able to do something */ @@ -1131,7 +1134,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) a = 0; BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) { - if (l_new->v == facedata[i].start) { + if (l_new->v == fd->start) { a = j + 1; break; } @@ -1156,7 +1159,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey); - if (facedata) BLI_array_free(facedata); + BLI_stack_free(facedata); if (edges) BLI_array_free(edges); if (verts) BLI_array_free(verts); BLI_array_free(loops_split); diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index d2d1c0854de..a06d40c8c0f 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -291,6 +291,7 @@ void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op) BMEdge *e; float (*cos)[3] = MEM_mallocN(sizeof(*cos) * BMO_slot_buffer_count(op->slots_in, "verts"), __func__); float *co, *co2, clip_dist = BMO_slot_float_get(op->slots_in, "clip_dist"); + const float fac = BMO_slot_float_get(op->slots_in, "factor"); int i, j, clipx, clipy, clipz; int xaxis, yaxis, zaxis; @@ -322,7 +323,7 @@ void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op) } mul_v3_fl(co, 1.0f / (float)j); - mid_v3_v3v3(co, co, v->co); + interp_v3_v3v3(co, v->co, co, fac); if (clipx && fabsf(v->co[0]) <= clip_dist) co[0] = 0.0f; diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c index ae9b882cea0..ed9e8783037 100644 --- a/source/blender/bmesh/tools/bmesh_bisect_plane.c +++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c @@ -53,7 +53,7 @@ /* -------------------------------------------------------------------- */ /* Math utils */ -static int plane_point_test_v3(const float plane[4], const float co[3], const float eps, float *r_depth) +static short plane_point_test_v3(const float plane[4], const float co[3], const float eps, float *r_depth) { const float f = plane_point_side_v3(plane, co); *r_depth = f; @@ -69,7 +69,8 @@ static int plane_point_test_v3(const float plane[4], const float co[3], const fl * later we may want to move this into some hash lookup * to a separate struct, but for now we can store in BMesh data */ -#define BM_VERT_DIR(v) ((v)->head.index) /* Direction -1/0/1 */ +#define BM_VERT_DIR(v) ((short *)(&(v)->head.index))[0] /* Direction -1/0/1 */ +#define BM_VERT_SKIP(v) ((short *)(&(v)->head.index))[1] /* Skip Vert 0/1 */ #define BM_VERT_DIST(v) ((v)->no[0]) /* Distance from the plane. */ #define BM_VERT_SORTVAL(v) ((v)->no[1]) /* Temp value for sorting. */ #define BM_VERT_LOOPINDEX(v) /* The verts index within a face (temp var) */ \ @@ -117,6 +118,7 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con STACK_DECLARE(vert_split_arr); BMLoop *l_iter, *l_first; bool use_dirs[3] = {false, false, false}; + bool is_inside = false; STACK_INIT(vert_split_arr, f_len_orig); @@ -129,6 +131,11 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con do { if (vert_is_center_test(l_iter->v)) { BLI_assert(BM_VERT_DIR(l_iter->v) == 0); + + /* if both are -1 or 1, or both are zero: + * don't flip 'inside' var while walking */ + BM_VERT_SKIP(l_iter->v) = (((BM_VERT_DIR(l_iter->prev->v) ^ BM_VERT_DIR(l_iter->next->v))) == 0); + STACK_PUSH(vert_split_arr, l_iter->v); } use_dirs[BM_VERT_DIR(l_iter->v) + 1] = true; @@ -230,15 +237,12 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con for (i = 0; i < STACK_SIZE(vert_split_arr) - 1; i++) { BMVert *v_a = vert_split_arr[i]; BMVert *v_b = vert_split_arr[i + 1]; - float co_mid[2]; - /* geometric test before doing face lookups, - * find if the split spans a filled region of the polygon. */ - mid_v2_v2v2(co_mid, - face_verts_proj_2d[BM_VERT_LOOPINDEX(v_a)], - face_verts_proj_2d[BM_VERT_LOOPINDEX(v_b)]); + if (!BM_VERT_SKIP(v_a)) { + is_inside = !is_inside; + } - if (isect_point_poly_v2(co_mid, (const float (*)[2])face_verts_proj_2d, f_len_orig, false)) { + if (is_inside) { BMLoop *l_a, *l_b; bool found = false; unsigned int j; @@ -254,7 +258,8 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con } } - BLI_assert(found == true); + /* ideally wont happen, but it can for self intersecting faces */ + // BLI_assert(found == true); /* in fact this simple test is good enough, * test if the loops are adjacent */ diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c new file mode 100644 index 00000000000..050d5ae4808 --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -0,0 +1,1511 @@ +/* + * ***** 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/tools/bmesh_region_match.c + * \ingroup bmesh + * + * Given a contiguous region of faces, + * find multiple matching regions (based on topology) and return them. + * + * Implementation: + * + * - Given a face region, find its topological center. + * - Compare this with other vertices surrounding geometry with this ones. + * (reduce the search space by creating a connectivity ID per vertex + * and only run comprehensive tests on those). + * - All hashes must be order independent so matching topology can be identified. + * - The term UUID here doesn't mean each ID is initially unique. + * (uniqueness is improved by re-hashing with connected data). + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" +#include "BLI_listbase.h" +#include "BLI_linklist.h" +#include "BLI_alloca.h" +#include "BLI_ghash.h" +#include "BLI_mempool.h" +#include "BLI_linklist_stack.h" + +#include "bmesh.h" + +#include "tools/bmesh_region_match.h" /* own incldue */ + +/* avoid re-creating ghash and pools for each search */ +#define USE_WALKER_REUSE + +/* do a first-pass id of all vertices, + * this avoids expensive checks on every item later on + * (works fine without, just slower) */ +#define USE_PIVOT_FASTMATCH + +/* otherwise use active element as pivot, for quick tests only */ +#define USE_PIVOT_SEARCH + +// #define DEBUG_TIME +// #define DEBUG_PRINT + +#ifdef DEBUG_TIME +# include "PIL_time.h" +# include "PIL_time_utildefines.h" +#endif + +#include "BLI_strict_flags.h" + + +/* -------------------------------------------------------------------- */ +/* UUID-Walk API */ + +/** \name Internal UUIDWalk API + * \{ */ + +#define PRIME_VERT_INIT 100003 + +typedef uintptr_t UUID_Int; + +typedef struct UUIDWalk { + + /* List of faces we can step onto (UUIDFaceStep's) */ + ListBase faces_step; + + /* Face & Vert UUID's */ + GHash *verts_uuid; + GHash *faces_uuid; + + /* memory pool for LinkNode's */ + BLI_mempool *link_pool; + + /* memory pool for LinkBase's */ + BLI_mempool *lbase_pool; + + /* memory pool for UUIDFaceStep's */ + BLI_mempool *step_pool; + BLI_mempool *step_pool_items; + + /* Optionaly use face-tag to isolate search */ + bool use_face_isolate; + + /* Increment for each pass added */ + UUID_Int pass; + + /* runtime vars, aviod re-creating each pass */ + struct { + GHash *verts_uuid; /* BMVert -> UUID */ + GSet *faces_step; /* BMFace */ + + GHash *faces_from_uuid; /* UUID -> UUIDFaceStepItem */ + + UUID_Int *rehash_store; + unsigned int rehash_store_len; + } cache; + +} UUIDWalk; + +/* stores a set of potential faces to step onto */ +typedef struct UUIDFaceStep { + struct UUIDFaceStep *next, *prev; + + /* unsorted 'BMFace' */ + LinkNode *faces; + + /* faces sorted into 'UUIDFaceStepItem' */ + ListBase items; +} UUIDFaceStep; + +/* store face-lists with same uuid */ +typedef struct UUIDFaceStepItem { + struct UUIDFaceStepItem *next, *prev; + uintptr_t uuid; + + LinkNode *list; + unsigned int list_len; +} UUIDFaceStepItem; + +BLI_INLINE bool bm_uuidwalk_face_test( + UUIDWalk *uuidwalk, BMFace *f) +{ + if (uuidwalk->use_face_isolate) { + return BM_elem_flag_test_bool(f, BM_ELEM_TAG); + } + else { + return true; + } +} + +BLI_INLINE bool bm_uuidwalk_vert_lookup( + UUIDWalk *uuidwalk, BMVert *v, UUID_Int *r_uuid) +{ + void **ret; + ret = BLI_ghash_lookup_p(uuidwalk->verts_uuid, v); + if (ret) { + *r_uuid = (UUID_Int)(*ret); + return true; + } + else { + return false; + } +} + +BLI_INLINE bool bm_uuidwalk_face_lookup( + UUIDWalk *uuidwalk, BMFace *f, UUID_Int *r_uuid) +{ + void **ret; + ret = BLI_ghash_lookup_p(uuidwalk->faces_uuid, f); + if (ret) { + *r_uuid = (UUID_Int)(*ret); + return true; + } + else { + return false; + } +} + +static unsigned int ghashutil_bmelem_indexhash(const void *key) +{ + const BMElem *ele = key; + return (unsigned int)BM_elem_index_get(ele); +} + +static bool ghashutil_bmelem_indexcmp(const void *a, const void *b) +{ + BLI_assert((a != b) == (BM_elem_index_get((BMElem *)a) != BM_elem_index_get((BMElem *)b))); + return (a != b); +} + +static GHash *ghash_bmelem_new_ex(const char *info, + const unsigned int nentries_reserve) +{ + return BLI_ghash_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve); +} + +static GSet *gset_bmelem_new_ex(const char *info, + const unsigned int nentries_reserve) +{ + return BLI_gset_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve); +} + + +static GHash *ghash_bmelem_new(const char *info) +{ + return ghash_bmelem_new_ex(info, 0); +} + +static GSet *gset_bmelem_new(const char *info) +{ + return gset_bmelem_new_ex(info, 0); +} + + +static void bm_uuidwalk_init( + UUIDWalk *uuidwalk, + const unsigned int faces_src_region_len, + const unsigned int verts_src_region_len) +{ + BLI_listbase_clear(&uuidwalk->faces_step); + + uuidwalk->verts_uuid = ghash_bmelem_new_ex(__func__, verts_src_region_len); + uuidwalk->faces_uuid = ghash_bmelem_new_ex(__func__, faces_src_region_len); + + uuidwalk->cache.verts_uuid = ghash_bmelem_new(__func__); + uuidwalk->cache.faces_step = gset_bmelem_new(__func__); + + /* works because 'int' ghash works for intptr_t too */ + uuidwalk->cache.faces_from_uuid = BLI_ghash_int_new(__func__); + + uuidwalk->cache.rehash_store = NULL; + uuidwalk->cache.rehash_store_len = 0; + + uuidwalk->use_face_isolate = false; + + /* smaller pool's for faster clearing */ + uuidwalk->link_pool = BLI_mempool_create(sizeof(LinkNode), 64, 64, BLI_MEMPOOL_NOP); + uuidwalk->step_pool = BLI_mempool_create(sizeof(UUIDFaceStep), 64, 64, BLI_MEMPOOL_NOP); + uuidwalk->step_pool_items = BLI_mempool_create(sizeof(UUIDFaceStepItem), 64, 64, BLI_MEMPOOL_NOP); + + uuidwalk->pass = 1; +} + +static void bm_uuidwalk_clear( + UUIDWalk *uuidwalk) +{ + BLI_listbase_clear(&uuidwalk->faces_step); + + BLI_ghash_clear(uuidwalk->verts_uuid, NULL, NULL); + BLI_ghash_clear(uuidwalk->faces_uuid, NULL, NULL); + + BLI_ghash_clear(uuidwalk->cache.verts_uuid, NULL, NULL); + BLI_gset_clear(uuidwalk->cache.faces_step, NULL); + BLI_ghash_clear(uuidwalk->cache.faces_from_uuid, NULL, NULL); + + /* keep rehash_store as-is, for reuse */ + + uuidwalk->use_face_isolate = false; + + BLI_mempool_clear(uuidwalk->link_pool); + BLI_mempool_clear(uuidwalk->step_pool); + BLI_mempool_clear(uuidwalk->step_pool_items); + + uuidwalk->pass = 1; +} + +static void bm_uuidwalk_free( + UUIDWalk *uuidwalk) +{ + /** + * Handled by pools + * + * - uuidwalk->faces_step + */ + + BLI_ghash_free(uuidwalk->verts_uuid, NULL, NULL); + BLI_ghash_free(uuidwalk->faces_uuid, NULL, NULL); + + /* cache */ + BLI_ghash_free(uuidwalk->cache.verts_uuid, NULL, NULL); + BLI_gset_free(uuidwalk->cache.faces_step, NULL); + BLI_ghash_free(uuidwalk->cache.faces_from_uuid, NULL, NULL); + MEM_SAFE_FREE(uuidwalk->cache.rehash_store); + + BLI_mempool_destroy(uuidwalk->link_pool); + BLI_mempool_destroy(uuidwalk->step_pool); + BLI_mempool_destroy(uuidwalk->step_pool_items); +} + +static UUID_Int bm_uuidwalk_calc_vert_uuid( + UUIDWalk *uuidwalk, BMVert *v) +{ +#define PRIME_VERT_SMALL 7 +#define PRIME_VERT_MID 43 +#define PRIME_VERT_LARGE 1031 + +#define PRIME_FACE_SMALL 13 +#define PRIME_FACE_MID 53 + + UUID_Int uuid; + + uuid = uuidwalk->pass * PRIME_VERT_LARGE; + + /* vert -> other */ + { + unsigned int tot = 0; + BMIter eiter; + BMEdge *e; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + BMVert *v_other = BM_edge_other_vert(e, v); + UUID_Int uuid_other; + if (bm_uuidwalk_vert_lookup(uuidwalk, v_other, &uuid_other)) { + uuid ^= (uuid_other * PRIME_VERT_SMALL); + tot += 1; + } + } + uuid ^= (tot * PRIME_VERT_MID); + } + + /* faces */ + { + unsigned int tot = 0; + BMIter iter; + BMFace *f; + + BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { + UUID_Int uuid_other; + if (bm_uuidwalk_face_lookup(uuidwalk, f, &uuid_other)) { + uuid ^= (uuid_other * PRIME_FACE_SMALL); + tot += 1; + } + } + uuid ^= (tot * PRIME_FACE_MID); + } + + return uuid; + +#undef PRIME_VERT_SMALL +#undef PRIME_VERT_MID +#undef PRIME_VERT_LARGE + +#undef PRIME_FACE_SMALL +#undef PRIME_FACE_MID +} + +static UUID_Int bm_uuidwalk_calc_face_uuid( + UUIDWalk *uuidwalk, BMFace *f) +{ +#define PRIME_VERT_SMALL 11 + +#define PRIME_FACE_SMALL 17 +#define PRIME_FACE_LARGE 1013 + + UUID_Int uuid; + + uuid = uuidwalk->pass * (unsigned int)f->len * PRIME_FACE_LARGE; + + /* face-verts */ + { + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + UUID_Int uuid_other; + if (bm_uuidwalk_vert_lookup(uuidwalk, l_iter->v, &uuid_other)) { + uuid ^= (uuid_other * PRIME_VERT_SMALL); + } + } while ((l_iter = l_iter->next) != l_first); + } + + /* face-faces (connected by edge) */ + { + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (l_iter->radial_next != l_iter) { + BMLoop *l_iter_radial = l_iter->radial_next; + do { + UUID_Int uuid_other; + if (bm_uuidwalk_face_lookup(uuidwalk, l_iter_radial->f, &uuid_other)) { + uuid ^= (uuid_other * PRIME_FACE_SMALL); + } + } while ((l_iter_radial = l_iter_radial->radial_next) != l_iter); + } + } while ((l_iter = l_iter->next) != l_first); + } + + return uuid; + +#undef PRIME_VERT_SMALL + +#undef PRIME_FACE_SMALL +#undef PRIME_FACE_LARGE +} + +static void bm_uuidwalk_rehash_reserve( + UUIDWalk *uuidwalk, unsigned int rehash_store_len_new) +{ + if (UNLIKELY(rehash_store_len_new > uuidwalk->cache.rehash_store_len)) { + /* avoid re-allocs */ + rehash_store_len_new *= 2; + uuidwalk->cache.rehash_store = + MEM_reallocN(uuidwalk->cache.rehash_store, + rehash_store_len_new * sizeof(*uuidwalk->cache.rehash_store)); + uuidwalk->cache.rehash_store_len = rehash_store_len_new; + } +} + +/** + * Re-hash all elements, delay updating so as not to create feedback loop. + */ +static void bm_uuidwalk_rehash( + UUIDWalk *uuidwalk) +{ + GHashIterator gh_iter; + UUID_Int *uuid_store; + unsigned int i; + + unsigned int rehash_store_len_new = (unsigned int)MAX2(BLI_ghash_size(uuidwalk->verts_uuid), + BLI_ghash_size(uuidwalk->faces_uuid)); + + bm_uuidwalk_rehash_reserve(uuidwalk, rehash_store_len_new); + uuid_store = uuidwalk->cache.rehash_store; + + /* verts */ + i = 0; + GHASH_ITER (gh_iter, uuidwalk->verts_uuid) { + BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + uuid_store[i++] = bm_uuidwalk_calc_vert_uuid(uuidwalk, v); + } + i = 0; + GHASH_ITER (gh_iter, uuidwalk->verts_uuid) { + void **uuid_p = BLI_ghashIterator_getValue_p(&gh_iter); + *((UUID_Int *)uuid_p) = uuid_store[i++]; + } + + /* faces */ + i = 0; + GHASH_ITER (gh_iter, uuidwalk->faces_uuid) { + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + uuid_store[i++] = bm_uuidwalk_calc_face_uuid(uuidwalk, f); + } + i = 0; + GHASH_ITER (gh_iter, uuidwalk->faces_uuid) { + void **uuid_p = BLI_ghashIterator_getValue_p(&gh_iter); + *((UUID_Int *)uuid_p) = uuid_store[i++]; + } +} + +static void bm_uuidwalk_rehash_facelinks( + UUIDWalk *uuidwalk, + LinkNode *faces, const unsigned int faces_len, + const bool is_init) +{ + UUID_Int *uuid_store; + LinkNode *f_link; + unsigned int i; + + bm_uuidwalk_rehash_reserve(uuidwalk, faces_len); + uuid_store = uuidwalk->cache.rehash_store; + + i = 0; + for (f_link = faces; f_link; f_link = f_link->next) { + BMFace *f = f_link->link; + uuid_store[i++] = bm_uuidwalk_calc_face_uuid(uuidwalk, f); + } + + i = 0; + if (is_init) { + for (f_link = faces; f_link; f_link = f_link->next) { + BMFace *f = f_link->link; + BLI_ghash_insert(uuidwalk->faces_uuid, f, (void *)uuid_store[i++]); + } + } + else { + for (f_link = faces; f_link; f_link = f_link->next) { + BMFace *f = f_link->link; + void **uuid_p = BLI_ghash_lookup_p(uuidwalk->faces_uuid, f); + *((UUID_Int *)uuid_p) = uuid_store[i++]; + } + } +} + +static bool bm_vert_is_uuid_connect( + UUIDWalk *uuidwalk, BMVert *v) +{ + BMIter eiter; + BMEdge *e; + + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + BMVert *v_other = BM_edge_other_vert(e, v); + if (BLI_ghash_haskey(uuidwalk->verts_uuid, v_other)) { + return true; + } + } + return false; +} + +static void bm_uuidwalk_pass_add( + UUIDWalk *uuidwalk, LinkNode *faces_pass, const unsigned int faces_pass_len) +{ + GHashIterator gh_iter; + GHash *verts_uuid_pass; + GSet *faces_step_next; + LinkNode *f_link; + + UUIDFaceStep *fstep; + + BLI_assert(faces_pass_len == (unsigned int)BLI_linklist_length(faces_pass)); + + /* rehash faces now all their verts have been added */ + bm_uuidwalk_rehash_facelinks(uuidwalk, faces_pass, faces_pass_len, true); + + /* create verts_new */ + verts_uuid_pass = uuidwalk->cache.verts_uuid; + faces_step_next = uuidwalk->cache.faces_step; + + BLI_assert(BLI_ghash_size(verts_uuid_pass) == 0); + BLI_assert(BLI_gset_size(faces_step_next) == 0); + + /* Add the face_step data from connected faces, creating new passes */ + fstep = BLI_mempool_alloc(uuidwalk->step_pool); + BLI_addhead(&uuidwalk->faces_step, fstep); + fstep->faces = NULL; + BLI_listbase_clear(&fstep->items); + + for (f_link = faces_pass; f_link; f_link = f_link->next) { + BMFace *f = f_link->link; + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + /* fill verts_new */ + if (!BLI_ghash_haskey(uuidwalk->verts_uuid, l_iter->v) && + !BLI_ghash_haskey(verts_uuid_pass, l_iter->v) && + (bm_vert_is_uuid_connect(uuidwalk, l_iter->v) == true)) + { + const UUID_Int uuid = bm_uuidwalk_calc_vert_uuid(uuidwalk, l_iter->v); + BLI_ghash_insert(verts_uuid_pass, l_iter->v, (void *)uuid); + } + + /* fill faces_step_next */ + if (l_iter->radial_next != l_iter) { + BMLoop *l_iter_radial = l_iter->radial_next; + do { + if (!BLI_ghash_haskey(uuidwalk->faces_uuid, l_iter_radial->f) && + !BLI_gset_haskey(faces_step_next, l_iter_radial->f) && + (bm_uuidwalk_face_test(uuidwalk, l_iter_radial->f))) + { + BLI_gset_insert(faces_step_next, l_iter_radial->f); + + /* add to fstep */ + BLI_linklist_prepend_pool(&fstep->faces, l_iter_radial->f, uuidwalk->link_pool); + } + } while ((l_iter_radial = l_iter_radial->radial_next) != l_iter); + } + } while ((l_iter = l_iter->next) != l_first); + } + + /* faces_uuid.update(verts_new) */ + GHASH_ITER (gh_iter, verts_uuid_pass) { + BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + void *uuid_p = BLI_ghashIterator_getValue(&gh_iter); + BLI_ghash_insert(uuidwalk->verts_uuid, v, uuid_p); + } + + /* rehash faces now all their verts have been added */ + bm_uuidwalk_rehash_facelinks(uuidwalk, faces_pass, faces_pass_len, false); + + uuidwalk->pass += 1; + + BLI_ghash_clear(uuidwalk->cache.verts_uuid, NULL, NULL); + BLI_gset_clear(uuidwalk->cache.faces_step, NULL); +} + +static int bm_face_len_cmp(const void *v1, const void *v2) +{ + const BMFace *f1 = v1, *f2 = v2; + + if (f1->len > f2->len) return 1; + else if (f1->len < f2->len) return -1; + else return 0; +} + +static unsigned int bm_uuidwalk_init_from_edge( + UUIDWalk *uuidwalk, BMEdge *e) +{ + BMLoop *l_iter = e->l; + unsigned int f_arr_len = (unsigned int)BM_edge_face_count(e); + BMFace **f_arr = BLI_array_alloca(f_arr, f_arr_len); + unsigned int fstep_num = 0, i = 0; + + do { + BMFace *f = l_iter->f; + if (bm_uuidwalk_face_test(uuidwalk, f)) { + f_arr[i++] = f; + } + } while ((l_iter = l_iter->radial_next) != e->l); + BLI_assert(i <= f_arr_len); + f_arr_len = i; + + qsort(f_arr, f_arr_len, sizeof(*f_arr), bm_face_len_cmp); + + /* start us off! */ + { + const UUID_Int uuid = PRIME_VERT_INIT; + BLI_ghash_insert(uuidwalk->verts_uuid, e->v1, (void *)uuid); + BLI_ghash_insert(uuidwalk->verts_uuid, e->v2, (void *)uuid); + } + + /* turning an array into LinkNode's seems odd, + * but this is just for initialization, + * elsewhere using LinkNode's makes more sense */ + for (i = 0; i < f_arr_len; i++) { + LinkNode *faces_pass = NULL; + const int f_len = f_arr[i]->len; + + do { + BLI_linklist_prepend_pool(&faces_pass, f_arr[i++], uuidwalk->link_pool); + } while (i < f_arr_len && (f_len == f_arr[i]->len)); + + bm_uuidwalk_pass_add(uuidwalk, faces_pass, i); + BLI_linklist_free_pool(faces_pass, NULL, uuidwalk->link_pool); + fstep_num += 1; + } + + return fstep_num; +} + +#undef PRIME_VERT_INIT + +/** \} */ + + +/** \name Internal UUIDFaceStep API + * \{ */ + +static int facestep_sort(const void *a, const void *b) +{ + const UUIDFaceStepItem *fstep_a = a; + const UUIDFaceStepItem *fstep_b = b; + return (fstep_a->uuid > fstep_b->uuid) ? 1 : 0; +} + +/** + * Put faces in lists based on their uuid's, + * re-run for each pass since rehashing may differentiate face-groups. + */ +static bool bm_uuidwalk_facestep_begin( + UUIDWalk *uuidwalk, UUIDFaceStep *fstep) +{ + LinkNode *f_link, *f_link_next, **f_link_prev_p; + bool ok = false; + + BLI_assert(BLI_ghash_size(uuidwalk->cache.faces_from_uuid) == 0); + BLI_assert(BLI_countlist(&fstep->items) == 0); + + f_link_prev_p = &fstep->faces; + for (f_link = fstep->faces; f_link; f_link = f_link_next) { + BMFace *f = f_link->link; + f_link_next = f_link->next; + + /* possible another pass added this face already, free in that case */ + if (!BLI_ghash_haskey(uuidwalk->faces_uuid, f)) { + const UUID_Int uuid = bm_uuidwalk_calc_face_uuid(uuidwalk, f); + UUIDFaceStepItem *fstep_item; + + ok = true; + + fstep_item = BLI_ghash_lookup(uuidwalk->cache.faces_from_uuid, (void *)uuid); + if (UNLIKELY(fstep_item == NULL)) { + fstep_item = BLI_mempool_alloc(uuidwalk->step_pool_items); + BLI_ghash_insert(uuidwalk->cache.faces_from_uuid, (void *)uuid, fstep_item); + + /* add to start, so its handled on the next round of passes */ + BLI_addhead(&fstep->items, fstep_item); + fstep_item->uuid = uuid; + fstep_item->list = NULL; + fstep_item->list_len = 0; + } + + BLI_linklist_prepend_pool(&fstep_item->list, f, uuidwalk->link_pool); + fstep_item->list_len += 1; + + f_link_prev_p = &f_link->next; + } + else { + *f_link_prev_p = f_link->next; + BLI_mempool_free(uuidwalk->link_pool, f_link); + } + } + + BLI_ghash_clear(uuidwalk->cache.faces_from_uuid, NULL, NULL); + + BLI_sortlist(&fstep->items, facestep_sort); + + return ok; +} + +/** + * Cleans up temp data from #bm_uuidwalk_facestep_begin + */ +static void bm_uuidwalk_facestep_end( + UUIDWalk *uuidwalk, UUIDFaceStep *fstep) +{ + UUIDFaceStepItem *fstep_item; + + while ((fstep_item = BLI_pophead(&fstep->items))) { + BLI_mempool_free(uuidwalk->step_pool_items, fstep_item); + } +} + +static void bm_uuidwalk_facestep_free( + UUIDWalk *uuidwalk, UUIDFaceStep *fstep) +{ + LinkNode *f_link, *f_link_next; + + BLI_assert(BLI_listbase_is_empty(&fstep->items)); + + for (f_link = fstep->faces; f_link; f_link = f_link_next) { + f_link_next = f_link->next; + BLI_mempool_free(uuidwalk->link_pool, f_link); + } + + BLI_remlink(&uuidwalk->faces_step, fstep); + BLI_mempool_free(uuidwalk->step_pool, fstep); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ +/* Main Loop to match up regions */ + +/** + * Given a face region and 2 candidate verts to begin mapping. + * return the matching region or NULL. + */ +static BMFace **bm_mesh_region_match_pair( +#ifdef USE_WALKER_REUSE + UUIDWalk *w_src, UUIDWalk *w_dst, +#endif + BMEdge *e_src, BMEdge *e_dst, + const unsigned int faces_src_region_len, + const unsigned int verts_src_region_len, + unsigned int *r_faces_result_len) +{ +#ifndef USE_WALKER_REUSE + UUIDWalk w_src_, w_dst_; + UUIDWalk *w_src = &w_src_, *w_dst = &w_dst_; +#endif + BMFace **faces_result = NULL; + bool found = false; + + BLI_assert(e_src != e_dst); + +#ifndef USE_WALKER_REUSE + bm_uuidwalk_init(w_src, faces_src_region_len, verts_src_region_len); + bm_uuidwalk_init(w_dst, faces_src_region_len, verts_src_region_len); +#endif + + w_src->use_face_isolate = true; + + /* setup the initial state */ + if (UNLIKELY(bm_uuidwalk_init_from_edge(w_src, e_src) != + bm_uuidwalk_init_from_edge(w_dst, e_dst))) + { + /* should never happen, if verts passed are compatible, but to be safe... */ + goto finally; + } + + bm_uuidwalk_rehash_reserve(w_src, MAX2(faces_src_region_len, verts_src_region_len)); + bm_uuidwalk_rehash_reserve(w_dst, MAX2(faces_src_region_len, verts_src_region_len)); + + while (true) { + bool ok = false; + + UUIDFaceStep *fstep_src = w_src->faces_step.first; + UUIDFaceStep *fstep_dst = w_dst->faces_step.first; + + BLI_assert(BLI_countlist(&w_src->faces_step) == BLI_countlist(&w_dst->faces_step)); + + while (fstep_src) { + + /* even if the destination has faces, + * it's not important, since the source doesn't, free and move-on. */ + if (fstep_src->faces == NULL) { + UUIDFaceStep *fstep_src_next = fstep_src->next; + UUIDFaceStep *fstep_dst_next = fstep_dst->next; + bm_uuidwalk_facestep_free(w_src, fstep_src); + bm_uuidwalk_facestep_free(w_dst, fstep_dst); + fstep_src = fstep_src_next; + fstep_dst = fstep_dst_next; + continue; + } + + if (bm_uuidwalk_facestep_begin(w_src, fstep_src) && + bm_uuidwalk_facestep_begin(w_dst, fstep_dst)) + { + /* Step over face-lists with matching UUID's + * both lists are sorted, so no need for lookups. + * The data is created on 'begin' and cleared on 'end' */ + UUIDFaceStepItem *fstep_item_src; + UUIDFaceStepItem *fstep_item_dst; + for (fstep_item_src = fstep_src->items.first, + fstep_item_dst = fstep_dst->items.first; + fstep_item_src && fstep_item_dst; + fstep_item_src = fstep_item_src->next, + fstep_item_dst = fstep_item_dst->next) + { + while ((fstep_item_dst != NULL) && + (fstep_item_dst->uuid < fstep_item_src->uuid)) + { + fstep_item_dst = fstep_item_dst->next; + } + + if ((fstep_item_dst == NULL) || + (fstep_item_src->uuid != fstep_item_dst->uuid) || + (fstep_item_src->list_len > fstep_item_dst->list_len)) + { + /* if the target walker has less than the source + * then the islands don't match, bail early */ + ok = false; + break; + } + + if (fstep_item_src->list_len == fstep_item_dst->list_len) { + /* found a match */ + bm_uuidwalk_pass_add(w_src, fstep_item_src->list, fstep_item_src->list_len); + bm_uuidwalk_pass_add(w_dst, fstep_item_dst->list, fstep_item_dst->list_len); + + BLI_linklist_free_pool(fstep_item_src->list, NULL, w_src->link_pool); + BLI_linklist_free_pool(fstep_item_dst->list, NULL, w_dst->link_pool); + + fstep_item_src->list = NULL; + fstep_item_src->list_len = 0; + + fstep_item_dst->list = NULL; + fstep_item_dst->list_len = 0; + + ok = true; + } + } + } + + bm_uuidwalk_facestep_end(w_src, fstep_src); + bm_uuidwalk_facestep_end(w_dst, fstep_dst); + + /* lock-step */ + fstep_src = fstep_src->next; + fstep_dst = fstep_dst->next; + } + + if (!ok) { + break; + } + + found = ((unsigned int)BLI_ghash_size(w_dst->faces_uuid) == faces_src_region_len); + if (found) { + break; + } + + /* Expensive! but some cases fails without. + * (also faster in other cases since it can rule-out invalid regions) */ + bm_uuidwalk_rehash(w_src); + bm_uuidwalk_rehash(w_dst); + } + + if (found) { + GHashIterator gh_iter; + const unsigned int faces_result_len = (unsigned int)BLI_ghash_size(w_dst->faces_uuid); + unsigned int i; + + faces_result = MEM_mallocN(sizeof(faces_result) * (faces_result_len + 1), __func__); + GHASH_ITER_INDEX (gh_iter, w_dst->faces_uuid, i) { + BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + faces_result[i] = f; + } + faces_result[faces_result_len] = NULL; + *r_faces_result_len = faces_result_len; + } + else { + *r_faces_result_len = 0; + } + +finally: + +#ifdef USE_WALKER_REUSE + bm_uuidwalk_clear(w_src); + bm_uuidwalk_clear(w_dst); +#else + bm_uuidwalk_free(w_src); + bm_uuidwalk_free(w_dst); +#endif + + return faces_result; +} + +/** + * Tag as visited, avoid re-use. + */ +static void bm_face_array_visit( + BMFace **faces, const unsigned int faces_len, + unsigned int *r_verts_len, + bool visit_faces) +{ + unsigned int verts_len = 0; + unsigned int i; + for (i = 0; i < faces_len; i++) { + BMFace *f = faces[i]; + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (r_verts_len) { + if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) { + verts_len += 1; + } + } + + BM_elem_flag_enable(l_iter->e, BM_ELEM_TAG); + BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG); + } while ((l_iter = l_iter->next) != l_first); + + if (visit_faces) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + } + + if (r_verts_len) { + *r_verts_len = verts_len; + } +} + +#ifdef USE_PIVOT_SEARCH + +/** \name Internal UUIDWalk API + * \{ */ + +/* signed user id */ +typedef intptr_t SUID_Int; + +static bool bm_edge_is_region_boundary(BMEdge *e) +{ + if (e->l->radial_next != e->l) { + BMLoop *l_iter = e->l; + do { + if (!BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) { + return true; + } + } while ((l_iter = l_iter->radial_next) != e->l); + return false; + } + else { + /* boundary */ + return true; + } +} + +static void bm_face_region_pivot_edge_use_best( + GHash *gh, BMEdge *e_test, + BMEdge **r_e_pivot_best, + SUID_Int e_pivot_best_id[2]) +{ + SUID_Int e_pivot_test_id[2]; + + e_pivot_test_id[0] = (SUID_Int)BLI_ghash_lookup(gh, e_test->v1); + e_pivot_test_id[1] = (SUID_Int)BLI_ghash_lookup(gh, e_test->v2); + if (e_pivot_test_id[0] > e_pivot_test_id[1]) { + SWAP(SUID_Int, e_pivot_test_id[0], e_pivot_test_id[1]); + } + + if ((*r_e_pivot_best == NULL) || + ((e_pivot_best_id[0] != e_pivot_test_id[0]) ? + (e_pivot_best_id[0] < e_pivot_test_id[0]) : + (e_pivot_best_id[1] < e_pivot_test_id[1]))) + { + e_pivot_best_id[0] = e_pivot_test_id[0]; + e_pivot_best_id[1] = e_pivot_test_id[1]; + + /* both verts are from the same pass, record this! */ + *r_e_pivot_best = e_test; + } +} + +/* quick id from a boundary vertex */ +static SUID_Int bm_face_region_vert_boundary_id(BMVert *v) +{ +#define PRIME_VERT_SMALL_A 7 +#define PRIME_VERT_SMALL_B 13 +#define PRIME_VERT_MID_A 103 +#define PRIME_VERT_MID_B 131 + + int tot = 0; + BMIter iter; + BMLoop *l; + SUID_Int id = PRIME_VERT_MID_A; + + BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + const bool is_boundary_vert = (bm_edge_is_region_boundary(l->e) || bm_edge_is_region_boundary(l->prev->e)); + id ^= l->f->len * (is_boundary_vert ? PRIME_VERT_SMALL_A : PRIME_VERT_SMALL_B); + tot += 1; + } + + id ^= (tot * PRIME_VERT_MID_B); + + return id ? ABS(id) : 1; + +#undef PRIME_VERT_SMALL_A +#undef PRIME_VERT_SMALL_B +#undef PRIME_VERT_MID_A +#undef PRIME_VERT_MID_B +} + +/** + * Accumulate id's from a previous pass (swap sign each pass) + */ +static SUID_Int bm_face_region_vert_pass_id(GHash *gh, BMVert *v) +{ + BMIter eiter; + BMEdge *e; + SUID_Int tot = 0; + SUID_Int v_sum_face_len = 0; + SUID_Int v_sum_id = 0; + SUID_Int id; + SUID_Int id_min = INTPTR_MIN + 1; + +#define PRIME_VERT_MID_A 23 +#define PRIME_VERT_MID_B 31 + + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BMVert *v_other = BM_edge_other_vert(e, v); + if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) { + /* non-zero values aren't allowed... so no need to check haskey */ + SUID_Int v_other_id = (SUID_Int)BLI_ghash_lookup(gh, v_other); + if (v_other_id > 0) { + v_sum_id += v_other_id; + tot += 1; + + /* face-count */ + { + BMLoop *l_iter = e->l; + do { + if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) { + v_sum_face_len += l_iter->f->len; + } + } while ((l_iter = l_iter->radial_next) != e->l); + } + } + } + } + } + + id = (tot * PRIME_VERT_MID_A); + id ^= (v_sum_face_len * PRIME_VERT_MID_B); + id ^= v_sum_id; + + /* disallow 0 & min (since it can't be flipped) */ + id = (UNLIKELY(id == 0) ? 1 : UNLIKELY(id < id_min) ? id_min : id); + + return ABS(id); + +#undef PRIME_VERT_MID_A +#undef PRIME_VERT_MID_B +} + +/** + * Take a face region and find the inner-most vertex. + * also calculate the number of connections to the boundary, + * and the total number unique of verts used by this face region. + * + * This is only called once on the source region (no need to be highly optimized). + */ +static BMEdge *bm_face_region_pivot_edge_find( + BMFace **faces_region, unsigned int faces_region_len, + unsigned int verts_region_len, + unsigned int *r_depth) +{ + /* note, keep deterministic where possible (geometry order independent) + * this function assumed all visit faces & edges are tagged */ + + BLI_LINKSTACK_DECLARE(vert_queue_prev, BMVert *); + BLI_LINKSTACK_DECLARE(vert_queue_next, BMVert *); + + GHash *gh = BLI_ghash_ptr_new(__func__); + unsigned int i; + + BMEdge *e_pivot = NULL; + /* pick any non-boundary edge (not ideal) */ + BMEdge *e_pivot_fallback = NULL; + + SUID_Int pass = 0; + + /* total verts in 'gs' we have visited - aka - not v_init_none */ + unsigned int vert_queue_used = 0; + + BLI_LINKSTACK_INIT(vert_queue_prev); + BLI_LINKSTACK_INIT(vert_queue_next); + + /* face-verts */ + for (i = 0; i < faces_region_len; i++) { + BMFace *f = faces_region[i]; + + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BMEdge *e = l_iter->e; + if (bm_edge_is_region_boundary(e)) { + unsigned int j; + for (j = 0; j < 2; j++) { + if (!BLI_ghash_haskey(gh, (&e->v1)[j])) { + SUID_Int v_id = bm_face_region_vert_boundary_id((&e->v1)[j]); + BLI_ghash_insert(gh, (&e->v1)[j], (void *)v_id); + BLI_LINKSTACK_PUSH(vert_queue_prev, (&e->v1)[j]); + vert_queue_used += 1; + } + } + } + else { + /* use incase (depth == 0), no interior verts */ + e_pivot_fallback = e; + } + } while ((l_iter = l_iter->next) != l_first); + } + + while (BLI_LINKSTACK_SIZE(vert_queue_prev)) { + BMVert *v; + while ((v = BLI_LINKSTACK_POP(vert_queue_prev))) { + BMIter eiter; + BMEdge *e; + BLI_assert(BLI_ghash_haskey(gh, v)); + BLI_assert((SUID_Int)BLI_ghash_lookup(gh, v) > 0); + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BMVert *v_other = BM_edge_other_vert(e, v); + if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) { + if (!BLI_ghash_haskey(gh, v_other)) { + /* add as negative, so we know not to read from them this pass */ + const SUID_Int v_id_other = -bm_face_region_vert_pass_id(gh, v_other); + BLI_ghash_insert(gh, v_other, (void *)v_id_other); + BLI_LINKSTACK_PUSH(vert_queue_next, v_other); + vert_queue_used += 1; + } + } + } + } + } + + /* flip all the newly added hashes to positive */ + { + LinkNode *v_link; + for (v_link = vert_queue_next; v_link; v_link = v_link->next) { + SUID_Int *v_id_p = (SUID_Int *)BLI_ghash_lookup_p(gh, v_link->link); + *v_id_p = -(*v_id_p); + BLI_assert(*v_id_p > 0); + } + } + + BLI_LINKSTACK_SWAP(vert_queue_prev, vert_queue_next); + pass += 1; + + if (vert_queue_used == verts_region_len) { + break; + } + } + + if (BLI_LINKSTACK_SIZE(vert_queue_prev) >= 2) { + /* common case - we managed to find some interior verts */ + LinkNode *v_link; + BMEdge *e_pivot_best = NULL; + SUID_Int e_pivot_best_id[2] = {0, 0}; + + /* temp untag, so we can quickly know what other verts are in this last pass */ + for (v_link = vert_queue_prev; v_link; v_link = v_link->next) { + BMVert *v = v_link->link; + BM_elem_flag_disable(v, BM_ELEM_TAG); + } + + /* restore correct tagging */ + for (v_link = vert_queue_prev; v_link; v_link = v_link->next) { + BMIter eiter; + BMEdge *e_test; + + BMVert *v = v_link->link; + BM_elem_flag_enable(v, BM_ELEM_TAG); + + BM_ITER_ELEM (e_test, &eiter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e_test, BM_ELEM_TAG)) { + BMVert *v_other = BM_edge_other_vert(e_test, v); + if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == false) { + bm_face_region_pivot_edge_use_best(gh, e_test, &e_pivot_best, e_pivot_best_id); + } + } + } + } + + e_pivot = e_pivot_best; + } + + if ((e_pivot == NULL) && BLI_LINKSTACK_SIZE(vert_queue_prev)) { + /* find the best single edge */ + BMEdge *e_pivot_best = NULL; + SUID_Int e_pivot_best_id[2] = {0, 0}; + + LinkNode *v_link; + + /* reduce a pass since we're having to step into a previous passes vert, + * and will be closer to the boundary */ + BLI_assert(pass != 0); + pass -= 1; + + for (v_link = vert_queue_prev; v_link; v_link = v_link->next) { + BMVert *v = v_link->link; + + BMIter eiter; + BMEdge *e_test; + BM_ITER_ELEM (e_test, &eiter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e_test, BM_ELEM_TAG)) { + BMVert *v_other = BM_edge_other_vert(e_test, v); + if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) { + bm_face_region_pivot_edge_use_best(gh, e_test, &e_pivot_best, e_pivot_best_id); + } + } + } + } + + e_pivot = e_pivot_best; + } + + BLI_LINKSTACK_FREE(vert_queue_prev); + BLI_LINKSTACK_FREE(vert_queue_next); + + BLI_ghash_free(gh, NULL, NULL); + + if (e_pivot == NULL) { +#ifdef DEBUG_PRINT + printf("%s: using fallback edge!\n", __func__); +#endif + e_pivot = e_pivot_fallback; + pass = 0; + } + + *r_depth = (unsigned int)pass; + + return e_pivot; +} +/** \} */ + +#endif /* USE_PIVOT_SEARCH */ + + +/* -------------------------------------------------------------------- */ +/* Quick UUID pass - identify candidates */ + +#ifdef USE_PIVOT_FASTMATCH + +/** \name Fast Match + * \{ */ + +typedef uintptr_t UUIDFashMatch; + +static UUIDFashMatch bm_vert_fasthash_single(BMVert *v) +{ + BMIter eiter; + BMEdge *e; + UUIDFashMatch e_num = 0, f_num = 0, l_num = 0; + +#define PRIME_EDGE 7 +#define PRIME_FACE 31 +#define PRIME_LOOP 61 + + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_edge_is_wire(e)) { + BMLoop *l_iter = e->l; + e_num += 1; + do { + f_num += 1; + l_num += (unsigned int)l_iter->f->len; + } while ((l_iter = l_iter->radial_next) != e->l); + } + } + + return ((e_num * PRIME_EDGE) ^ + (f_num * PRIME_FACE) * + (l_num * PRIME_LOOP)); + +#undef PRIME_EDGE +#undef PRIME_FACE +#undef PRIME_LOOP +} + +static UUIDFashMatch *bm_vert_fasthash_create( + BMesh *bm, const unsigned int depth) +{ + UUIDFashMatch *id_prev; + UUIDFashMatch *id_curr; + unsigned int pass, i; + BMVert *v; + BMIter iter; + + id_prev = MEM_mallocN(sizeof(*id_prev) * (unsigned int)bm->totvert, __func__); + id_curr = MEM_mallocN(sizeof(*id_curr) * (unsigned int)bm->totvert, __func__); + + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + id_prev[i] = bm_vert_fasthash_single(v); + } + + for (pass = 0; pass < depth; pass++) { + BMEdge *e; + + memcpy(id_curr, id_prev, sizeof(*id_prev) * (unsigned int)bm->totvert); + + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_edge_is_wire(e) == false) { + const int i1 = BM_elem_index_get(e->v1); + const int i2 = BM_elem_index_get(e->v2); + + id_curr[i1] += id_prev[i2]; + id_curr[i2] += id_prev[i1]; + } + } + } + MEM_freeN(id_prev); + + return id_curr; +} + +static void bm_vert_fasthash_edge_order( + UUIDFashMatch *fm, const BMEdge *e, UUIDFashMatch e_fm[2]) +{ + e_fm[0] = fm[BM_elem_index_get(e->v1)]; + e_fm[1] = fm[BM_elem_index_get(e->v2)]; + + if (e_fm[0] > e_fm[1]) { + SWAP(UUIDFashMatch, e_fm[0], e_fm[1]); + } +} + +static bool bm_vert_fasthash_edge_is_match( + UUIDFashMatch *fm, const BMEdge *e_a, const BMEdge *e_b) +{ + UUIDFashMatch e_a_fm[2]; + UUIDFashMatch e_b_fm[2]; + + bm_vert_fasthash_edge_order(fm, e_a, e_a_fm); + bm_vert_fasthash_edge_order(fm, e_b, e_b_fm); + + return ((e_a_fm[0] == e_b_fm[0]) && + (e_a_fm[1] == e_b_fm[1])); +} + +static void bm_vert_fasthash_destroy( + UUIDFashMatch *fm) +{ + MEM_freeN(fm); +} + +/** \} */ + +#endif /* USE_PIVOT_FASTMATCH */ + + +/** + * Take a face-region and return a list of matching face-regions. + * + * \param faces_region A single, contiguous face-region. + * \return A list of matching null-terminated face-region arrays. + */ +int BM_mesh_region_match( + BMesh *bm, + BMFace **faces_region, unsigned int faces_region_len, + ListBase *r_face_regions) +{ + BMEdge *e_src; + BMEdge *e_dst; + BMIter iter; + unsigned int verts_region_len = 0; + unsigned int faces_result_len = 0; + /* number of steps from e_src to a boundary vert */ + unsigned int depth; + + +#ifdef USE_WALKER_REUSE + UUIDWalk w_src, w_dst; +#endif + +#ifdef USE_PIVOT_FASTMATCH + UUIDFashMatch *fm; +#endif + +#ifdef DEBUG_PRINT + int search_num = 0; +#endif + +#ifdef DEBUG_TIME + TIMEIT_START(region_match); +#endif + + /* initialize visited verts */ + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + bm_face_array_visit(faces_region, faces_region_len, &verts_region_len, true); + + /* needed for 'ghashutil_bmelem_indexhash' */ + BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); + +#ifdef USE_PIVOT_SEARCH + e_src = bm_face_region_pivot_edge_find( + faces_region, faces_region_len, + verts_region_len, &depth); + + /* see which edge is added */ +#if 0 + BM_select_history_clear(bm); + if (e_src) { + BM_select_history_store(bm, e_src); + } +#endif + +#else + /* quick test only! */ + e_src = BM_mesh_active_edge_get(bm); +#endif + + if (e_src == NULL) { +#ifdef DEBUG_PRINT + printf("Couldn't find 'e_src'"); +#endif + return 0; + } + + BLI_listbase_clear(r_face_regions); + +#ifdef USE_PIVOT_FASTMATCH + if (depth > 0) { + fm = bm_vert_fasthash_create(bm, depth); + } + else { + fm = NULL; + } +#endif + +#ifdef USE_WALKER_REUSE + bm_uuidwalk_init(&w_src, faces_region_len, verts_region_len); + bm_uuidwalk_init(&w_dst, faces_region_len, verts_region_len); +#endif + + BM_ITER_MESH (e_dst, &iter, bm, BM_EDGES_OF_MESH) { + BMFace **faces_result; + unsigned int faces_result_len_out; + + if (BM_elem_flag_test(e_dst, BM_ELEM_TAG)) { + continue; + } + +#ifdef USE_PIVOT_FASTMATCH + if (fm && !bm_vert_fasthash_edge_is_match(fm, e_src, e_dst)) { + continue; + } +#endif + +#ifdef DEBUG_PRINT + search_num += 1; +#endif + + faces_result = bm_mesh_region_match_pair( +#ifdef USE_WALKER_REUSE + &w_src, &w_dst, +#endif + e_src, e_dst, + faces_region_len, + verts_region_len, + &faces_result_len_out); + + /* tag verts as visited */ + if (faces_result) { + LinkData *link; + + bm_face_array_visit(faces_result, faces_result_len_out, NULL, false); + + link = BLI_genericNodeN(faces_result); + BLI_addtail(r_face_regions, link); + faces_result_len += 1; + } + } + +#ifdef USE_WALKER_REUSE + bm_uuidwalk_free(&w_src); + bm_uuidwalk_free(&w_dst); +#else + (void)bm_uuidwalk_clear; +#endif + +#ifdef USE_PIVOT_FASTMATCH + if (fm) { + bm_vert_fasthash_destroy(fm); + } +#endif + +#ifdef DEBUG_PRINT + printf("%s: search: %d, found %d\n", __func__, search_num, faces_result_len); +#endif + +#ifdef DEBUG_TIME + TIMEIT_END(region_match); +#endif + + return (int)faces_result_len; +} diff --git a/source/blender/bmesh/tools/bmesh_region_match.h b/source/blender/bmesh/tools/bmesh_region_match.h new file mode 100644 index 00000000000..edf8369b070 --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_region_match.h @@ -0,0 +1,33 @@ +/* + * ***** 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 ***** + */ + +#ifndef __BMESH_REGION_MATCH_H__ +#define __BMESH_REGION_MATCH_H__ + +/** \file blender/bmesh/tools/bmesh_region_match.h + * \ingroup bmesh + */ + +int BM_mesh_region_match( + BMesh *bm, + BMFace **faces_region, unsigned int faces_region_len, + ListBase *r_face_regions); + +#endif /* __BMESH_REGION_MATCH_H__ */ diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index 223ab3eca2a..ffbbb8623ac 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -111,16 +111,28 @@ int collada_export(Scene *sce, eObjectSet objectSet = (export_settings.selected) ? OB_SET_SELECTED : OB_SET_ALL; export_settings.export_set = BKE_object_relational_superset(sce, objectSet, (eObRelationTypes)includeFilter); - - if (export_settings.sort_by_name) - bc_bubble_sort_by_Object_name(export_settings.export_set); + int export_count = BLI_linklist_length(export_settings.export_set); + + if (export_count==0) + { + if (export_settings.selected) { + fprintf(stderr, "Collada: Found no objects to export.\nPlease ensure that all objects which shall be exported are also visible in the 3D Viewport.\n"); + } + else{ + fprintf(stderr, "Collada: Your scene seems to be empty. No Objects will be exported.\n"); + } + } + else { + if (export_settings.sort_by_name) + bc_bubble_sort_by_Object_name(export_settings.export_set); + } DocumentExporter exporter(&export_settings); exporter.exportCurrentScene(sce); BLI_linklist_free(export_settings.export_set, NULL); - return 1; + return export_count; } /* end extern C */ diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp index 76e52c14685..f3d0c33d3b3 100644 --- a/source/blender/compositor/nodes/COM_BlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BlurNode.cpp @@ -105,6 +105,7 @@ void BlurNode::convertToOperations(NodeConverter &converter, const CompositorCon GaussianXBlurOperation *operationx = new GaussianXBlurOperation(); operationx->setData(data); operationx->setQuality(quality); + operationx->checkOpenCL(); converter.addOperation(operationx); converter.mapInputSocket(getInputSocket(1), operationx->getInputSocket(1)); @@ -112,6 +113,7 @@ void BlurNode::convertToOperations(NodeConverter &converter, const CompositorCon GaussianYBlurOperation *operationy = new GaussianYBlurOperation(); operationy->setData(data); operationy->setQuality(quality); + operationy->checkOpenCL(); converter.addOperation(operationy); converter.mapInputSocket(getInputSocket(1), operationy->getInputSocket(1)); diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index 0aefba3bb7c..0838d281de7 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -21,6 +21,7 @@ */ #include "COM_GaussianXBlurOperation.h" +#include "COM_OpenCLDevice.h" #include "BLI_math.h" #include "MEM_guardedalloc.h" @@ -124,6 +125,32 @@ void GaussianXBlurOperation::executePixel(float output[4], int x, int y, void *d mul_v4_v4fl(output, color_accum, 1.0f / multiplier_accum); } +void GaussianXBlurOperation::executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp) +{ + cl_kernel gaussianXBlurOperationKernel = device->COM_clCreateKernel("gaussianXBlurOperationKernel", NULL); + cl_int filter_size = this->m_filtersize; + + cl_mem gausstab = clCreateBuffer(device->getContext(), + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + sizeof(float) * (this->m_filtersize * 2 + 1), + this->m_gausstab, + NULL); + + device->COM_clAttachMemoryBufferToKernelParameter(gaussianXBlurOperationKernel, 0, 1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter(gaussianXBlurOperationKernel, 2, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter(gaussianXBlurOperationKernel, 3, outputMemoryBuffer); + clSetKernelArg(gaussianXBlurOperationKernel, 4, sizeof(cl_int), &filter_size); + device->COM_clAttachSizeToKernelParameter(gaussianXBlurOperationKernel, 5, this); + clSetKernelArg(gaussianXBlurOperationKernel, 6, sizeof(cl_mem), &gausstab); + + device->COM_clEnqueueRange(gaussianXBlurOperationKernel, outputMemoryBuffer, 7, this); + + clReleaseMemObject(gausstab); +} + void GaussianXBlurOperation::deinitExecution() { BlurBaseOperation::deinitExecution(); diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h index e391320a007..d7ae8b1e3dc 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.h @@ -40,7 +40,12 @@ public: * @brief the inner loop of this program */ void executePixel(float output[4], int x, int y, void *data); - + + void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp); + /** * @brief initialize the execution */ @@ -53,5 +58,9 @@ public: void *initializeTileData(rcti *rect); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + + void checkOpenCL() { + this->setOpenCL(m_data.sizex >= 128); + } }; #endif diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp index a05a1ab6a23..6172f954087 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp @@ -21,6 +21,7 @@ */ #include "COM_GaussianYBlurOperation.h" +#include "COM_OpenCLDevice.h" #include "BLI_math.h" #include "MEM_guardedalloc.h" @@ -126,6 +127,32 @@ void GaussianYBlurOperation::executePixel(float output[4], int x, int y, void *d mul_v4_v4fl(output, color_accum, 1.0f / multiplier_accum); } +void GaussianYBlurOperation::executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp) +{ + cl_kernel gaussianYBlurOperationKernel = device->COM_clCreateKernel("gaussianYBlurOperationKernel", NULL); + cl_int filter_size = this->m_filtersize; + + cl_mem gausstab = clCreateBuffer(device->getContext(), + CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, + sizeof(float) * (this->m_filtersize * 2 + 1), + this->m_gausstab, + NULL); + + device->COM_clAttachMemoryBufferToKernelParameter(gaussianYBlurOperationKernel, 0, 1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter(gaussianYBlurOperationKernel, 2, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter(gaussianYBlurOperationKernel, 3, outputMemoryBuffer); + clSetKernelArg(gaussianYBlurOperationKernel, 4, sizeof(cl_int), &filter_size); + device->COM_clAttachSizeToKernelParameter(gaussianYBlurOperationKernel, 5, this); + clSetKernelArg(gaussianYBlurOperationKernel, 6, sizeof(cl_mem), &gausstab); + + device->COM_clEnqueueRange(gaussianYBlurOperationKernel, outputMemoryBuffer, 7, this); + + clReleaseMemObject(gausstab); +} + void GaussianYBlurOperation::deinitExecution() { BlurBaseOperation::deinitExecution(); diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h index 22b6562077d..4b5751c0968 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.h +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.h @@ -40,7 +40,12 @@ public: * the inner loop of this program */ void executePixel(float output[4], int x, int y, void *data); - + + void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, + list<cl_kernel> *clKernelsToCleanUp); + /** * @brief initialize the execution */ @@ -53,5 +58,9 @@ public: void *initializeTileData(rcti *rect); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + + void checkOpenCL() { + this->setOpenCL(m_data.sizex >= 128); + } }; #endif diff --git a/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp b/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp index 9fb9efe4fc7..ddc09ecb483 100644 --- a/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingBlurOperation.cpp @@ -49,37 +49,27 @@ void *KeyingBlurOperation::initializeTileData(rcti *rect) void KeyingBlurOperation::executePixel(float output[4], int x, int y, void *data) { MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + const int bufferWidth = inputBuffer->getWidth(); float *buffer = inputBuffer->getBuffer(); - - int bufferWidth = inputBuffer->getWidth(); - int bufferHeight = inputBuffer->getHeight(); - - int i, count = 0; - + int count = 0; float average = 0.0f; if (this->m_axis == 0) { - for (i = -this->m_size + 1; i < this->m_size; i++) { - int cx = x + i; - - if (cx >= 0 && cx < bufferWidth) { - int bufferIndex = (y * bufferWidth + cx) * 4; - - average += buffer[bufferIndex]; - count++; - } + const int start = max(0, x - this->m_size + 1), + end = min(bufferWidth, x + this->m_size); + for (int cx = start; cx < end; ++cx) { + int bufferIndex = (y * bufferWidth + cx) * 4; + average += buffer[bufferIndex]; + count++; } } else { - for (i = -this->m_size + 1; i < this->m_size; i++) { - int cy = y + i; - - if (cy >= 0 && cy < bufferHeight) { - int bufferIndex = (cy * bufferWidth + x) * 4; - - average += buffer[bufferIndex]; - count++; - } + const int start = max(0, y - this->m_size + 1), + end = min(inputBuffer->getHeight(), y + this->m_size); + for (int cy = start; cy < end; ++cy) { + int bufferIndex = (cy * bufferWidth + x) * 4; + average += buffer[bufferIndex]; + count++; } } diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index 17b85847fcf..1633d2a2f1d 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -188,9 +188,9 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri BLI_freelistN(&edges); if (triangulation->triangles_total) { - rctf *rect; + rcti *rect; rect = triangulation->triangles_AABB = - (rctf *) MEM_callocN(sizeof(rctf) * triangulation->triangles_total, "voronoi triangulation AABB"); + (rcti *) MEM_callocN(sizeof(rcti) * triangulation->triangles_total, "voronoi triangulation AABB"); for (i = 0; i < triangulation->triangles_total; i++, rect++) { int *triangle = triangulation->triangles[i]; @@ -206,11 +206,11 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri minmax_v2v2_v2(min, max, b->co); minmax_v2v2_v2(min, max, c->co); - rect->xmin = min[0]; - rect->ymin = min[1]; + rect->xmin = (int)min[0]; + rect->ymin = (int)min[1]; - rect->xmax = max[0]; - rect->ymax = max[1]; + rect->xmax = (int)max[0] + 1; + rect->ymax = (int)max[1] + 1; } } @@ -224,7 +224,6 @@ void *KeyingScreenOperation::initializeTileData(rcti *rect) int triangles_allocated = 0; int chunk_size = 20; int i; - rctf rect_float; if (this->m_movieClip == NULL) return NULL; @@ -242,14 +241,10 @@ void *KeyingScreenOperation::initializeTileData(rcti *rect) if (!triangulation) return NULL; - BLI_rctf_init(&rect_float, rect->xmin, rect->xmax, rect->ymin, rect->ymax); - tile_data = (TileData *) MEM_callocN(sizeof(TileData), "keying screen tile data"); for (i = 0; i < triangulation->triangles_total; i++) { - bool ok = BLI_rctf_isect(&rect_float, &triangulation->triangles_AABB[i], NULL); - - if (ok) { + if (BLI_rcti_isect(rect, &triangulation->triangles_AABB[i], NULL)) { tile_data->triangles_total++; if (tile_data->triangles_total > triangles_allocated) { @@ -316,7 +311,7 @@ void KeyingScreenOperation::executePixel(float output[4], int x, int y, void *da for (i = 0; i < tile_data->triangles_total; i++) { int triangle_idx = tile_data->triangles[i]; - rctf *rect = &triangulation->triangles_AABB[triangle_idx]; + rcti *rect = &triangulation->triangles_AABB[triangle_idx]; if (IN_RANGE_INCL(x, rect->xmin, rect->xmax) && IN_RANGE_INCL(y, rect->ymin, rect->ymax)) { int *triangle = triangulation->triangles[triangle_idx]; diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.h b/source/blender/compositor/operations/COM_KeyingScreenOperation.h index 10cf48e57f4..b1a5c0c39c7 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.h +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.h @@ -47,7 +47,7 @@ protected: VoronoiTriangulationPoint *triangulated_points; int (*triangles)[3]; int triangulated_points_total, triangles_total; - rctf *triangles_AABB; + rcti *triangles_AABB; } TriangulationData; typedef struct TileData { diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cpp b/source/blender/compositor/operations/COM_MapUVOperation.cpp index 87ad1d6afa4..6bf730253e7 100644 --- a/source/blender/compositor/operations/COM_MapUVOperation.cpp +++ b/source/blender/compositor/operations/COM_MapUVOperation.cpp @@ -62,7 +62,7 @@ void MapUVOperation::executePixelSampled(float output[4], float x, float y, Pixe */ float du = len_v2(deriv[0]); float dv = len_v2(deriv[1]); - float factor = 1.0f - threshold * (du + dv); + float factor = 1.0f - threshold * (du / m_inputColorProgram->getWidth() + dv / m_inputColorProgram->getHeight()); if (factor < 0.f) alpha = 0.f; else alpha *= factor; diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h index 479ce161eea..d399edba6e9 100644 --- a/source/blender/compositor/operations/COM_MixOperation.h +++ b/source/blender/compositor/operations/COM_MixOperation.h @@ -76,7 +76,7 @@ public: void setUseValueAlphaMultiply(const bool value) { this->m_valueAlphaMultiply = value; } - bool useValueAlphaMultiply() { return this->m_valueAlphaMultiply; } + inline bool useValueAlphaMultiply() { return this->m_valueAlphaMultiply; } void setUseClamp(bool value) { this->m_useClamp = value; } }; diff --git a/source/blender/compositor/operations/COM_OpenCLKernels.cl b/source/blender/compositor/operations/COM_OpenCLKernels.cl index 00b3825d8b3..1b965eb8659 100644 --- a/source/blender/compositor/operations/COM_OpenCLKernels.cl +++ b/source/blender/compositor/operations/COM_OpenCLKernels.cl @@ -250,3 +250,66 @@ __kernel void directionalBlurKernel(__read_only image2d_t inputImage, __write_o write_imagef(output, coords, col); } + +// KERNEL --- GAUSSIAN BLUR --- +__kernel void gaussianXBlurOperationKernel(__read_only image2d_t inputImage, + int2 offsetInput, + __write_only image2d_t output, + int2 offsetOutput, + int filter_size, + int2 dimension, + __global float *gausstab, + int2 offset) +{ + float4 color = {0.0f, 0.0f, 0.0f, 0.0f}; + int2 coords = {get_global_id(0), get_global_id(1)}; + coords += offset; + const int2 realCoordinate = coords + offsetOutput; + int2 inputCoordinate = realCoordinate - offsetInput; + float weight = 0.0f; + + int xmin = max(realCoordinate.x - filter_size, 0) - offsetInput.x; + int xmax = min(realCoordinate.x + filter_size + 1, dimension.x) - offsetInput.x; + + for (int nx = xmin, i = max(filter_size - realCoordinate.x, 0); nx < xmax; ++nx, ++i) { + float w = gausstab[i]; + inputCoordinate.x = nx; + color += read_imagef(inputImage, SAMPLER_NEAREST, inputCoordinate) * w; + weight += w; + } + + color *= (1.0f / weight); + + write_imagef(output, coords, color); +} + +__kernel void gaussianYBlurOperationKernel(__read_only image2d_t inputImage, + int2 offsetInput, + __write_only image2d_t output, + int2 offsetOutput, + int filter_size, + int2 dimension, + __global float *gausstab, + int2 offset) +{ + float4 color = {0.0f, 0.0f, 0.0f, 0.0f}; + int2 coords = {get_global_id(0), get_global_id(1)}; + coords += offset; + const int2 realCoordinate = coords + offsetOutput; + int2 inputCoordinate = realCoordinate - offsetInput; + float weight = 0.0f; + + int ymin = max(realCoordinate.y - filter_size, 0) - offsetInput.y; + int ymax = min(realCoordinate.y + filter_size + 1, dimension.y) - offsetInput.y; + + for (int ny = ymin, i = max(filter_size - realCoordinate.y, 0); ny < ymax; ++ny, ++i) { + float w = gausstab[i]; + inputCoordinate.y = ny; + color += read_imagef(inputImage, SAMPLER_NEAREST, inputCoordinate) * w; + weight += w; + } + + color *= (1.0f / weight); + + write_imagef(output, coords, color); +} diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp index 9a34dccacb1..bcef652a8b5 100644 --- a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp +++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp @@ -138,22 +138,35 @@ struct BufferLineAccumulator { int x, y, num; float v, dv; float falloff_factor; + float border[4]; + + if ((int)pt_ofs[0] == 0 && (int)pt_ofs[1] == 0) { + copy_v4_v4(output, input->getBuffer() + COM_NUMBER_OF_CHANNELS * ((int)source[0] + input->getWidth() * (int)source[1])); + return; + } /* initialise the iteration variables */ float *buffer = init_buffer_iterator(input, source, pt_ofs, dist_min, dist_max, x, y, num, v, dv, falloff_factor); - - int tot = 0; + zero_v3(border); + border[3] = 1.0f; /* v_local keeps track of when to decrement v (see below) */ float v_local = v - floorf(v); for (int i = 0; i < num; i++) { - /* range check, abort when running beyond the image border */ - if (x < rect.xmin || x >= rect.xmax || y < rect.ymin || y >= rect.ymax) - break; - - float f = 1.0f - (float)i * falloff_factor; - madd_v4_v4fl(output, buffer, buffer[3] * f * f); + float weight = 1.0f - (float)i * falloff_factor; + weight *= weight; + + /* range check, use last valid color when running beyond the image border */ + if (x >= rect.xmin && x < rect.xmax && y >= rect.ymin && y < rect.ymax) { + madd_v4_v4fl(output, buffer, buffer[3] * weight); + /* use as border color in case subsequent pixels are out of bounds */ + copy_v4_v4(border, buffer); + } + else { + madd_v4_v4fl(output, border, border[3] * weight); + } + /* TODO implement proper filtering here, see * http://en.wikipedia.org/wiki/Lanczos_resampling * http://en.wikipedia.org/wiki/Sinc_function @@ -161,9 +174,8 @@ struct BufferLineAccumulator { * using lanczos with x = distance from the line segment, * normalized to a == 0.5f, could give a good result * - * for now just count samples and divide equally at the end ... + * for now just divide equally at the end ... */ - tot++; /* decrement u */ x -= fxx; diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 481912f4d1f..296a52e7f20 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -426,74 +426,6 @@ bool ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int a /* ************************************************** */ /* UI-Button Interface */ -/** - * Temporary wrapper for driver operators for buttons to make it easier to create - * such drivers by rerouting all paths through the active object instead so that - * they will get picked up by the dependency system. - * - * \param C Context pointer - for getting active data - * \param[in,out] ptr RNA pointer for property's datablock. May be modified as result of path remapping. - * \param prop RNA definition of property to add for - * \return MEM_alloc'd string representing the path to the property from the given #PointerRNA - */ -static char *get_driver_path_hack(bContext *C, PointerRNA *ptr, PropertyRNA *prop) -{ - ID *id = (ID *)ptr->id.data; - ScrArea *sa = CTX_wm_area(C); - - /* get standard path which may be extended */ - char *basepath = RNA_path_from_ID_to_property(ptr, prop); - char *path = basepath; /* in case no remapping is needed */ - - - /* Remapping will only be performed in the Properties Editor, as only this - * restricts the subspace of options to the 'active' data (a manageable state) - */ - // TODO: watch out for pinned context? - if ((sa) && (sa->spacetype == SPACE_BUTS)) { - Object *ob = CTX_data_active_object(C); - - if (ob && id) { - /* only id-types which can be remapped to go through objects should be considered */ - switch (GS(id->name)) { - case ID_TE: /* textures */ - { - Material *ma = give_current_material(ob, ob->actcol); - Tex *tex = give_current_material_texture(ma); - - /* assumes: texture will only be shown if it is active material's active texture it's ok */ - if ((ID *)tex == id) { - char name_esc_ma[(sizeof(ma->id.name) - 2) * 2]; - char name_esc_tex[(sizeof(tex->id.name) - 2) * 2]; - - BLI_strescape(name_esc_ma, ma->id.name + 2, sizeof(name_esc_ma)); - BLI_strescape(name_esc_tex, tex->id.name + 2, sizeof(name_esc_tex)); - - /* create new path */ - // TODO: use RNA path functions to construct step by step instead? - // FIXME: maybe this isn't even needed anymore... - path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", - name_esc_ma, name_esc_tex, basepath); - - /* free old one */ - MEM_freeN(basepath); - } - break; - } - } - - /* fix RNA pointer, as we've now changed the ID root by changing the paths */ - if (basepath != path) { - /* rebase provided pointer so that it starts from object... */ - RNA_pointer_create(&ob->id, ptr->type, ptr->data, ptr); - } - } - } - - /* the path should now have been corrected for use */ - return path; -} - /* Add Driver Button Operator ------------------------ */ static int add_driver_button_exec(bContext *C, wmOperator *op) @@ -511,7 +443,7 @@ static int add_driver_button_exec(bContext *C, wmOperator *op) index = -1; if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - char *path = get_driver_path_hack(C, &ptr, prop); + char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; if (path) { @@ -566,7 +498,7 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op) index = -1; if (ptr.id.data && ptr.data && prop) { - char *path = get_driver_path_hack(C, &ptr, prop); + char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0); MEM_freeN(path); @@ -613,7 +545,7 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op) uiContextActiveProperty(C, &ptr, &prop, &index); if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - char *path = get_driver_path_hack(C, &ptr, prop); + char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); if (path) { /* only copy the driver for the button that this was involved for */ @@ -657,7 +589,7 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op) uiContextActiveProperty(C, &ptr, &prop, &index); if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - char *path = get_driver_path_hack(C, &ptr, prop); + char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL); if (path) { /* only copy the driver for the button that this was involved for */ diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 1e4d9bac246..b7ab7fe064d 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -70,7 +70,7 @@ void ED_armature_apply_transform(Object *ob, float mat[4][4]) /* Put the armature into editmode */ ED_armature_to_edit(arm); - /* Transform the bones*/ + /* Transform the bones */ ED_armature_transform_bones(arm, mat); /* Turn the list into an armature */ @@ -100,7 +100,7 @@ void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4]) mul_m4_v3(mat, ebone->head); mul_m4_v3(mat, ebone->tail); - /* apply the transfiormed roll back */ + /* apply the transformed roll back */ mat3_to_vec_roll(tmat, NULL, &ebone->roll); ebone->rad_head *= scale; @@ -190,7 +190,7 @@ void ED_armature_origin_set(Scene *scene, Object *ob, float cursor[3], int cente /* Adjust object location for new centerpoint */ if (centermode && obedit == NULL) { - mul_mat3_m4_v3(ob->obmat, cent); /* ommit translation part */ + mul_mat3_m4_v3(ob->obmat, cent); /* omit translation part */ add_v3_v3(ob->loc, cent); } } diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 1d054ffc2e9..6d616384b9a 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -237,7 +237,7 @@ void armature_select_mirrored(struct bArmature *arm); void armature_tag_unselect(struct bArmature *arm); void *get_nearest_bone(struct bContext *C, short findunsel, int x, int y); -void *get_bone_from_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, short hits, short findunsel); +void *get_bone_from_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest); int bone_looper(struct Object *ob, struct Bone *bone, void *data, int (*bone_func)(struct Object *, struct Bone *, void *)); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index e4ba8728e55..75fa4a5433f 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -245,7 +245,7 @@ int join_armature_exec(bContext *C, wmOperator *op) invert_m4_m4(imat, premat); mul_m4_m4m4(difmat, imat, postmat); - curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]); + curbone->roll -= atan2f(difmat[2][0], difmat[2][2]); } /* Fix Constraints and Other Links to this Bone and Armature */ diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 12d13b05ee1..c6ef76c570c 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -73,7 +73,7 @@ Bone *get_indexed_bone(Object *ob, int index) /* See if there are any selected bones in this buffer */ /* only bones from base are checked on */ -void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel) +void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest) { Object *obedit = scene->obedit; // XXX get from context Bone *bone; @@ -82,6 +82,7 @@ void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, unsigned int hitresult; short i; bool takeNext = false; + int minsel = 0xffffffff, minunsel = 0xffffffff; for (i = 0; i < hits; i++) { hitresult = buffer[3 + (i * 4)]; @@ -102,7 +103,7 @@ void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, else sel = !(bone->flag & BONE_SELECTED); - data = bone; + data = bone; } else { data = NULL; @@ -123,14 +124,28 @@ void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, if (data) { if (sel) { - if (!firstSel) firstSel = data; - takeNext = 1; + if (do_nearest) { + if (minsel > buffer[4 * i + 1]) { + firstSel = data; + minsel = buffer[4 * i + 1]; + } + } + else { + if (!firstSel) firstSel = data; + takeNext = 1; + } } else { - if (!firstunSel) - firstunSel = data; - if (takeNext) - return data; + if (do_nearest) { + if (minunsel > buffer[4 * i + 1]) { + firstunSel = data; + minunsel = buffer[4 * i + 1]; + } + } + else { + if (!firstunSel) firstunSel = data; + if (takeNext) return data; + } } } } @@ -163,7 +178,7 @@ void *get_nearest_bone(bContext *C, short findunsel, int x, int y) hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true); if (hits > 0) - return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel); + return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel, true); return NULL; } diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index ba105325b97..d75a23a6322 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -1492,9 +1492,9 @@ static int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gestu return added; } -static int cmpIntersections(void *i1, void *i2) +static int cmpIntersections(const void *i1, const void *i2) { - SK_Intersection *isect1 = i1, *isect2 = i2; + const SK_Intersection *isect1 = i1, *isect2 = i2; if (isect1->stroke == isect2->stroke) { if (isect1->before < isect2->before) { diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 76284ba44de..ba5ef4f3b5d 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -133,14 +133,14 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select) /* called from editview.c, for mode-less pose selection */ /* assumes scene obact and basact is still on old situation */ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, - bool extend, bool deselect, bool toggle) + bool extend, bool deselect, bool toggle, bool do_nearest) { Object *ob = base->object; Bone *nearBone; if (!ob || !ob->pose) return 0; - nearBone = get_bone_from_selectbuffer(scene, base, buffer, hits, 1); + nearBone = get_bone_from_selectbuffer(scene, base, buffer, hits, 1, do_nearest); /* if the bone cannot be affected, don't do anything */ if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) { diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 1449453936f..4655deec4c4 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -977,9 +977,12 @@ static int move_cursor(bContext *C, int type, const bool select) EditFont *ef = cu->editfont; int cursmove = -1; + if ((select) && (ef->selstart == 0)) { + ef->selstart = ef->selend = ef->pos + 1; + } + switch (type) { case LINE_BEGIN: - if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1; while (ef->pos > 0) { if (ef->textbuf[ef->pos - 1] == '\n') break; if (ef->textbufinfo[ef->pos - 1].flag & CU_CHINFO_WRAP) break; @@ -989,7 +992,6 @@ static int move_cursor(bContext *C, int type, const bool select) break; case LINE_END: - if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1; while (ef->pos < ef->len) { if (ef->textbuf[ef->pos] == 0) break; if (ef->textbuf[ef->pos] == '\n') break; @@ -1002,7 +1004,6 @@ static int move_cursor(bContext *C, int type, const bool select) case PREV_WORD: { int pos = ef->pos; - if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1; BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true); ef->pos = pos; cursmove = FO_CURS; @@ -1012,7 +1013,6 @@ static int move_cursor(bContext *C, int type, const bool select) case NEXT_WORD: { int pos = ef->pos; - if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1; BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true); ef->pos = pos; cursmove = FO_CURS; @@ -1020,35 +1020,29 @@ static int move_cursor(bContext *C, int type, const bool select) } case PREV_CHAR: - if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1; ef->pos--; cursmove = FO_CURS; break; case NEXT_CHAR: - if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1; ef->pos++; cursmove = FO_CURS; break; case PREV_LINE: - if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1; cursmove = FO_CURSUP; break; case NEXT_LINE: - if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1; cursmove = FO_CURSDOWN; break; case PREV_PAGE: - if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1; cursmove = FO_PAGEUP; break; case NEXT_PAGE: - if ((select) && (ef->selstart == 0)) ef->selstart = ef->selend = ef->pos + 1; cursmove = FO_PAGEDOWN; break; } diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 6eac9f14bf6..24c80cbf005 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -123,7 +123,7 @@ void ED_armature_deselect_all(struct Object *obedit, int toggle); void ED_armature_deselect_all_visible(struct Object *obedit); int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, - short hits, bool extend, bool deselect, bool toggle); + short hits, bool extend, bool deselect, bool toggle, bool do_nearest); bool mouse_armature(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); int join_armature_exec(struct bContext *C, struct wmOperator *op); struct Bone *get_indexed_bone(struct Object *ob, int index); diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index db13c628ade..a9995de068e 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -69,8 +69,6 @@ void ED_image_point_pos__reverse(struct SpaceImage *sima, struct ARegion *ar, co bool ED_space_image_show_render(struct SpaceImage *sima); bool ED_space_image_show_paint(struct SpaceImage *sima); bool ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit); -bool ED_space_image_show_texpaint(struct SpaceImage *sima, struct Object *ob); -bool ED_space_image_show_uvshadow(struct SpaceImage *sima, struct Object *obedit); bool ED_space_image_paint_curve(const struct bContext *C); diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h index 14595a4c668..ab1dbabe793 100644 --- a/source/blender/editors/include/ED_render.h +++ b/source/blender/editors/include/ED_render.h @@ -35,7 +35,6 @@ struct ID; struct Main; struct MTex; struct Render; -struct RenderInfo; struct Scene; struct ScrArea; struct RegionView3D; @@ -56,18 +55,6 @@ void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated void ED_viewport_render_kill_jobs(const struct bContext *C, bool free_database); struct Scene *ED_render_job_get_scene(const struct bContext *C); -/* render_preview.c */ - -/* stores rendered preview - is also used for icons */ -typedef struct RenderInfo { - int pr_rectx; - int pr_recty; - short curtile, tottile; - rcti disprect; /* storage for view3d preview rect */ - unsigned int *rect; - struct Render *re; /* persistent render */ -} RenderInfo; - /* Render the preview * * pr_method: diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 1e9756ff771..bc794bf3350 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -295,7 +295,6 @@ typedef enum { #define UI_GRAD_L_ALT 10 #define UI_PALETTE_COLOR 20 -#define UI_PALETTE_COLOR_ACTIVE 1 /* Drawing * diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index fa0832b6273..48e54270e95 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -61,7 +61,7 @@ static FCurve *ui_but_get_fcurve(uiBut *but, bAction **action, bool *r_driven) * but works well enough in typical cases */ int rnaindex = (but->rnaindex == -1) ? 0 : but->rnaindex; - return rna_get_fcurve(&but->rnapoin, but->rnaprop, rnaindex, action, r_driven); + return rna_get_fcurve_context_ui(but->block->evil_C, &but->rnapoin, but->rnaprop, rnaindex, action, r_driven); } void ui_but_anim_flag(uiBut *but, float cfra) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 33bb46ced7f..9138ac92ab9 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3111,8 +3111,9 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, c } } else if (data->state == BUTTON_STATE_WAIT_KEY_EVENT) { - if (event->type == MOUSEMOVE) + if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { return WM_UI_HANDLER_CONTINUE; + } if (event->val == KM_PRESS) { if (WM_key_event_string(event->type)[0]) @@ -4255,11 +4256,21 @@ static bool ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, return changed; } +static void ui_palette_set_active(uiBut *but) +{ + if ((int)(but->a1) == UI_PALETTE_COLOR) { + Palette *palette = but->rnapoin.id.data; + PaletteColor *color = but->rnapoin.data; + palette->active_color = BLI_findindex(&palette->colors, color); + } +} + static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { /* first handle click on icondrag type button */ if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) { + ui_palette_set_active(but); if (ui_but_mouse_inside_icon(but, data->region, event)) { button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); data->dragstartx = event->x; @@ -4269,6 +4280,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co } #ifdef USE_DRAG_TOGGLE if (event->type == LEFTMOUSE && event->val == KM_PRESS) { + ui_palette_set_active(but); button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); data->dragstartx = event->x; data->dragstarty = event->y; @@ -4277,6 +4289,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co #endif /* regular open menu */ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) { + ui_palette_set_active(but); button_activate_state(C, but, BUTTON_STATE_MENU_OPEN); return WM_UI_HANDLER_BREAK; } @@ -4306,9 +4319,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co else if ((int)(but->a1) == UI_PALETTE_COLOR && event->type == DELKEY && event->val == KM_PRESS) { - Scene *scene = CTX_data_scene(C); - Paint *paint = BKE_paint_get_active(scene); - Palette *palette = BKE_paint_palette(paint); + Palette *palette = but->rnapoin.id.data; PaletteColor *color = but->rnapoin.data; BKE_palette_color_remove(palette, color); @@ -4333,13 +4344,6 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if ((int)(but->a1) == UI_PALETTE_COLOR) { - Palette *palette = but->rnapoin.id.data; - PaletteColor *color = but->rnapoin.data; - palette->active_color = BLI_findindex(&palette->colors, color); - - /* enforce redraw, sometimes state here can already be exit */ - ED_region_tag_redraw(data->region); - if (!event->ctrl) { float color[3]; Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index cdc611a60f4..2f66c4a9900 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -225,7 +225,7 @@ struct uiBut { * (type == NUM), Use to store RNA 'precision' value, for dragging and click-step. * (type == LABEL), If (a1 == 1.0f) use a2 as a blending factor. * (type == SEARCH_MENU) Use as number or columns. - * (type == COLOR) Use as indication of active palette color + * (type == COLOR) Use as index in palette (not so good, needs refactor) */ float a2; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 27af550b173..c2bd6d307d1 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1442,7 +1442,7 @@ typedef struct CollItemSearch { int iconid; } CollItemSearch; -static int sort_search_items_list(void *a, void *b) +static int sort_search_items_list(const void *a, const void *b) { CollItemSearch *cis1 = (CollItemSearch *)a; CollItemSearch *cis2 = (CollItemSearch *)b; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 364a62bd2a0..b0bea42e3bc 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2407,8 +2407,7 @@ void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname, RNA_pointer_create(&palette->id, &RNA_PaletteColor, color, &ptr); uiDefButR(block, COLOR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, &ptr, "color", -1, 0.0, 1.0, - UI_PALETTE_COLOR, (col_id == palette->active_color) ? UI_PALETTE_COLOR_ACTIVE : 0.0, ""); - + UI_PALETTE_COLOR, col_id, ""); row_cols++; col_id++; } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index ff46925edaa..11b9b9c83cc 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2172,8 +2172,8 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti * glVertex2f(centx, centy); for (a = 0; a <= tot; a++, ang += radstep) { - float si = sin(ang); - float co = cos(ang); + float si = sinf(ang); + float co = cosf(ang); ui_hsvcircle_vals_from_pos(hsv, hsv + 1, rect, centx + co * radius, centy + si * radius); @@ -2898,11 +2898,18 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat widgetbase_draw(&wtb, wcol); - if (but->a1 == UI_PALETTE_COLOR && but->a2 == UI_PALETTE_COLOR_ACTIVE) { + if (but->a1 == UI_PALETTE_COLOR && ((Palette *)but->rnapoin.id.data)->active_color == (int)but->a2) { float width = rect->xmax - rect->xmin; float height = rect->ymax - rect->ymin; - - glColor4ubv((unsigned char *)wcol->outline); + /* find color luminance and change it slightly */ + float bw = rgb_to_bw(col); + + if (bw > 0.5) + bw -= 0.5; + else + bw += 0.5; + + glColor4f(bw, bw, bw, 1.0); glBegin(GL_TRIANGLES); glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.9f * height); glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.5f * height); @@ -3834,7 +3841,7 @@ void ui_draw_pie_center(uiBlock *block) int subd = 40; - float angle = atan2(pie_dir[1], pie_dir[0]); + float angle = atan2f(pie_dir[1], pie_dir[0]); float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? ((float)M_PI / 2.0f) : ((float)M_PI / 4.0f); glPushMatrix(); diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index a4130540b1b..bbf4447dd72 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -96,7 +96,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int use_object_instantiation; int sort_by_name; int export_transformation_type; - int open_sim; + int open_sim; + + int export_count; if (!RNA_struct_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); @@ -148,33 +150,36 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) ED_object_editmode_load(CTX_data_edit_object(C)); - - if (collada_export(CTX_data_scene(C), - filepath, - apply_modifiers, - export_mesh_type, - selected, - include_children, - include_armatures, - include_shapekeys, - deform_bones_only, - - active_uv_only, - include_uv_textures, - include_material_textures, - use_texture_copies, - - triangulate, - use_object_instantiation, - sort_by_name, - export_transformation_type, - open_sim)) - { - return OPERATOR_FINISHED; + export_count = collada_export(CTX_data_scene(C), + filepath, + apply_modifiers, + export_mesh_type, + selected, + include_children, + include_armatures, + include_shapekeys, + deform_bones_only, + + active_uv_only, + include_uv_textures, + include_material_textures, + use_texture_copies, + + triangulate, + use_object_instantiation, + sort_by_name, + export_transformation_type, + open_sim); + + if (export_count == 0) { + BKE_report(op->reports, RPT_WARNING, "Export file is empty"); + return OPERATOR_CANCELLED; } else { - BKE_report(op->reports, RPT_WARNING, "Export file not created"); - return OPERATOR_CANCELLED; + char buff[100]; + sprintf(buff, "Exported %d Objects", export_count); + BKE_report(op->reports, RPT_INFO, buff); + return OPERATOR_FINISHED; } } @@ -350,8 +355,8 @@ void WM_OT_collada_export(wmOperatorType *ot) RNA_def_enum(ot->srna, "export_transformation_type_selection", prop_bc_export_transformation_type, 0, "Transform", "Transformation type for translation, scale and rotation"); - RNA_def_boolean(ot->srna, "open_sim", 0, "Export for OpenSim", - "Compatibility mode for OpenSim and compatible online worlds"); + RNA_def_boolean(ot->srna, "open_sim", 0, "Export to SL/OpenSim", + "Compatibility mode for SL, OpenSim and other compatible online worlds"); } diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 1acdff8b824..e2eb32e86d9 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -550,6 +550,8 @@ void ED_keymap_mask(wmKeyConfig *keyconf) /* duplicate */ WM_keymap_add_item(keymap, "MASK_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "MASK_OT_copy_splines", CKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MASK_OT_paste_splines", VKEY, KM_PRESS, KM_CTRL, 0); /* for image editor only */ WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 9f8388f1fe0..c3959f90318 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -580,7 +580,10 @@ static bool spline_under_mouse_get(const bContext *C, } } } - if (closest_spline != NULL) { + /* TODO(sergey): Chech whether tesellated spline point is closer + * to the mouse than the spline center. + */ + if (closest_dist_squared < 32.0f * 32.0f && closest_spline != NULL) { *mask_layer_r = closest_layer; *mask_spline_r = closest_spline; return true; @@ -2294,6 +2297,10 @@ static int copy_splines_exec(bContext *C, wmOperator *UNUSED(op)) Mask *mask = CTX_data_edit_mask(C); MaskLayer *mask_layer = BKE_mask_layer_active(mask); + if (mask_layer == NULL) { + return OPERATOR_CANCELLED; + } + BKE_mask_clipboard_copy_from_layer(mask_layer); return OPERATOR_FINISHED; @@ -2331,6 +2338,10 @@ static int paste_splines_exec(bContext *C, wmOperator *UNUSED(op)) Mask *mask = CTX_data_edit_mask(C); MaskLayer *mask_layer = BKE_mask_layer_active(mask); + if (mask_layer == NULL) { + mask_layer = BKE_mask_layer_new(mask, ""); + } + BKE_mask_clipboard_paste_to_layer(CTX_data_main(C), mask_layer); /* TODO: only update edited splines */ diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 76c41adf444..f5a7e82a8a8 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2157,7 +2157,7 @@ static ListBase *find_hole(KnifeTool_OpData *kcd, ListBase *fedges) static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, ListBase **mainchain, ListBase **sidechain) { - float **fco, **hco; + float (*fco)[2], (*hco)[2]; BMVert **fv; KnifeVert **hv; KnifeEdge **he; @@ -2179,8 +2179,8 @@ static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, L /* Gather 2d projections of hole and face vertex coordinates. * Use best-axis projection - not completely accurate, maybe revisit */ axis_dominant_v3(&ax, &ay, f->no); - hco = BLI_memarena_alloc(kcd->arena, nh * sizeof(float *)); - fco = BLI_memarena_alloc(kcd->arena, nf * sizeof(float *)); + hco = BLI_memarena_alloc(kcd->arena, nh * sizeof(float[2])); + fco = BLI_memarena_alloc(kcd->arena, nf * sizeof(float[2])); hv = BLI_memarena_alloc(kcd->arena, nh * sizeof(KnifeVert *)); fv = BLI_memarena_alloc(kcd->arena, nf * sizeof(BMVert *)); he = BLI_memarena_alloc(kcd->arena, nh * sizeof(KnifeEdge *)); @@ -2198,7 +2198,6 @@ static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, L kfv = kfvother; BLI_assert(kfv == kfe->v1 || kfv == kfe->v2); } - hco[i] = BLI_memarena_alloc(kcd->arena, 2 * sizeof(float)); hco[i][0] = kfv->co[ax]; hco[i][1] = kfv->co[ay]; hv[i] = kfv; @@ -2208,7 +2207,6 @@ static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, L j = 0; BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) { - fco[j] = BLI_memarena_alloc(kcd->arena, 2 * sizeof(float)); fco[j][0] = v->co[ax]; fco[j][1] = v->co[ay]; fv[j] = v; diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 59fbe739d03..b5508ef8b82 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -75,6 +75,9 @@ typedef struct RingSelOpData { float (*edges)[2][3]; int totedge; + float (*points)[3]; + int totpoint; + ViewContext vc; Object *ob; @@ -91,9 +94,8 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) { View3D *v3d = CTX_wm_view3d(C); RingSelOpData *lcd = arg; - int i; - if (lcd->totedge > 0) { + if ((lcd->totedge > 0) || (lcd->totpoint > 0)) { if (v3d && v3d->zbuf) glDisable(GL_DEPTH_TEST); @@ -101,12 +103,23 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) glMultMatrixf(lcd->ob->obmat); glColor3ub(255, 0, 255); - glBegin(GL_LINES); - for (i = 0; i < lcd->totedge; i++) { - glVertex3fv(lcd->edges[i][0]); - glVertex3fv(lcd->edges[i][1]); + if (lcd->totedge > 0) { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, lcd->edges); + glDrawArrays(GL_LINES, 0, lcd->totedge * 2); + glDisableClientState(GL_VERTEX_ARRAY); + } + + if (lcd->totpoint > 0) { + glPointSize(3.0f); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, lcd->points); + glDrawArrays(GL_POINTS, 0, lcd->totpoint); + glDisableClientState(GL_VERTEX_ARRAY); + + glPointSize(1.0f); } - glEnd(); glPopMatrix(); if (v3d && v3d->zbuf) @@ -178,52 +191,43 @@ static void edgering_vcos_get(DerivedMesh *dm, BMVert *v[2][2], float r_cos[2][2 } } -static void edgering_sel(RingSelOpData *lcd, int previewlines, bool select) +static void edgering_vcos_get_pair(DerivedMesh *dm, BMVert *v[2], float r_cos[2][3]) { - BMEditMesh *em = lcd->em; - DerivedMesh *dm = EDBM_mesh_deform_dm_get(em); - BMEdge *eed_start = lcd->eed; - BMEdge *eed, *eed_last; - BMVert *v[2][2], *v_last; - BMWalker walker; - float (*edges)[2][3] = NULL; - BLI_array_declare(edges); - int i, tot = 0; - - memset(v, 0, sizeof(v)); - - if (!eed_start) - return; - - if (lcd->edges) { - MEM_freeN(lcd->edges); - lcd->edges = NULL; - lcd->totedge = 0; + if (dm) { + int j; + for (j = 0; j < 2; j++) { + dm->getVertCo(dm, BM_elem_index_get(v[j]), r_cos[j]); + } } - - if (!lcd->extend) { - EDBM_flag_disable_all(lcd->em, BM_ELEM_SELECT); + else { + int j; + for (j = 0; j < 2; j++) { + copy_v3_v3(r_cos[j], v[j]->co); + } } +} - if (select) { - BMW_init(&walker, em->bm, BMW_EDGERING, - BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, - BMW_FLAG_TEST_HIDDEN, - BMW_NIL_LAY); - - for (eed = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) { - BM_edge_select_set(em->bm, eed, true); - } - BMW_end(&walker); +static void edgering_preview_free(RingSelOpData *lcd) +{ + MEM_SAFE_FREE(lcd->edges); + lcd->totedge = 0; - return; - } + MEM_SAFE_FREE(lcd->points); + lcd->totpoint = 0; +} - if (dm) { - BM_mesh_elem_table_ensure(lcd->em->bm, BM_VERT); - } +static void edgering_preview_calc_edges(RingSelOpData *lcd, DerivedMesh *dm, const int previewlines) +{ + BMesh *bm = lcd->em->bm; + BMWalker walker; + BMEdge *eed_start = lcd->eed; + BMEdge *eed, *eed_last; + BMVert *v[2][2] = {{NULL}}, *v_last; + float (*edges)[2][3] = NULL; + BLI_array_declare(edges); + int i, tot = 0; - BMW_init(&walker, em->bm, BMW_EDGERING, + BMW_init(&walker, bm, BMW_EDGERING, BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); @@ -261,7 +265,7 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, bool select) } eed_last = eed; } - + if ((eed_last != eed_start) && #ifdef BMW_EDGERING_NGON BM_edge_share_face_check(eed_last, eed_start) @@ -274,7 +278,7 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, bool select) v[1][1] = v[0][1]; edgering_find_order(eed_last, eed_start, v_last, v); - + BLI_array_grow_items(edges, previewlines); for (i = 1; i <= previewlines; i++) { @@ -298,15 +302,83 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, bool select) lcd->totedge = tot; } +static void edgering_preview_calc_points(RingSelOpData *lcd, DerivedMesh *dm, const int previewlines) +{ + float v_cos[2][3]; + float (*points)[3]; + int i, tot = 0; + + if (dm) { + BM_mesh_elem_table_ensure(lcd->em->bm, BM_VERT); + } + + points = MEM_mallocN(sizeof(*lcd->points) * previewlines, __func__); + + edgering_vcos_get_pair(dm, &lcd->eed->v1, v_cos); + + for (i = 1; i <= previewlines; i++) { + const float fac = (i / ((float)previewlines + 1)); + interp_v3_v3v3(points[tot], v_cos[0], v_cos[1], fac); + tot++; + } + + lcd->points = points; + lcd->totpoint = previewlines; +} + +static void edgering_preview_calc(RingSelOpData *lcd, const int previewlines) +{ + DerivedMesh *dm; + + BLI_assert(lcd->eed != NULL); + + edgering_preview_free(lcd); + + dm = EDBM_mesh_deform_dm_get(lcd->em); + if (dm) { + BM_mesh_elem_table_ensure(lcd->em->bm, BM_VERT); + } + + if (BM_edge_is_wire(lcd->eed)) { + edgering_preview_calc_points(lcd, dm, previewlines); + } + else { + edgering_preview_calc_edges(lcd, dm, previewlines); + } +} + +static void edgering_select(RingSelOpData *lcd) +{ + BMEditMesh *em = lcd->em; + BMEdge *eed_start = lcd->eed; + BMWalker walker; + BMEdge *eed; + + if (!eed_start) + return; + + if (!lcd->extend) { + EDBM_flag_disable_all(lcd->em, BM_ELEM_SELECT); + } + + BMW_init(&walker, em->bm, BMW_EDGERING, + BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, + BMW_FLAG_TEST_HIDDEN, + BMW_NIL_LAY); + + for (eed = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) { + BM_edge_select_set(em->bm, eed, true); + } + BMW_end(&walker); +} + static void ringsel_find_edge(RingSelOpData *lcd, const int previewlines) { if (lcd->eed) { - edgering_sel(lcd, previewlines, false); + edgering_preview_calc(lcd, previewlines); } - else if (lcd->edges) { - MEM_freeN(lcd->edges); - lcd->edges = NULL; - lcd->totedge = 0; + else { + edgering_preview_free(lcd); } } @@ -324,26 +396,37 @@ static void ringsel_finish(bContext *C, wmOperator *op) if (lcd->eed) { BMEditMesh *em = lcd->em; + BMVert *v_eed_orig[2] = {lcd->eed->v1, lcd->eed->v2}; - edgering_sel(lcd, cuts, true); + edgering_select(lcd); if (lcd->do_cut) { const bool is_macro = (op->opm != NULL); + /* a single edge (rare, but better support) */ + const bool is_single = (BM_edge_is_wire(lcd->eed)); + const int seltype = is_single ? SUBDIV_SELECT_INNER : SUBDIV_SELECT_LOOPCUT; + /* Enable gridfill, so that intersecting loopcut works as one would expect. * Note though that it will break edgeslide in this specific case. * See [#31939]. */ BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, smoothness, smooth_falloff, true, 0.0f, 0.0f, - cuts, - SUBDIV_SELECT_LOOPCUT, SUBD_PATH, 0, true, + cuts, seltype, SUBD_PATH, 0, true, use_only_quads, 0); /* when used in a macro tessface is already re-recalculated */ EDBM_update_generic(em, (is_macro == false), true); + if (is_single) { + /* de-select endpoints */ + BM_vert_select_set(em->bm, v_eed_orig[0], false); + BM_vert_select_set(em->bm, v_eed_orig[1], false); + + EDBM_selectmode_flush_ex(lcd->em, SCE_SELECT_VERTEX); + } /* we cant slide multiple edges in vertex select mode */ - if (is_macro && (cuts > 1) && (em->selectmode & SCE_SELECT_VERTEX)) { + else if (is_macro && (cuts > 1) && (em->selectmode & SCE_SELECT_VERTEX)) { EDBM_selectmode_disable(lcd->vc.scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); } /* force edge slide to edge select mode in in face select mode */ @@ -378,8 +461,7 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op) /* deactivate the extra drawing stuff in 3D-View */ ED_region_draw_cb_exit(lcd->ar->type, lcd->draw_handle); - if (lcd->edges) - MEM_freeN(lcd->edges); + edgering_preview_free(lcd); ED_region_tag_redraw(lcd->ar); @@ -594,7 +676,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) ringsel_exit(C, op); ED_area_headerprint(CTX_wm_area(C), NULL); - return OPERATOR_FINISHED; + return OPERATOR_CANCELLED; case ESCKEY: if (event->val == KM_RELEASE) { /* cancel */ diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 3b993332db0..4f149bf2c52 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -309,8 +309,7 @@ static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm) uid_start = uid; uid = uid_end + bm->totedge; - BLI_array_grow_one(eloop_pairs); - lp = &eloop_pairs[BLI_array_count(eloop_pairs) - 1]; + lp = BLI_array_append_ret(eloop_pairs); BM_edge_loop_pair(e_last, &lp->l_a, &lp->l_b); /* no need to check, we know this will be true */ @@ -323,8 +322,7 @@ static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm) } /* null terminate */ - BLI_array_grow_one(eloop_pairs); - lp = &eloop_pairs[BLI_array_count(eloop_pairs) - 1]; + lp = BLI_array_append_ret(eloop_pairs); lp->l_a = lp->l_b = NULL; return eloop_pairs; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 9cdfb43ae15..473da4c9756 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -66,6 +66,8 @@ #include "UI_resources.h" +#include "bmesh_tools.h" + #include "mesh_intern.h" /* own include */ /* use bmesh operator flags for a few operators */ @@ -929,6 +931,96 @@ void MESH_OT_select_similar(wmOperatorType *ot) } +/* -------------------------------------------------------------------- */ +/* Select Similar Regions */ + +static int edbm_select_similar_region_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + bool changed = false; + + /* group vars */ + int *groups_array; + int (*group_index)[2]; + int group_tot; + int i; + + if (bm->totfacesel < 2) { + BKE_report(op->reports, RPT_ERROR, "No face regions selected"); + return OPERATOR_CANCELLED; + } + + groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__); + group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index, + NULL, NULL, + BM_ELEM_SELECT, BM_VERT); + + BM_mesh_elem_table_ensure(bm, BM_FACE); + + for (i = 0; i < group_tot; i++) { + ListBase faces_regions; + int tot; + + const int fg_sta = group_index[i][0]; + const int fg_len = group_index[i][1]; + int j; + BMFace **fg = MEM_mallocN(sizeof(*fg) * fg_len, __func__); + + + for (j = 0; j < fg_len; j++) { + fg[j] = BM_face_at_index(bm, groups_array[fg_sta + j]); + } + + tot = BM_mesh_region_match(bm, fg, fg_len, &faces_regions); + + MEM_freeN(fg); + + if (tot) { + LinkData *link; + while ((link = BLI_pophead(&faces_regions))) { + BMFace *f, **faces = link->data; + unsigned int i = 0; + while ((f = faces[i++])) { + BM_face_select_set(bm, f, true); + } + MEM_freeN(faces); + MEM_freeN(link); + + changed = true; + } + } + } + + MEM_freeN(groups_array); + + if (changed) { + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit); + } + else { + BKE_report(op->reports, RPT_WARNING, "No matching face regions found"); + } + + return OPERATOR_FINISHED; +} + +void MESH_OT_select_similar_region(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Similar Regions"; + ot->idname = "MESH_OT_select_similar_region"; + ot->description = "Select similar face regions to the current selection"; + + /* api callbacks */ + ot->exec = edbm_select_similar_region_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + + /* **************** Mode Select *************** */ static int edbm_select_mode_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 3f1023b7fb4..20c7f4eb521 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -1288,7 +1288,8 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) bool mirrx = false, mirry = false, mirrz = false; int i, repeat; float clip_dist = 0.0f; - bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; + const float fac = RNA_float_get(op->ptr, "factor"); + const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; const bool xaxis = RNA_boolean_get(op->ptr, "xaxis"); const bool yaxis = RNA_boolean_get(op->ptr, "yaxis"); @@ -1322,12 +1323,12 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) repeat = RNA_int_get(op->ptr, "repeat"); if (!repeat) repeat = 1; - + for (i = 0; i < repeat; i++) { if (!EDBM_op_callf(em, op, - "smooth_vert verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clip_dist=%f " - "use_axis_x=%b use_axis_y=%b use_axis_z=%b", - BM_ELEM_SELECT, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis)) + "smooth_vert verts=%hv factor=%f mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b " + "clip_dist=%f use_axis_x=%b use_axis_y=%b use_axis_z=%b", + BM_ELEM_SELECT, fac, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis)) { return OPERATOR_CANCELLED; } @@ -1358,7 +1359,8 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Number of times to smooth the mesh", "", 1, 100); + RNA_def_float(ot->srna, "factor", 0.5f, -10.0f, 10.0f, "Smoothing", "Smoothing factor", 0.0f, 1.0f); + RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Repeat", "Number of times to smooth the mesh", 1, 100); RNA_def_boolean(ot->srna, "xaxis", 1, "X-Axis", "Smooth along the X axis"); RNA_def_boolean(ot->srna, "yaxis", 1, "Y-Axis", "Smooth along the Y axis"); RNA_def_boolean(ot->srna, "zaxis", 1, "Z-Axis", "Smooth along the Z axis"); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index bf8559add6f..68471bfc2ba 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -47,6 +47,7 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_paint.h" #include "BKE_report.h" #include "BKE_editmesh.h" @@ -502,6 +503,12 @@ static int mesh_uv_texture_add_exec(bContext *C, wmOperator *UNUSED(op)) if (ED_mesh_uv_texture_add(me, NULL, true) == -1) return OPERATOR_CANCELLED; + if (ob->mode & OB_MODE_TEXTURE_PAINT) { + Scene *scene = CTX_data_scene(C); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + } + return OPERATOR_FINISHED; } @@ -622,6 +629,12 @@ static int mesh_uv_texture_remove_exec(bContext *C, wmOperator *UNUSED(op)) if (!ED_mesh_uv_texture_remove_active(me)) return OPERATOR_CANCELLED; + if (ob->mode & OB_MODE_TEXTURE_PAINT) { + Scene *scene = CTX_data_scene(C); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + } + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 76f6cb5ebb8..6ba91097ec4 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -137,6 +137,7 @@ void MESH_OT_rip_edge(struct wmOperatorType *ot); /* *** editmesh_select.c *** */ void MESH_OT_select_similar(struct wmOperatorType *ot); +void MESH_OT_select_similar_region(struct wmOperatorType *ot); void MESH_OT_select_mode(struct wmOperatorType *ot); void MESH_OT_loop_multi_select(struct wmOperatorType *ot); void MESH_OT_loop_select(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 31653efa735..e7dc5a69d53 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -130,6 +130,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_edge_face_add); WM_operatortype_append(MESH_OT_shortest_path_pick); WM_operatortype_append(MESH_OT_select_similar); + WM_operatortype_append(MESH_OT_select_similar_region); WM_operatortype_append(MESH_OT_select_mode); WM_operatortype_append(MESH_OT_loop_multi_select); WM_operatortype_append(MESH_OT_mark_seam); @@ -342,7 +343,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MESH_OT_faces_select_linked_flat", FKEY, KM_PRESS, (KM_CTRL | KM_SHIFT | KM_ALT), 0); - WM_keymap_add_item(keymap, "MESH_OT_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0); /* selection mode */ WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_select_mode", TABKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index d252ae20270..16f4f61f92b 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -999,7 +999,7 @@ static int mirror_facerotation(MFace *a, MFace *b) return -1; } -static int mirror_facecmp(const void *a, const void *b) +static bool mirror_facecmp(const void *a, const void *b) { return (mirror_facerotation((MFace *)a, (MFace *)b) == -1); } diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index 2402ecb498d..b8957514159 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -682,6 +682,7 @@ static void finish_bake_internal(BakeRender *bkr) } BKE_image_release_ibuf(ima, ibuf, NULL); + DAG_id_tag_update(&ima->id, 0); } } diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 372ca33fa4b..5746f9efd56 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -56,6 +56,7 @@ #include "BKE_modifier.h" #include "BKE_mesh.h" #include "BKE_screen.h" +#include "BKE_depsgraph.h" #include "RE_engine.h" #include "RE_pipeline.h" @@ -260,13 +261,14 @@ static bool write_internal_bake_pixels( } /* force OpenGL reload */ -static void reset_images_gpu(BakeImages *bake_images) +static void refresh_images(BakeImages *bake_images) { int i; for (i = 0; i < bake_images->size; i++) { Image *ima = bake_images->data[i].image; if (ima->ok == IMA_OK_LOADED) { GPU_free_image(ima); + DAG_id_tag_update(&ima->id, 0); } } } @@ -966,7 +968,7 @@ cage_cleanup: } if (is_save_internal) - reset_images_gpu(&bake_images); + refresh_images(&bake_images); cleanup: diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 0d58eaee5fa..abc0516cf2b 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2411,10 +2411,13 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent return OPERATOR_CANCELLED; assign_material(base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF); - + + DAG_id_tag_update(&base->object->id, OB_RECALC_OB); + + WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, base->object); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma); - + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index a1b8478a0e1..f19765a5344 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -974,7 +974,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) DAG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA); copy_v3_v3(centn, cent); - mul_mat3_m4_v3(ob_other->obmat, centn); /* ommit translation part */ + mul_mat3_m4_v3(ob_other->obmat, centn); /* omit translation part */ add_v3_v3(ob_other->loc, centn); BKE_object_where_is_calc(scene, ob_other); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 6897861c81c..777bbabb6e8 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -4324,10 +4324,10 @@ static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op) return OPERATOR_FINISHED; } -static int vgroup_sort_name(void *def_a_ptr, void *def_b_ptr) +static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr) { - bDeformGroup *def_a = (bDeformGroup *)def_a_ptr; - bDeformGroup *def_b = (bDeformGroup *)def_b_ptr; + const bDeformGroup *def_a = def_a_ptr; + const bDeformGroup *def_b = def_b_ptr; return BLI_natstrcmp(def_a->name, def_b->name); } diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 5401cef8351..76344b77dd3 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -319,7 +319,7 @@ void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra) if (pset->flag & PE_FADE_TIME && pset->selectmode==SCE_SELECT_POINT) { LOOP_POINTS { LOOP_KEYS { - if (fabs(cfra-*key->time) < pset->fade_frames) + if (fabsf(cfra - *key->time) < pset->fade_frames) key->flag &= ~PEK_HIDE; else { key->flag |= PEK_HIDE; @@ -463,7 +463,7 @@ static bool key_inside_circle(PEData *data, float rad, const float co[3], float dx= data->mval[0] - screen_co[0]; dy= data->mval[1] - screen_co[1]; - dist= sqrt(dx*dx + dy*dy); + dist = sqrtf(dx * dx + dy * dy); if (dist > rad) return 0; @@ -2932,7 +2932,7 @@ static void brush_cut(PEData *data, int pa_index) d= dv * rad2 - d*d; if (d > 0.0f) { - d= sqrt(d); + d= sqrtf(d); cut_time= -(v0*xo0 + v1*xo1 + d); @@ -3678,7 +3678,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) pset->flag &= ~PE_LOCK_FIRST; if (((pset->brushtype == PE_BRUSH_ADD) ? - (sqrt(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first) + (sqrtf(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first) { PEData data= bedit->data; diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 3972ed1c49e..b53891f4880 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -1063,8 +1063,8 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor WM_jobs_start(CTX_wm_manager(C), wm_job); } else { - short dummy_stop, dummy_do_update; - float dummy_progress; + short dummy_stop = 0, dummy_do_update = 0; + float dummy_progress = 0.0f; /* blocking, use with exec() */ fluidbake_startjob((void *)fb, &dummy_stop, &dummy_do_update, &dummy_progress); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 01f00a8458a..450a3b19889 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -88,6 +88,7 @@ #include "PIL_time.h" #include "RE_pipeline.h" +#include "RE_engine.h" #include "WM_api.h" #include "WM_types.h" @@ -213,6 +214,12 @@ void ED_preview_init_dbase(void) #endif } +static bool check_engine_supports_textures(Scene *scene) +{ + RenderEngineType *type = RE_engines_find(scene->r.engine); + return type->flag & RE_USE_TEXTURE_PREVIEW; +} + void ED_preview_free_dbase(void) { if (G_pr_main) @@ -299,7 +306,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre sce->r.cfra = scene->r.cfra; - if (id_type == ID_TE) { + if (id_type == ID_TE && !check_engine_supports_textures(scene)) { /* Force blender internal for texture icons and nodes render, * seems commonly used render engines does not support * such kind of rendering. @@ -751,12 +758,6 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs if (sp->pr_rect) RE_ResultGet32(re, sp->pr_rect); } - else { - /* validate owner */ - //if (ri->rect == NULL) - // ri->rect= MEM_mallocN(sizeof(int) * ri->pr_rectx*ri->pr_recty, "BIF_previewrender"); - //RE_ResultGet32(re, ri->rect); - } /* unassign the pointers, reset vars */ preview_prepare_scene(sp->scene, NULL, GS(id->name), sp); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 72b4da64c3e..6c996bcbd67 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -58,6 +58,7 @@ #include "BKE_linestyle.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_paint.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_texture.h" @@ -102,8 +103,15 @@ static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op)) if (!ob) return OPERATOR_CANCELLED; - + object_add_material_slot(ob); + + if (ob->mode & OB_MODE_TEXTURE_PAINT) { + Scene *scene = CTX_data_scene(C); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + } + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob); WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_PREVIEW, ob); @@ -138,8 +146,15 @@ static int material_slot_remove_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode"); return OPERATOR_CANCELLED; } - + object_remove_material_slot(ob); + + if (ob->mode & OB_MODE_TEXTURE_PAINT) { + Scene *scene = CTX_data_scene(C); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + } + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, ob); diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 6b58d3d55aa..df7ca9f11b2 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -166,7 +166,6 @@ void ED_render_engine_changed(Main *bmain) bScreen *sc; ScrArea *sa; Scene *scene; - Material *ma; for (sc = bmain->screen.first; sc; sc = sc->id.next) for (sa = sc->areabase.first; sa; sa = sa->next) @@ -176,13 +175,6 @@ void ED_render_engine_changed(Main *bmain) for (scene = bmain->scene.first; scene; scene = scene->id.next) ED_render_id_flush_update(bmain, &scene->id); - - /* reset texture painting. Sending one dependency graph signal for any material should - * refresh any texture slots */ - ma = bmain->mat.first; - if (ma) { - DAG_id_tag_update(&ma->id, 0); - } } /***************************** Updates *********************************** @@ -482,15 +474,22 @@ static void image_changed(Main *bmain, Image *ima) texture_changed(bmain, tex); } -static void scene_changed(Main *bmain, Scene *UNUSED(scene)) +static void scene_changed(Main *bmain, Scene *scene) { Object *ob; Material *ma; /* glsl */ - for (ob = bmain->object.first; ob; ob = ob->id.next) + for (ob = bmain->object.first; ob; ob = ob->id.next) { if (ob->gpulamp.first) GPU_lamp_free(ob); + + if (ob->mode & OB_MODE_TEXTURE_PAINT) { + BKE_texpaint_slots_refresh_object(scene, ob); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + GPU_drawobject_free(ob->derivedFinal); + } + } for (ma = bmain->mat.first; ma; ma = ma->id.next) if (ma->gpumaterial.first) diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 7b9ede38b39..e27ef705fad 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -521,14 +521,15 @@ static int project_brush_radius(ViewContext *vc, } } -static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc, - int x, int y, int *pixel_radius, - float location[3]) +static bool sculpt_get_brush_geometry( + bContext *C, ViewContext *vc, + int x, int y, int *pixel_radius, + float location[3]) { Scene *scene = CTX_data_scene(C); Paint *paint = BKE_paint_get_active_from_context(C); float mouse[2]; - int hit; + bool hit; mouse[0] = x; mouse[1] = y; @@ -1011,7 +1012,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) * special mode of drawing will go away */ if ((mode == PAINT_SCULPT) && vc.obact->sculpt) { float location[3]; - int pixel_radius, hit; + int pixel_radius; + bool hit; /* test if brush is over the mesh */ hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 7c19528a049..f4189b512e5 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -57,6 +57,7 @@ #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" #include "BKE_brush.h" #include "BKE_image.h" #include "BKE_main.h" @@ -87,6 +88,7 @@ #include "RNA_enum_types.h" #include "GPU_draw.h" +#include "GPU_buffers.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -527,8 +529,11 @@ BlurKernel *paint_new_blur_kernel(Brush *br, bool proj) kernel->pixel_len = radius; } else { - radius = br->blur_kernel_radius; + if (br->blur_kernel_radius <= 0) + br->blur_kernel_radius = 1; + radius = br->blur_kernel_radius; + side = kernel->side = radius * 2 + 1; kernel->side_squared = kernel->side * kernel->side; kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data"); @@ -543,11 +548,11 @@ BlurKernel *paint_new_blur_kernel(Brush *br, bool proj) case KERNEL_GAUSSIAN: { - /* at standard deviation of 3.0 kernel is at about zero */ + /* at 3.0 standard deviations distance, kernel is about zero */ float standard_dev = radius / 3.0f; /* make the necessary adjustment to the value for use in the normal distribution formula */ - standard_dev = standard_dev * standard_dev * 2; + standard_dev = -standard_dev * standard_dev * 2; for (i = 0; i < side; i++) { for (j = 0; j < side; j++) { @@ -749,14 +754,16 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo copy_v2_v2(pop->prevmouse, mouse); copy_v2_v2(pop->startmouse, mouse); - if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) { - pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, gradient_draw_line, pop); - } - /* initialize from context */ if (CTX_wm_region_view3d(C)) { Object *ob = OBACT; - paint_proj_mesh_data_ensure(C, ob, op); + bool uvs, mat, tex, stencil; + if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) { + BKE_paint_data_warning(op->reports, uvs, mat, tex, stencil); + MEM_freeN(pop); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + return NULL; + } pop->mode = PAINT_MODE_3D_PROJECT; pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode); } @@ -770,6 +777,10 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo return NULL; } + if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) { + pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, gradient_draw_line, pop); + } + settings->imapaint.flag |= IMAGEPAINT_DRAWING; ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name, ED_image_undo_restore, ED_image_undo_free, NULL); @@ -1378,28 +1389,31 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) * cache in case we are loading a file */ BKE_texpaint_slots_refresh_object(scene, ob); - paint_proj_mesh_data_ensure(C, ob, op); - + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + /* entering paint mode also sets image to editors */ if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) { Material *ma = give_current_material(ob, ob->actcol); /* set the current material active paint slot on image editor */ - if (ma->texpaintslot) + if (ma && ma->texpaintslot) ima = ma->texpaintslot[ma->paint_active_slot].ima; } else if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) { ima = imapaint->canvas; } - for (sc = bmain->screen.first; sc; sc = sc->id.next) { - ScrArea *sa; - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - for (sl = sa->spacedata.first; sl; sl = sl->next) { - if (sl->spacetype == SPACE_IMAGE) { - SpaceImage *sima = (SpaceImage *)sl; - - ED_space_image_set(sima, scene, scene->obedit, ima); + if (ima) { + for (sc = bmain->screen.first; sc; sc = sc->id.next) { + ScrArea *sa; + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)sl; + + if (!sima->pin) + ED_space_image_set(sima, scene, scene->obedit, ima); + } } } } @@ -1416,7 +1430,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) toggle_paint_cursor(C, 1); } - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + GPU_drawobject_free(ob->derivedFinal); WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene); return OPERATOR_FINISHED; @@ -1482,12 +1496,17 @@ void PAINT_OT_brush_colors_flip(wmOperatorType *ot) void ED_imapaint_bucket_fill(struct bContext *C, float color[3], wmOperator *op) { + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = sima->image; + ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name, ED_image_undo_restore, ED_image_undo_free, NULL); paint_2d_bucket_fill(C, color, NULL, NULL, NULL); ED_undo_paint_push_end(UNDO_PAINT_IMAGE); + + DAG_id_tag_update(&ima->id, 0); } diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 165888b3c09..5530f947b8c 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -1564,7 +1564,7 @@ void paint_2d_gradient_fill( sub_v2_v2v2(tangent, image_final, image_init); line_len = len_squared_v2(tangent); line_len_sq_inv = 1.0f / line_len; - line_len = sqrt(line_len); + line_len = sqrtf(line_len); do_float = (ibuf->rect_float != NULL); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 0fb3e278f40..f9124db7a5e 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -74,6 +74,7 @@ #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" +#include "BKE_node.h" #include "BKE_paint.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -84,6 +85,7 @@ #include "ED_image.h" #include "ED_mesh.h" +#include "ED_node.h" #include "ED_paint.h" #include "ED_screen.h" #include "ED_uvedit.h" @@ -362,7 +364,7 @@ static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int { MFace *mf = ps->dm_mface + face_index; Material *ma = ps->dm->mat[mf->mat_nr]; - return ma->texpaintslot + ma->paint_active_slot; + return ma ? ma->texpaintslot + ma->paint_active_slot : NULL; } static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_index) @@ -373,7 +375,7 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_ else { MFace *mf = ps->dm_mface + face_index; Material *ma = ps->dm->mat[mf->mat_nr]; - TexPaintSlot *slot = ma->texpaintslot + ma->paint_active_slot; + TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL; return slot ? slot->ima : ps->canvas_ima; } } @@ -382,14 +384,14 @@ static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int { MFace *mf = ps->dm_mface + face_index; Material *ma = ps->dm->mat[mf->mat_nr]; - return ma->texpaintslot + ma->paint_clone_slot; + return ma ? ma->texpaintslot + ma->paint_clone_slot : NULL; } static Image *project_paint_face_clone_image(const ProjPaintState *ps, int face_index) { MFace *mf = ps->dm_mface + face_index; Material *ma = ps->dm->mat[mf->mat_nr]; - TexPaintSlot *slot = ma->texpaintslot + ma->paint_clone_slot; + TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL; return slot ? slot->ima : ps->clone_ima; } @@ -4077,7 +4079,7 @@ static void *do_projectpaint_thread(void *ph_v) sub_v2_v2v2(tangent, pos, lastpos); line_len = len_squared_v2(tangent); line_len_sq_inv = 1.0f / line_len; - line_len = sqrt(line_len); + line_len = sqrtf(line_len); switch (brush->gradient_fill_mode) { case BRUSH_GRADIENT_LINEAR: @@ -4533,9 +4535,14 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int settings->imapaint.clone : NULL; /* setup projection painting data */ - ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1; - ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1; - ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1; + if (ps->tool != PAINT_TOOL_FILL) { + ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1; + ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1; + ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1; + } + else { + ps->do_backfacecull = ps->do_occlude = ps->do_mask_normal = 0; + } ps->do_new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); /* only cache the value */ if (ps->tool == PAINT_TOOL_CLONE) @@ -4660,13 +4667,18 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) IDProperty *idgroup; IDProperty *view_data = NULL; Object *ob = OBACT; + bool uvs, mat, tex; if (ob == NULL || ob->type != OB_MESH) { BKE_report(op->reports, RPT_ERROR, "No active mesh object"); return OPERATOR_CANCELLED; } - paint_proj_mesh_data_ensure(C, ob, op); + if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, NULL)) { + BKE_paint_data_warning(op->reports, uvs, mat, tex, true); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + return OPERATOR_CANCELLED; + } project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL); @@ -4858,108 +4870,78 @@ void PAINT_OT_image_from_view(wmOperatorType *ot) * Data generation for projective texturing * * *******************************************/ +void BKE_paint_data_warning(struct ReportList *reports, bool uvs, bool mat, bool tex, bool stencil) +{ + BKE_reportf(reports, RPT_WARNING, "Missing%s%s%s%s detected!", + !uvs ? " UVs," : "", + !mat ? " Materials," : "", + !tex ? " Textures," : "", + !stencil ? " Stencil," : "" + ); +} /* Make sure that active object has a material, and assign UVs and image layers if they do not exist */ -void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op) +bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil) { Mesh *me; int layernum; - ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint); - bScreen *sc; - Scene *scene = CTX_data_scene(C); - Main *bmain = CTX_data_main(C); + ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; Brush *br = BKE_paint_brush(&imapaint->paint); + bool hasmat = true; + bool hastex = true; + bool hasstencil = true; + bool hasuvs = true; + imapaint->missing_data = 0; + BLI_assert(ob->type == OB_MESH); - /* no material, add one */ - if (ob->totcol == 0) { - Material *ma = BKE_material_add(CTX_data_main(C), "Material"); - /* no material found, just assign to first slot */ - assign_material(ob, ma, 1, BKE_MAT_ASSIGN_USERPREF); - proj_paint_add_slot(C, ma, NULL); - } - else { - /* there may be material slots but they may be empty, check */ - int i; - - for (i = 1; i < ob->totcol + 1; i++) { - Material *ma = give_current_material(ob, i); - - if (ma) { - if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) { + if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) { + /* no material, add one */ + if (ob->totcol == 0) { + hasmat = false; + hastex = false; + } + else { + /* there may be material slots but they may be empty, check */ + int i; + hasmat = false; + hastex = false; + + for (i = 1; i < ob->totcol + 1; i++) { + Material *ma = give_current_material(ob, i); + + if (ma) { + hasmat = true; if (!ma->texpaintslot) { /* refresh here just in case */ BKE_texpaint_slot_refresh_cache(scene, ma); /* if still no slots, we have to add */ - if (!ma->texpaintslot) { - proj_paint_add_slot(C, ma, NULL); - - if (ma->texpaintslot) { - for (sc = bmain->screen.first; sc; sc = sc->id.next) { - ScrArea *sa; - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - for (sl = sa->spacedata.first; sl; sl = sl->next) { - if (sl->spacetype == SPACE_IMAGE) { - SpaceImage *sima = (SpaceImage *)sl; - - ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[0].ima); - } - } - } - } - } + if (ma->texpaintslot) { + hastex = true; + break; } } + else { + hastex = true; + break; + } } } - else { - Material *ma = BKE_material_add(CTX_data_main(C), "Material"); - /* no material found, just assign to first slot */ - assign_material(ob, ma, i, BKE_MAT_ASSIGN_USERPREF); - proj_paint_add_slot(C, ma, NULL); - } } } - - if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) { + else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) { if (imapaint->canvas == NULL) { - int width; - int height; - Main *bmain = CTX_data_main(C); - float color[4] = {0.0, 0.0, 0.0, 1.0}; - - width = 1024; - height = 1024; - imapaint->canvas = BKE_image_add_generated(bmain, width, height, "Canvas", 32, false, IMA_GENTYPE_BLANK, color); - - GPU_drawobject_free(ob->derivedFinal); - - for (sc = bmain->screen.first; sc; sc = sc->id.next) { - ScrArea *sa; - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - for (sl = sa->spacedata.first; sl; sl = sl->next) { - if (sl->spacetype == SPACE_IMAGE) { - SpaceImage *sima = (SpaceImage *)sl; - - ED_space_image_set(sima, scene, scene->obedit, imapaint->canvas); - } - } - } - } + hastex = false; } } - + me = BKE_mesh_from_object(ob); layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); if (layernum == 0) { - BKE_reportf(op->reports, RPT_WARNING, "Object did not have UV map, manual unwrap recommended"); - - ED_mesh_uv_texture_add(me, "UVMap", true); + hasuvs = false; } /* Make sure we have a stencil to paint on! */ @@ -4967,16 +4949,29 @@ void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op) imapaint->flag |= IMAGEPAINT_PROJECT_LAYER_STENCIL; if (imapaint->stencil == NULL) { - int width; - int height; - Main *bmain = CTX_data_main(C); - float color[4] = {0.0, 0.0, 0.0, 1.0}; - - width = 1024; - height = 1024; - imapaint->stencil = BKE_image_add_generated(bmain, width, height, "Stencil", 32, false, IMA_GENTYPE_BLANK, color); + hasstencil = false; } } + + if (!hasuvs) imapaint->missing_data |= IMAGEPAINT_MISSING_UVS; + if (!hasmat) imapaint->missing_data |= IMAGEPAINT_MISSING_MATERIAL; + if (!hastex) imapaint->missing_data |= IMAGEPAINT_MISSING_TEX; + if (!hasstencil) imapaint->missing_data |= IMAGEPAINT_MISSING_STENCIL; + + if (uvs) { + *uvs = hasuvs; + } + if (mat) { + *mat = hasmat; + } + if (tex) { + *tex = hastex; + } + if (stencil) { + *stencil = hasstencil; + } + + return hasuvs && hasmat && hastex && hasstencil; } /* Add layer operator */ @@ -4999,30 +4994,74 @@ static EnumPropertyItem layer_type_items[] = { {0, NULL, 0, NULL, NULL} }; -bool proj_paint_add_slot(bContext *C, Material *ma, wmOperator *op) +static Image *proj_paint_image_create(wmOperator *op, Main *bmain) +{ + Image *ima; + float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color"; + int width = 1024; + int height = 1024; + bool use_float = false; + short gen_type = IMA_GENTYPE_BLANK; + bool alpha = false; + + if (op) { + width = RNA_int_get(op->ptr, "width"); + height = RNA_int_get(op->ptr, "height"); + use_float = RNA_boolean_get(op->ptr, "float"); + gen_type = RNA_enum_get(op->ptr, "generated_type"); + RNA_float_get_array(op->ptr, "color", color); + alpha = RNA_boolean_get(op->ptr, "alpha"); + RNA_string_get(op->ptr, "name", imagename); + } + ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float, + gen_type, color); + + return ima; +} + +static bool proj_paint_add_slot(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); Scene *scene = CTX_data_scene(C); + Material *ma; bool is_bi = BKE_scene_uses_blender_internal(scene); + Image *ima = NULL; if (!ob) return false; - if (!ma) - ma = give_current_material(ob, ob->actcol); + ma = give_current_material(ob, ob->actcol); if (ma) { + Main *bmain = CTX_data_main(C); - if (!is_bi || ma->use_nodes) { - /* not supported for now */ + if (!is_bi && BKE_scene_use_new_shading_nodes(scene)) { + bNode *imanode; + bNodeTree *ntree = ma->nodetree; + + if (!ntree) { + ED_node_shader_default(C, &ma->id); + ntree = ma->nodetree; + } + + ma->use_nodes = true; + + /* try to add an image node */ + imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE); + + ima = proj_paint_image_create(op, bmain); + imanode->id = &ima->id; + + nodeSetActive(ntree, imanode); + + ntreeUpdateTree(CTX_data_main(C), ntree); } else { MTex *mtex = add_mtex_id(&ma->id, -1); /* successful creation of mtex layer, now create set */ if (mtex) { - Main *bmain = CTX_data_main(C); - Image *ima; int type = MAP_COL; int type_id = 0; @@ -5042,47 +5081,36 @@ bool proj_paint_add_slot(bContext *C, Material *ma, wmOperator *op) mtex->mapto = type; if (mtex->tex) { - float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color"; - int width = 1024; - int height = 1024; - bool use_float = false; - short gen_type = IMA_GENTYPE_BLANK; - bool alpha = false; - - if (op) { - width = RNA_int_get(op->ptr, "width"); - height = RNA_int_get(op->ptr, "height"); - use_float = RNA_boolean_get(op->ptr, "float"); - gen_type = RNA_enum_get(op->ptr, "generated_type"); - RNA_float_get_array(op->ptr, "color", color); - alpha = RNA_boolean_get(op->ptr, "alpha"); - RNA_string_get(op->ptr, "name", imagename); - } - - ima = mtex->tex->ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float, - gen_type, color); - - BKE_texpaint_slot_refresh_cache(scene, ma); - BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE); - WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex); - WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima); - DAG_id_tag_update(&ma->id, 0); - ED_area_tag_redraw(CTX_wm_area(C)); + ima = mtex->tex->ima = proj_paint_image_create(op, bmain); } WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C)); - return true; } + WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex); + } + + if (ima) { + BKE_texpaint_slot_refresh_cache(scene, ma); + BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE); + WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima); + DAG_id_tag_update(&ma->id, 0); + ED_area_tag_redraw(CTX_wm_area(C)); + + return true; } } - + return false; } static int texture_paint_add_texture_paint_slot_exec(bContext *C, wmOperator *op) { - return proj_paint_add_slot(C, NULL, op); + if (proj_paint_add_slot(C, op)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } @@ -5093,6 +5121,12 @@ static int texture_paint_add_texture_paint_slot_invoke(bContext *C, wmOperator * Material *ma = give_current_material(ob, ob->actcol); int type = RNA_enum_get(op->ptr, "type"); + if (!ma) { + ma = BKE_material_add(CTX_data_main(C), "Material"); + /* no material found, just assign to first slot */ + assign_material(ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF); + } + type = RNA_enum_from_value(layer_type_items, type); /* get the name of the texture layer type */ @@ -5180,7 +5214,7 @@ void PAINT_OT_delete_texture_paint_slot(wmOperatorType *ot) { /* identifiers */ ot->name = "Delete Texture Paint Slot"; - ot->description = "Add a texture paint slot"; + ot->description = "Delete selected texture paint slot"; ot->idname = "PAINT_OT_delete_texture_paint_slot"; /* api callbacks */ diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 5e1ac0cf8a8..c3b7ec60e71 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -169,8 +169,6 @@ void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float m void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], const bool eraser, float pressure, float distance, float size); void paint_proj_redraw(const struct bContext *C, void *pps, bool final); void paint_proj_stroke_done(void *ps); -void paint_proj_mesh_data_ensure(bContext *C, struct Object *ob, struct wmOperator *op); -bool proj_paint_add_slot(bContext *C, struct Material *ma, struct wmOperator *op); void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance, float pressure, float color[3], struct ColorManagedDisplay *display); bool paint_use_opacity_masking(struct Brush *brush); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 8faa4cfaf33..24ef735affe 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -319,7 +319,7 @@ static void mask_lasso_px_cb(int x, int y, void *user_data) static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) { int mcords_tot; - int (*mcords)[2] = (int (*)[2])WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); if (mcords) { float clip_planes[4][4], clip_planes_final[4][4]; @@ -349,13 +349,13 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) ob = vc.obact; ED_view3d_ob_project_mat_get(vc.rv3d, ob, data.projviewobjmat); - BLI_lasso_boundbox(&data.rect, (const int (*)[2])mcords, mcords_tot); + BLI_lasso_boundbox(&data.rect, mcords, mcords_tot); data.width = data.rect.xmax - data.rect.xmin; - data.px = MEM_callocN(sizeof(*data.px) * data.width * (data.rect.ymax - data.rect.ymin), "lasso_mask_pixel_buffer"); + data.px = MEM_callocN(sizeof(*data.px) * data.width * (data.rect.ymax - data.rect.ymin), __func__); fill_poly_v2i_n( data.rect.xmin, data.rect.ymin, data.rect.xmax, data.rect.ymax, - (const int (*)[2])mcords, mcords_tot, + mcords, mcords_tot, mask_lasso_px_cb, &data); ED_view3d_clipping_calc(&bb, clip_planes, &mats, &data.rect); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 90161fa87dd..dc6be9caa53 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -228,8 +228,9 @@ static int palette_color_delete_exec(bContext *C, wmOperator *UNUSED(op)) { Paint *paint = BKE_paint_get_active_from_context(C); Palette *palette = paint->palette; + PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color); - BKE_palette_color_delete(palette); + BKE_palette_color_remove(palette, color); return OPERATOR_FINISHED; } @@ -666,7 +667,7 @@ static void stencil_set_target(StencilControlData *scd) scd->lenorig = len_v2(mdiff); - scd->init_angle = atan2(mdiff[1], mdiff[0]); + scd->init_angle = atan2f(mdiff[1], mdiff[0]); } static int stencil_control_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -762,7 +763,7 @@ static void stencil_control_calculate(StencilControlData *scd, const int mval[2] { float angle; sub_v2_v2v2(mdiff, mvalf, scd->pos_target); - angle = atan2(mdiff[1], mdiff[0]); + angle = atan2f(mdiff[1], mdiff[0]); angle = scd->init_rot + angle - scd->init_angle; if (angle < 0.0f) angle += (float)(2 * M_PI); @@ -915,7 +916,7 @@ static int stencil_fit_image_aspect_exec(bContext *C, wmOperator *op) stencil_area = br->stencil_dimension[0] * br->stencil_dimension[1]; } - factor = sqrt(stencil_area / orig_area); + factor = sqrtf(stencil_area / orig_area); if (do_mask) { br->mask_stencil_dimension[0] = factor * aspx; diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 8f189b49aa6..101d176b00f 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -283,9 +283,9 @@ static bool paint_brush_update(bContext *C, const float dx = mouse[0] - stroke->initial_mouse[0]; const float dy = mouse[1] - stroke->initial_mouse[1]; - ups->anchored_size = ups->pixel_radius = sqrt(dx * dx + dy * dy); + ups->anchored_size = ups->pixel_radius = sqrtf(dx * dx + dy * dy); - ups->brush_rotation = atan2(dx, dy) + M_PI; + ups->brush_rotation = atan2f(dx, dy) + M_PI; if (brush->flag & BRUSH_EDGE_TO_EDGE) { halfway[0] = dx * 0.5f + stroke->initial_mouse[0]; @@ -498,7 +498,7 @@ static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing) for (i = 0; i < n; i++) { float xx; - xx = fabs(x0 + i * h); + xx = fabsf(x0 + i * h); if (xx < 1.0f) sum += BKE_brush_curve_strength(br, xx, 1); @@ -758,7 +758,7 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode) bool paint_supports_texture(PaintMode mode) { - /* ommit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */ + /* omit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */ return ELEM(mode, PAINT_SCULPT, PAINT_VERTEX, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D); } diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index f34d0ff3f7b..e03c8a5f106 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -395,7 +395,7 @@ static Image *imapaint_face_image(DerivedMesh *dm, int face_index) Image *ima; MFace *mf = dm->getTessFaceArray(dm) + face_index; Material *ma = dm->mat[mf->mat_nr]; - ima = ma->texpaintslot[ma->paint_active_slot].ima; + ima = ma ? ma->texpaintslot[ma->paint_active_slot].ima : NULL; return ima; } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 33d0510c08a..766048d54bb 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -192,8 +192,8 @@ typedef struct StrokeCache { float true_location[3]; float location[3]; - float pen_flip; - float invert; + bool pen_flip; + bool invert; float pressure; float mouse[2]; float bstrength; @@ -550,7 +550,7 @@ static bool sculpt_brush_test(SculptBrushTest *test, const float co[3]) if (sculpt_brush_test_clipping(test, co)) { return 0; } - test->dist = sqrt(distsq); + test->dist = sqrtf(distsq); return 1; } else { @@ -809,10 +809,10 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather, Unifi return alpha * pressure * feather; case SCULPT_TOOL_SNAKE_HOOK: - return feather; + return root_alpha * feather; case SCULPT_TOOL_GRAB: - return feather; + return root_alpha * feather; case SCULPT_TOOL_ROTATE: return alpha * pressure * feather; @@ -2553,7 +2553,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno sub_v3_v3v3(val, intr, vd.co); if (plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrt(test.dist), + const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2626,7 +2626,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) sub_v3_v3v3(val, intr, vd.co); if (plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrt(test.dist), + const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2792,7 +2792,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) if (plane_trim(ss->cache, brush, val)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, - sqrt(test.dist), + sqrtf(test.dist), vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2856,7 +2856,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod if (plane_trim(ss->cache, brush, val)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, - sqrt(test.dist), + sqrtf(test.dist), vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2899,7 +2899,7 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl BKE_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq(&test, vd.co)) { - const float fade = tex_strength(ss, brush, vd.co, sqrt(test.dist), vd.no, + const float fade = tex_strength(ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], offset, fade); @@ -4006,14 +4006,14 @@ static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob) typedef struct { SculptSession *ss; const float *ray_start, *ray_normal; - int hit; + bool hit; float dist; int original; } SculptRaycastData; typedef struct { const float *ray_start, *ray_normal; - int hit; + bool hit; float dist; float detail; } SculptDetailRaycastData; @@ -4145,7 +4145,7 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession sculpt_update_tex(scene, sd, ss); } -static int sculpt_brush_stroke_init(bContext *C, wmOperator *op) +static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 292d6236bab..d90eaafa379 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -273,7 +273,7 @@ static void HC_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, Temp_UVData *tmp_uvdata; float diff[2]; int i; - float radius_root = sqrt(radius); + float radius_root = sqrtf(radius); Brush *brush = BKE_paint_brush(sculptdata->uvsculpt); tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData), "Temporal data"); @@ -316,7 +316,7 @@ static void HC_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, if ((dist = dot_v2v2(diff, diff)) <= radius) { UvElement *element; float strength; - strength = alpha * BKE_brush_curve_strength(brush, sqrt(dist), radius_root); + strength = alpha * BKE_brush_curve_strength(brush, sqrtf(dist), radius_root); sculptdata->uv[i].uv[0] = (1.0f - strength) * sculptdata->uv[i].uv[0] + strength * (tmp_uvdata[i].p[0] - 0.5f * (tmp_uvdata[i].b[0] + tmp_uvdata[i].sum_b[0] / tmp_uvdata[i].ncounter)); sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] + strength * (tmp_uvdata[i].p[1] - 0.5f * (tmp_uvdata[i].b[1] + tmp_uvdata[i].sum_b[1] / tmp_uvdata[i].ncounter)); @@ -345,7 +345,7 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *scul Temp_UVData *tmp_uvdata; float diff[2]; int i; - float radius_root = sqrt(radius); + float radius_root = sqrtf(radius); Brush *brush = BKE_paint_brush(sculptdata->uvsculpt); tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData), "Temporal data"); @@ -380,7 +380,7 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *scul if ((dist = dot_v2v2(diff, diff)) <= radius) { UvElement *element; float strength; - strength = alpha * BKE_brush_curve_strength(brush, sqrt(dist), radius_root); + strength = alpha * BKE_brush_curve_strength(brush, sqrtf(dist), radius_root); sculptdata->uv[i].uv[0] = (1.0f - strength) * sculptdata->uv[i].uv[0] + strength * tmp_uvdata[i].p[0]; sculptdata->uv[i].uv[1] = (1.0f - strength) * sculptdata->uv[i].uv[1] + strength * tmp_uvdata[i].p[1]; @@ -434,7 +434,7 @@ static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, const wmEvent *e /* We will compare squares to save some computation */ radius = radius * radius; - radius_root = sqrt(radius); + radius_root = sqrtf(radius); /* * Pinch Tool @@ -455,7 +455,7 @@ static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, const wmEvent *e if ((dist = dot_v2v2(diff, diff)) <= radius) { UvElement *element; float strength; - strength = alpha * BKE_brush_curve_strength(brush, sqrt(dist), radius_root); + strength = alpha * BKE_brush_curve_strength(brush, sqrtf(dist), radius_root); normalize_v2(diff); sculptdata->uv[i].uv[0] -= strength * diff[0] * 0.001f; @@ -563,7 +563,7 @@ static unsigned int uv_edge_hash(const void *key) BLI_ghashutil_uinthash(edge->uv1)); } -static int uv_edge_compare(const void *a, const void *b) +static bool uv_edge_compare(const void *a, const void *b) { UvEdge *edge1 = (UvEdge *)a; UvEdge *edge2 = (UvEdge *)b; @@ -803,7 +803,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm aspectRatio = width / (float)height; radius /= (width * zoomx); radius = radius * radius; - radius_root = sqrt(radius); + radius_root = sqrtf(radius); /* Allocate selection stack */ data->initial_stroke = MEM_mallocN(sizeof(*data->initial_stroke), "uv_sculpt_initial_stroke"); @@ -829,7 +829,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm diff[1] /= aspectRatio; if ((dist = dot_v2v2(diff, diff)) <= radius) { float strength; - strength = alpha * BKE_brush_curve_strength(brush, sqrt(dist), radius_root); + strength = alpha * BKE_brush_curve_strength(brush, sqrtf(dist), radius_root); data->initial_stroke->initialSelection[counter].uv = i; data->initial_stroke->initialSelection[counter].strength = strength; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index a6fbb0c399d..a797a60f74c 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -754,6 +754,10 @@ static void clip_keymap(struct wmKeyConfig *keyconf) RNA_string_set(kmi->ptr, "data_path", "space_data.pivot_point"); RNA_string_set(kmi->ptr, "value", "INDIVIDUAL_ORIGINS"); + /* Copy-paste */ + WM_keymap_add_item(keymap, "CLIP_OT_copy_tracks", CKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "CLIP_OT_paste_tracks", VKEY, KM_PRESS, KM_CTRL, 0); + /* ******** Hotkeys avalaible for preview region only ******** */ keymap = WM_keymap_find(keyconf, "Clip Graph Editor", SPACE_CLIP, 0); diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index abbffcd8546..fb6b1a0033c 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -3811,7 +3811,9 @@ static int paste_tracks_exec(bContext *C, wmOperator *UNUSED(op)) MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); + ListBase *tracks_base = BKE_tracking_object_get_tracks(tracking, object); + BKE_tracking_tracks_deselect_all(tracks_base); BKE_tracking_clipboard_paste_tracks(tracking, object); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index d049a45fd90..1915f45fc87 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -443,7 +443,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingASCII)) continue; - fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL); CFRelease(pathString); CFRelease(cfURL); diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 7e90008d8d2..ed6e6ba1e1b 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -809,6 +809,10 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE); uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + + if (ima->gen_type == IMA_GENTYPE_BLANK) { + uiItemR(layout, &imaptr, "generated_color", 0, NULL, ICON_NONE); + } } } diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 24b1c54dd9f..757059ebc29 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -303,13 +303,6 @@ bool ED_space_image_show_paint(SpaceImage *sima) return (sima->mode == SI_MODE_PAINT); } -bool ED_space_image_show_texpaint(SpaceImage *sima, Object *ob) -{ - return (ob && ob->type == OB_MESH && - ob->mode == OB_MODE_TEXTURE_PAINT && - !(sima->flag & SI_NO_DRAW_TEXPAINT)); -} - bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit) { if (sima && (ED_space_image_show_render(sima) || ED_space_image_show_paint(sima))) @@ -327,24 +320,6 @@ bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit) return false; } -bool ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit) -{ - if (ED_space_image_show_render(sima)) - return false; - - if (ED_space_image_show_paint(sima)) - if (obedit && obedit->type == OB_MESH) { - struct BMEditMesh *em = BKE_editmesh_from_object(obedit); - bool ret; - - ret = EDBM_mtexpoly_check(em); - - return ret && !(sima->flag & SI_NO_DRAW_TEXPAINT); - } - - return false; -} - /* matches clip function */ bool ED_space_image_check_show_maskedit(Scene *scene, SpaceImage *sima) { diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index c87e547b6ea..58b56e99119 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -49,17 +49,20 @@ #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" #include "BKE_icons.h" #include "BKE_image.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_packedFile.h" +#include "BKE_paint.h" #include "BKE_report.h" #include "BKE_screen.h" #include "BKE_sound.h" #include "GPU_draw.h" +#include "GPU_buffers.h" #include "IMB_colormanagement.h" #include "IMB_imbuf.h" @@ -1001,10 +1004,10 @@ static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *p RNA_END } -static int image_cmp_frame(void *a, void *b) +static int image_cmp_frame(const void *a, const void *b) { - ImageFrame *frame_a = (ImageFrame *)a; - ImageFrame *frame_b = (ImageFrame *)b; + const ImageFrame *frame_a = a; + const ImageFrame *frame_b = b; if (frame_a->framenr < frame_b->framenr) return -1; if (frame_a->framenr > frame_b->framenr) return 1; @@ -1905,6 +1908,12 @@ void IMAGE_OT_reload(wmOperatorType *ot) /********************** new image operator *********************/ #define IMA_DEF_NAME N_("Untitled") +enum { + GEN_CONTEXT_NONE = 0, + GEN_CONTEXT_PAINT_CANVAS = 1, + GEN_CONTEXT_PAINT_STENCIL = 2 +}; + static int image_new_exec(bContext *C, wmOperator *op) { SpaceImage *sima; @@ -1918,6 +1927,7 @@ static int image_new_exec(bContext *C, wmOperator *op) char *name = _name; float color[4]; int width, height, floatbuf, gen_type, alpha; + int gen_context; /* retrieve state */ sima = CTX_wm_space_image(C); @@ -1937,6 +1947,7 @@ static int image_new_exec(bContext *C, wmOperator *op) gen_type = RNA_enum_get(op->ptr, "generated_type"); RNA_float_get_array(op->ptr, "color", color); alpha = RNA_boolean_get(op->ptr, "alpha"); + gen_context = RNA_enum_get(op->ptr, "gen_context"); if (!alpha) color[3] = 1.0f; @@ -1961,6 +1972,40 @@ static int image_new_exec(bContext *C, wmOperator *op) else if (sima) { ED_space_image_set(sima, scene, obedit, ima); } + else if (gen_context == GEN_CONTEXT_PAINT_CANVAS) { + bScreen *sc; + Object *ob = CTX_data_active_object(C); + + GPU_drawobject_free(ob->derivedFinal); + if (scene->toolsettings->imapaint.canvas) + id_us_min(&scene->toolsettings->imapaint.canvas->id); + scene->toolsettings->imapaint.canvas = ima; + + for (sc = bmain->screen.first; sc; sc = sc->id.next) { + ScrArea *sa; + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)sl; + + if (!sima->pin) + ED_space_image_set(sima, scene, scene->obedit, ima); + } + } + } + } + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + } + else if (gen_context == GEN_CONTEXT_PAINT_STENCIL) { + Object *ob = CTX_data_active_object(C); + if (scene->toolsettings->imapaint.stencil) + id_us_min(&scene->toolsettings->imapaint.stencil->id); + scene->toolsettings->imapaint.stencil = ima; + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); + } else { Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; if (tex && tex->type == TEX_IMAGE) { @@ -1991,6 +2036,13 @@ void IMAGE_OT_new(wmOperatorType *ot) { PropertyRNA *prop; static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + + static EnumPropertyItem gen_context_items[] = { + {GEN_CONTEXT_NONE, "NONE", 0, "None", ""}, + {GEN_CONTEXT_PAINT_CANVAS, "PAINT_CANVAS", 0, "Paint Canvas", ""}, + {GEN_CONTEXT_PAINT_STENCIL, "PAINT_STENCIL", 0, "Paint Stencil", ""}, + {0, NULL, 0, NULL, NULL} + }; /* identifiers */ ot->name = "New Image"; @@ -2017,7 +2069,7 @@ void IMAGE_OT_new(wmOperatorType *ot) RNA_def_enum(ot->srna, "generated_type", image_generated_type_items, IMA_GENTYPE_BLANK, "Generated Type", "Fill the image with a grid for UV map testing"); RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth"); - prop = RNA_def_boolean(ot->srna, "texstencil", 0, "Stencil", "Set Image as stencil"); + prop = RNA_def_enum(ot->srna, "gen_context", gen_context_items, 0, "Gen Context", "Generation context"); RNA_def_property_flag(prop, PROP_HIDDEN); } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index ffe9f13af3f..ab616bf592f 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -540,7 +540,7 @@ static void image_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn) break; } case NC_WM: - if(wmn->data == ND_UNDO) { + if (wmn->data == ND_UNDO) { ED_area_tag_redraw(sa); ED_area_tag_refresh(sa); } diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 97a2383c03f..973ce56857c 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -67,12 +67,12 @@ typedef struct bNodeListItem { struct bNode *node; } bNodeListItem; -static int sort_nodes_locx(void *a, void *b) +static int sort_nodes_locx(const void *a, const void *b) { - bNodeListItem *nli1 = (bNodeListItem *)a; - bNodeListItem *nli2 = (bNodeListItem *)b; - bNode *node1 = nli1->node; - bNode *node2 = nli2->node; + const bNodeListItem *nli1 = a; + const bNodeListItem *nli2 = b; + const bNode *node1 = nli1->node; + const bNode *node2 = nli2->node; if (node1->locx > node2->locx) return 1; diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 5a78ea6ebd8..de580f612a0 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -248,22 +248,34 @@ static bool node_select_grouped_name(SpaceNode *snode, bNode *node_act, const bo bNode *node; bool changed = false; const unsigned int delims[] = {'.', '-', '_', '\0'}; - size_t index_act, index_curr; + size_t pref_len_act, pref_len_curr; char *sep, *suf_act, *suf_curr; - index_act = BLI_str_partition_ex_utf8(node_act->name, delims, &sep, &suf_act, from_right); + pref_len_act = BLI_str_partition_ex_utf8(node_act->name, delims, &sep, &suf_act, from_right); - if (index_act > 0) { - for (node = snode->edittree->nodes.first; node; node = node->next) { - if ((node->flag & SELECT) == 0) { - index_curr = BLI_str_partition_ex_utf8(node->name, delims, &sep, &suf_curr, from_right); - if ((from_right && STREQ(suf_act, suf_curr)) || - (!from_right && (index_act == index_curr) && STREQLEN(node_act->name, node->name, index_act))) - { - nodeSetSelected(node, true); - changed = true; - } - } + /* Note: in case we are searching for suffix, and found none, use whole name as suffix. */ + if (from_right && !(sep && suf_act)) { + pref_len_act = 0; + suf_act = node_act->name; + } + + for (node = snode->edittree->nodes.first; node; node = node->next) { + if (node->flag & SELECT) { + continue; + } + pref_len_curr = BLI_str_partition_ex_utf8(node->name, delims, &sep, &suf_curr, from_right); + + /* Same as with active node name! */ + if (from_right && !(sep && suf_curr)) { + pref_len_curr = 0; + suf_curr = node->name; + } + + if ((from_right && STREQ(suf_act, suf_curr)) || + (!from_right && (pref_len_act == pref_len_curr) && STREQLEN(node_act->name, node->name, pref_len_act))) + { + nodeSetSelected(node, true); + changed = true; } } diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 875639da113..ccaeae34927 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -511,7 +511,7 @@ static void node_area_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn) } break; case NC_WM: - if(wmn->data == ND_UNDO) { + if (wmn->data == ND_UNDO) { ED_area_tag_refresh(sa); } break; diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 95802be9ef9..af827d6dc5a 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -373,9 +373,11 @@ static const char *txt_utf8_forward_columns(const char *str, int columns, int *p static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w, const char *format, int skip) { + const bool use_syntax = (st->showsyntax && format); FlattenString fs; int basex, lines; int i, wrap, end, max, columns, padding; /* column */ + /* warning, only valid when 'use_syntax' is set */ int a, fstart, fpos; /* utf8 chars */ int mi, ma, mstart, mend; /* mem */ char fmt_prev = 0xff; @@ -397,8 +399,11 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w /* skip hidden part of line */ if (skip) { skip--; - fstart = fpos = end; - mstart = mend; + if (use_syntax) { + /* currently fpos only used when formatting */ + fpos += BLI_strnlen_utf8(str + mstart, mend - mstart); + } + fstart = fpos; mstart = mend; mend = txt_utf8_forward_columns(str + mend, max, &padding) - str; end = (wrap += max - padding); continue; @@ -406,7 +411,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w /* Draw the visible portion of text on the overshot line */ for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) { - if (st->showsyntax && format) { + if (use_syntax) { if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]); } x += text_font_draw_character_utf8(st, x, y, str + ma); @@ -428,7 +433,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w /* Draw the remaining text */ for (a = fstart, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) { - if (st->showsyntax && format) { + if (use_syntax) { if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]); } @@ -442,6 +447,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w static void text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int x, int y, const char *format) { + const bool use_syntax = (st->showsyntax && format); FlattenString fs; int columns, size, n, w = 0, padding, amount = 0; const char *in = NULL; @@ -474,7 +480,7 @@ static void text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int x, x += st->cwidth * padding; - if (st->showsyntax && format) { + if (use_syntax) { int a, str_shift = 0; char fmt_prev = 0xff; diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 2e3d8d056e8..852edaac7dc 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -473,7 +473,9 @@ static void txt_write_file(Text *text, ReportList *reports) for (tmp = text->lines.first; tmp; tmp = tmp->next) { fputs(tmp->line, fp); - fputc('\n', fp); + if (tmp->next) { + fputc('\n', fp); + } } fclose(fp); diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 2fd4b0bc21d..88c57d45b79 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -405,6 +405,7 @@ static void time_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) case NC_OBJECT: { switch (wmn->data) { + case ND_BONE_SELECT: case ND_BONE_ACTIVE: case ND_POINTCACHE: case ND_MODIFIER: diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index fb97a6ac9f4..fa9ba23e454 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -279,10 +279,10 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material * if (!ma && BKE_image_has_alpha(texface->tpage)) alphablend = GPU_BLEND_ALPHA; } - else if (texpaint && ma) { + else if (texpaint) { if (gtexdraw.texpaint_material) - ima = ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL; - else + ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL; + else ima = gtexdraw.canvas; } else @@ -315,6 +315,14 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material * glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); glBindTexture(GL_TEXTURE_2D, ima->bindcode); glActiveTexture(GL_TEXTURE0); } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index e7b6e50ef1c..d155918f7f9 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -302,7 +302,8 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) if (BKE_scene_use_new_shading_nodes(scene)) return false; - return ((scene->gm.matmode == GAME_MAT_GLSL) || (v3d->drawtype == OB_MATERIAL)) && (dt > OB_SOLID); + return ((scene->gm.matmode == GAME_MAT_GLSL && v3d->drawtype == OB_TEXTURE) || + (v3d->drawtype == OB_MATERIAL)) && (dt > OB_SOLID); } static bool check_alpha_pass(Base *base) @@ -5181,7 +5182,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv /* restore & clean up */ if (1) { //ob_dt > OB_WIRE) { if (part->draw_col == PART_DRAW_COL_MAT) - glDisable(GL_COLOR_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); glDisable(GL_COLOR_MATERIAL); } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 8b76ec3a56d..0e3621aa91f 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -698,10 +698,6 @@ static void view3d_main_area_free(ARegion *ar) if (rv3d->localvd) MEM_freeN(rv3d->localvd); if (rv3d->clipbb) MEM_freeN(rv3d->clipbb); - if (rv3d->ri) { - // XXX BIF_view3d_previewrender_free(rv3d); - } - if (rv3d->render_engine) RE_engine_free(rv3d->render_engine); @@ -735,7 +731,6 @@ static void *view3d_main_area_duplicate(void *poin) new->depths = NULL; new->gpuoffscreen = NULL; - new->ri = NULL; new->render_engine = NULL; new->sms = NULL; new->smooth_timer = NULL; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 004b3e1b7d3..61bfb0176ef 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1091,6 +1091,9 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) /* passepartout, specified in camera edit buttons */ if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) { + const float winx = (ar->winx + 1); + const float winy = (ar->winy + 1); + if (ca->passepartalpha == 1.0f) { glColor3f(0, 0, 0); } @@ -1100,11 +1103,11 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) glColor4f(0, 0, 0, ca->passepartalpha); } if (x1i > 0.0f) - glRectf(0.0, (float)ar->winy, x1i, 0.0); - if (x2i < (float)ar->winx) - glRectf(x2i, (float)ar->winy, (float)ar->winx, 0.0); - if (y2i < (float)ar->winy) - glRectf(x1i, (float)ar->winy, x2i, y2i); + glRectf(0.0, winy, x1i, 0.0); + if (x2i < winx) + glRectf(x2i, winy, winx, 0.0); + if (y2i < winy) + glRectf(x1i, winy, x2i, y2i); if (y2i > 0.0f) glRectf(x1i, y1i, x2i, 0.0); @@ -1585,6 +1588,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0; for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { + bgpic->iuser.scene = scene; /* Needed for render results. */ if ((bgpic->flag & V3D_BGPIC_FOREGROUND) != fg_flag) continue; @@ -1598,9 +1602,10 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, float x1, y1, x2, y2; ImBuf *ibuf = NULL, *freeibuf, *releaseibuf; + void *lock; - Image *ima; - MovieClip *clip; + Image *ima = NULL; + MovieClip *clip = NULL; /* disable individual images */ if ((bgpic->flag & V3D_BGPIC_DISABLED)) @@ -1617,16 +1622,14 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, ibuf = NULL; /* frame is out of range, dont show */ } else { - ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, NULL); + ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock); releaseibuf = ibuf; } image_aspect[0] = ima->aspx; - image_aspect[1] = ima->aspx; + image_aspect[1] = ima->aspy; } else if (bgpic->source == V3D_BGPIC_MOVIE) { - clip = NULL; - /* TODO: skip drawing when out of frame range (as image sequences do above) */ if (bgpic->flag & V3D_BGPIC_CAMERACLIP) { @@ -1664,7 +1667,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, if (freeibuf) IMB_freeImBuf(freeibuf); if (releaseibuf) - BKE_image_release_ibuf(ima, releaseibuf, NULL); + BKE_image_release_ibuf(ima, releaseibuf, lock); continue; } @@ -1763,7 +1766,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, if (freeibuf) IMB_freeImBuf(freeibuf); if (releaseibuf) - BKE_image_release_ibuf(ima, releaseibuf, NULL); + BKE_image_release_ibuf(ima, releaseibuf, lock); continue; } @@ -1830,7 +1833,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, if (freeibuf) IMB_freeImBuf(freeibuf); if (releaseibuf) - BKE_image_release_ibuf(ima, releaseibuf, NULL); + BKE_image_release_ibuf(ima, releaseibuf, lock); } } } @@ -1981,8 +1984,10 @@ static void draw_dupli_objects_color( GLuint displist = 0; unsigned char color_rgb[3]; const short dflag_dupli = dflag | DRAW_CONSTCOLOR; - short transflag, use_displist = -1; /* -1 is initialize */ + short transflag; + bool use_displist = false; /* -1 is initialize */ char dt; + bool testbb = false; short dtx; DupliApplyData *apply_data; @@ -2037,71 +2042,77 @@ static void draw_dupli_objects_color( tbase.object->transflag |= OB_NEG_SCALE; else tbase.object->transflag &= ~OB_NEG_SCALE; - + /* should move outside the loop but possible color is set in draw_object still */ if ((dflag & DRAW_CONSTCOLOR) == 0) { glColor3ubv(color_rgb); } - + /* generate displist, test for new object */ if (dob_prev && dob_prev->ob != dob->ob) { if (use_displist == true) glDeleteLists(displist, 1); - - use_displist = -1; + + use_displist = false; + } + + if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) { + bb = *bb_tmp; /* must make a copy */ + testbb = true; } - /* generate displist */ - if (use_displist == -1) { - - /* note, since this was added, its checked (dob->type == OB_DUPLIGROUP) - * however this is very slow, it was probably needed for the NLA - * offset feature (used in group-duplicate.blend but no longer works in 2.5) - * so for now it should be ok to - campbell */ - - if ( /* if this is the last no need to make a displist */ - (dob_next == NULL || dob_next->ob != dob->ob) || - /* lamp drawing messes with matrices, could be handled smarter... but this works */ - (dob->ob->type == OB_LAMP) || - (dob->type == OB_DUPLIGROUP && dob->animated) || - !(bb_tmp = BKE_object_boundbox_get(dob->ob)) || - draw_glsl_material(scene, dob->ob, v3d, dt) || - check_object_draw_texture(scene, v3d, dt) || - (base->object == OBACT && v3d->flag2 & V3D_SOLID_MATCAP)) - { - // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2); - use_displist = false; - } - else { - // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2); - bb = *bb_tmp; /* must make a copy */ - - /* disable boundbox check for list creation */ - BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1); - /* need this for next part of code */ - unit_m4(dob->ob->obmat); /* obmat gets restored */ - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - draw_object(scene, ar, v3d, &tbase, dflag_dupli); - glEndList(); - - use_displist = true; - BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0); + if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) { + /* generate displist */ + if (use_displist == false) { + + /* note, since this was added, its checked (dob->type == OB_DUPLIGROUP) + * however this is very slow, it was probably needed for the NLA + * offset feature (used in group-duplicate.blend but no longer works in 2.5) + * so for now it should be ok to - campbell */ + + if ( /* if this is the last no need to make a displist */ + (dob_next == NULL || dob_next->ob != dob->ob) || + /* lamp drawing messes with matrices, could be handled smarter... but this works */ + (dob->ob->type == OB_LAMP) || + (dob->type == OB_DUPLIGROUP && dob->animated) || + !bb_tmp || + draw_glsl_material(scene, dob->ob, v3d, dt) || + check_object_draw_texture(scene, v3d, dt) || + (v3d->flag2 & V3D_SOLID_MATCAP) != 0) + { + // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2); + use_displist = false; + } + else { + // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2); + + /* disable boundbox check for list creation */ + BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1); + /* need this for next part of code */ + unit_m4(dob->ob->obmat); /* obmat gets restored */ + + displist = glGenLists(1); + glNewList(displist, GL_COMPILE); + draw_object(scene, ar, v3d, &tbase, dflag_dupli); + glEndList(); + + use_displist = true; + BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0); + } } - } - if (use_displist) { - if (ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) { + + if (use_displist) { + glPushMatrix(); glMultMatrixf(dob->mat); glCallList(displist); - glLoadMatrixf(rv3d->viewmat); + glPopMatrix(); + } + else { + copy_m4_m4(dob->ob->obmat, dob->mat); + draw_object(scene, ar, v3d, &tbase, dflag_dupli); } } - else { - copy_m4_m4(dob->ob->obmat, dob->mat); - draw_object(scene, ar, v3d, &tbase, dflag_dupli); - } - + tbase.object->dt = dt; tbase.object->dtx = dtx; tbase.object->transflag = transflag; @@ -2473,7 +2484,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) v3d->drawtype = OB_SOLID; v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp); - v3d->flag2 &= ~V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP; + v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP); v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW; GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat); @@ -2515,8 +2526,11 @@ CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d) mask |= CD_MASK_ORCO; } else { - if (scene->gm.matmode == GAME_MAT_GLSL || v3d->drawtype == OB_MATERIAL) + if ((scene->gm.matmode == GAME_MAT_GLSL && v3d->drawtype == OB_TEXTURE) || + (v3d->drawtype == OB_MATERIAL)) + { mask |= CD_MASK_ORCO; + } } } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index db675b09896..f54e7ae06f6 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1037,8 +1037,8 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) * - dragged. */ phi = si * (float)(M_PI / 2.0); - q1[0] = cos(phi); - mul_v3_fl(q1 + 1, sin(phi)); + q1[0] = cosf(phi); + mul_v3_fl(q1 + 1, sinf(phi)); mul_qt_qtqt(vod->viewquat, q1, vod->oldquat); viewrotate_apply_dyn_ofs(vod, vod->viewquat); @@ -1448,7 +1448,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, ScrArea *sa, /* Perform the up/down rotation */ angle = ndof->dt * rot[0]; quat[0] = cosf(angle); - mul_v3_v3fl(quat + 1, xvec, sin(angle)); + mul_v3_v3fl(quat + 1, xvec, sinf(angle)); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat); /* Perform the orbital rotation */ @@ -3423,7 +3423,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) /* find the closest Z pixel */ depth_close = view3d_depth_near(&depth_temp); - MEM_freeN(depth_temp.depths); + MEM_SAFE_FREE(depth_temp.depths); } cent[0] = (((double)rect.xmin) + ((double)rect.xmax)) / 2; @@ -4640,7 +4640,7 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg view3d_update_depths_rect(ar, &depth_temp, &rect); depth_close = view3d_depth_near(&depth_temp); - if (depth_temp.depths) MEM_freeN(depth_temp.depths); + MEM_SAFE_FREE(depth_temp.depths); return depth_close; } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 46ea52054c5..ae429289ffd 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1181,14 +1181,14 @@ static short selectbuffer_ret_hits_15(unsigned int *UNUSED(buffer), const short static short selectbuffer_ret_hits_9(unsigned int *buffer, const short hits15, const short hits9) { const int offs = 4 * hits15; - memcpy(buffer, buffer + offs, 4 * offs); + memcpy(buffer, buffer + offs, 4 * hits9); return hits9; } static short selectbuffer_ret_hits_5(unsigned int *buffer, const short hits15, const short hits9, const short hits5) { const int offs = 4 * hits15 + 4 * hits9; - memcpy(buffer, buffer + offs, 4 * offs); + memcpy(buffer, buffer + offs, 4 * hits5); return hits5; } @@ -1522,7 +1522,7 @@ static bool mouse_select(bContext *C, const int mval[2], } } } - else if (ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend, deselect, toggle) ) { + else if (ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend, deselect, toggle, do_nearest)) { /* then bone is found */ /* we make the armature selected: @@ -1972,7 +1972,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool ED_armature_sync_selection(arm->edbo); - return OPERATOR_CANCELLED; + return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, bool select, bool extend) diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 7bdf39d6768..c54948b23c6 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -961,7 +961,7 @@ static int walkApply(bContext *C, WalkInfo *walk) /* clamp the angle limits */ /* it ranges from 90.0f to -90.0f */ - angle = -asin(rv3d->viewmat[2][2]); + angle = -asinf(rv3d->viewmat[2][2]); if (angle > WALK_TOP_LIMIT && y > 0.0f) y = 0.0f; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 008022a9859..24499688835 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -58,6 +58,7 @@ #include "BKE_particle.h" #include "BKE_unit.h" #include "BKE_mask.h" +#include "BKE_report.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -270,7 +271,8 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) r_vec[0] = dx; r_vec[1] = dy; } - else { const float mval_f[2] = {(float)dx, (float)dy}; + else { + const float mval_f[2] = {(float)dx, (float)dy}; ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac); } } @@ -2053,7 +2055,6 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve initTransInfo(C, t, op, event); if (t->spacetype == SPACE_VIEW3D) { - //calc_manipulator_stats(curarea); initTransformOrientation(C, t); t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW); @@ -4066,6 +4067,9 @@ static void initTranslation(TransInfo *t) { if (t->spacetype == SPACE_ACTION) { /* this space uses time translate */ + BKE_report(t->reports, RPT_ERROR, + "Use 'Time_Translate' transform mode instead of 'Translation' mode " + "for translating keyframes in Dope Sheet Editor"); t->state = TRANS_CANCEL; } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 012f9185d8b..67d55639528 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -537,7 +537,6 @@ void restoreBones(TransInfo *t); /*********************** exported from transform_manipulator.c ********** */ bool gimbal_axis(struct Object *ob, float gmat[3][3]); /* return 0 when no gimbal for selection */ -int calc_manipulator_stats(const struct bContext *C); /*********************** TransData Creation and General Handling *********** */ void createTransData(struct bContext *C, TransInfo *t); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index aa215613841..47adbb6d16d 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1711,7 +1711,9 @@ static void createTransLatticeVerts(TransInfo *t) if (bp->f1 & SELECT) { td->flag = TD_SELECTED; } - else td->flag = 0; + else { + td->flag = 0; + } copy_m3_m3(td->smtx, smtx); copy_m3_m3(td->mtx, mtx); @@ -3068,10 +3070,10 @@ static void createTransNlaData(bContext *C, TransInfo *t) /* ********************* ACTION EDITOR ****************** */ -static int gpf_cmp_frame(void *thunk, void *a, void *b) +static int gpf_cmp_frame(void *thunk, const void *a, const void *b) { - bGPDframe *frame_a = a; - bGPDframe *frame_b = b; + const bGPDframe *frame_a = a; + const bGPDframe *frame_b = b; if (frame_a->framenum < frame_b->framenum) return -1; if (frame_a->framenum > frame_b->framenum) return 1; @@ -3085,10 +3087,10 @@ static int gpf_cmp_frame(void *thunk, void *a, void *b) return 0; } -static int masklay_shape_cmp_frame(void *thunk, void *a, void *b) +static int masklay_shape_cmp_frame(void *thunk, const void *a, const void *b) { - MaskLayerShape *frame_a = a; - MaskLayerShape *frame_b = b; + const MaskLayerShape *frame_a = a; + const MaskLayerShape *frame_b = b; if (frame_a->frame < frame_b->frame) return -1; if (frame_a->frame > frame_b->frame) return 1; diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 2161e52d7b2..37a6d50e149 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -262,7 +262,7 @@ bool gimbal_axis(Object *ob, float gmat[3][3]) /* centroid, boundbox, of selection */ /* returns total items selected */ -int calc_manipulator_stats(const bContext *C) +static int calc_manipulator_stats(const bContext *C) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index abef2c9fc30..af563f71376 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -872,9 +872,9 @@ static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]) cross_v3_v3v3(tmp, start, end); if (dot_v3v3(tmp, axis) < 0.0f) - angle = -acos(dot_v3v3(start, end)); + angle = -acosf(dot_v3v3(start, end)); else - angle = acos(dot_v3v3(start, end)); + angle = acosf(dot_v3v3(start, end)); } else { float mtx[3][3]; @@ -884,7 +884,7 @@ static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]) mul_m3_v3(mtx, end); mul_m3_v3(mtx, start); - angle = atan2(start[1], start[0]) - atan2(end[1], end[0]); + angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]); } if (angle > (float)M_PI) { @@ -2036,10 +2036,10 @@ bool snapObjectsRayEx(Scene *scene, Base *base_act, View3D *v3d, ARegion *ar, Ob /******************** PEELING *********************************/ -static int cmpPeel(void *arg1, void *arg2) +static int cmpPeel(const void *arg1, const void *arg2) { - DepthPeel *p1 = arg1; - DepthPeel *p2 = arg2; + const DepthPeel *p1 = arg1; + const DepthPeel *p2 = arg2; int val = 0; if (p1->depth < p2->depth) { diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 36c96a8d011..83fd7e6505d 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -946,14 +946,30 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glPointSize(1.0); } + +static void draw_uv_shadows_get(SpaceImage *sima, Object *ob, Object *obedit, bool *show_shadow, bool *show_texpaint) +{ + *show_shadow = *show_texpaint = false; + + if (ED_space_image_show_render(sima) || (sima->flag & SI_NO_DRAW_TEXPAINT)) + return; + + if ((sima->mode == SI_MODE_PAINT) && obedit && obedit->type == OB_MESH) { + struct BMEditMesh *em = BKE_editmesh_from_object(obedit); + + *show_shadow = EDBM_mtexpoly_check(em); + } + + *show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT); +} + void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit, Object *obact) { ToolSettings *toolsettings = scene->toolsettings; - int show_uvedit, show_uvshadow, show_texpaint_uvshadow; + bool show_uvedit, show_uvshadow, show_texpaint_uvshadow; - show_texpaint_uvshadow = ED_space_image_show_texpaint(sima, obact); show_uvedit = ED_space_image_show_uvedit(sima, obedit); - show_uvshadow = ED_space_image_show_uvshadow(sima, obedit); + draw_uv_shadows_get(sima, obact, obedit, &show_uvshadow, &show_texpaint_uvshadow); if (show_uvedit || show_uvshadow || show_texpaint_uvshadow) { if (show_uvshadow) diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index 5f22a201600..79f53e1d971 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -372,7 +372,7 @@ static float p_vec_angle(float *v1, float *v2, float *v3) else if (dot >= 1.0f) return 0.0f; else - return (float)acos(dot); + return acosf(dot); } static float p_vec2_angle(float *v1, float *v2, float *v3) @@ -433,7 +433,7 @@ static float p_edge_length(PEdge *e) d[1] = v2->co[1] - v1->co[1]; d[2] = v2->co[2] - v1->co[2]; - return sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + return sqrtf(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); } static float p_edge_uv_length(PEdge *e) @@ -444,7 +444,7 @@ static float p_edge_uv_length(PEdge *e) d[0] = v2->uv[0] - v1->uv[0]; d[1] = v2->uv[1] - v1->uv[1]; - return sqrt(d[0] * d[0] + d[1] * d[1]); + return sqrtf(d[0] * d[0] + d[1] * d[1]); } static void p_chart_uv_bbox(PChart *chart, float minv[2], float maxv[2]) @@ -2353,8 +2353,8 @@ static void p_abf_compute_sines(PAbfSystem *sys) float *sine = sys->sine, *cosine = sys->cosine, *alpha = sys->alpha; for (i = 0; i < sys->nangles; i++, sine++, cosine++, alpha++) { - *sine = sin(*alpha); - *cosine = cos(*alpha); + *sine = sinf(*alpha); + *cosine = cosf(*alpha); } } @@ -3163,9 +3163,9 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart) SWAP(PVert *, v2, v3); } - sina1 = sin(a1); - sina2 = sin(a2); - sina3 = sin(a3); + sina1 = sinf(a1); + sina2 = sinf(a2); + sina3 = sinf(a3); sinmax = max_fff(sina1, sina2, sina3); @@ -3314,7 +3314,7 @@ static float p_face_stretch(PFace *f) a = dot_v3v3(Ps, Ps); c = dot_v3v3(Pt, Pt); - T = sqrt(0.5f * (a + c)); + T = sqrtf(0.5f * (a + c)); if (f->flag & PFACE_FILLED) T *= 0.2f; @@ -3630,8 +3630,8 @@ static float p_chart_minimum_area_angle(PChart *chart) static void p_chart_rotate_minimum_area(PChart *chart) { float angle = p_chart_minimum_area_angle(chart); - float sine = sin(angle); - float cosine = cos(angle); + float sine = sinf(angle); + float cosine = cosf(angle); PVert *v; for (v = chart->verts; v; v = v->nextlink) { @@ -4045,7 +4045,7 @@ static void p_smooth(PChart *chart) diff[0] = p[0] - oldp[0]; diff[1] = p[1] - oldp[1]; - length = sqrt(diff[0] * diff[0] + diff[1] * diff[1]); + length = len_v2(diff); d = max_ff(d, length); moved += length; } @@ -4559,7 +4559,7 @@ void param_pack(ParamHandle *handle, float margin, bool do_rotate) box->index = i; /* warning this index skips PCHART_NOPACK boxes */ if (margin > 0.0f) - area += sqrt(box->w * box->h); + area += sqrtf(box->w * box->h); } if (margin > 0.0f) { @@ -4661,7 +4661,7 @@ void param_average(ParamHandle *handle) /* Move center to 0,0 */ p_chart_uv_translate(chart, trans); - p_chart_uv_scale(chart, sqrt(fac / tot_fac)); + p_chart_uv_scale(chart, sqrtf(fac / tot_fac)); /* Move to original center */ trans[0] = -trans[0]; diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index ba4b65f4ed4..fcd5267fd44 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -1360,7 +1360,7 @@ static unsigned int uv_edge_hash(const void *key) BLI_ghashutil_uinthash(edge->uv1); } -static int uv_edge_compare(const void *a, const void *b) +static bool uv_edge_compare(const void *a, const void *b) { UvEdge *edge1 = (UvEdge *)a; UvEdge *edge2 = (UvEdge *)b; diff --git a/source/blender/freestyle/CMakeLists.txt b/source/blender/freestyle/CMakeLists.txt index c94a5ac9f92..bfd1c17df7d 100644 --- a/source/blender/freestyle/CMakeLists.txt +++ b/source/blender/freestyle/CMakeLists.txt @@ -412,6 +412,8 @@ set(SRC intern/scene_graph/OrientedLineRep.h intern/scene_graph/Rep.cpp intern/scene_graph/Rep.h + intern/scene_graph/SceneHash.cpp + intern/scene_graph/SceneHash.h intern/scene_graph/ScenePrettyPrinter.cpp intern/scene_graph/ScenePrettyPrinter.h intern/scene_graph/SceneVisitor.cpp diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h index fc9fc35e410..9766372507b 100644 --- a/source/blender/freestyle/FRS_freestyle.h +++ b/source/blender/freestyle/FRS_freestyle.h @@ -48,6 +48,7 @@ int FRS_is_freestyle_enabled(struct SceneRenderLayer *srl); void FRS_init_stroke_rendering(struct Render *re); struct Render *FRS_do_stroke_rendering(struct Render *re, struct SceneRenderLayer *srl, int render); void FRS_finish_stroke_rendering(struct Render *re); +void FRS_free_view_map_cache(void); void FRS_composite_result(struct Render *re, struct SceneRenderLayer *srl, struct Render *freestyle_render); void FRS_exit(void); diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp index 176199600ac..7ecb4164caf 100644 --- a/source/blender/freestyle/intern/application/Controller.cpp +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -118,6 +118,7 @@ Controller::Controller() _Canvas = new AppCanvas; _inter = new PythonInterpreter(); + _EnableViewMapCache = false; _EnableQI = true; _EnableFaceSmoothness = false; _ComputeRidges = true; @@ -126,6 +127,7 @@ Controller::Controller() _ComputeMaterialBoundaries = true; _sphereRadius = 1.0; _creaseAngle = 134.43; + prevSceneHash = -1.0; init_options(); } @@ -212,6 +214,19 @@ void Controller::setContext(bContext *C) py_inter->setContext(C); } +bool Controller::hitViewMapCache() +{ + if (!_EnableViewMapCache) { + return false; + } + real hashCode = sceneHashFunc.getValue(); + if (prevSceneHash == hashCode) { + return (NULL != _ViewMap); + } + prevSceneHash = hashCode; + return false; +} + int Controller::LoadMesh(Render *re, SceneRenderLayer *srl) { BlenderFileLoader loader(re, srl); @@ -242,6 +257,7 @@ int Controller::LoadMesh(Render *re, SceneRenderLayer *srl) if (G.debug & G_DEBUG_FREESTYLE) { cout << "Scene loaded" << endl; printf("Mesh cleaning : %lf\n", duration); + printf("View map cache : %s\n", _EnableViewMapCache ? "enabled" : "disabled"); } _SceneNumFaces += loader.numFacesRead(); @@ -263,6 +279,22 @@ int Controller::LoadMesh(Render *re, SceneRenderLayer *srl) if (_pRenderMonitor->testBreak()) return 0; + if (_EnableViewMapCache) { + sceneHashFunc.reset(); + blenderScene->accept(sceneHashFunc); + if (G.debug & G_DEBUG_FREESTYLE) { + printf("Scene hash : %.16e\n", sceneHashFunc.getValue()); + } + if (hitViewMapCache()) { + ClearRootNode(); + return 0; + } + else { + delete _ViewMap; + _ViewMap = NULL; + } + } + _Chrono.start(); WXEdgeBuilder wx_builder; @@ -357,7 +389,7 @@ void Controller::DeleteWingedEdge() _minEdgeSize = DBL_MAX; } -void Controller::DeleteViewMap() +void Controller::DeleteViewMap(bool freeCache) { _pView->DetachSilhouette(); if (NULL != _SilhouetteNode) { @@ -387,14 +419,20 @@ void Controller::DeleteViewMap() _pView->DetachDebug(); if (NULL != _DebugNode) { - int ref = _DebugNode->destroy(); + int ref = _DebugNode->destroy(); if (0 == ref) _DebugNode->addRef(); } if (NULL != _ViewMap) { - delete _ViewMap; - _ViewMap = NULL; + if (freeCache || !_EnableViewMapCache) { + delete _ViewMap; + _ViewMap = NULL; + prevSceneHash = -1.0; + } + else { + _ViewMap->Clean(); + } } } @@ -403,40 +441,7 @@ void Controller::ComputeViewMap() if (!_ListOfModels.size()) return; - if (NULL != _ViewMap) { - delete _ViewMap; - _ViewMap = NULL; - } - - _pView->DetachDebug(); - if (NULL != _DebugNode) { - int ref = _DebugNode->destroy(); - if (0 == ref) - _DebugNode->addRef(); - } - - _pView->DetachSilhouette(); - if (NULL != _SilhouetteNode) { - int ref = _SilhouetteNode->destroy(); - if (0 == ref) - delete _SilhouetteNode; - } - -#if 0 - if (NULL != _ProjectedSilhouette) { - int ref = _ProjectedSilhouette->destroy(); - if (0 == ref) - delete _ProjectedSilhouette; - } - - if (NULL != _VisibleProjectedSilhouette) { - int ref = _VisibleProjectedSilhouette->destroy(); - if (0 == ref) { - delete _VisibleProjectedSilhouette; - _VisibleProjectedSilhouette = NULL; - } - } -#endif + DeleteViewMap(true); // retrieve the 3D viewpoint and transformations information //---------------------------------------------------------- @@ -763,6 +768,16 @@ int Controller::getVisibilityAlgo() return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL; } +void Controller::setViewMapCache(bool iBool) +{ + _EnableViewMapCache = iBool; +} + +bool Controller::getViewMapCache() const +{ + return _EnableViewMapCache; +} + void Controller::setQuantitativeInvisibility(bool iBool) { _EnableQI = iBool; diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h index f5e50347d0f..9fe57d92cf4 100644 --- a/source/blender/freestyle/intern/application/Controller.h +++ b/source/blender/freestyle/intern/application/Controller.h @@ -32,6 +32,7 @@ //#include "ConfigIO.h" #include "../geometry/FastGrid.h" +#include "../scene_graph/SceneHash.h" #include "../system/Interpreter.h" #include "../system/ProgressBar.h" #include "../system/Precision.h" @@ -96,7 +97,7 @@ public: void Clear(); void ClearRootNode(); void DeleteWingedEdge(); - void DeleteViewMap(); + void DeleteViewMap(bool freeCache = false); void toggleLayer(unsigned index, bool iDisplay); void setModified(unsigned index, bool iMod); void resetModified(bool iMod=false); @@ -118,6 +119,8 @@ public: void setVisibilityAlgo(int algo); int getVisibilityAlgo(); + void setViewMapCache(bool iBool); + bool getViewMapCache() const; void setQuantitativeInvisibility(bool iBool); // if true, we compute quantitativeInvisibility bool getQuantitativeInvisibility() const; void setFaceSmoothness(bool iBool); @@ -144,6 +147,8 @@ public: void setModulesDir(const string& dir); string getModulesDir() const; + bool hitViewMapCache(); + void resetInterpreter(); public: @@ -231,6 +236,7 @@ private: string _help_index; string _browser_cmd; + bool _EnableViewMapCache; bool _EnableQI; bool _EnableFaceSmoothness; bool _ComputeRidges; @@ -244,6 +250,9 @@ private: FEdgeXDetector edgeDetector; + SceneHash sceneHashFunc; + real prevSceneHash; + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Controller") #endif diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 32f49d48ee7..4dd4598cc91 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -474,6 +474,9 @@ static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl) cout << " Z = " << (z ? "enabled" : "disabled") << endl; } + if (controller->hitViewMapCache()) + return; + // compute view map re->i.infostr = "Freestyle: View map creation"; re->stats_draw(re->sdh, &re->i); @@ -589,6 +592,7 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) RenderMonitor monitor(re); controller->setRenderMonitor(&monitor); + controller->setViewMapCache((srl->freestyleConfig.flags & FREESTYLE_VIEW_MAP_CACHE) ? true : false); if (G.debug & G_DEBUG_FREESTYLE) { cout << endl; @@ -647,6 +651,17 @@ void FRS_finish_stroke_rendering(Render *re) controller->Clear(); } +void FRS_free_view_map_cache(void) +{ + // free cache + controller->DeleteViewMap(true); +#if 0 + if (G.debug & G_DEBUG_FREESTYLE) { + printf("View map cache freed\n"); + } +#endif +} + //======================================================= // Freestyle Panel Configuration //======================================================= diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp index 15cc4c3a0b0..4d0d140474a 100644 --- a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp +++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp @@ -80,9 +80,9 @@ PyDoc_STRVAR(FrsMaterial_doc, " :arg emission: The emissive color.\n" " :type emission: :class:`mathutils.Vector`, list or tuple of 4 float values\n" " :arg shininess: The shininess coefficient.\n" -" :type shininess: :class:float\n" +" :type shininess: float\n" " :arg priority: The line color priority.\n" -" :type priority: :class:int"); +" :type priority: int"); static int FrsMaterial_init(BPy_FrsMaterial *self, PyObject *args, PyObject *kwds) { @@ -311,7 +311,7 @@ void FrsMaterial_mathutils_register_callback() PyDoc_STRVAR(FrsMaterial_line_doc, "RGBA components of the line color of the material.\n" "\n" -":type: mathutils.Vector"); +":type: :class:`mathutils.Vector`"); static PyObject *FrsMaterial_line_get(BPy_FrsMaterial *self, void *UNUSED(closure)) { @@ -333,7 +333,7 @@ static int FrsMaterial_line_set(BPy_FrsMaterial *self, PyObject *value, void *UN PyDoc_STRVAR(FrsMaterial_diffuse_doc, "RGBA components of the diffuse color of the material.\n" "\n" -":type: mathutils.Vector"); +":type: :class:`mathutils.Vector`"); static PyObject *FrsMaterial_diffuse_get(BPy_FrsMaterial *self, void *UNUSED(closure)) { @@ -355,7 +355,7 @@ static int FrsMaterial_diffuse_set(BPy_FrsMaterial *self, PyObject *value, void PyDoc_STRVAR(FrsMaterial_specular_doc, "RGBA components of the specular color of the material.\n" "\n" -":type: mathutils.Vector"); +":type: :class:`mathutils.Vector`"); static PyObject *FrsMaterial_specular_get(BPy_FrsMaterial *self, void *UNUSED(closure)) { @@ -377,7 +377,7 @@ static int FrsMaterial_specular_set(BPy_FrsMaterial *self, PyObject *value, void PyDoc_STRVAR(FrsMaterial_ambient_doc, "RGBA components of the ambient color of the material.\n" "\n" -":type: mathutils.Color"); +":type: :class:`mathutils.Color`"); static PyObject *FrsMaterial_ambient_get(BPy_FrsMaterial *self, void *UNUSED(closure)) { @@ -399,7 +399,7 @@ static int FrsMaterial_ambient_set(BPy_FrsMaterial *self, PyObject *value, void PyDoc_STRVAR(FrsMaterial_emission_doc, "RGBA components of the emissive color of the material.\n" "\n" -":type: mathutils.Color"); +":type: :class:`mathutils.Color`"); static PyObject *FrsMaterial_emission_get(BPy_FrsMaterial *self, void *UNUSED(closure)) { diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.cpp b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp index 9355c9cd677..8f23800fb7a 100644 --- a/source/blender/freestyle/intern/python/BPy_Interface0D.cpp +++ b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp @@ -165,7 +165,7 @@ static PyObject *Interface0D_name_get(BPy_Interface0D *self, void *UNUSED(closur PyDoc_STRVAR(Interface0D_point_3d_doc, "The 3D point of this 0D element.\n" "\n" -":type: mathutils.Vector"); +":type: :class:`mathutils.Vector`"); static PyObject *Interface0D_point_3d_get(BPy_Interface0D *self, void *UNUSED(closure)) { @@ -217,7 +217,7 @@ static PyObject *Interface0D_projected_z_get(BPy_Interface0D *self, void *UNUSED PyDoc_STRVAR(Interface0D_point_2d_doc, "The 2D point of this 0D element.\n" "\n" -":type: mathutils.Vector"); +":type: :class:`mathutils.Vector`"); static PyObject *Interface0D_point_2d_get(BPy_Interface0D *self, void *UNUSED(closure)) { diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp index 123fbab7b30..d3cb44f5903 100644 --- a/source/blender/freestyle/intern/python/BPy_Operators.cpp +++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp @@ -74,7 +74,7 @@ PyDoc_STRVAR(Operators_select_doc, " condition.\n" "\n" " :arg pred: The predicate expressing this condition.\n" -" :type pred: UnaryPredicate1D"); +" :type pred: :class:`UnaryPredicate1D`"); static PyObject *Operators_select(BPy_Operators *self, PyObject *args, PyObject *kwds) { @@ -372,7 +372,7 @@ PyDoc_STRVAR(Operators_recursive_split_doc, " condition. This predicate is evaluated for each curve before it\n" " actually gets split. If pred_1d(chain) is true, the curve won't be\n" " split anymore.\n" -" :type pred: :class:`UnaryPredicate1D`\n" +" :type pred_1d: :class:`UnaryPredicate1D`\n" " :arg sampling: The resolution used to sample the chain for the\n" " predicates evaluation. (The chain is not actually resampled, a\n" " virtual point only progresses along the curve using this\n" @@ -404,7 +404,7 @@ PyDoc_STRVAR(Operators_recursive_split_doc, " condition. This predicate is evaluated for each curve before it\n" " actually gets split. If pred_1d(chain) is true, the curve won't be\n" " split anymore.\n" -" :type pred: :class:`UnaryPredicate1D`\n" +" :type pred_1d: :class:`UnaryPredicate1D`\n" " :arg sampling: The resolution used to sample the chain for the\n" " predicates evaluation. (The chain is not actually resampled; a\n" " virtual point only progresses along the curve using this\n" @@ -484,7 +484,7 @@ PyDoc_STRVAR(Operators_sort_doc, " comparison predicate given as argument.\n" "\n" " :arg pred: The binary predicate used for the comparison.\n" -" :type pred: BinaryPredicate1D"); +" :type pred: :class:`BinaryPredicate1D`"); static PyObject *Operators_sort(BPy_Operators *self, PyObject *args, PyObject *kwds) { @@ -515,7 +515,7 @@ PyDoc_STRVAR(Operators_create_doc, " transform as a stroke.\n" " :type pred: :class:`UnaryPredicate1D`\n" " :arg shaders: The list of shaders used to shade the strokes.\n" -" :type shaders: List of StrokeShader objects"); +" :type shaders: list of :class:`StrokeShader` objects"); static PyObject *Operators_create(BPy_Operators *self, PyObject *args, PyObject *kwds) { @@ -548,6 +548,30 @@ static PyObject *Operators_create(BPy_Operators *self, PyObject *args, PyObject Py_RETURN_NONE; } +PyDoc_STRVAR(Operators_reset_doc, +".. staticmethod:: reset(delete_strokes=True)\n" +"\n" +" Resets the line stylization process to the initial state. The results of\n" +" stroke creation are accumulated if **delete_strokes** is set to False.\n" +"\n" +" :arg delete_strokes: Delete the strokes that are currently stored.\n" +" :type delete_strokes: bool\n"); + +static PyObject *Operators_reset(BPy_Operators *self, PyObject *args, PyObject *kwds) +{ + static const char *kwlist[] = {"delete_strokes", NULL}; + PyObject *obj1 = 0; + if (PyArg_ParseTupleAndKeywords(args, kwds, "|O!", (char **)kwlist, &PyBool_Type, &obj1)) { + // true is the default + Operators::reset(obj1 ? bool_from_PyBool(obj1) : true); + } + else { + PyErr_SetString(PyExc_RuntimeError, "Operators.reset() failed"); + return NULL; + } + Py_RETURN_NONE; +} + PyDoc_STRVAR(Operators_get_viewedge_from_index_doc, ".. staticmethod:: get_viewedge_from_index(i)\n" "\n" @@ -671,6 +695,7 @@ static PyMethodDef BPy_Operators_methods[] = { Operators_recursive_split_doc}, {"sort", (PyCFunction) Operators_sort, METH_VARARGS | METH_KEYWORDS | METH_STATIC, Operators_sort_doc}, {"create", (PyCFunction) Operators_create, METH_VARARGS | METH_KEYWORDS | METH_STATIC, Operators_create_doc}, + {"reset", (PyCFunction) Operators_reset, METH_VARARGS | METH_KEYWORDS | METH_STATIC, Operators_reset_doc}, {"get_viewedge_from_index", (PyCFunction) Operators_get_viewedge_from_index, METH_VARARGS | METH_KEYWORDS | METH_STATIC, Operators_get_viewedge_from_index_doc}, {"get_chain_from_index", (PyCFunction) Operators_get_chain_from_index, METH_VARARGS | METH_KEYWORDS | METH_STATIC, diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp index 22ffdedb3d9..43313ef5213 100644 --- a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp +++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp @@ -515,7 +515,7 @@ static int StrokeAttribute_alpha_set(BPy_StrokeAttribute *self, PyObject *value, PyDoc_STRVAR(StrokeAttribute_color_doc, "RGB components of the stroke color.\n" "\n" -":type: mathutils.Color"); +":type: :class:`mathutils.Color`"); static PyObject *StrokeAttribute_color_get(BPy_StrokeAttribute *self, void *UNUSED(closure)) { @@ -539,7 +539,7 @@ PyDoc_STRVAR(StrokeAttribute_thickness_doc, "The right (left) component is the thickness on the right (left) of the vertex\n" "when following the stroke.\n" "\n" -":type: mathutils.Vector"); +":type: :class:`mathutils.Vector`"); static PyObject *StrokeAttribute_thickness_get(BPy_StrokeAttribute *self, void *UNUSED(closure)) { diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp index 67cf28eb7cb..8fa87166c7d 100644 --- a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp @@ -33,16 +33,16 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char FalseBP1D___doc__[] = -"Class hierarchy: :class:`BinaryPredicate1D` > :class:`FalseBP1D`\n" +"Class hierarchy: :class:`freestyle.types.BinaryPredicate1D` > :class:`FalseBP1D`\n" "\n" ".. method:: __call__(inter1, inter2)\n" "\n" " Always returns false.\n" "\n" " :arg inter1: The first Interface1D object.\n" -" :type inter1: :class:`Interface1D`\n" +" :type inter1: :class:`freestyle.types.Interface1D`\n" " :arg inter2: The second Interface1D object.\n" -" :type inter2: :class:`Interface1D`\n" +" :type inter2: :class:`freestyle.types.Interface1D`\n" " :return: False.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp index 155cc29502b..8a0a4ded58d 100644 --- a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp @@ -33,7 +33,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char Length2DBP1D___doc__[] = -"Class hierarchy: :class:`BinaryPredicate1D` > :class:`Length2DBP1D`\n" +"Class hierarchy: :class:`freestyle.types.BinaryPredicate1D` > :class:`Length2DBP1D`\n" "\n" ".. method:: __call__(inter1, inter2)\n" "\n" @@ -41,9 +41,9 @@ static char Length2DBP1D___doc__[] = " of inter2.\n" "\n" " :arg inter1: The first Interface1D object.\n" -" :type inter1: :class:`Interface1D`\n" +" :type inter1: :class:`freestyle.types.Interface1D`\n" " :arg inter2: The second Interface1D object.\n" -" :type inter2: :class:`Interface1D`\n" +" :type inter2: :class:`freestyle.types.Interface1D`\n" " :return: True or false.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp index 77147745389..b4a256e6f66 100644 --- a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp @@ -33,16 +33,16 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char SameShapeIdBP1D___doc__[] = -"Class hierarchy: :class:`BinaryPredicate1D` > :class:`SameShapeIdBP1D`\n" +"Class hierarchy: :class:`freestyle.types.BinaryPredicate1D` > :class:`SameShapeIdBP1D`\n" "\n" ".. method:: __call__(inter1, inter2)\n" "\n" " Returns true if inter1 and inter2 belong to the same shape.\n" "\n" " :arg inter1: The first Interface1D object.\n" -" :type inter1: :class:`Interface1D`\n" +" :type inter1: :class:`freestyle.types.Interface1D`\n" " :arg inter2: The second Interface1D object.\n" -" :type inter2: :class:`Interface1D`\n" +" :type inter2: :class:`freestyle.types.Interface1D`\n" " :return: True or false.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp index f7d702da28d..6306905b4aa 100644 --- a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp @@ -33,16 +33,16 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char TrueBP1D___doc__[] = -"Class hierarchy: :class:`BinaryPredicate1D` > :class:`TrueBP1D`\n" +"Class hierarchy: :class:`freestyle.types.BinaryPredicate1D` > :class:`TrueBP1D`\n" "\n" ".. method:: __call__(inter1, inter2)\n" "\n" " Always returns true.\n" "\n" " :arg inter1: The first Interface1D object.\n" -" :type inter1: :class:`Interface1D`\n" +" :type inter1: :class:`freestyle.types.Interface1D`\n" " :arg inter2: The second Interface1D object.\n" -" :type inter2: :class:`Interface1D`\n" +" :type inter2: :class:`freestyle.types.Interface1D`\n" " :return: True.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp index f029e434988..2072faa43ef 100644 --- a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp @@ -38,7 +38,7 @@ extern "C" { //ViewMapGradientNormBP1D(int level, IntegrationType iType=MEAN, float sampling=2.0) static char ViewMapGradientNormBP1D___doc__[] = -"Class hierarchy: :class:`BinaryPredicate1D` > :class:`ViewMapGradientNormBP1D`\n" +"Class hierarchy: :class:`freestyle.types.BinaryPredicate1D` > :class:`ViewMapGradientNormBP1D`\n" "\n" ".. method:: __init__(level, integration_type=IntegrationType.MEAN, sampling=2.0)\n" "\n" @@ -49,7 +49,7 @@ static char ViewMapGradientNormBP1D___doc__[] = " :type level: int\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" " :arg sampling: The resolution used to sample the chain:\n" " GetViewMapGradientNormF0D is evaluated at each sample point and\n" " the result is obtained by combining the resulting values into a\n" @@ -62,9 +62,9 @@ static char ViewMapGradientNormBP1D___doc__[] = " higher for inter1 than for inter2.\n" "\n" " :arg inter1: The first Interface1D object.\n" -" :type inter1: :class:`Interface1D`\n" +" :type inter1: :class:`freestyle.types.Interface1D`\n" " :arg inter2: The second Interface1D object.\n" -" :type inter2: :class:`Interface1D`\n" +" :type inter2: :class:`freestyle.types.Interface1D`\n" " :return: True or false.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp index 65d80283fca..ae4fe0764b6 100644 --- a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp @@ -226,7 +226,7 @@ void StrokeVertex_mathutils_register_callback() PyDoc_STRVAR(StrokeVertex_attribute_doc, "StrokeAttribute for this StrokeVertex.\n" "\n" -":type: StrokeAttribute"); +":type: :class:`StrokeAttribute`"); static PyObject *StrokeVertex_attribute_get(BPy_StrokeVertex *self, void *UNUSED(closure)) { @@ -267,7 +267,7 @@ static int StrokeVertex_curvilinear_abscissa_set(BPy_StrokeVertex *self, PyObjec PyDoc_STRVAR(StrokeVertex_point_doc, "2D point coordinates.\n" "\n" -":type: mathutils.Vector"); +":type: :class:`mathutils.Vector`"); static PyObject *StrokeVertex_point_get(BPy_StrokeVertex *self, void *UNUSED(closure)) { diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp index 99ac72db028..6e253b7bf5d 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp @@ -38,7 +38,10 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- PyDoc_STRVAR(ChainPredicateIterator_doc, -"Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator` > :class:`ChainingIterator` > " + +"Class hierarchy: :class:`freestyle.types.Iterator` >\n" +":class:`freestyle.types.ViewEdgeIterator` >\n" +":class:`freestyle.types.ChainingIterator` >\n" ":class:`ChainPredicateIterator`\n" "\n" "A \"generic\" user-controlled ViewEdge iterator. This iterator is in\n" @@ -63,7 +66,7 @@ PyDoc_STRVAR(ChainPredicateIterator_doc, " already been chained must be ignored ot not.\n" " :type restrict_to_unvisited: bool\n" " :arg begin: The ViewEdge from where to start the iteration.\n" -" :type begin: :class:`ViewEdge` or None\n" +" :type begin: :class:`freestyle.types.ViewEdge` or None\n" " :arg orientation: If true, we'll look for the next ViewEdge among\n" " the ViewEdges that surround the ending ViewVertex of begin. If\n" " false, we'll search over the ViewEdges surrounding the ending\n" @@ -77,10 +80,10 @@ PyDoc_STRVAR(ChainPredicateIterator_doc, " predicate, a starting ViewEdge and its orientation.\n" "\n" " :arg upred: The unary predicate that the next ViewEdge must satisfy.\n" -" :type upred: :class:`UnaryPredicate1D`\n" +" :type upred: :class:`freestyle.types.UnaryPredicate1D`\n" " :arg bpred: The binary predicate that the next ViewEdge must\n" " satisfy together with the actual pointed ViewEdge.\n" -" :type bpred: :class:`BinaryPredicate1D`\n" +" :type bpred: :class:`freestyle.types.BinaryPredicate1D`\n" " :arg restrict_to_selection: Indicates whether to force the chaining\n" " to stay within the set of selected ViewEdges or not.\n" " :type restrict_to_selection: bool\n" @@ -88,7 +91,7 @@ PyDoc_STRVAR(ChainPredicateIterator_doc, " already been chained must be ignored ot not.\n" " :type restrict_to_unvisited: bool\n" " :arg begin: The ViewEdge from where to start the iteration.\n" -" :type begin: :class:`ViewEdge` or None\n" +" :type begin: :class:`freestyle.types.ViewEdge` or None\n" " :arg orientation: If true, we'll look for the next ViewEdge among\n" " the ViewEdges that surround the ending ViewVertex of begin. If\n" " false, we'll search over the ViewEdges surrounding the ending\n" diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp index 1a082ac93bb..08cfffec860 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp @@ -39,7 +39,9 @@ extern "C" { // ChainSilhouetteIterator (const ChainSilhouetteIterator &brother) PyDoc_STRVAR(ChainSilhouetteIterator_doc, -"Class hierarchy: :class:`Iterator` > :class:`ViewEdgeIterator` > :class:`ChainingIterator` > " +"Class hierarchy: :class:`freestyle.types.Iterator` >\n" +":class:`freestyle.types.ViewEdgeIterator` >\n" +":class:`freestyle.types.ChainingIterator` >\n" ":class:`ChainSilhouetteIterator`\n" "\n" "A ViewEdge Iterator used to follow ViewEdges the most naturally. For\n" @@ -58,7 +60,7 @@ PyDoc_STRVAR(ChainSilhouetteIterator_doc, " to stay within the set of selected ViewEdges or not.\n" " :type restrict_to_selection: bool\n" " :arg begin: The ViewEdge from where to start the iteration.\n" -" :type begin: :class:`ViewEdge` or None\n" +" :type begin: :class:`freestyle.types.ViewEdge` or None\n" " :arg orientation: If true, we'll look for the next ViewEdge among\n" " the ViewEdges that surround the ending ViewVertex of begin. If\n" " false, we'll search over the ViewEdges surrounding the ending\n" diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp index fca4c979bbb..c972db1e680 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp @@ -138,8 +138,8 @@ static PyObject *Interface0DIterator_iternext(BPy_Interface0DIterator *self) PyDoc_STRVAR(Interface0DIterator_object_doc, "The 0D object currently pointed to by this iterator. Note that the object\n" "may be an instance of an Interface0D subclass. For example if the iterator\n" -"has been created from :method:`Stroke.vertices_begin`, the .object property\n" -"refers to a :class:`StrokeVertex` object.\n" +"has been created from the `vertices_begin()` method of the :class:`Stroke`\n" +"class, the .object property refers to a :class:`StrokeVertex` object.\n" "\n" ":type: :class:`Interface0D` or one of its subclasses."); diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp index 045377e747e..26b83791585 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char BackboneStretcherShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`BackboneStretcherShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`BackboneStretcherShader`\n" "\n" "[Geometry shader]\n" "\n" @@ -52,7 +52,7 @@ static char BackboneStretcherShader___doc__[] = " respective directions: v(1)v(0) and v(n-1)v(n).\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int BackboneStretcherShader___init__(BPy_BackboneStretcherShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp index 002d6798df9..df076e0453a 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char BezierCurveShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`BezierCurveShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`BezierCurveShader`\n" "\n" "[Geometry shader]\n" "\n" @@ -54,7 +54,7 @@ static char BezierCurveShader___doc__[] = " Bezier Curve approximation of the original backbone geometry.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int BezierCurveShader___init__(BPy_BezierCurveShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp index 379fb7e1b12..0e603e00f97 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char BlenderTextureShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`BlenderTextureShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`BlenderTextureShader`\n" "\n" "[Texture shader]\n" "\n" @@ -47,7 +47,8 @@ static char BlenderTextureShader___doc__[] = "\n" " :arg texture: A line style texture slot or a shader node tree to define\n" " a set of textures.\n" -" :type texture: :class:`LineStyleTextureSlot` or :class:`ShaderNodeTree`\n" +" :type texture: :class:`bpy.types.LineStyleTextureSlot` or\n" +" :class:`bpy.types.ShaderNodeTree`\n" "\n" ".. method:: shade(stroke)\n" "\n" @@ -55,7 +56,7 @@ static char BlenderTextureShader___doc__[] = " simulate marks.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int BlenderTextureShader___init__(BPy_BlenderTextureShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp index 6b0c1424d61..fb85ee5a792 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp @@ -36,7 +36,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char CalligraphicShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`CalligraphicShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`CalligraphicShader`\n" "\n" "[Thickness Shader]\n" "\n" @@ -65,7 +65,7 @@ static char CalligraphicShader___doc__[] = " perpendicular to this one, and an interpolation inbetween.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int CalligraphicShader___init__(BPy_CalligraphicShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp index f3b9167de09..c4ed45ec820 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ColorNoiseShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`ColorNoiseShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`ColorNoiseShader`\n" "\n" "[Color shader]\n" "\n" @@ -53,7 +53,7 @@ static char ColorNoiseShader___doc__[] = " Shader to add noise to the stroke colors.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int ColorNoiseShader___init__(BPy_ColorNoiseShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp index 183edd1f6a0..173e00b0ed8 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp @@ -36,7 +36,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ColorVariationPatternShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`ColorVariationPatternShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`ColorVariationPatternShader`\n" "\n" "[Color shader]\n" "\n" @@ -57,7 +57,7 @@ static char ColorVariationPatternShader___doc__[] = " result of the multiplication of the pattern and the original color.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int ColorVariationPatternShader___init__(BPy_ColorVariationPatternShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp index b5607f7a7b4..6607d5798f4 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ConstantColorShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`ConstantColorShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`ConstantColorShader`\n" "\n" "[Color shader]\n" "\n" @@ -57,7 +57,7 @@ static char ConstantColorShader___doc__[] = " Assigns a constant color to every vertex of the Stroke.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int ConstantColorShader___init__(BPy_ConstantColorShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp index 6bc348dd7c5..c8cc41303d8 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ConstantThicknessShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`ConstantThicknessShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`ConstantThicknessShader`\n" "\n" "[Thickness shader]\n" "\n" @@ -51,7 +51,7 @@ static char ConstantThicknessShader___doc__[] = " Assigns an absolute constant thickness to every vertex of the Stroke.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int ConstantThicknessShader___init__(BPy_ConstantThicknessShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp index 119ba84abd3..6e1886398b6 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ConstrainedIncreasingThicknessShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`ConstrainedIncreasingThicknessShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`ConstrainedIncreasingThicknessShader`\n" "\n" "[Thickness shader]\n" "\n" @@ -57,7 +57,7 @@ static char ConstrainedIncreasingThicknessShader___doc__[] = " fat short lines.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int ConstrainedIncreasingThicknessShader___init__(BPy_ConstrainedIncreasingThicknessShader *self, PyObject *args, PyObject *kwds) diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp index e2a9a99a392..0c9b26fa434 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GuidingLinesShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`GuidingLinesShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`GuidingLinesShader`\n" "\n" "[Geometry shader]\n" "\n" @@ -59,7 +59,7 @@ static char GuidingLinesShader___doc__[] = " approximation is.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int GuidingLinesShader___init__(BPy_GuidingLinesShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp index cec0aeba58c..1ed98d62dd9 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char IncreasingColorShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`IncreasingColorShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`IncreasingColorShader`\n" "\n" "[Color shader]\n" "\n" @@ -67,7 +67,7 @@ static char IncreasingColorShader___doc__[] = " between the first and the last vertex.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int IncreasingColorShader___init__(BPy_IncreasingColorShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp index ef84b9d6fd3..c9c38a9b70a 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char IncreasingThicknessShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`IncreasingThicknessShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`IncreasingThicknessShader`\n" "\n" "[Thickness shader]\n" "\n" @@ -57,7 +57,7 @@ static char IncreasingThicknessShader___doc__[] = " linearly interpolated from A to B.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int IncreasingThicknessShader___init__(BPy_IncreasingThicknessShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp index f405162a918..f5df1ed929f 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char PolygonalizationShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`PolygonalizationShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`PolygonalizationShader`\n" "\n" "[Geometry shader]\n" "\n" @@ -58,7 +58,7 @@ static char PolygonalizationShader___doc__[] = " error is reached.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int PolygonalizationShader___init__(BPy_PolygonalizationShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp index 94e95362ce7..2fa7b00a3b7 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char SamplingShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`SamplingShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`SamplingShader`\n" "\n" "[Geometry shader]\n" "\n" @@ -51,7 +51,7 @@ static char SamplingShader___doc__[] = " Resamples the stroke.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int SamplingShader___init__(BPy_SamplingShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp index ca69561d8e0..750dc6b9eb1 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char SmoothingShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`SmoothingShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`SmoothingShader`\n" "\n" "[Geometry shader]\n" "\n" @@ -71,7 +71,7 @@ static char SmoothingShader___doc__[] = " prevent the diffusion across corners.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int SmoothingShader___init__(BPy_SmoothingShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp index ae96400de8f..b28c3bd0f96 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp @@ -36,7 +36,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char SpatialNoiseShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`SpatialNoiseShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`SpatialNoiseShader`\n" "\n" "[Geometry shader]\n" "\n" @@ -61,7 +61,7 @@ static char SpatialNoiseShader___doc__[] = " more noisy.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int SpatialNoiseShader___init__(BPy_SpatialNoiseShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp index 5522dd46f0a..db2807addc4 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char StrokeTextureShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`StrokeTextureShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`StrokeTextureShader`\n" "\n" "[Texture shader]\n" "\n" @@ -49,7 +49,7 @@ static char StrokeTextureShader___doc__[] = " :type texture_file: str\n" " :arg medium_type: The medium type and therefore, the blending mode\n" " that must be used for the rendering of this stroke.\n" -" :type medium_type: :class:`MediumType`\n" +" :type medium_type: :class:`freestyle.types.MediumType`\n" " :arg tips: Tells whether the texture includes tips or not. If it\n" " is the case, the texture image must respect the following format.\n" " :type tips: bool\n" @@ -74,7 +74,7 @@ static char StrokeTextureShader___doc__[] = " simulate its marks system.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int StrokeTextureShader___init__(BPy_StrokeTextureShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp index 5a7657f2dad..33962f8e41a 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char StrokeTextureStepShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`StrokeTextureStepShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`StrokeTextureStepShader`\n" "\n" "[Texture shader]\n" "\n" @@ -51,7 +51,7 @@ static char StrokeTextureStepShader___doc__[] = " Assigns a spacing factor to the texture coordinates of the Stroke.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int StrokeTextureStepShader___init__(BPy_StrokeTextureStepShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp index 11bac684cf0..78a07cb6c38 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char TextureAssignerShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`TextureAssignerShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`TextureAssignerShader`\n" "\n" "[Texture shader]\n" "\n" @@ -67,7 +67,7 @@ static char TextureAssignerShader___doc__[] = " * Default: `/brushes/smoothAlpha.bmp`, `Stroke.OPAQUE_MEDIUM`\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int TextureAssignerShader___init__(BPy_TextureAssignerShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp index 655a5c8fe98..acd4f4172fb 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ThicknessNoiseShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`ThicknessNoiseShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`ThicknessNoiseShader`\n" "\n" "[Thickness shader]\n" "\n" @@ -53,7 +53,7 @@ static char ThicknessNoiseShader___doc__[] = " Adds some noise to the stroke thickness.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int ThicknessNoiseShader___init__(BPy_ThicknessNoiseShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp index 1f892455b29..3196065cd34 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp @@ -36,7 +36,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ThicknessVariationPatternShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`ThicknessVariationPatternShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`ThicknessVariationPatternShader`\n" "\n" "[Thickness shader]\n" "\n" @@ -61,7 +61,7 @@ static char ThicknessVariationPatternShader___doc__[] = " original thickness.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int ThicknessVariationPatternShader___init__(BPy_ThicknessVariationPatternShader *self, PyObject *args, PyObject *kwds) diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp index 8b04ee0886f..543cd17c01e 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char TipRemoverShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`TipRemoverShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`TipRemoverShader`\n" "\n" "[Geometry shader]\n" "\n" @@ -52,7 +52,7 @@ static char TipRemoverShader___doc__[] = " Removes the stroke's extremities.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int TipRemoverShader___init__(BPy_TipRemoverShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp index 0c060ef6ed9..b838cae9817 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char fstreamShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`fstreamShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`fstreamShader`\n" "\n" "[Output shader]\n" "\n" @@ -51,7 +51,7 @@ static char fstreamShader___doc__[] = " Streams the Stroke in a file.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int fstreamShader___init__(BPy_fstreamShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp index daa10e1b38f..97a6ca0d39e 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char streamShader___doc__[] = -"Class hierarchy: :class:`StrokeShader` > :class:`streamShader`\n" +"Class hierarchy: :class:`freestyle.types.StrokeShader` > :class:`streamShader`\n" "\n" "[Output shader]\n" "\n" @@ -48,7 +48,7 @@ static char streamShader___doc__[] = " Streams the Stroke into stdout.\n" "\n" " :arg stroke: A Stroke object.\n" -" :type stroke: :class:`Stroke`\n"; +" :type stroke: :class:`freestyle.types.Stroke`\n"; static int streamShader___init__(BPy_streamShader *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp index e2e49116106..841338ef81c 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ShapeIdF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DId` > :class:`ShapeIdF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DId` > :class:`ShapeIdF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,19 +43,20 @@ static char ShapeIdF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the :class:`Id` of the Shape the :class:`Interface0D`\n" -" pointed by the Interface0DIterator belongs to. This evaluation can\n" -" be ambiguous (in the case of a :class:`TVertex` for example). This\n" +" Returns the :class:`freestyle.types.Id` of the Shape the\n" +" :class:`freestyle.types.Interface0D` pointed by the\n" +" Interface0DIterator belongs to. This evaluation can be ambiguous (in\n" +" the case of a :class:`freestyle.types.TVertex` for example). This\n" " functor tries to remove this ambiguity using the context offered by\n" -" the 1D element to which the Interface0DIterator belongs to.\n" -" However, there still can be problematic cases, and the user willing\n" -" to deal with this cases in a specific way should implement its own\n" +" the 1D element to which the Interface0DIterator belongs to. However,\n" +" there still can be problematic cases, and the user willing to deal\n" +" with this cases in a specific way should implement its own\n" " getShapeIdF0D functor.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The Id of the Shape the pointed Interface0D belongs to.\n" -" :rtype: :class:`Id`\n"; +" :rtype: :class:`freestyle.types.Id`\n"; static int ShapeIdF0D___init__(BPy_ShapeIdF0D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp index b54ed48edc3..cbb905dcf2e 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char MaterialF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DMaterial` > :class:`MaterialF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DMaterial` > :class:`MaterialF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -44,22 +44,22 @@ static char MaterialF0D___doc__[] = ".. method:: __call__(it)\n" "\n" " Returns the material of the object evaluated at the\n" -" :class:`Interface0D` pointed by the Interface0DIterator. This\n" -" evaluation can be ambiguous (in the case of a :class:`TVertex` for\n" -" example. This functor tries to remove this ambiguity using the\n" -" context offered by the 1D element to which the Interface0DIterator\n" -" belongs to and by arbitrary choosing the material of the face that\n" -" lies on its left when following the 1D element if there are two\n" -" different materials on each side of the point. However, there\n" -" still can be problematic cases, and the user willing to deal with\n" -" this cases in a specific way should implement its own getMaterial\n" -" functor.\n" +" :class:`freestyle.types.Interface0D` pointed by the\n" +" Interface0DIterator. This evaluation can be ambiguous (in the case of\n" +" a :class:`freestyle.types.TVertex` for example. This functor tries to\n" +" remove this ambiguity using the context offered by the 1D element to\n" +" which the Interface0DIterator belongs to and by arbitrary choosing the\n" +" material of the face that lies on its left when following the 1D\n" +" element if there are two different materials on each side of the\n" +" point. However, there still can be problematic cases, and the user\n" +" willing to deal with this cases in a specific way should implement its\n" +" own getMaterial functor.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The material of the object evaluated at the pointed\n" " Interface0D.\n" -" :rtype: :class:`Material`\n"; +" :rtype: :class:`freestyle.types.Material`\n"; static int MaterialF0D___init__(BPy_MaterialF0D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp index 63c32655da3..41ce2f5d197 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char CurveNatureF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DEdgeNature` > :class:`CurveNatureF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DEdgeNature` > :class:`CurveNatureF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,14 +43,14 @@ static char CurveNatureF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the :class:`Nature` of the 1D element the Interface0D pointed\n" -" by the Interface0DIterator belongs to.\n" +" Returns the :class:`freestyle.types.Nature` of the 1D element the\n" +" Interface0D pointed by the Interface0DIterator belongs to.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The nature of the 1D element to which the pointed Interface0D\n" " belongs.\n" -" :rtype: :class:`Nature`\n"; +" :rtype: :class:`freestyle.types.Nature`\n"; static int CurveNatureF0D___init__(BPy_CurveNatureF0D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp index 10152f594c9..bfe060bc046 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char Normal2DF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec2f` > :class:`Normal2DF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DVec2f` > :class:`Normal2DF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -44,12 +44,12 @@ static char Normal2DF0D___doc__[] = ".. method:: __call__(it)\n" "\n" " Returns a two-dimensional vector giving the normalized 2D normal to\n" -" the 1D element to which the :class:`Interface0D` pointed by the\n" -" Interface0DIterator belongs. The normal is evaluated at the pointed\n" -" Interface0D.\n" +" the 1D element to which the :class:`freestyle.types.Interface0D`\n" +" pointed by the Interface0DIterator belongs. The normal is evaluated\n" +" at the pointed Interface0D.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The 2D normal of the 1D element evaluated at the pointed\n" " Interface0D.\n" " :rtype: :class:`mathutils.Vector`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp index a97b53451c7..70d122bd97a 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char VertexOrientation2DF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec2f` > :class:`VertexOrientation2DF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DVec2f` > :class:`VertexOrientation2DF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,13 +43,13 @@ static char VertexOrientation2DF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns a two-dimensional vector giving the 2D oriented tangent to\n" -" the 1D element to which the :class:`Interface0D` pointed by the\n" -" Interface0DIterator belongs. The 2D oriented tangent is evaluated\n" -" at the pointed Interface0D.\n" +" Returns a two-dimensional vector giving the 2D oriented tangent to the\n" +" 1D element to which the :class:`freestyle.types.Interface0D` pointed\n" +" by the Interface0DIterator belongs. The 2D oriented tangent is\n" +" evaluated at the pointed Interface0D.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The 2D oriented tangent to the 1D element evaluated at the\n" " pointed Interface0D.\n" " :rtype: :class:`mathutils.Vector`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp index ffa8996f9b2..6b010af4228 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char VertexOrientation3DF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVec3f` > :class:`VertexOrientation3DF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DVec3f` > :class:`VertexOrientation3DF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,13 +43,13 @@ static char VertexOrientation3DF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns a three-dimensional vector giving the 3D oriented tangent\n" -" to the 1D element to which the :class:`Interface0D` pointed by the\n" -" Interface0DIterator belongs. The 3D oriented tangent is evaluated\n" -" at the pointed Interface0D.\n" +" Returns a three-dimensional vector giving the 3D oriented tangent to\n" +" the 1D element to which the :class:`freestyle.types.Interface0D`\n" +" pointed by the Interface0DIterator belongs. The 3D oriented tangent\n" +" is evaluated at the pointed Interface0D.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The 3D oriented tangent to the 1D element evaluated at the\n" " pointed Interface0D.\n" " :rtype: :class:`mathutils.Vector`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp index 3523b08982a..ba16fec1539 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetOccludeeF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DViewShape` > :class:`GetOccludeeF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DViewShape` > :class:`GetOccludeeF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,13 +43,13 @@ static char GetOccludeeF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the :class:`ViewShape` that the Interface0D pointed by the\n" -" Interface0DIterator occludes.\n" +" Returns the :class:`freestyle.types.ViewShape` that the Interface0D\n" +" pointed by the Interface0DIterator occludes.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The ViewShape occluded by the pointed Interface0D.\n" -" :rtype: :class:`ViewShape`\n"; +" :rtype: :class:`freestyle.types.ViewShape`\n"; static int GetOccludeeF0D___init__(BPy_GetOccludeeF0D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp index 234dc648ff5..5e4111de924 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp @@ -35,21 +35,21 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetShapeF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DViewShape` > :class:`GetShapeF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DViewShape` > :class:`GetShapeF0D`\n" "\n" ".. method:: __init__()\n" "\n" -" Builds a GetShapeF0D.cpp object.\n" +" Builds a GetShapeF0D object.\n" "\n" ".. method:: __call__(it)\n" "\n" -" Returns the :class:`ViewShape` containing the Interface0D pointed\n" -" by the Interface0DIterator.\n" +" Returns the :class:`freestyle.types.ViewShape` containing the\n" +" Interface0D pointed by the Interface0DIterator.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The ViewShape containing the pointed Interface0D.\n" -" :rtype: :class:`ViewShape`\n"; +" :rtype: :class:`freestyle.types.ViewShape`\n"; static int GetShapeF0D___init__(BPy_GetShapeF0D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp index 3d343762b8e..55f7bab3bb3 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char Curvature2DAngleF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`Curvature2DAngleF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DDouble` > :class:`Curvature2DAngleF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,13 +43,13 @@ static char Curvature2DAngleF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns a real value giving the 2D curvature (as an angle) of the\n" -" 1D element to which the :class:`Interface0D` pointed by the\n" -" Interface0DIterator belongs. The 2D curvature is evaluated at the\n" +" Returns a real value giving the 2D curvature (as an angle) of the 1D\n" +" element to which the :class:`freestyle.types.Interface0D` pointed by\n" +" the Interface0DIterator belongs. The 2D curvature is evaluated at the\n" " Interface0D.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The 2D curvature of the 1D element evaluated at the\n" " pointed Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp index 84a3fd79608..2aac3f4f1f0 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char DensityF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`DensityF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DDouble` > :class:`DensityF0D`\n" "\n" ".. method:: __init__(sigma=2.0)\n" "\n" @@ -49,12 +49,13 @@ static char DensityF0D___doc__[] = ".. method:: __call__(it)\n" "\n" " Returns the density of the (result) image evaluated at the\n" -" :class:`Interface0D` pointed by the Interface0DIterator. This\n" -" density is evaluated using a pixels square window around the\n" -" evaluation point and integrating these values using a gaussian.\n" +" :class:`freestyle.types.Interface0D` pointed by the\n" +" Interface0DIterator. This density is evaluated using a pixels square\n" +" window around the evaluation point and integrating these values using\n" +" a gaussian.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The density of the image evaluated at the pointed\n" " Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp index d901b245247..123772b3fc7 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetProjectedXF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetProjectedXF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DDouble` > :class:`GetProjectedXF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,11 +43,11 @@ static char GetProjectedXF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the X 3D projected coordinate of the :class:`Interface0D`\n" +" Returns the X 3D projected coordinate of the :class:`freestyle.types.Interface0D`\n" " pointed by the Interface0DIterator.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The X 3D projected coordinate of the pointed Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp index 2d82182f011..f4e3d6ba76f 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetProjectedYF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetProjectedYF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DDouble` > :class:`GetProjectedYF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,11 +43,11 @@ static char GetProjectedYF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the Y 3D projected coordinate of the :class:`Interface0D`\n" +" Returns the Y 3D projected coordinate of the :class:`freestyle.types.Interface0D`\n" " pointed by the Interface0DIterator.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The Y 3D projected coordinate of the pointed Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp index 9766985954b..116bb75fc55 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetProjectedZF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetProjectedZF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DDouble` > :class:`GetProjectedZF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,11 +43,11 @@ static char GetProjectedZF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the Z 3D projected coordinate of the :class:`Interface0D`\n" +" Returns the Z 3D projected coordinate of the :class:`freestyle.types.Interface0D`\n" " pointed by the Interface0DIterator.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The Z 3D projected coordinate of the pointed Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp index 9ee87c63bdd..614e92cf7c2 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetXF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetXF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DDouble` > :class:`GetXF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,11 +43,11 @@ static char GetXF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the X 3D coordinate of the :class:`Interface0D` pointed by\n" +" Returns the X 3D coordinate of the :class:`freestyle.types.Interface0D` pointed by\n" " the Interface0DIterator.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The X 3D coordinate of the pointed Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp index 90f8f74e989..1a953b9ebca 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetYF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetYF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DDouble` > :class:`GetYF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,11 +43,11 @@ static char GetYF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the Y 3D coordinate of the :class:`Interface0D` pointed by\n" +" Returns the Y 3D coordinate of the :class:`freestyle.types.Interface0D` pointed by\n" " the Interface0DIterator.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The Y 3D coordinate of the pointed Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp index 8876f2200c2..c985e0f5c99 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetZF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`GetZF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DDouble` > :class:`GetZF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,11 +43,11 @@ static char GetZF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the Z 3D coordinate of the :class:`Interface0D` pointed by\n" +" Returns the Z 3D coordinate of the :class:`freestyle.types.Interface0D` pointed by\n" " the Interface0DIterator.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The Z 3D coordinate of the pointed Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp index af5edb4eac7..3c7f3b412fe 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char LocalAverageDepthF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`LocalAverageDepthF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DDouble` > :class:`LocalAverageDepthF0D`\n" "\n" ".. method:: __init__(mask_size=5.0)\n" "\n" @@ -46,12 +46,13 @@ static char LocalAverageDepthF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the average depth around the :class:`Interface0D` pointed\n" -" by the Interface0DIterator. The result is obtained by querying the\n" -" depth buffer on a window around that point.\n" +" Returns the average depth around the\n" +" :class:`freestyle.types.Interface0D` pointed by the\n" +" Interface0DIterator. The result is obtained by querying the depth\n" +" buffer on a window around that point.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The average depth around the pointed Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp index b64f6c06e93..f0c58352f4a 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ZDiscontinuityF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DDouble` > :class:`ZDiscontinuityF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DDouble` > :class:`ZDiscontinuityF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -44,14 +44,14 @@ static char ZDiscontinuityF0D___doc__[] = ".. method:: __call__(it)\n" "\n" " Returns a real value giving the distance between the\n" -" :class:`Interface0D` pointed by the Interface0DIterator and the\n" -" shape that lies behind (occludee). This distance is evaluated in\n" -" the camera space and normalized between 0 and 1. Therefore, if no\n" -" object is occluded by the shape to which the Interface0D belongs to,\n" -" 1 is returned.\n" +" :class:`freestyle.types.Interface0D` pointed by the\n" +" Interface0DIterator and the shape that lies behind (occludee). This\n" +" distance is evaluated in the camera space and normalized between 0 and\n" +" 1. Therefore, if no object is occluded by the shape to which the\n" +" Interface0D belongs to, 1 is returned.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The normalized distance between the pointed Interface0D\n" " and the occludee.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp index 96db3ca7375..a2358e6ebae 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetCurvilinearAbscissaF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`GetCurvilinearAbscissaF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DFloat` > :class:`GetCurvilinearAbscissaF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,12 +43,12 @@ static char GetCurvilinearAbscissaF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the curvilinear abscissa of the :class:`Interface0D`\n" -" pointed by the Interface0DIterator in the context of its 1D\n" -" element.\n" +" Returns the curvilinear abscissa of the\n" +" :class:`freestyle.types.Interface0D` pointed by the\n" +" Interface0DIterator in the context of its 1D element.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The curvilinear abscissa of the pointed Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp index 045a5041b9c..43061747398 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetParameterF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`GetParameterF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DFloat` > :class:`GetParameterF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,11 +43,11 @@ static char GetParameterF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the parameter of the :class:`Interface0D` pointed by the\n" -" Interface0DIterator in the context of its 1D element.\n" +" Returns the parameter of the :class:`freestyle.types.Interface0D`\n" +" pointed by the Interface0DIterator in the context of its 1D element.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The parameter of an Interface0D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp index 43aebe8c4ec..cecec01dcb5 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetViewMapGradientNormF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`GetViewMapGradientNormF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DFloat` > :class:`GetViewMapGradientNormF0D`\n" "\n" ".. method:: __init__(level)\n" "\n" @@ -51,7 +51,7 @@ static char GetViewMapGradientNormF0D___doc__[] = " image.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The norm of the gradient of the global viewmap density\n" " image.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp index c1f316a45d3..313826f9307 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ReadCompleteViewMapPixelF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`ReadCompleteViewMapPixelF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DFloat` > :class:`ReadCompleteViewMapPixelF0D`\n" "\n" ".. method:: __init__(level)\n" "\n" @@ -50,7 +50,7 @@ static char ReadCompleteViewMapPixelF0D___doc__[] = " Reads a pixel in one of the level of the complete viewmap.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: A pixel in one of the level of the complete viewmap.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp index a5c8c0c3b04..8bfccf4c80a 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ReadMapPixelF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`ReadMapPixelF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DFloat` > :class:`ReadMapPixelF0D`\n" "\n" ".. method:: __init__(map_name, level)\n" "\n" @@ -52,7 +52,7 @@ static char ReadMapPixelF0D___doc__[] = " Reads a pixel in a map.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: A pixel in a map.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp index e46d9f316eb..b36ddf84e71 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ReadSteerableViewMapPixelF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DFloat` > :class:`ReadSteerableViewMapPixelF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DFloat` > :class:`ReadSteerableViewMapPixelF0D`\n" "\n" ".. method:: __init__(orientation, level)\n" "\n" @@ -53,7 +53,7 @@ static char ReadSteerableViewMapPixelF0D___doc__[] = " Reads a pixel in one of the level of one of the steerable viewmaps.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: A pixel in one of the level of one of the steerable viewmaps.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp index bcd17213c55..8ec982815c8 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char QuantitativeInvisibilityF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DUnsigned` > :class:`QuantitativeInvisibilityF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DUnsigned` > :class:`QuantitativeInvisibilityF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,17 +43,17 @@ static char QuantitativeInvisibilityF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns the quantitative invisibility of the :class:`Interface0D`\n" -" pointed by the Interface0DIterator. This evaluation can be\n" -" ambiguous (in the case of a :class:`TVertex` for example). This\n" -" functor tries to remove this ambiguity using the context offered by\n" -" the 1D element to which the Interface0D belongs to. However, there\n" -" still can be problematic cases, and the user willing to deal with\n" -" this cases in a specific way should implement its own getQIF0D\n" -" functor.\n" +" Returns the quantitative invisibility of the\n" +" :class:`freestyle.types.Interface0D` pointed by the\n" +" Interface0DIterator. This evaluation can be ambiguous (in the case of\n" +" a :class:`freestyle.types.TVertex` for example). This functor tries\n" +" to remove this ambiguity using the context offered by the 1D element\n" +" to which the Interface0D belongs to. However, there still can be\n" +" problematic cases, and the user willing to deal with this cases in a\n" +" specific way should implement its own getQIF0D functor.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: The quantitative invisibility of the pointed Interface0D.\n" " :rtype: int\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp index e6dce989822..5504bff74ae 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetOccludersF0D___doc__[] = -"Class hierarchy: :class:`UnaryFunction0D` > :class:`UnaryFunction0DVectorViewShape` > :class:`GetOccludersF0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction0D` > :class:`freestyle.types.UnaryFunction0DVectorViewShape` > :class:`GetOccludersF0D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -43,14 +43,14 @@ static char GetOccludersF0D___doc__[] = "\n" ".. method:: __call__(it)\n" "\n" -" Returns a list of :class:`ViewShape` objects occluding the\n" -" :class:`Interface0D` pointed by the Interface0DIterator.\n" +" Returns a list of :class:`freestyle.types.ViewShape` objects occluding the\n" +" :class:`freestyle.types.Interface0D` pointed by the Interface0DIterator.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: A list of ViewShape objects occluding the pointed\n" " Interface0D.\n" -" :rtype: list of :class:`ViewShape` objects\n"; +" :rtype: list of :class:`freestyle.types.ViewShape` objects\n"; static int GetOccludersF0D___init__(BPy_GetOccludersF0D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp index 70c454c2c71..55092416cc2 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char CurveNatureF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DEdgeNature` > :class:`CurveNatureF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DEdgeNature` > :class:`CurveNatureF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,21 +45,22 @@ static char CurveNatureF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" -" Returns the nature of the Interface1D (silhouette, ridge, crease,\n" -" and so on). Except if the Interface1D is a :class:`ViewEdge`, this\n" -" result might be ambiguous. Indeed, the Interface1D might result\n" -" from the gathering of several 1D elements, each one being of a\n" -" different nature. An integration method, such as the MEAN, might\n" -" give, in this case, irrelevant results.\n" +" Returns the nature of the Interface1D (silhouette, ridge, crease, and\n" +" so on). Except if the Interface1D is a\n" +" :class:`freestyle.types.ViewEdge`, this result might be ambiguous.\n" +" Indeed, the Interface1D might result from the gathering of several 1D\n" +" elements, each one being of a different nature. An integration\n" +" method, such as the MEAN, might give, in this case, irrelevant\n" +" results.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The nature of the Interface1D.\n" -" :rtype: :class:`Nature`\n"; +" :rtype: :class:`freestyle.types.Nature`\n"; static int CurveNatureF1D___init__(BPy_CurveNatureF1D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp index 6be8b81f43f..76330c77927 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char Normal2DF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec2f` > :class:`Normal2DF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DVec2f` > :class:`Normal2DF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,14 +45,14 @@ static char Normal2DF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Returns the 2D normal for the Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The 2D normal for the Interface1D.\n" " :rtype: :class:`mathutils.Vector`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp index 01a6f8bd602..07aa9071c57 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char Orientation2DF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec2f` > :class:`Orientation2DF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DVec2f` > :class:`Orientation2DF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,14 +45,14 @@ static char Orientation2DF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Returns the 2D orientation of the Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The 2D orientation of the Interface1D.\n" " :rtype: :class:`mathutils.Vector`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp index 4d76fb709d8..56dd67b1d2f 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char Orientation3DF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVec3f` > :class:`Orientation3DF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DVec3f` > :class:`Orientation3DF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,14 +45,14 @@ static char Orientation3DF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Returns the 3D orientation of the Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The 3D orientation of the Interface1D.\n" " :rtype: :class:`mathutils.Vector`\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp index 4278f088863..e5779ce36e1 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char Curvature2DAngleF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`Curvature2DAngleF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`Curvature2DAngleF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,14 +45,14 @@ static char Curvature2DAngleF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Returns the 2D curvature as an angle for an Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The 2D curvature as an angle.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp index 5beb724e9af..ffee3ec81f2 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char DensityF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`DensityF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`DensityF1D`\n" "\n" ".. method:: __init__(sigma=2.0, integration_type=IntegrationType.MEAN, sampling=2.0)\n" "\n" @@ -48,7 +48,7 @@ static char DensityF1D___doc__[] = " :type sigma: float\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" " :arg sampling: The resolution used to sample the chain: the\n" " corresponding 0D function is evaluated at each sample point and\n" " the result is obtained by combining the resulting values into a\n" @@ -59,12 +59,12 @@ static char DensityF1D___doc__[] = "\n" " Returns the density evaluated for an Interface1D. The density is\n" " evaluated for a set of points along the Interface1D (using the\n" -" :class:`DensityF0D` functor) with a user-defined sampling and then\n" -" integrated into a single value using a user-defined integration\n" -" method.\n" +" :class:`freestyle.functions.DensityF0D` functor) with a user-defined\n" +" sampling and then integrated into a single value using a user-defined\n" +" integration method.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The density evaluated for an Interface1D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp index 1a0588383fc..9164032488e 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetCompleteViewMapDensityF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetCompleteViewMapDensityF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`GetCompleteViewMapDensityF1D`\n" "\n" ".. method:: __init__(level, integration_type=IntegrationType.MEAN, sampling=2.0)\n" "\n" @@ -48,7 +48,7 @@ static char GetCompleteViewMapDensityF1D___doc__[] = " :type level: int\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" " :arg sampling: The resolution used to sample the chain: the\n" " corresponding 0D function is evaluated at each sample point and\n" " the result is obtained by combining the resulting values into a\n" @@ -58,13 +58,14 @@ static char GetCompleteViewMapDensityF1D___doc__[] = ".. method:: __call__(inter)\n" "\n" " Returns the density evaluated for an Interface1D in the complete\n" -" viewmap image. The density is evaluated for a set of points along\n" -" the Interface1D (using the :class:`ReadCompleteViewMapPixelF0D`\n" -" functor) and then integrated into a single value using a\n" -" user-defined integration method.\n" +" viewmap image. The density is evaluated for a set of points along the\n" +" Interface1D (using the\n" +" :class:`freestyle.functions.ReadCompleteViewMapPixelF0D` functor) and\n" +" then integrated into a single value using a user-defined integration\n" +" method.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The density evaluated for the Interface1D in the complete\n" " viewmap image.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp index 41841a83374..517b07f5c7f 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetDirectionalViewMapDensityF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` " +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` " "> :class:`GetDirectionalViewMapDensityF1D`\n" "\n" ".. method:: __init__(orientation, level, integration_type=IntegrationType.MEAN, sampling=2.0)\n" @@ -52,7 +52,7 @@ static char GetDirectionalViewMapDensityF1D___doc__[] = " :type level: int\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" " :arg sampling: The resolution used to sample the chain: the\n" " corresponding 0D function is evaluated at each sample point and\n" " the result is obtained by combining the resulting values into a\n" @@ -61,15 +61,16 @@ static char GetDirectionalViewMapDensityF1D___doc__[] = "\n" ".. method:: __call__(inter)\n" "\n" -" Returns the density evaluated for an Interface1D in of the\n" -" steerable viewmaps image. The direction telling which Directional\n" -" map to choose is explicitely specified by the user. The density is\n" -" evaluated for a set of points along the Interface1D (using the\n" -" :class:`ReadSteerableViewMapPixelF0D` functor) and then integrated\n" -" into a single value using a user-defined integration method.\n" +" Returns the density evaluated for an Interface1D in of the steerable\n" +" viewmaps image. The direction telling which Directional map to choose\n" +" is explicitely specified by the user. The density is evaluated for a\n" +" set of points along the Interface1D (using the\n" +" :class:`freestyle.functions.ReadSteerableViewMapPixelF0D` functor) and\n" +" then integrated into a single value using a user-defined integration\n" +" method.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: the density evaluated for an Interface1D in of the\n" " steerable viewmaps image.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp index 9baec0fe70a..290b43e5ea6 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetProjectedXF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetProjectedXF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`GetProjectedXF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,14 +45,14 @@ static char GetProjectedXF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values. \n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Returns the projected X 3D coordinate of an Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The projected X 3D coordinate of an Interface1D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp index 004f014cc0d..7d9f7461908 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetProjectedYF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetProjectedYF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`GetProjectedYF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,14 +45,14 @@ static char GetProjectedYF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values. \n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Returns the projected Y 3D coordinate of an Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The projected Y 3D coordinate of an Interface1D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp index daafe1a3b6f..b8e8cf5e57e 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetProjectedZF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetProjectedZF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`GetProjectedZF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,14 +45,14 @@ static char GetProjectedZF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values. \n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Returns the projected Z 3D coordinate of an Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The projected Z 3D coordinate of an Interface1D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp index 199e437639f..c67485e7d36 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetSteerableViewMapDensityF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetSteerableViewMapDensityF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`GetSteerableViewMapDensityF1D`\n" "\n" ".. method:: __init__(level, integration_type=IntegrationType.MEAN, sampling=2.0)\n" "\n" @@ -48,7 +48,7 @@ static char GetSteerableViewMapDensityF1D___doc__[] = " :type level: int\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" " :arg sampling: The resolution used to sample the chain: the\n" " corresponding 0D function is evaluated at each sample point and\n" " the result is obtained by combining the resulting values into a\n" @@ -58,11 +58,12 @@ static char GetSteerableViewMapDensityF1D___doc__[] = ".. method:: __call__(inter)\n" "\n" " Returns the density of the ViewMap for a given Interface1D. The\n" -" density of each :class:`FEdge` is evaluated in the proper steerable\n" -" :class:`ViewMap` depending on its orientation.\n" +" density of each :class:`freestyle.types.FEdge` is evaluated in the\n" +" proper steerable :class:`freestyle.types.ViewMap` depending on its\n" +" orientation.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The density of the ViewMap for a given Interface1D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp index 5c9bd76a4b3..ebcb273082e 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetViewMapGradientNormF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetViewMapGradientNormF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`GetViewMapGradientNormF1D`\n" "\n" ".. method:: __init__(level, integration_type=IntegrationType.MEAN, sampling=2.0)\n" "\n" @@ -48,7 +48,7 @@ static char GetViewMapGradientNormF1D___doc__[] = " :type level: int\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" " :arg sampling: The resolution used to sample the chain: the\n" " corresponding 0D function is evaluated at each sample point and\n" " the result is obtained by combining the resulting values into a\n" @@ -58,11 +58,12 @@ static char GetViewMapGradientNormF1D___doc__[] = ".. method:: __call__(inter)\n" "\n" " Returns the density of the ViewMap for a given Interface1D. The\n" -" density of each :class:`FEdge` is evaluated in the proper steerable\n" -" :class:`ViewMap` depending on its orientation.\n" +" density of each :class:`freestyle.types.FEdge` is evaluated in the\n" +" proper steerable :class:`freestyle.types.ViewMap` depending on its\n" +" orientation.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The density of the ViewMap for a given Interface1D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp index fa749a05c69..b55a4a79fe9 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetXF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetXF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`GetXF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,14 +45,14 @@ static char GetXF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Returns the X 3D coordinate of an Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The X 3D coordinate of the Interface1D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp index 96022997763..d760ef948f0 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetYF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetYF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`GetYF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,14 +45,14 @@ static char GetYF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Returns the Y 3D coordinate of an Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The Y 3D coordinate of the Interface1D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp index 46695affe49..72a8b22630d 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetZF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`GetZF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`GetZF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,14 +45,14 @@ static char GetZF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Returns the Z 3D coordinate of an Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The Z 3D coordinate of the Interface1D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp index 3638908c5bd..424f08c07c0 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char LocalAverageDepthF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`LocalAverageDepthF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`LocalAverageDepthF1D`\n" "\n" ".. method:: __init__(sigma, integration_type=IntegrationType.MEAN)\n" "\n" @@ -48,18 +48,18 @@ static char LocalAverageDepthF1D___doc__[] = " :type sigma: float\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" -" Returns the average depth evaluated for an Interface1D. The\n" -" average depth is evaluated for a set of points along the\n" -" Interface1D (using the :class:`LocalAverageDepthF0D` functor) with\n" -" a user-defined sampling and then integrated into a single value\n" -" using a user-defined integration method.\n" +" Returns the average depth evaluated for an Interface1D. The average\n" +" depth is evaluated for a set of points along the Interface1D (using\n" +" the :class:`freestyle.functions.LocalAverageDepthF0D` functor) with a\n" +" user-defined sampling and then integrated into a single value using a\n" +" user-defined integration method.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The average depth evaluated for the Interface1D.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp index 65fde596e23..488675142b6 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ZDiscontinuityF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DDouble` > :class:`ZDiscontinuityF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DDouble` > :class:`ZDiscontinuityF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,7 +45,7 @@ static char ZDiscontinuityF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" @@ -56,7 +56,7 @@ static char ZDiscontinuityF1D___doc__[] = " Interface1D belongs to, 1 is returned.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The normalized distance between the Interface1D and the occludee.\n" " :rtype: float\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp index c70493e9140..a21efd655ab 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char QuantitativeInvisibilityF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DUnsigned` > :class:`QuantitativeInvisibilityF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DUnsigned` > :class:`QuantitativeInvisibilityF1D`\n" "\n" ".. method:: __init__(integration_type=IntegrationType.MEAN)\n" "\n" @@ -45,18 +45,18 @@ static char QuantitativeInvisibilityF1D___doc__[] = "\n" " :arg integration_type: The integration method used to compute a single value\n" " from a set of values.\n" -" :type integration_type: :class:`IntegrationType`\n" +" :type integration_type: :class:`freestyle.types.IntegrationType`\n" "\n" ".. method:: __call__(inter)\n" "\n" -" Returns the Quantitative Invisibility of an Interface1D element.\n" -" If the Interface1D is a :class:`ViewEdge`, then there is no\n" -" ambiguity concerning the result. But, if the Interface1D results\n" +" Returns the Quantitative Invisibility of an Interface1D element. If\n" +" the Interface1D is a :class:`freestyle.types.ViewEdge`, then there is\n" +" no ambiguity concerning the result. But, if the Interface1D results\n" " of a chaining (chain, stroke), then it might be made of several 1D\n" " elements of different Quantitative Invisibilities.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: The Quantitative Invisibility of the Interface1D.\n" " :rtype: int\n"; diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp index d0c16f8dae2..e4e7560822d 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetOccludeeF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape` > :class:`GetOccludeeF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DVectorViewShape` > :class:`GetOccludeeF1D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -48,9 +48,9 @@ static char GetOccludeeF1D___doc__[] = " Returns a list of occluded shapes covered by this Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: A list of occluded shapes covered by the Interface1D.\n" -" :rtype: list of :class:`ViewShape` objects\n"; +" :rtype: list of :class:`freestyle.types.ViewShape` objects\n"; static int GetOccludeeF1D___init__(BPy_GetOccludeeF1D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp index 62612c7cc19..ced04a5077a 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetOccludersF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape` > :class:`GetOccludersF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DVectorViewShape` > :class:`GetOccludersF1D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -48,9 +48,9 @@ static char GetOccludersF1D___doc__[] = " Returns a list of occluding shapes that cover this Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: A list of occluding shapes that cover the Interface1D.\n" -" :rtype: list of :class:`ViewShape` objects\n"; +" :rtype: list of :class:`freestyle.types.ViewShape` objects\n"; static int GetOccludersF1D___init__(BPy_GetOccludersF1D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp index 1dab3962ec2..f26f8105a9e 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char GetShapeF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVectorViewShape` > :class:`GetShapeF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DVectorViewShape` > :class:`GetShapeF1D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -48,9 +48,9 @@ static char GetShapeF1D___doc__[] = " Returns a list of shapes covered by this Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: A list of shapes covered by the Interface1D.\n" -" :rtype: list of :class:`ViewShape` objects\n"; +" :rtype: list of :class:`freestyle.types.ViewShape` objects\n"; static int GetShapeF1D___init__(BPy_GetShapeF1D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp index e585829ff0a..128deeccd11 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ChainingTimeStampF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid` > :class:`ChainingTimeStampF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DVoid` > :class:`ChainingTimeStampF1D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -48,7 +48,7 @@ static char ChainingTimeStampF1D___doc__[] = " Sets the chaining time stamp of the Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n"; +" :type inter: :class:`freestyle.types.Interface1D`\n"; static int ChainingTimeStampF1D___init__(BPy_ChainingTimeStampF1D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp index 96d594ff56e..64a92a8e357 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char IncrementChainingTimeStampF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid` > :class:`IncrementChainingTimeStampF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DVoid` > :class:`IncrementChainingTimeStampF1D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -48,7 +48,7 @@ static char IncrementChainingTimeStampF1D___doc__[] = " Increments the chaining time stamp of the Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n"; +" :type inter: :class:`freestyle.types.Interface1D`\n"; static int IncrementChainingTimeStampF1D___init__(BPy_IncrementChainingTimeStampF1D *self, PyObject *args, PyObject *kwds) diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp index 715bbaafdba..2cd359eea61 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp @@ -37,7 +37,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char TimeStampF1D___doc__[] = -"Class hierarchy: :class:`UnaryFunction1D` > :class:`UnaryFunction1DVoid` > :class:`TimeStampF1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryFunction1D` > :class:`freestyle.types.UnaryFunction1DVoid` > :class:`TimeStampF1D`\n" "\n" ".. method:: __init__()\n" "\n" @@ -48,7 +48,7 @@ static char TimeStampF1D___doc__[] = " Returns the time stamp of the Interface1D.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n"; +" :type inter: :class:`freestyle.types.Interface1D`\n"; static int TimeStampF1D___init__(BPy_TimeStampF1D *self, PyObject *args, PyObject *kwds) { diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp index 896348d143c..36511e01358 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp @@ -33,14 +33,14 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char FalseUP0D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate0D` > :class:`FalseUP0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate0D` > :class:`FalseUP0D`\n" "\n" ".. method:: __call__(it)\n" "\n" " Always returns false.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: False.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp index c4c157dd689..f5da320a31c 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp @@ -33,14 +33,14 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char TrueUP0D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate0D` > :class:`TrueUP0D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate0D` > :class:`TrueUP0D`\n" "\n" ".. method:: __call__(it)\n" "\n" " Always returns true.\n" "\n" " :arg it: An Interface0DIterator object.\n" -" :type it: :class:`Interface0DIterator`\n" +" :type it: :class:`freestyle.types.Interface0DIterator`\n" " :return: True.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp index 8365f9b832a..d0ced2ad4c3 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp @@ -33,7 +33,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ContourUP1D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate1D` > :class:`ContourUP1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate1D` > :class:`ContourUP1D`\n" "\n" ".. method:: __call__(inter)\n" "\n" @@ -41,7 +41,7 @@ static char ContourUP1D___doc__[] = " contour if it is borded by a different shape on each of its sides.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: True if the Interface1D is a contour, false otherwise.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp index b0bd67744c5..807d76f4731 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp @@ -35,7 +35,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char DensityLowerThanUP1D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate1D` > :class:`DensityLowerThanUP1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate1D` > :class:`DensityLowerThanUP1D`\n" "\n" ".. method:: __init__(threshold, sigma=2.0)\n" "\n" @@ -45,7 +45,7 @@ static char DensityLowerThanUP1D___doc__[] = " having a density lower than this threshold will match.\n" " :type threshold: float\n" " :arg sigma: The sigma value defining the density evaluation window\n" -" size used in the :class:`DensityF0D` functor.\n" +" size used in the :class:`freestyle.functions.DensityF0D` functor.\n" " :type sigma: float\n" "\n" ".. method:: __call__(inter)\n" @@ -54,7 +54,7 @@ static char DensityLowerThanUP1D___doc__[] = " than a user-defined density value.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: True if the density is lower than a threshold.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp index 5cc5e0cf12a..f8a7ff8650c 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp @@ -33,7 +33,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char EqualToChainingTimeStampUP1D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate1D` > :class:`EqualToChainingTimeStampUP1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate1D` > :class:`freestyle.types.EqualToChainingTimeStampUP1D`\n" "\n" ".. method:: __init__(ts)\n" "\n" @@ -48,7 +48,7 @@ static char EqualToChainingTimeStampUP1D___doc__[] = " user-defined value.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: True if the time stamp is equal to a user-defined value.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp index a2cafcf5fd2..ffed4f966e6 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp @@ -33,7 +33,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char EqualToTimeStampUP1D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate1D` > :class:`EqualToTimeStampUP1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate1D` > :class:`EqualToTimeStampUP1D`\n" "\n" ".. method:: __init__(ts)\n" "\n" @@ -48,7 +48,7 @@ static char EqualToTimeStampUP1D___doc__[] = " user-defined value.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: True if the time stamp is equal to a user-defined value.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp index 486b020ef6a..140ebb86454 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp @@ -33,7 +33,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ExternalContourUP1D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate1D` > :class:`ExternalContourUP1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate1D` > :class:`ExternalContourUP1D`\n" "\n" ".. method:: __call__(inter)\n" "\n" @@ -42,7 +42,7 @@ static char ExternalContourUP1D___doc__[] = " one of its sides.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: True if the Interface1D is an external contour, false\n" " otherwise.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp index 098f449048e..2d1e99aed2b 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp @@ -33,14 +33,14 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char FalseUP1D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate1D` > :class:`FalseUP1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate1D` > :class:`FalseUP1D`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Always returns false.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: False.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp index 143aac7d4c5..806ad8168ac 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp @@ -33,7 +33,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char QuantitativeInvisibilityUP1D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate1D` > :class:`QuantitativeInvisibilityUP1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate1D` > :class:`QuantitativeInvisibilityUP1D`\n" "\n" ".. method:: __init__(qi=0)\n" "\n" @@ -46,11 +46,12 @@ static char QuantitativeInvisibilityUP1D___doc__[] = ".. method:: __call__(inter)\n" "\n" " Returns true if the Quantitative Invisibility evaluated at an\n" -" Interface1D, using the :class:`QuantitativeInvisibilityF1D`\n" -" functor, equals a certain user-defined value.\n" +" Interface1D, using the\n" +" :class:`freestyle.functions.QuantitativeInvisibilityF1D` functor,\n" +" equals a certain user-defined value.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: True if Quantitative Invisibility equals a user-defined\n" " value.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp index 998d6b1ed61..93970972aac 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp @@ -33,7 +33,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char ShapeUP1D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate1D` > :class:`ShapeUP1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate1D` > :class:`ShapeUP1D`\n" "\n" ".. method:: __init__(first, second=0)\n" "\n" @@ -46,11 +46,11 @@ static char ShapeUP1D___doc__[] = "\n" ".. method:: __call__(inter)\n" "\n" -" Returns true if the shape to which the Interface1D belongs to has\n" -" the same :class:`Id` as the one specified by the user.\n" +" Returns true if the shape to which the Interface1D belongs to has the\n" +" same :class:`freestyle.types.Id` as the one specified by the user.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: True if Interface1D belongs to the shape of the\n" " user-specified Id.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp index 8444fbfc365..d4ca82721d5 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp @@ -33,14 +33,14 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char TrueUP1D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate1D` > :class:`TrueUP1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate1D` > :class:`TrueUP1D`\n" "\n" ".. method:: __call__(inter)\n" "\n" " Always returns true.\n" "\n" " :arg inter: An Interface1D object.\n" -" :type inter: :class:`Interface1D`\n" +" :type inter: :class:`freestyle.types.Interface1D`\n" " :return: True.\n" " :rtype: bool\n"; diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp index 7e310fe593d..6f08cd1c796 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp @@ -33,7 +33,7 @@ extern "C" { //------------------------INSTANCE METHODS ---------------------------------- static char WithinImageBoundaryUP1D___doc__[] = -"Class hierarchy: :class:`UnaryPredicate1D` > :class:`WithinImageBoundaryUP1D`\n" +"Class hierarchy: :class:`freestyle.types.UnaryPredicate1D` > :class:`WithinImageBoundaryUP1D`\n" "\n" ".. method:: __init__(xmin, ymin, xmax, ymax)\n" "\n" diff --git a/source/blender/freestyle/intern/scene_graph/SceneHash.cpp b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp new file mode 100644 index 00000000000..6e8856f1b93 --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/SceneHash.cpp @@ -0,0 +1,39 @@ +/* + * ***** 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/freestyle/intern/scene_graph/SceneHash.cpp + * \ingroup freestyle + */ + +#include "SceneHash.h" + +namespace Freestyle { + +void SceneHash::visitIndexedFaceSet(IndexedFaceSet& ifs) +{ + const real *v = ifs.vertices(); + const unsigned n = ifs.vsize(); + + for (unsigned i = 0; i < n; i++) { + _hashcode += v[i]; + } +} + +} /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/scene_graph/SceneHash.h b/source/blender/freestyle/intern/scene_graph/SceneHash.h new file mode 100644 index 00000000000..8f5f847eaab --- /dev/null +++ b/source/blender/freestyle/intern/scene_graph/SceneHash.h @@ -0,0 +1,67 @@ +/* + * ***** 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 ***** + */ + +#ifndef __FREESTYLE_SCENE_HASH_H__ +#define __FREESTYLE_SCENE_HASH_H__ + +/** \file blender/freestyle/intern/scene_graph/SceneHash.h + * \ingroup freestyle + */ + +#include "IndexedFaceSet.h" +#include "SceneVisitor.h" + +#ifdef WITH_CXX_GUARDEDALLOC +#include "MEM_guardedalloc.h" +#endif + +namespace Freestyle { + +class SceneHash : public SceneVisitor +{ +public: + inline SceneHash() : SceneVisitor() + { + _hashcode = 0.0; + } + + virtual ~SceneHash() {} + + VISIT_DECL(IndexedFaceSet) + + inline real getValue() { + return _hashcode; + } + + inline void reset() { + _hashcode = 0.0; + } + +private: + real _hashcode; + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SceneHash") +#endif +}; + +} /* namespace Freestyle */ + +#endif // __FREESTYLE_SCENE_HASH_H__ diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp index b7b5eb4162b..69ca45d3ec7 100644 --- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp +++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp @@ -808,9 +808,10 @@ int BezierCurveShader::shade(Stroke& stroke) const ++it) { (it)->setAttribute(*a); - if ((index <= index1) || (index > index2)) + if ((index <= index1) || (index > index2)) { ++a; - ++index; + } + ++index; } return 0; } diff --git a/source/blender/freestyle/intern/stroke/Chain.cpp b/source/blender/freestyle/intern/stroke/Chain.cpp index 7fd756472b0..0e8c2c9ae6f 100644 --- a/source/blender/freestyle/intern/stroke/Chain.cpp +++ b/source/blender/freestyle/intern/stroke/Chain.cpp @@ -59,6 +59,7 @@ void Chain::push_viewedge_back(ViewEdge *iViewEdge, bool orientation) CurvePoint *cp = _Vertices.back(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f); SVertex *sv_first = (*vfirst); FEdge *fe = _fedgeB->duplicate(); + fe->setTemporary(true); fe->setVertexB(sv_first); fe->vertexA()->shape()->AddEdge(fe); fe->vertexA()->AddFEdge(fe); @@ -119,6 +120,7 @@ void Chain::push_viewedge_front(ViewEdge *iViewEdge, bool orientation) SVertex *sv_curr = (*v); FEdge *fe = (orientation) ? iViewEdge->fedgeA() : iViewEdge->fedgeB(); FEdge *fe2 = fe->duplicate(); + fe2->setTemporary(true); fe2->setVertexA(sv_curr); fe2->setVertexB(sv_last); sv_last->AddFEdge(fe2); diff --git a/source/blender/freestyle/intern/stroke/Chain.h b/source/blender/freestyle/intern/stroke/Chain.h index 95e825e270b..6cf3a7199bf 100644 --- a/source/blender/freestyle/intern/stroke/Chain.h +++ b/source/blender/freestyle/intern/stroke/Chain.h @@ -106,6 +106,10 @@ public: { return _splittingId; } + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Chain") +#endif }; } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/Curve.h b/source/blender/freestyle/intern/stroke/Curve.h index 6b799c921a4..726b238c74b 100644 --- a/source/blender/freestyle/intern/stroke/Curve.h +++ b/source/blender/freestyle/intern/stroke/Curve.h @@ -341,6 +341,10 @@ public: real curvatureFredo() const; Vec2d directionFredo() const; #endif + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:CurvePoint") +#endif }; @@ -586,6 +590,10 @@ public: * At each iteration a virtual temporary CurvePoint is created. */ virtual Interface0DIterator pointsEnd(float t = 0.0f); + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Curve") +#endif }; } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/Operators.cpp b/source/blender/freestyle/intern/stroke/Operators.cpp index 427994f80f1..87ba34e8f42 100644 --- a/source/blender/freestyle/intern/stroke/Operators.cpp +++ b/source/blender/freestyle/intern/stroke/Operators.cpp @@ -1242,7 +1242,7 @@ error: return -1; } -void Operators::reset() +void Operators::reset(bool removeStrokes) { ViewMap *vm = ViewMap::getInstance(); if (!vm) { @@ -1253,11 +1253,7 @@ void Operators::reset() for (I1DContainer::iterator it = _current_chains_set.begin(); it != _current_chains_set.end(); ++it) delete *it; _current_chains_set.clear(); -#if 0 - _current_view_edges_set.insert(_current_view_edges_set.begin(), - vm->ViewEdges().begin(), - vm->ViewEdges().end()); -#else + ViewMap::viewedges_container& vedges = vm->ViewEdges(); ViewMap::viewedges_container::iterator ve = vedges.begin(), veend = vedges.end(); for (; ve != veend; ++ve) { @@ -1265,9 +1261,9 @@ void Operators::reset() continue; _current_view_edges_set.push_back(*ve); } -#endif _current_set = &_current_view_edges_set; - _current_strokes_set.clear(); + if (removeStrokes) + _current_strokes_set.clear(); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/stroke/Operators.h b/source/blender/freestyle/intern/stroke/Operators.h index 59ebec57246..c7b0e3f8b81 100644 --- a/source/blender/freestyle/intern/stroke/Operators.h +++ b/source/blender/freestyle/intern/stroke/Operators.h @@ -259,7 +259,7 @@ public: return &_current_strokes_set; } - static void reset(); + static void reset(bool removeStrokes=true); private: Operators() {} diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h index 86c667a38b6..8ff801ed144 100644 --- a/source/blender/freestyle/intern/stroke/Stroke.h +++ b/source/blender/freestyle/intern/stroke/Stroke.h @@ -474,6 +474,10 @@ public: /* interface definition */ /* inherited */ + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:StrokeVertex") +#endif }; @@ -862,6 +866,10 @@ public: virtual Interface0DIterator pointsBegin(float t = 0.0f); virtual Interface0DIterator pointsEnd(float t = 0.0f); + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Stroke") +#endif }; diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp index 9c9cd88f188..a5e526fc490 100644 --- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp @@ -63,14 +63,14 @@ void FEdgeXDetector::processShapes(WingedEdge& we) WXFace *wxf = dynamic_cast<WXFace*>(*wf); wxf->Clear(); } - _computeViewIndependant = true; + _computeViewIndependent = true; } - else if (!(wxs)->getComputeViewIndependantFlag()) { + else if (!(wxs)->getComputeViewIndependentFlag()) { wxs->Reset(); - _computeViewIndependant = false; + _computeViewIndependent = false; } else { - _computeViewIndependant = true; + _computeViewIndependent = true; } preProcessShape(wxs); if (progressBarDisplay) @@ -97,8 +97,8 @@ void FEdgeXDetector::processShapes(WingedEdge& we) if (progressBarDisplay) _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); - wxs->setComputeViewIndependantFlag(false); - _computeViewIndependant = false; + wxs->setComputeViewIndependentFlag(false); + _computeViewIndependent = false; _changes = false; // reset user data @@ -187,8 +187,8 @@ void FEdgeXDetector::computeCurvatures(WXVertex *vertex) CurvatureInfo *C; float radius = _sphereRadius * _meanEdgeSize; - // view independant stuff - if (_computeViewIndependant) { + // view independent stuff + if (_computeViewIndependent) { C = new CurvatureInfo(); vertex->setCurvatures(C); OGF::NormalCycle ncycle; @@ -333,7 +333,7 @@ void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge) ///////// void FEdgeXDetector::processBorderShape(WXShape *iWShape) { - if (!_computeViewIndependant) + if (!_computeViewIndependent) return; // Make a pass on the edges to detect the BORDER vector<WEdge*>::iterator we, weend; @@ -358,7 +358,7 @@ void FEdgeXDetector::ProcessBorderEdge(WXEdge *iEdge) ///////// void FEdgeXDetector::processCreaseShape(WXShape *iWShape) { - if (!_computeViewIndependant) + if (!_computeViewIndependent) return; // Make a pass on the edges to detect the CREASE @@ -390,7 +390,7 @@ void FEdgeXDetector::processRidgesAndValleysShape(WXShape *iWShape) // Don't forget to add the built layer to the face at the end of the ProcessFace: //iFace->AddSmoothLayer(faceLayer); - if (!_computeViewIndependant) + if (!_computeViewIndependent) return; // Here the curvatures must already have been computed @@ -684,7 +684,7 @@ void FEdgeXDetector::postProcessSuggestiveContourFace(WXFace *iFace) //////////////////// void FEdgeXDetector::processMaterialBoundaryShape(WXShape *iWShape) { - if (!_computeViewIndependant) + if (!_computeViewIndependent) return; // Make a pass on the edges to detect material boundaries vector<WEdge*>::iterator we, weend; diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h index 8adf685a6eb..8170fc5baab 100644 --- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h @@ -57,7 +57,7 @@ public: { _pProgressBar = NULL; _pRenderMonitor = NULL; - _computeViewIndependant = true; + _computeViewIndependent = true; _bbox_diagonal = 1.0; _meanEdgeSize = 0; _computeRidgesAndValleys = true; @@ -213,7 +213,7 @@ protected: Vec3r _Viewpoint; real _bbox_diagonal; // diagonal of the current processed shape bbox //oldtmp values - bool _computeViewIndependant; + bool _computeViewIndependent; real _meanK1; real _meanKr; real _minK1; diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h index d838b98c1a8..94b00157ccd 100644 --- a/source/blender/freestyle/intern/view_map/Silhouette.h +++ b/source/blender/freestyle/intern/view_map/Silhouette.h @@ -378,6 +378,17 @@ public: _FEdges.push_back(iFEdge); } + /*! Remove an FEdge from the list of edges emanating from this SVertex. */ + inline void RemoveFEdge(FEdge *iFEdge) + { + for (vector<FEdge *>::iterator fe = _FEdges.begin(), fend = _FEdges.end(); fe != fend; fe++) { + if (iFEdge == (*fe)) { + _FEdges.erase(fe); + break; + } + } + } + /* replaces edge 1 by edge 2 in the list of edges */ inline void Replace(FEdge *e1, FEdge *e2) { @@ -441,6 +452,10 @@ public: /*! angle in radians */ inline real curvature2d_as_angle() const; #endif + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SVertex") +#endif }; /**********************************/ @@ -518,6 +533,8 @@ protected: bool _isInImage; + bool _isTemporary; + public: /*! A field that can be used by the user to store any data. * This field must be reseted afterwards using ResetUserData(). @@ -538,6 +555,7 @@ public: _occludeeEmpty = true; _isSmooth = false; _isInImage = true; + _isTemporary = false; } /*! Builds an FEdge going from vA to vB. */ @@ -554,6 +572,7 @@ public: _occludeeEmpty = true; _isSmooth = false; _isInImage = true; + _isTemporary = false; } /*! Copy constructor */ @@ -573,6 +592,7 @@ public: _occludeeEmpty = iBrother._occludeeEmpty; _isSmooth = iBrother._isSmooth; _isInImage = iBrother._isInImage; + _isTemporary = iBrother._isTemporary; iBrother.userdata = this; userdata = 0; } @@ -708,6 +728,11 @@ public: return _isInImage; } + inline bool isTemporary() const + { + return _isTemporary; + } + /* modifiers */ /*! Sets the first SVertex. */ inline void setVertexA(SVertex *vA) @@ -803,6 +828,11 @@ public: _isInImage = iFlag; } + inline void setTemporary(bool iFlag) + { + _isTemporary = iFlag; + } + /* checks whether two FEdge have a common vertex. * Returns a pointer on the common vertex if it exists, NULL otherwise. */ @@ -931,6 +961,10 @@ public: * The sampling with which we want to iterate over points of this FEdge. */ virtual inline Interface0DIterator pointsEnd(float t = 0.0f); + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdge") +#endif }; // @@ -1241,6 +1275,10 @@ public: { _bFaceMark = iFaceMark; } + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSharp") +#endif }; /*! Class defining a smooth edge. This kind of edge typically runs across a face of the input mesh. It can be @@ -1353,6 +1391,10 @@ public: { _FrsMaterialIndex = i; } + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSmooth") +#endif }; diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp index fd5ebb99f72..6bb0082e379 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp @@ -63,6 +63,30 @@ ViewMap::~ViewMap() _VEdges.clear(); } +void ViewMap::Clean() +{ + vector<FEdge*> tmpEdges; + + for (vector<ViewShape*>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend; vs++) { + vector<FEdge*>& edges = (*vs)->sshape()->getEdgeList(); + for (vector<FEdge*>::iterator it = edges.begin(), itend = edges.end(); it != itend; it++) { + if ((*it)->isTemporary()) { + (*it)->setTemporary(false); // avoid being counted multiple times + tmpEdges.push_back(*it); + } + } + } + + for (vector<FEdge*>::iterator it = tmpEdges.begin(), itend = tmpEdges.end(); it != itend; it++) { + for (vector<ViewShape*>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend; vs++) { + (*vs)->sshape()->RemoveEdge(*it); + } + (*it)->vertexA()->RemoveFEdge(*it); + (*it)->vertexB()->RemoveFEdge(*it); + delete (*it); + } +} + ViewShape *ViewMap::viewShape(unsigned id) { int index = _shapeIdToIndex[id]; diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h index d87341503fa..0ee1864e086 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.h +++ b/source/blender/freestyle/intern/view_map/ViewMap.h @@ -236,6 +236,9 @@ public: /* connects a FEdge to the graph trough a SVertex */ //FEdge *Connect(FEdge *ioEdge, SVertex *ioVertex); + /* Clean temporary FEdges created by chaining */ + virtual void Clean(); + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMap") #endif @@ -369,7 +372,6 @@ public: #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewVertex") #endif - }; /**********************************/ @@ -642,7 +644,6 @@ public: #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:TVertex") #endif - }; @@ -859,7 +860,6 @@ public: #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:NonTVertex") #endif - }; /**********************************/ @@ -1379,7 +1379,6 @@ public: #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewEdge") #endif - }; diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h index ce9749369fc..3c9ec7a7e3d 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdge.h +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h @@ -718,18 +718,18 @@ public: typedef WXShape type_name; protected: - bool _computeViewIndependant; // flag to indicate whether the view independant stuff must be computed or not + bool _computeViewIndependent; // flag to indicate whether the view independent stuff must be computed or not public: inline WXShape() : WShape() { - _computeViewIndependant = true; + _computeViewIndependent = true; } /*! copy constructor */ inline WXShape(WXShape& iBrother) : WShape(iBrother) { - _computeViewIndependant = iBrother._computeViewIndependant; + _computeViewIndependent = iBrother._computeViewIndependent; } virtual WShape *duplicate() @@ -740,14 +740,14 @@ public: virtual ~WXShape() {} - inline bool getComputeViewIndependantFlag() const + inline bool getComputeViewIndependentFlag() const { - return _computeViewIndependant; + return _computeViewIndependent; } - inline void setComputeViewIndependantFlag(bool iFlag) + inline void setComputeViewIndependentFlag(bool iFlag) { - _computeViewIndependant = iFlag; + _computeViewIndependent = iFlag; } /*! designed to build a specialized WFace for use in MakeFace */ diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index ca8997913bf..04f8e68431a 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -719,9 +719,12 @@ void GPU_invalid_tex_bind(int mode) void GPU_invalid_tex_free(void) { - GPU_texture_free(GG.invalid_tex_1D); - GPU_texture_free(GG.invalid_tex_2D); - GPU_texture_free(GG.invalid_tex_3D); + if (GG.invalid_tex_1D) + GPU_texture_free(GG.invalid_tex_1D); + if (GG.invalid_tex_2D) + GPU_texture_free(GG.invalid_tex_2D); + if (GG.invalid_tex_3D) + GPU_texture_free(GG.invalid_tex_3D); } diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 6578f4b9697..f91fd7a8c1e 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -737,8 +737,9 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la i = is; GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i); - GPU_link(mat, "set_value", GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &lcol); + GPU_link(mat, "set_rgb", GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &lcol); shade_light_textures(mat, lamp, &lcol); + GPU_link(mat, "shade_mul_value_v3", GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob), lcol, &lcol); #if 0 if (ma->mode & MA_TANGENT_VN) @@ -1714,9 +1715,9 @@ void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float ener lamp->energy = energy; if (lamp->mode & LA_NEG) lamp->energy= -lamp->energy; - lamp->col[0]= r* lamp->energy; - lamp->col[1]= g* lamp->energy; - lamp->col[2]= b* lamp->energy; + lamp->col[0]= r; + lamp->col[1]= g; + lamp->col[2]= b; } void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2) @@ -1748,9 +1749,9 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l lamp->energy = la->energy; if (lamp->mode & LA_NEG) lamp->energy= -lamp->energy; - lamp->col[0]= la->r*lamp->energy; - lamp->col[1]= la->g*lamp->energy; - lamp->col[2]= la->b*lamp->energy; + lamp->col[0]= la->r; + lamp->col[1]= la->g; + lamp->col[2]= la->b; GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat); @@ -2013,6 +2014,7 @@ GPUNodeLink *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **co *col = GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob); visifac = lamp_get_visibility(mat, lamp, lv, dist); + /* looks like it's not used? psy-fi */ shade_light_textures(mat, lamp, col); if (GPU_lamp_has_shadow_buffer(lamp)) { diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c index da92c52d62c..afd6af9efae 100644 --- a/source/blender/gpu/intern/gpu_select.c +++ b/source/blender/gpu/intern/gpu_select.c @@ -126,7 +126,7 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, c } else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) { glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); + glDepthMask(GL_FALSE); glDepthFunc(GL_EQUAL); } } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 3ba36c11311..23716c8105d 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1960,6 +1960,11 @@ void shade_mul_value(float fac, vec4 col, out vec4 outcol) outcol = col*fac; } +void shade_mul_value_v3(float fac, vec3 col, out vec3 outcol) +{ + outcol = col*fac; +} + void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol) { outcol = vec4(col.rgb*obcol.rgb, col.a); diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 5077ccec256..afff97a8409 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -68,7 +68,7 @@ extern "C" { #include "itasc_plugin.h" // default parameters -bItasc DefIKParam; +static bItasc DefIKParam; // in case of animation mode, feedback and timestep is fixed // #define ANIM_TIMESTEP 1.0 diff --git a/source/blender/imbuf/intern/cache.c b/source/blender/imbuf/intern/cache.c index 0c17dd21434..677c3dbe700 100644 --- a/source/blender/imbuf/intern/cache.c +++ b/source/blender/imbuf/intern/cache.c @@ -101,14 +101,14 @@ static unsigned int imb_global_tile_hash(const void *gtile_p) return ((unsigned int)(intptr_t)gtile->ibuf) * 769 + gtile->tx * 53 + gtile->ty * 97; } -static int imb_global_tile_cmp(const void *a_p, const void *b_p) +static bool imb_global_tile_cmp(const void *a_p, const void *b_p) { const ImGlobalTile *a = a_p; const ImGlobalTile *b = b_p; - if (a->ibuf == b->ibuf && a->tx == b->tx && a->ty == b->ty) return 0; - else if (a->ibuf < b->ibuf || a->tx < b->tx || a->ty < b->ty) return -1; - else return 1; + return ((a->ibuf != b->ibuf) || + (a->tx != b->tx) || + (a->ty != b->ty)); } static unsigned int imb_thread_tile_hash(const void *ttile_p) @@ -118,14 +118,14 @@ static unsigned int imb_thread_tile_hash(const void *ttile_p) return ((unsigned int)(intptr_t)ttile->ibuf) * 769 + ttile->tx * 53 + ttile->ty * 97; } -static int imb_thread_tile_cmp(const void *a_p, const void *b_p) +static bool imb_thread_tile_cmp(const void *a_p, const void *b_p) { const ImThreadTile *a = a_p; const ImThreadTile *b = b_p; - if (a->ibuf == b->ibuf && a->tx == b->tx && a->ty == b->ty) return 0; - else if (a->ibuf < b->ibuf || a->tx < b->tx || a->ty < b->ty) return -1; - else return 1; + return ((a->ibuf != b->ibuf) || + (a->tx != b->tx) || + (a->ty != b->ty)); } /******************************** Load/Unload ********************************/ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 06dd128137b..5dd6b366a93 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -252,22 +252,13 @@ static unsigned int colormanage_hashhash(const void *key_v) return rval; } -static int colormanage_hashcmp(const void *av, const void *bv) +static bool colormanage_hashcmp(const void *av, const void *bv) { const ColormanageCacheKey *a = (ColormanageCacheKey *) av; const ColormanageCacheKey *b = (ColormanageCacheKey *) bv; - if (a->view < b->view) - return -1; - else if (a->view > b->view) - return 1; - - if (a->display < b->display) - return -1; - else if (a->display > b->display) - return 1; - - return 0; + return ((a->view != b->view) || + (a->display != b->display)); } static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf) diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c index ea75673e5f0..1641bd3089b 100644 --- a/source/blender/imbuf/intern/moviecache.c +++ b/source/blender/imbuf/intern/moviecache.c @@ -104,7 +104,7 @@ static unsigned int moviecache_hashhash(const void *keyv) return key->cache_owner->hashfp(key->userkey); } -static int moviecache_hashcmp(const void *av, const void *bv) +static bool moviecache_hashcmp(const void *av, const void *bv) { const MovieCacheKey *a = (MovieCacheKey *)av; const MovieCacheKey *b = (MovieCacheKey *)bv; diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index f0bcfcea62d..bb09c57d1e5 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -58,7 +58,7 @@ static void imb_handle_alpha(ImBuf *ibuf, int flags, char colorspace[IM_MAX_SPAC int alpha_flags; if (colorspace) { - if (ibuf->rect) { + if (ibuf->rect != NULL && ibuf->rect_float == NULL) { /* byte buffer is never internally converted to some standard space, * store pointer to it's color space descriptor instead */ diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 8483e5f08f9..33d1445fb93 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -182,7 +182,7 @@ typedef struct PreviewImage { #define ID_CU MAKE_ID2('C', 'U') /* Curve */ #define ID_MB MAKE_ID2('M', 'B') /* MetaBall */ #define ID_MA MAKE_ID2('M', 'A') /* Material */ -#define ID_TE MAKE_ID2('T', 'E') /* Texture */ +#define ID_TE MAKE_ID2('T', 'E') /* Tex (Texture) */ #define ID_IM MAKE_ID2('I', 'M') /* Image */ #define ID_LT MAKE_ID2('L', 'T') /* Lattice */ #define ID_LA MAKE_ID2('L', 'A') /* Lamp */ @@ -192,25 +192,25 @@ typedef struct PreviewImage { #define ID_WO MAKE_ID2('W', 'O') /* World */ #define ID_SCR MAKE_ID2('S', 'R') /* Screen */ #define ID_SCRN MAKE_ID2('S', 'N') /* (depreciated?) */ -#define ID_VF MAKE_ID2('V', 'F') /* VectorFont */ +#define ID_VF MAKE_ID2('V', 'F') /* VFont (Vector Font) */ #define ID_TXT MAKE_ID2('T', 'X') /* Text */ #define ID_SPK MAKE_ID2('S', 'K') /* Speaker */ #define ID_SO MAKE_ID2('S', 'O') /* Sound */ #define ID_GR MAKE_ID2('G', 'R') /* Group */ #define ID_ID MAKE_ID2('I', 'D') /* (internal use only) */ -#define ID_AR MAKE_ID2('A', 'R') /* Armature */ -#define ID_AC MAKE_ID2('A', 'C') /* Action */ +#define ID_AR MAKE_ID2('A', 'R') /* bArmature */ +#define ID_AC MAKE_ID2('A', 'C') /* bAction */ #define ID_SCRIPT MAKE_ID2('P', 'Y') /* Script (depreciated) */ -#define ID_NT MAKE_ID2('N', 'T') /* NodeTree */ +#define ID_NT MAKE_ID2('N', 'T') /* bNodeTree */ #define ID_BR MAKE_ID2('B', 'R') /* Brush */ #define ID_PA MAKE_ID2('P', 'A') /* ParticleSettings */ -#define ID_GD MAKE_ID2('G', 'D') /* GreasePencil */ +#define ID_GD MAKE_ID2('G', 'D') /* bGPdata, (Grease Pencil) */ #define ID_WM MAKE_ID2('W', 'M') /* WindowManager */ #define ID_MC MAKE_ID2('M', 'C') /* MovieClip */ #define ID_MSK MAKE_ID2('M', 'S') /* Mask */ #define ID_LS MAKE_ID2('L', 'S') /* FreestyleLineStyle */ #define ID_PAL MAKE_ID2('P', 'L') /* Palette */ -#define ID_PC MAKE_ID2('P', 'C') /* Paint Curve */ +#define ID_PC MAKE_ID2('P', 'C') /* PaintCurve */ /* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */ #define ID_SEQ MAKE_ID2('S', 'Q') diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 9fbd70419f4..b14861fcf47 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -153,8 +153,8 @@ typedef struct Palette ListBase colors; ListBase deleted; - int num_of_colours; int active_color; + int pad; } Palette; typedef struct PaintCurvePoint diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h index 195c7eb4841..d099511a088 100644 --- a/source/blender/makesdna/DNA_freestyle_types.h +++ b/source/blender/makesdna/DNA_freestyle_types.h @@ -50,6 +50,7 @@ struct Text; #define FREESTYLE_FACE_SMOOTHNESS_FLAG (1 << 3) #define FREESTYLE_ADVANCED_OPTIONS_FLAG (1 << 4) #define FREESTYLE_CULLING (1 << 5) +#define FREESTYLE_VIEW_MAP_CACHE (1 << 6) /* FreestyleConfig::mode */ #define FREESTYLE_CONTROL_SCRIPT_MODE 1 diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 0b9dddd0ea5..b66772f0bb9 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -109,6 +109,7 @@ typedef struct Image { int gen_x, gen_y; char gen_type, gen_flag; short gen_depth; + float gen_color[4]; /* display aspect - for UV editing images resized for faster openGL display */ float aspx, aspy; diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index b7aae005e3b..a920182d5a3 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -131,26 +131,26 @@ typedef struct Lamp { #define LA_YF_PHOTON 5 /* mode */ -#define LA_SHAD_BUF 1 -#define LA_HALO 2 -#define LA_LAYER 4 -#define LA_QUAD 8 /* no longer used */ -#define LA_NEG 16 -#define LA_ONLYSHADOW 32 -#define LA_SPHERE 64 -#define LA_SQUARE 128 -#define LA_TEXTURE 256 -#define LA_OSATEX 512 -/* #define LA_DEEP_SHADOW 1024 */ /* not used anywhere */ -#define LA_NO_DIFF 2048 -#define LA_NO_SPEC 4096 -#define LA_SHAD_RAY 8192 +#define LA_SHAD_BUF (1 << 0) +#define LA_HALO (1 << 1) +#define LA_LAYER (1 << 2) +#define LA_QUAD (1 << 3) /* no longer used */ +#define LA_NEG (1 << 4) +#define LA_ONLYSHADOW (1 << 5) +#define LA_SPHERE (1 << 6) +#define LA_SQUARE (1 << 7) +#define LA_TEXTURE (1 << 8) +#define LA_OSATEX (1 << 9) +/* #define LA_DEEP_SHADOW (1 << 10) */ /* not used anywhere */ +#define LA_NO_DIFF (1 << 11) +#define LA_NO_SPEC (1 << 12) +#define LA_SHAD_RAY (1 << 13) /* yafray: lamp shadowbuffer flag, softlight */ /* Since it is used with LOCAL lamp, can't use LA_SHAD */ -/* #define LA_YF_SOFT 16384 */ /* no longer used */ -#define LA_LAYER_SHADOW 32768 -#define LA_SHAD_TEX (1<<16) -#define LA_SHOW_CONE (1<<17) +/* #define LA_YF_SOFT (1 << 14) */ /* no longer used */ +#define LA_LAYER_SHADOW (1 << 15) +#define LA_SHAD_TEX (1 << 16) +#define LA_SHOW_CONE (1 << 17) /* layer_shadow */ #define LA_LAYER_SHADOW_BOTH 0 diff --git a/source/blender/makesdna/DNA_linestyle_types.h b/source/blender/makesdna/DNA_linestyle_types.h index bac03b4efd7..262bcb5981a 100644 --- a/source/blender/makesdna/DNA_linestyle_types.h +++ b/source/blender/makesdna/DNA_linestyle_types.h @@ -387,6 +387,7 @@ typedef struct LineStyleThicknessModifier_Calligraphy { #define LS_NO_SORTING (1 << 11) #define LS_REVERSE_ORDER (1 << 12) /* for sorting */ #define LS_TEXTURE (1 << 13) +#define LS_CHAIN_COUNT (1 << 14) /* FreestyleLineStyle::chaining */ #define LS_CHAINING_PLAIN 1 @@ -406,6 +407,8 @@ typedef struct LineStyleThicknessModifier_Calligraphy { /* FreestyleLineStyle::sort_key */ #define LS_SORT_KEY_DISTANCE_FROM_CAMERA 1 #define LS_SORT_KEY_2D_LENGTH 2 +#define LS_SORT_KEY_PROJECTED_X 3 +#define LS_SORT_KEY_PROJECTED_Y 4 /* FreestyleLineStyle::integration_type */ #define LS_INTEGRATION_MEAN 1 @@ -428,13 +431,14 @@ typedef struct FreestyleLineStyle { float split_length; float min_angle, max_angle; /* in radians, for splitting */ float min_length, max_length; + unsigned int chain_count; unsigned short split_dash1, split_gap1; unsigned short split_dash2, split_gap2; unsigned short split_dash3, split_gap3; int sort_key, integration_type; float texstep; short texact, pr_texture; - short use_nodes, pad; + short use_nodes, pad[3]; unsigned short dash1, gap1, dash2, gap2, dash3, gap3; int panel; /* for UI */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index c8b8e4d52a4..f8f962107f6 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -242,6 +242,7 @@ typedef enum ScenePassType { SCE_PASS_SUBSURFACE_DIRECT = (1 << 28), SCE_PASS_SUBSURFACE_INDIRECT = (1 << 29), SCE_PASS_SUBSURFACE_COLOR = (1 << 30), + SCE_PASS_DEBUG = (1 << 31), /* This is a virtual pass. */ } ScenePassType; /* note, srl->passflag is treestore element 'nr' in outliner, short still... */ @@ -835,7 +836,7 @@ typedef struct Paint { typedef struct ImagePaintSettings { Paint paint; - short flag, pad; + short flag, missing_data; /* for projection painting only */ short seam_bleed, normal_angle; @@ -1733,6 +1734,11 @@ typedef enum ImagePaintMode { #define IMAGEPAINT_PROJECT_LAYER_STENCIL 256 #define IMAGEPAINT_PROJECT_LAYER_STENCIL_INV 512 +#define IMAGEPAINT_MISSING_UVS (1 << 0) +#define IMAGEPAINT_MISSING_MATERIAL (1 << 1) +#define IMAGEPAINT_MISSING_TEX (1 << 2) +#define IMAGEPAINT_MISSING_STENCIL (1 << 3) + /* toolsettings->uvcalc_flag */ #define UVCALC_FILLHOLES 1 #define UVCALC_NO_ASPECT_CORRECT 2 /* would call this UVCALC_ASPECT_CORRECT, except it should be default with old file */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 6f57f549efb..a267217abf6 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -57,7 +57,6 @@ struct Scopes; struct Histogram; struct SpaceIpo; struct BlendHandle; -struct RenderInfo; struct bNodeTree; struct uiBlock; struct FileList; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index ed59014cf75..382fd8c1dbd 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -534,13 +534,13 @@ typedef struct UserDef { float fcu_inactive_alpha; /* opacity of inactive F-Curves in F-Curve Editor */ float pixelsize; /* private, set by GHOST, to multiply DPI with */ + int virtual_pixel; /* virtual pixelsize mode */ short pie_interaction_type; /* if keeping a pie menu spawn button pressed after this time, it turns into * a drag/release pie menu */ short pie_initial_timeout; /* direction in the pie menu will always be calculated from the initial position * within this time limit */ int pie_animation_timeout; - int pad2; short pie_menu_radius; /* pie menu radius */ short pie_menu_threshold; /* pie menu distance from center before a direction is set */ @@ -854,6 +854,11 @@ typedef enum eImageDrawMethod { IMAGE_DRAW_METHOD_DRAWPIXELS = 3, } eImageDrawMethod; +typedef enum eUserpref_VirtualPixel { + VIRTUAL_PIXEL_NATIVE = 0, + VIRTUAL_PIXEL_DOUBLE = 1, +} eUserpref_VirtualPixel; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 98c12e9cc11..3efba488299 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -41,7 +41,6 @@ struct Base; struct BoundBox; struct MovieClip; struct MovieClipUser; -struct RenderInfo; struct RenderEngine; struct bGPdata; struct SmoothView3DStore; @@ -102,7 +101,6 @@ typedef struct RegionView3D { struct BoundBox *clipbb; struct RegionView3D *localvd; /* allocated backup of its self while in localview */ - struct RenderInfo *ri; struct RenderEngine *render_engine; struct ViewDepths *depths; void *gpuoffscreen; diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index d0af2a522a7..4e7a564e9d4 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -118,6 +118,9 @@ if env['WITH_BF_OCEANSIM']: if env['WITH_BF_CYCLES']: defs.append('WITH_CYCLES') + if env['WITH_BF_CYCLES_DEBUG']: + defs.append('WITH_CYCLES_DEBUG') + if env['WITH_BF_SDL']: defs.append('WITH_SDL') @@ -127,6 +130,10 @@ if env['WITH_BF_OPENAL']: if env['WITH_BF_JACK']: defs.append('WITH_JACK') +if env['WITH_BF_FREESTYLE']: + defs.append('WITH_FREESTYLE') + incs += ' ../freestyle' + if env['OURPLATFORM'] == 'linux': cflags='-pthread' diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index e6bd9fb79b4..9a53ebcec03 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -155,6 +155,9 @@ set(INC_SYS if(WITH_CYCLES) add_definitions(-DWITH_CYCLES) + if(WITH_CYCLES_DEBUG) + add_definitions(-DWITH_CYCLES_DEBUG) + endif() endif() if(WITH_PYTHON) @@ -265,6 +268,9 @@ if(WITH_BULLET) endif() if(WITH_FREESTYLE) + list(APPEND INC + ../../freestyle + ) add_definitions(-DWITH_FREESTYLE) endif() diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index 4e643fb302f..d1eab5ca9db 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -142,9 +142,12 @@ if env['WITH_BF_COLLADA']: if env['WITH_BF_CYCLES']: defs.append('WITH_CYCLES') + if env['WITH_BF_CYCLES_DEBUG']: + defs.append('WITH_CYCLES_DEBUG') if env['WITH_BF_FREESTYLE']: defs.append('WITH_FREESTYLE') + incs += ' ../../freestyle' if env['OURPLATFORM'] == 'linux': cflags='-pthread' diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 83fe56102ac..51d81295f8c 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -60,11 +60,14 @@ EnumPropertyItem id_type_items[] = { {ID_LI, "LIBRARY", ICON_LIBRARY_DATA_DIRECT, "Library", ""}, {ID_LS, "LINESTYLE", ICON_LINE_DATA, "Line Style", ""}, {ID_LT, "LATTICE", ICON_LATTICE_DATA, "Lattice", ""}, + {ID_MSK, "MASK", ICON_MOD_MASK, "Mask", ""}, {ID_MA, "MATERIAL", ICON_MATERIAL_DATA, "Material", ""}, {ID_MB, "META", ICON_META_DATA, "MetaBall", ""}, {ID_ME, "MESH", ICON_MESH_DATA, "Mesh", ""}, {ID_NT, "NODETREE", ICON_NODETREE, "NodeTree", ""}, {ID_OB, "OBJECT", ICON_OBJECT_DATA, "Object", ""}, + {ID_PC, "PAINTCURVE", ICON_CURVE_BEZCURVE, "Paint Curve", ""}, + {ID_PAL, "PALETTE", ICON_COLOR, "Palette", ""}, {ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""}, {ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""}, {ID_SCR, "SCREEN", ICON_SPLITSCREEN, "Screen", ""}, diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 1ff99271146..bbc2e0572fa 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -264,7 +264,7 @@ static int rna_BrushCapabilities_has_spacing_get(PointerRNA *ptr) return (!(br->flag & BRUSH_ANCHORED)); } -static int rna_SculptToolCapabilities_has_strength_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_strength_pressure_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return !ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK); @@ -689,7 +689,7 @@ static void rna_def_sculpt_capabilities(BlenderRNA *brna) SCULPT_TOOL_CAPABILITY(has_secondary_color, "Has Secondary Color"); SCULPT_TOOL_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke"); SCULPT_TOOL_CAPABILITY(has_space_attenuation, "Has Space Attenuation"); - SCULPT_TOOL_CAPABILITY(has_strength, "Has Strength"); + SCULPT_TOOL_CAPABILITY(has_strength_pressure, "Has Strength Pressure"); SCULPT_TOOL_CAPABILITY(has_gravity, "Has Gravity"); #undef SCULPT_CAPABILITY diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 0b129bab524..90c9cd108cd 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -589,6 +589,13 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "generated_color", PROP_FLOAT, PROP_COLOR); + RNA_def_property_float_sdna(prop, NULL, "gen_color"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Color", "Fill color for the generated image"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + /* realtime properties */ prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 1fb46c009a0..d9a59c4dc55 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -115,7 +115,7 @@ static void rna_Image_save(Image *image, bContext *C, ReportList *reports) if (ibuf) { char filename[FILE_MAX]; BLI_strncpy(filename, image->name, sizeof(filename)); - BLI_path_abs(filename, G.main->name); + BLI_path_abs(filename, ID_BLEND_PATH(G.main, &image->id)); if (image->packedfile) { if (writePackedFile(reports, image->name, image->packedfile, 0) != RET_OK) { diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c index 96b81f12620..2259db1de66 100644 --- a/source/blender/makesrna/intern/rna_linestyle.c +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -1322,6 +1322,8 @@ static void rna_def_linestyle(BlenderRNA *brna) static EnumPropertyItem sort_key_items[] = { {LS_SORT_KEY_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", 0, "Distance from Camera", "Sort by distance from camera (closer lines lie on top of further lines)"}, {LS_SORT_KEY_2D_LENGTH, "2D_LENGTH", 0, "2D Length", "Sort by curvilinear 2D length (longer lines lie on top of shorter lines)"}, + {LS_SORT_KEY_PROJECTED_X, "PROJECTED_X", 0, "Projected X", "Sort by the projected X value in the image coordinate system"}, + {LS_SORT_KEY_PROJECTED_Y, "PROJECTED_Y", 0, "Projected Y", "Sort by the projected Y value in the image coordinate system"}, {0, NULL, 0, NULL, NULL} }; static EnumPropertyItem sort_order_items[] = { @@ -1488,6 +1490,16 @@ static void rna_def_linestyle(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Max 2D Length", "Maximum curvilinear 2D length for the selection of chains"); RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + prop = RNA_def_property(srna, "use_chain_count", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_CHAIN_COUNT); + RNA_def_property_ui_text(prop, "Use Chain Count", "Enable the selection of first N chains"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "chain_count", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "chain_count"); + RNA_def_property_ui_text(prop, "Chain Count", "Chain count for the selection of first N chains"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + prop = RNA_def_property(srna, "use_split_pattern", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_SPLIT_PATTERN); RNA_def_property_ui_text(prop, "Use Split Pattern", "Enable chain splitting by dashed line patterns"); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 1ef39ec4a77..2e4f24fc0ce 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -204,7 +204,9 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain, Scene *s for (sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_IMAGE) { SpaceImage *sima = (SpaceImage *)sl; - ED_space_image_set(sima, scene, scene->obedit, image); + + if (!sima->pin) + ED_space_image_set(sima, scene, scene->obedit, image); } } } diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 699bfaa0f93..690468a5278 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2624,7 +2624,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "dupfacesca"); RNA_def_property_range(prop, 0.001f, 10000.0f); RNA_def_property_ui_text(prop, "Dupli Faces Scale", "Scale the DupliFace objects"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); prop = RNA_def_property(srna, "dupli_group", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "dup_group"); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 284377d34f9..0ee654d4ecc 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -71,6 +71,9 @@ EnumPropertyItem render_pass_type_items[] = { {SCE_PASS_SUBSURFACE_DIRECT, "SUBSURFACE_DIRECT", 0, "Subsurface Direct", ""}, {SCE_PASS_SUBSURFACE_INDIRECT, "SUBSURFACE_INDIRECT", 0, "Subsurface Indirect", ""}, {SCE_PASS_SUBSURFACE_COLOR, "SUBSURFACE_COLOR", 0, "Subsurface Color", ""}, +#ifdef WITH_CYCLES_DEBUG + {SCE_PASS_DEBUG, "DEBUG", 0, "Pass used for render engine debugging", ""}, +#endif {0, NULL, 0, NULL, NULL} }; @@ -584,6 +587,10 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_PREVIEW); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + prop = RNA_def_property(srna, "bl_use_texture_preview", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_TEXTURE_PREVIEW); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + prop = RNA_def_property(srna, "bl_use_postprocess", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "type->flag", RE_USE_POSTPROCESS); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); @@ -683,6 +690,11 @@ static void rna_def_render_pass(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static EnumPropertyItem render_pass_debug_type_items[] = { + {RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS, "BVH_TRAVERSAL_STEPS", 0, "BVH Traversal Steps", ""}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "RenderPass", NULL); RNA_def_struct_ui_text(srna, "Render Pass", ""); @@ -712,6 +724,11 @@ static void rna_def_render_pass(BlenderRNA *brna) RNA_def_property_dynamic_array_funcs(prop, "rna_RenderPass_rect_get_length"); RNA_def_property_float_funcs(prop, "rna_RenderPass_rect_get", "rna_RenderPass_rect_set", NULL); + prop = RNA_def_property(srna, "debug_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "debug_type"); + RNA_def_property_enum_items(prop, render_pass_debug_type_items); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_define_verify_sdna(1); } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 682a7f4ee31..70ce87ab68b 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -370,6 +370,10 @@ EnumPropertyItem bake_save_mode_items[] = { #include "RE_engine.h" +#ifdef WITH_FREESTYLE +#include "FRS_freestyle.h" +#endif + static void rna_SpaceImageEditor_uv_sculpt_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr)) { ED_space_image_uv_sculpt_update(bmain->wm.first, scene->toolsettings); @@ -1179,6 +1183,13 @@ static void rna_Scene_freestyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene) DAG_id_tag_update(&scene->id, 0); } +static void rna_Scene_use_view_map_cache_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) +{ +#ifdef WITH_FREESTYLE + FRS_free_view_map_cache(); +#endif +} + static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value) { Scene *scene = (Scene *)ptr->id.data; @@ -3109,6 +3120,11 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) "Enable advanced edge detection options (sphere radius and Kr derivative epsilon)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_freestyle_update"); + prop = RNA_def_property(srna, "use_view_map_cache", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_VIEW_MAP_CACHE); + RNA_def_property_ui_text(prop, "View Map Cache", "Keep the computed view map and avoid re-calculating it if mesh geometry is unchanged"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_use_view_map_cache_update"); + prop = RNA_def_property(srna, "sphere_radius", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sphere_radius"); RNA_def_property_range(prop, 0.0, 1000.0); @@ -4547,7 +4563,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "alphamode"); RNA_def_property_enum_items(prop, alpha_mode_items); RNA_def_property_ui_text(prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "octree_resolution", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "ocres"); @@ -4609,45 +4625,45 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_shadows", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_SHADOW); RNA_def_property_ui_text(prop, "Shadows", "Calculate shadows while rendering"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "use_envmaps", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_ENVMAP); RNA_def_property_ui_text(prop, "Environment Maps", "Calculate environment maps while rendering"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "use_sss", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_SSS); RNA_def_property_ui_text(prop, "Subsurface Scattering", "Calculate sub-surface scattering in materials rendering"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "use_raytrace", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_RAYTRACE); RNA_def_property_ui_text(prop, "Raytracing", "Pre-calculate the raytrace accelerator and render raytracing effects"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "use_textures", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "scemode", R_NO_TEX); RNA_def_property_ui_text(prop, "Textures", "Use textures to affect material properties"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "use_edge_enhance", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_EDGE); RNA_def_property_ui_text(prop, "Edge", "Create a toon outline around the edges of geometry"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "edge_threshold", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "edgeint"); RNA_def_property_range(prop, 0, 255); RNA_def_property_ui_text(prop, "Edge Threshold", "Threshold for drawing outlines on geometry edges"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "edge_color", PROP_FLOAT, PROP_COLOR); RNA_def_property_float_sdna(prop, NULL, "edgeR"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Edge Color", "Edge color"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", R_EDGE_FRS); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index d48d8589f96..09e42e48e93 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -308,12 +308,22 @@ static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), Scene *scene, PointerR BKE_texpaint_slots_refresh_object(scene, ob); /* we assume that changing the current mode will invalidate the uv layers so we need to refresh display */ - GPU_drawobject_free(ob->derivedFinal); - WM_main_add_notifier(NC_GEOM | ND_DATA, &ob->id); + GPU_drawobject_free(ob->derivedFinal); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); +} + +static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) +{ + Object *ob = OBACT; + GPU_drawobject_free(ob->derivedFinal); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); + WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); } static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr)) { + Object *ob = OBACT; bScreen *sc; Image *ima = scene->toolsettings->imapaint.canvas; @@ -324,14 +334,23 @@ static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UN for (sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_IMAGE) { SpaceImage *sima = (SpaceImage *)sl; - ED_space_image_set(sima, scene, scene->obedit, ima); + + if (!sima->pin) + ED_space_image_set(sima, scene, scene->obedit, ima); } } } } - + + GPU_drawobject_free(ob->derivedFinal); + BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); } + +static int rna_ImaPaint_detect_data(ImagePaintSettings *imapaint) +{ + return imapaint->missing_data == 0; +} #else static void rna_def_palettecolor(BlenderRNA *brna) @@ -612,6 +631,7 @@ static void rna_def_image_paint(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; static EnumPropertyItem paint_type_items[] = { {IMAGEPAINT_MODE_MATERIAL, "MATERIAL", 0, @@ -625,6 +645,13 @@ static void rna_def_image_paint(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ImagePaintSettings"); RNA_def_struct_path_func(srna, "rna_ImagePaintSettings_path"); RNA_def_struct_ui_text(srna, "Image Paint", "Properties of image and texture painting mode"); + + /* functions */ + func = RNA_def_function(srna, "detect_data", "rna_ImaPaint_detect_data"); + RNA_def_function_ui_description(func, "Check if required texpaint data exist"); + + /* return type */ + RNA_def_function_return(func, RNA_def_boolean(func, "ok", 1, "", "")); /* booleans */ prop = RNA_def_property(srna, "use_occlude", PROP_BOOLEAN, PROP_NONE); @@ -656,7 +683,7 @@ static void rna_def_image_paint(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "stencil"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Stencil Image", "Image used as stencil"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_viewport_update"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update"); prop = RNA_def_property(srna, "canvas", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -698,7 +725,32 @@ static void rna_def_image_paint(BlenderRNA *brna) prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, paint_type_items); RNA_def_property_ui_text(prop, "Mode", "Mode of operation for projection painting"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update"); + + /* Missing data */ + prop = RNA_def_property(srna, "missing_uvs", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_UVS); + RNA_def_property_ui_text(prop, "Missing UVs", + "A UV layer is missing on the mesh"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "missing_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_MATERIAL); + RNA_def_property_ui_text(prop, "Missing Materials", + "The mesh is missing materials"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "missing_stencil", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_STENCIL); + RNA_def_property_ui_text(prop, "Missing Stencil", + "Image Painting does not have a stencil"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "missing_texture", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "missing_data", IMAGEPAINT_MISSING_TEX); + RNA_def_property_ui_text(prop, "Missing Texture", + "Image Painting does not have a texture to paint on"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); } static void rna_def_particle_edit(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 887670eb5ff..55262a98b2e 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -311,7 +311,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "resolution_max", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "maxres"); - RNA_def_property_range(prop, 24, 512); + RNA_def_property_range(prop, 6, 512); RNA_def_property_ui_range(prop, 24, 512, 2, -1); RNA_def_property_ui_text(prop, "Max Res", "Maximal resolution used in the fluid domain"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index aa378955fb0..7fdc9ba1e79 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -120,6 +120,16 @@ static void rna_userdef_dpi_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ } +static void rna_userdef_virtual_pixel_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) +{ + /* font's are stored at each DPI level, without this we can easy load 100's of fonts */ + BLF_cache_clear(); + + BKE_userdef_state(); + WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */ + WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ +} + static void rna_userdef_language_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { BLF_cache_clear(); @@ -3743,6 +3753,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem virtual_pixel_mode_items[] = { + {VIRTUAL_PIXEL_NATIVE, "NATIVE", 0, "Native", "Use native pixel size of the display"}, + {VIRTUAL_PIXEL_DOUBLE, "DOUBLE", 0, "Double", "Use double the native pixel size of the display"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "UserPreferencesSystem", NULL); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); @@ -3762,6 +3778,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); + prop = RNA_def_property(srna, "virtual_pixel_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "virtual_pixel"); + RNA_def_property_enum_items(prop, virtual_pixel_mode_items); + RNA_def_property_ui_text(prop, "Virtual Pixel Mode", "Modify the pixel size for hi-res devices"); + RNA_def_property_update(prop, 0, "rna_userdef_virtual_pixel_update"); + prop = RNA_def_property(srna, "font_path_ui", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "font_path_ui"); RNA_def_property_ui_text(prop, "Interface Font", "Path to interface font"); diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 584df9eee75..06e9f8f5b67 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -132,6 +132,10 @@ if(WITH_MOD_OCEANSIM) add_definitions(-DWITH_OCEANSIM) endif() +if(WITH_BULLET) + add_definitions(-DWITH_BULLET) +endif() + if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/modifiers/SConscript b/source/blender/modifiers/SConscript index 88bf33db38e..c15a562abc0 100644 --- a/source/blender/modifiers/SConscript +++ b/source/blender/modifiers/SConscript @@ -63,6 +63,9 @@ if env['WITH_BF_FLUID']: if env['WITH_BF_OCEANSIM']: defs.append('WITH_OCEANSIM') +if env['WITH_BF_BULLET']: + defs.append('WITH_BULLET') + if env['WITH_BF_GAMEENGINE']: incs.append('#/extern/recastnavigation') defs.append('WITH_GAMEENGINE') diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 2768d9412d7..40db49afef2 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -404,6 +404,12 @@ static DerivedMesh *arrayModifier_doArray( int *full_doubles_map = NULL; int tot_doubles; + const bool use_merge = amd->flags & MOD_ARR_MERGE; + const bool use_recalc_normals = (dm->dirty & DM_DIRTY_NORMALS) || use_merge; + const bool use_offset_ob = ((amd->offset_type & MOD_ARR_OFF_OBJ) && amd->offset_ob); + /* allow pole vertices to be used by many faces */ + const bool with_follow = use_offset_ob; + int start_cap_nverts = 0, start_cap_nedges = 0, start_cap_npolys = 0, start_cap_nloops = 0; int end_cap_nverts = 0, end_cap_nedges = 0, end_cap_npolys = 0, end_cap_nloops = 0; int result_nverts = 0, result_nedges = 0, result_npolys = 0, result_nloops = 0; @@ -451,7 +457,7 @@ static DerivedMesh *arrayModifier_doArray( offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, chunk_nverts, j); } - if ((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) { + if (use_offset_ob) { float obinv[4][4]; float result_mat[4][4]; @@ -514,7 +520,7 @@ static DerivedMesh *arrayModifier_doArray( result = CDDM_from_template(dm, result_nverts, result_nedges, 0, result_nloops, result_npolys); result_dm_verts = CDDM_get_verts(result); - if (amd->flags & MOD_ARR_MERGE) { + if (use_merge) { /* Will need full_doubles_map for handling merge */ full_doubles_map = MEM_mallocN(sizeof(int) * result_nverts, "mod array doubles map"); fill_vn_i(full_doubles_map, result_nverts, -1); @@ -561,6 +567,15 @@ static DerivedMesh *arrayModifier_doArray( /* apply offset to all new verts */ for (i = 0; i < chunk_nverts; i++, mv++, mv_prev++) { mul_m4_v3(current_offset, mv->co); + + /* We have to correct normals too, if we do not tag them as dirty! */ + if (!use_recalc_normals) { + float no[3]; + normal_short_to_float_v3(no, mv->no); + mul_mat3_m4_v3(current_offset, no); + normalize_v3(no); + normal_float_to_short_v3(mv->no, no); + } } /* adjust edge vertex indices */ @@ -583,7 +598,7 @@ static DerivedMesh *arrayModifier_doArray( } /* Handle merge between chunk n and n-1 */ - if ((amd->flags & MOD_ARR_MERGE) && (c >= 1)) { + if (use_merge && (c >= 1)) { if (!offset_has_scale && (c >= 2)) { /* Mapping chunk 3 to chunk 2 is a translation of mapping 2 to 1 * ... that is except if scaling makes the distance grow */ @@ -594,10 +609,15 @@ static DerivedMesh *arrayModifier_doArray( int target = full_doubles_map[prev_chunk_index]; if (target != -1) { target += chunk_nverts; /* translate mapping */ - /* The rule here is to not follow mapping to chunk N-2, which could be too far - * so if target vertex was itself mapped, then this vertex is not mapped */ if (full_doubles_map[target] != -1) { - target = -1; + if (with_follow) { + target = full_doubles_map[target]; + } + else { + /* The rule here is to not follow mapping to chunk N-2, which could be too far + * so if target vertex was itself mapped, then this vertex is not mapped */ + target = -1; + } } } full_doubles_map[this_chunk_index] = target; @@ -612,7 +632,7 @@ static DerivedMesh *arrayModifier_doArray( c * chunk_nverts, chunk_nverts, amd->merge_dist, - false); + with_follow); } } } @@ -622,10 +642,7 @@ static DerivedMesh *arrayModifier_doArray( copy_m4_m4(final_offset, current_offset); - if ((amd->flags & MOD_ARR_MERGE) && - (amd->flags & MOD_ARR_MERGEFINAL) && - (count > 1)) - { + if (use_merge && (amd->flags & MOD_ARR_MERGEFINAL) && (count > 1)) { /* Merge first and last copies */ dm_mvert_map_doubles( full_doubles_map, @@ -635,7 +652,7 @@ static DerivedMesh *arrayModifier_doArray( first_chunk_start, first_chunk_nverts, amd->merge_dist, - false); + with_follow); } /* start capping */ @@ -651,7 +668,7 @@ static DerivedMesh *arrayModifier_doArray( result_npolys - start_cap_npolys - end_cap_npolys, start_cap_nverts, start_cap_nedges, start_cap_nloops, start_cap_npolys); /* Identify doubles with first chunk */ - if (amd->flags & MOD_ARR_MERGE) { + if (use_merge) { dm_mvert_map_doubles( full_doubles_map, result_dm_verts, @@ -676,7 +693,7 @@ static DerivedMesh *arrayModifier_doArray( result_npolys - end_cap_npolys, end_cap_nverts, end_cap_nedges, end_cap_nloops, end_cap_npolys); /* Identify doubles with last chunk */ - if (amd->flags & MOD_ARR_MERGE) { + if (use_merge) { dm_mvert_map_doubles( full_doubles_map, result_dm_verts, @@ -690,19 +707,17 @@ static DerivedMesh *arrayModifier_doArray( } /* done capping */ - /* In case org dm has dirty normals, or we made some merging, mark normals as dirty in new dm! - * TODO: we may need to set other dirty flags as well? - */ - if ((dm->dirty & DM_DIRTY_NORMALS) || full_doubles_map) { - result->dirty |= DM_DIRTY_NORMALS; - } - /* Handle merging */ tot_doubles = 0; - if (full_doubles_map) { + if (use_merge) { for (i = 0; i < result_nverts; i++) { if (full_doubles_map[i] != -1) { - tot_doubles++; + if (i == full_doubles_map[i]) { + full_doubles_map[i] = -1; + } + else { + tot_doubles++; + } } } if (tot_doubles > 0) { @@ -710,6 +725,14 @@ static DerivedMesh *arrayModifier_doArray( } MEM_freeN(full_doubles_map); } + + /* In case org dm has dirty normals, or we made some merging, mark normals as dirty in new dm! + * TODO: we may need to set other dirty flags as well? + */ + if (use_recalc_normals) { + result->dirty |= DM_DIRTY_NORMALS; + } + return result; } diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 825015fa25c..1e422806d80 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -218,6 +218,7 @@ static bool skin_frame_find_contained_faces(const Frame *frame, /* Returns true if hull is successfully built, false otherwise */ static bool build_hull(SkinOutput *so, Frame **frames, int totframe) { +#ifdef WITH_BULLET BMesh *bm = so->bm; BMOperator op; BMIter iter; @@ -326,6 +327,11 @@ static bool build_hull(SkinOutput *so, Frame **frames, int totframe) BM_mesh_delete_hflag_tagged(bm, BM_ELEM_TAG, BM_EDGE | BM_FACE); return true; +#else + (void)so, (void)frames, (void)totframe; + (void)skin_frame_find_contained_faces; + return false; +#endif } /* Returns the average frame side length (frames are rectangular, so diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 76986583ef5..7349ca9f9ef 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -60,7 +60,7 @@ static void copyData(ModifierData *md, ModifierData *target) static bool isDisabled(ModifierData *UNUSED(md), int UNUSED(useRenderParams)) { - return 0; + return false; } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) @@ -75,6 +75,11 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) } +static bool dependsOnNormals(ModifierData *UNUSED(md)) +{ + return true; +} + static DerivedMesh *WireframeModifier_do( WireframeModifierData *wmd, Object *ob, DerivedMesh *dm) { DerivedMesh *result; @@ -135,7 +140,7 @@ ModifierTypeInfo modifierType_Wireframe = { /* isDisabled */ isDisabled, /* updateDepgraph */ NULL, /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, + /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c index 0893d2022a0..2347564c696 100644 --- a/source/blender/nodes/intern/node_exec.c +++ b/source/blender/nodes/intern/node_exec.c @@ -160,7 +160,6 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNo bNode **nodelist; int totnodes, n; /* XXX texnodes have threading issues with muting, have to disable it there ... */ - bool use_muting = (ntree->type != NTREE_TEXTURE); /* ensure all sock->link pointers and node levels are correct */ ntreeUpdateTree(G.main, ntree); @@ -184,7 +183,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNo for (sock = node->inputs.first; sock; sock = sock->next) node_init_input_index(sock, &index); - if (use_muting && (node->flag & NODE_MUTED || node->type == NODE_REROUTE)) { + if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { for (sock = node->outputs.first; sock; sock = sock->next) node_init_output_index(sock, &index, &node->internal_links); } @@ -306,7 +305,7 @@ bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *call */ // if (node->typeinfo->compatibility == NODE_NEW_SHADING) // return false; - if (node->typeinfo->execfunc) + if (node->typeinfo->execfunc && !(node->flag & NODE_MUTED)) node->typeinfo->execfunc(callerdata, thread, node, &nodeexec->data, nsin, nsout); } } diff --git a/source/blender/nodes/shader/nodes/node_shader_camera.c b/source/blender/nodes/shader/nodes/node_shader_camera.c index 231af7e7d37..49ebb15d7a4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_camera.c +++ b/source/blender/nodes/shader/nodes/node_shader_camera.c @@ -47,7 +47,7 @@ static void node_shader_exec_camera(void *data, int UNUSED(thread), bNode *UNUSE ShadeInput *shi = ((ShaderCallData *)data)->shi; /* Data we need for shading. */ copy_v3_v3(out[0]->vec, shi->co); /* get view vector */ - out[1]->vec[0] = fabs(shi->co[2]); /* get view z-depth */ + out[1]->vec[0] = fabsf(shi->co[2]); /* get view z-depth */ out[2]->vec[0] = normalize_v3(out[0]->vec); /* get view distance */ } } diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index d5ba8231cce..dc5971909d2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -74,25 +74,25 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode case 4: /* Sine */ { if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ - r = sin(a); + r = sinf(a); else - r = sin(b); + r = sinf(b); break; } case 5: /* Cosine */ { if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ - r = cos(a); + r = cosf(a); else - r = cos(b); + r = cosf(b); break; } case 6: /* Tangent */ { if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ - r = tan(a); + r = tanf(a); else - r = tan(b); + r = tanf(b); break; } case 7: /* Arc-Sine */ @@ -100,14 +100,14 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */ /* Can't do the impossible... */ if (a <= 1 && a >= -1) - r = asin(a); + r = asinf(a); else r = 0.0; } else { /* Can't do the impossible... */ if (b <= 1 && b >= -1) - r = asin(b); + r = asinf(b); else r = 0.0; } @@ -118,14 +118,14 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */ /* Can't do the impossible... */ if (a <= 1 && a >= -1) - r = acos(a); + r = acosf(a); else r = 0.0; } else { /* Can't do the impossible... */ if (b <= 1 && b >= -1) - r = acos(b); + r = acosf(b); else r = 0.0; } @@ -218,7 +218,7 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode } case 18: /* Absolute */ { - r = fabs(a); + r = fabsf(a); break; } } diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c index b40bf6bc71a..f2ea2faa5a7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c +++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c @@ -59,14 +59,14 @@ static void node_shader_exec_vect_math(void *UNUSED(data), int UNUSED(thread), b out[0]->vec[1] = vec1[1] + vec2[1]; out[0]->vec[2] = vec1[2] + vec2[2]; - out[1]->vec[0] = (fabs(out[0]->vec[0]) + fabs(out[0]->vec[0]) + fabs(out[0]->vec[0])) / 3; + out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[0])) / 3; } else if (node->custom1 == 1) { /* Subtract */ out[0]->vec[0] = vec1[0] - vec2[0]; out[0]->vec[1] = vec1[1] - vec2[1]; out[0]->vec[2] = vec1[2] - vec2[2]; - out[1]->vec[0] = (fabs(out[0]->vec[0]) + fabs(out[0]->vec[0]) + fabs(out[0]->vec[0])) / 3; + out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[0])) / 3; } else if (node->custom1 == 2) { /* Average */ out[0]->vec[0] = vec1[0] + vec2[0]; diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 02f15705ad1..1b790f87faf 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -140,7 +140,7 @@ static void foreach_nodeclass(Scene *UNUSED(scene), void *calldata, bNodeClassCa /* XXX muting disabled in previews because of threading issues with the main execution * it works here, but disabled for consistency */ -#if 0 +#if 1 static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) { bNode *node, *node_next; diff --git a/source/blender/nodes/texture/node_texture_util.c b/source/blender/nodes/texture/node_texture_util.c index e01b7ec49f1..42c684b8247 100644 --- a/source/blender/nodes/texture/node_texture_util.c +++ b/source/blender/nodes/texture/node_texture_util.c @@ -140,11 +140,19 @@ void tex_do_preview(bNodePreview *preview, const float coord[2], const float col void tex_output(bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *cdata) { TexDelegate *dg; - if (!out->data) - /* Freed in tex_end_exec (node.c) */ - dg = out->data = MEM_mallocN(sizeof(TexDelegate), "tex delegate"); - else - dg = out->data; + + if (node->flag & NODE_MUTED) { + /* do not add a delegate if the node is muted */ + return; + } + else { + if (!out->data) + /* Freed in tex_end_exec (node.c) */ + dg = out->data = MEM_mallocN(sizeof(TexDelegate), "tex delegate"); + else + dg = out->data; + } + dg->cdata = cdata; dg->fn = texfn; diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c index 9bd2532b4b8..94e778e10fb 100644 --- a/source/blender/nodes/texture/nodes/node_texture_math.c +++ b/source/blender/nodes/texture/nodes/node_texture_math.c @@ -72,24 +72,24 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor } case 4: /* Sine */ { - *out = sin(in0); + *out = sinf(in0); break; } case 5: /* Cosine */ { - *out = cos(in0); + *out = cosf(in0); break; } case 6: /* Tangent */ { - *out = tan(in0); + *out = tanf(in0); break; } case 7: /* Arc-Sine */ { /* Can't do the impossible... */ if (in0 <= 1 && in0 >= -1) - *out = asin(in0); + *out = asinf(in0); else *out = 0.0; break; @@ -98,7 +98,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor { /* Can't do the impossible... */ if (in0 <= 1 && in0 >= -1) - *out = acos(in0); + *out = acosf(in0); else *out = 0.0; break; @@ -185,7 +185,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor case 18: /* Absolute */ { - *out = fabs(in0); + *out = fabsf(in0); break; } diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index 9c9b69186ab..2c07df98973 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -507,7 +507,7 @@ static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObjec return -1; } } - /* fall-through */ + break; } default: /* TODO --- many others */ diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index 109e5606037..0114e8e65e4 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -86,16 +86,15 @@ static unsigned int _ghashutil_keyhash(const void *ptr) return hash ^ BLI_ghashutil_strhash(key->msgid); } -static int _ghashutil_keycmp(const void *a, const void *b) +static bool _ghashutil_keycmp(const void *a, const void *b) { const GHashKey *A = a; const GHashKey *B = b; /* Note: comparing msgid first, most of the time it will be enough! */ - int cmp = BLI_ghashutil_strcmp(A->msgid, B->msgid); - if (cmp == 0) + if (BLI_ghashutil_strcmp(A->msgid, B->msgid) == false) return BLI_ghashutil_strcmp(A->msgctxt, B->msgctxt); - return cmp; + return true; /* true means they are not equal! */ } static void _ghashutil_keyfree(void *ptr) diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index ddfbfecc46e..d46c95a25b8 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -420,7 +420,7 @@ static void python_script_error_jump_text(struct Text *text) typedef struct { PyObject_HEAD PyObject *md_dict; - /* ommit other values, we only want the dict. */ + /* omit other values, we only want the dict. */ } PyModuleObject; #endif diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 75fe05ae2f5..ae3476f5802 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -947,7 +947,7 @@ static PyObject *Quaternion_magnitude_get(QuaternionObject *self, void *UNUSED(c if (BaseMath_ReadCallback(self) == -1) return NULL; - return PyFloat_FromDouble(sqrt(dot_qtqt(self->quat, self->quat))); + return PyFloat_FromDouble(sqrtf(dot_qtqt(self->quat, self->quat))); } PyDoc_STRVAR(Quaternion_angle_doc, diff --git a/source/blender/python/rna_dump.py b/source/blender/python/rna_dump.py index 15cc60d997e..7259ceb67a0 100644 --- a/source/blender/python/rna_dump.py +++ b/source/blender/python/rna_dump.py @@ -1,22 +1,22 @@ - # ***** 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. - # - # Contributor(s): Campbell Barton - # - # #**** END GPL LICENSE BLOCK #**** +# ##### 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. +# +# Contributor(s): Campbell Barton +# +# ##### END GPL LICENSE BLOCK ##### # <pep8 compliant> diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 8e326e770fc..e516c954737 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -162,6 +162,10 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_CYCLES AND WITH_CYCLES_DEBUG) + add_definitions(-DWITH_CYCLES_DEBUG) +endif() + if(APPLE) # SSE math is enabled by default on x86_64 if(CMAKE_OSX_ARCHITECTURES MATCHES "i386") diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index 297e4fcecd4..7f459444a39 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -103,6 +103,9 @@ if env['WITH_BF_GAMEENGINE']: if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') +if env['WITH_BF_CYCLES'] and env['WITH_BF_CYCLES_DEBUG']: + defs.append('WITH_CYCLES_DEBUG') + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 24f8cbee401..4b0473f7483 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -60,6 +60,7 @@ struct BakePixel; #define RE_USE_SHADING_NODES 16 #define RE_USE_EXCLUDE_LAYERS 32 #define RE_USE_SAVE_BUFFERS 64 +#define RE_USE_TEXTURE_PREVIEW 128 /* RenderEngine.flag */ #define RE_ENGINE_ANIMATION 1 diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 3b54de4c943..61795c2c173 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -72,8 +72,13 @@ typedef struct RenderPass { char chan_id[8]; /* amount defined in openexr_multi.h */ float *rect; int rectx, recty; + int debug_type; } RenderPass; +enum { + RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS = 0, +}; + /* a renderlayer is a full image, but with all passes and samples */ /* size of the rects is defined in RenderResult */ /* after render, the Combined pass is in rectf, for renderlayers read from files it is a real pass */ diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp index 24804b8c0ad..6cbb0761358 100644 --- a/source/blender/render/intern/raytrace/rayobject_octree.cpp +++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp @@ -657,7 +657,7 @@ static void RE_rayobject_octree_done(RayObject *tree) oc->ocfacy = (oc->ocres - 0.1f) / t01; oc->ocfacz = (oc->ocres - 0.1f) / t02; - oc->ocsize = sqrt(t00 * t00 + t01 * t01 + t02 * t02); /* global, max size octree */ + oc->ocsize = sqrtf(t00 * t00 + t01 * t01 + t02 * t02); /* global, max size octree */ for (c = 0; c < oc->ro_nodes_used; c++) { octree_fill_rayface(oc, oc->ro_nodes[c]); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index e6f054583b1..69dd9607c3b 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -762,7 +762,7 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, Par w= vec[2]*re->winmat[2][3] + re->winmat[3][3]; dx= re->winx*cross[0]*re->winmat[0][0]; dy= re->winy*cross[1]*re->winmat[1][1]; - w= sqrt(dx*dx + dy*dy)/w; + w = sqrtf(dx * dx + dy * dy) / w; if (w!=0.0f) { float fac; @@ -927,7 +927,7 @@ static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, Par w= vec[2]*re->winmat[2][3] + re->winmat[3][3]; dx= re->winx*dvec[0]*re->winmat[0][0]/w; dy= re->winy*dvec[1]*re->winmat[1][1]/w; - w= sqrt(dx*dx + dy*dy); + w = sqrtf(dx * dx + dy * dy); if (dot_v3v3(anor, nor)<sd->adapt_angle && w>sd->adapt_pix) { vlr= RE_findOrAddVlak(obr, obr->totvlak++); vlr->flag= flag; @@ -3796,8 +3796,8 @@ static GroupObject *add_render_lamp(Render *re, Object *ob) normalize_v3(lar->imat[1]); normalize_v3(lar->imat[2]); - xn= saacos(lar->spotsi); - xn= sin(xn)/cos(xn); + xn = saacos(lar->spotsi); + xn = sinf(xn) / cosf(xn); lar->spottexfac= 1.0f/(xn); if (lar->mode & LA_ONLYSHADOW) { @@ -3820,7 +3820,7 @@ static GroupObject *add_render_lamp(Render *re, Object *ob) /* z factor, for a normalized volume */ angle= saacos(lar->spotsi); xn= lar->spotsi; - yn= sin(angle); + yn = sinf(angle); lar->sh_zfac= yn/xn; /* pre-scale */ lar->sh_invcampos[2]*= lar->sh_zfac; @@ -5438,7 +5438,7 @@ static float *calculate_strandsurface_speedvectors(Render *re, ObjectInstanceRen { if (mesh->co && mesh->prevco && mesh->nextco) { float winsq= (float)re->winx*(float)re->winy; /* int's can wrap on large images */ - float winroot= sqrt(winsq); + float winroot= sqrtf(winsq); float (*winspeed)[4]; float ho[4], prevho[4], nextho[4], winmat[4][4], vec[2]; int a; @@ -5477,7 +5477,7 @@ static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *ve StrandSurface *mesh= NULL; float *speed, (*winspeed)[4]=NULL, ho[4], winmat[4][4]; float *co1, *co2, *co3, *co4, w[4]; - float winsq= (float)re->winx*(float)re->winy, winroot= sqrt(winsq); /* int's can wrap on large images */ + float winsq = (float)re->winx * (float)re->winy, winroot = sqrtf(winsq); /* int's can wrap on large images */ int a, *face, *index; if (obi->flag & R_TRANSFORMED) @@ -5544,7 +5544,7 @@ static int load_fluidsimspeedvectors(Render *re, ObjectInstanceRen *obi, float * VertRen *ver= NULL; float *speed, div, zco[2], avgvel[4] = {0.0, 0.0, 0.0, 0.0}; float zmulx= re->winx/2, zmuly= re->winy/2, len; - float winsq= (float)re->winx*(float)re->winy, winroot= sqrt(winsq); /* int's can wrap on large images */ + float winsq = (float)re->winx * (float)re->winy, winroot= sqrtf(winsq); /* int's can wrap on large images */ int a, j; float hoco[4], ho[4], fsvec[4], camco[4]; float mat[4][4], winmat[4][4]; diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index 5fd4747f19b..353ba5d5caa 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -190,7 +190,7 @@ static float calc_weight(Render *re, float *weight, int i, int j) for (a = 0; a < re->osa; a++) { x = re->jit[a][0] + i; y = re->jit[a][1] + j; - dist = sqrt(x * x + y * y); + dist = sqrtf(x * x + y * y); weight[a] = 0.0; diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c index 4ac1593d1bb..6ba85ea5329 100644 --- a/source/blender/render/intern/source/multires_bake.c +++ b/source/blender/render/intern/source/multires_bake.c @@ -42,6 +42,7 @@ #include "BLI_threads.h" #include "BKE_ccg.h" +#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_multires.h" @@ -1154,10 +1155,10 @@ static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void /* this gives results identical to the so-called cosine * weighted distribution relative to the north pole. */ - float SiPhi = sqrt(SiSqPhi); + float SiPhi = sqrtf(SiSqPhi); float CoPhi = SiSqPhi < 1.0f ? sqrtf(1.0f - SiSqPhi) : 0; - float CoThe = cos(Theta); - float SiThe = sin(Theta); + float CoThe = cosf(Theta); + float SiThe = sinf(Theta); const float dx = CoThe * CoPhi; const float dy = SiThe * CoPhi; @@ -1297,6 +1298,7 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) } BKE_image_release_ibuf(ima, ibuf, NULL); + DAG_id_tag_update(&ima->id, 0); } } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 32bd67cb1f2..7b43c77537f 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -699,25 +699,27 @@ static void render_result_rescale(Render *re) RR_USE_MEM, RR_ALL_LAYERS); - dst_rectf = re->result->rectf; - if (dst_rectf == NULL) { - RenderLayer *rl; - rl = render_get_active_layer(re, re->result); - if (rl != NULL) { - dst_rectf = rl->rectf; + if (re->result != NULL) { + dst_rectf = re->result->rectf; + if (dst_rectf == NULL) { + RenderLayer *rl; + rl = render_get_active_layer(re, re->result); + if (rl != NULL) { + dst_rectf = rl->rectf; + } } - } - scale_x = (float) result->rectx / re->result->rectx; - scale_y = (float) result->recty / re->result->recty; - for (x = 0; x < re->result->rectx; ++x) { - for (y = 0; y < re->result->recty; ++y) { - int src_x = x * scale_x, - src_y = y * scale_y; - int dst_index = y * re->result->rectx + x, - src_index = src_y * result->rectx + src_x; - copy_v4_v4(dst_rectf + dst_index * 4, - src_rectf + src_index * 4); + scale_x = (float) result->rectx / re->result->rectx; + scale_y = (float) result->recty / re->result->recty; + for (x = 0; x < re->result->rectx; ++x) { + for (y = 0; y < re->result->recty; ++y) { + int src_x = x * scale_x, + src_y = y * scale_y; + int dst_index = y * re->result->rectx + x, + src_index = src_y * result->rectx + src_x; + copy_v4_v4(dst_rectf + dst_index * 4, + src_rectf + src_index * 4); + } } } } @@ -1013,8 +1015,8 @@ static bool find_next_pano_slice(Render *re, int *slice, int *minx, rctf *viewpl /* rotate database according to part coordinates */ project_renderdata(re, projectverto, 1, -R.panodxp * phi, 1); - R.panosi = sin(R.panodxp * phi); - R.panoco = cos(R.panodxp * phi); + R.panosi = sinf(R.panodxp * phi); + R.panoco = cosf(R.panodxp * phi); } (*slice)++; @@ -1638,6 +1640,10 @@ static void do_render_fields_blur_3d(Render *re) if (re->r.mode & R_BORDER) { if ((re->r.mode & R_CROP) == 0) { RenderResult *rres; + + /* backup */ + const rcti orig_disprect = re->disprect; + const int orig_rectx = re->rectx, orig_recty = re->recty; BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); @@ -1660,6 +1666,11 @@ static void do_render_fields_blur_3d(Render *re) re->display_init(re->dih, re->result); re->display_update(re->duh, re->result, NULL); + + /* restore the disprect from border */ + re->disprect = orig_disprect; + re->rectx = orig_rectx; + re->recty = orig_recty; } else { /* set offset (again) for use in compositor, disprect was manipulated. */ @@ -2651,7 +2662,16 @@ bool RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList * } #endif } - + +#ifdef WITH_FREESTYLE + if (scene->r.mode & R_EDGE_FRS) { + if (scene->r.mode & R_FIELDS) { + BKE_report(reports, RPT_ERROR, "Fields not supported in Freestyle"); + return false; + } + } +#endif + /* layer flag tests */ if (!render_scene_has_layers_to_render(scene)) { BKE_report(reports, RPT_ERROR, "All render layers are disabled"); diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c index 09a6a6374be..014df802a78 100644 --- a/source/blender/render/intern/source/pixelshading.c +++ b/source/blender/render/intern/source/pixelshading.c @@ -160,7 +160,7 @@ static void render_lighting_halo(HaloRen *har, float col_r[3]) x = max_ff(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2])); /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ - inpr= 1.0/(sqrt(1.0f+x*x)); + inpr = 1.0 / (sqrtf(1.0f + x * x)); } else inpr= 0.0; } @@ -206,7 +206,7 @@ static void render_lighting_halo(HaloRen *har, float col_r[3]) /* dot product and reflectivity*/ - inp = 1.0 - fabs(dot_v3v3(vn, lv)); + inp = 1.0 - fabsf(dot_v3v3(vn, lv)); /* inp= cos(0.5*M_PI-acos(inp)); */ @@ -329,7 +329,7 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz, } } - radist= sqrt(dist); + radist = sqrtf(dist); /* watch it: not used nicely: flarec is set at zero in pixstruct */ if (flarec) har->pixels+= (int)(har->rad-radist); @@ -366,17 +366,15 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz, else dist= dist/har->radsq; if (har->type & HA_FLARECIRC) { - - dist= 0.5+fabs(dist-0.5f); - + dist = 0.5 + fabsf(dist - 0.5f); } if (har->hard>=30) { - dist= sqrt(dist); + dist = sqrtf(dist); if (har->hard>=40) { - dist= sinf(dist*(float)M_PI_2); + dist = sinf(dist*(float)M_PI_2); if (har->hard>=50) { - dist= sqrt(dist); + dist = sqrtf(dist); } } } @@ -399,7 +397,7 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz, rc= hashvectf + (ofs % 768); - fac= fabs( (xn)*rc[0]+(yn)*rc[1]); + fac = fabsf((xn) * rc[0] + (yn) * rc[1]); if (fac< 1.0f ) linef+= (1.0f-fac); @@ -411,15 +409,15 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz, if (har->starpoints) { float ster, angle; /* rotation */ - angle= atan2(yn, xn); - angle*= (1.0f+0.25f*har->starpoints); + angle = atan2f(yn, xn); + angle *= (1.0f+0.25f*har->starpoints); co= cosf(angle); si= sinf(angle); angle= (co*xn+si*yn)*(co*yn-si*xn); - ster= fabs(angle); + ster = fabsf(angle); if (ster>1.0f) { ster= (har->rad)/(ster); diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 799f7fa2f2e..ac2e85a33b3 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -384,7 +384,7 @@ static void accum_density(void *userdata, int index, float squared_dist) else if (pdr->falloff_type == TEX_PD_FALLOFF_CONSTANT) density = pdr->squared_radius; else if (pdr->falloff_type == TEX_PD_FALLOFF_ROOT) - density = sqrt(dist); + density = sqrtf(dist); else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE) { if (pdr->point_data_used & POINT_DATA_LIFE) density = dist*MIN2(pdr->point_data[pdr->offset + index], 1.0f); diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 7e56d93f23b..ff1f502cc1a 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -651,7 +651,7 @@ static float shade_by_transmission(Isect *is, ShadeInput *shi, ShadeResult *shr) const float dx= shi->co[0] - is->start[0]; const float dy= shi->co[1] - is->start[1]; const float dz= shi->co[2] - is->start[2]; - d= sqrt(dx*dx+dy*dy+dz*dz); + d = sqrtf(dx * dx + dy * dy + dz * dz); if (d > shi->mat->tx_limit) d= shi->mat->tx_limit; @@ -1117,7 +1117,7 @@ static void QMC_samplePhong(float vec[3], QMCSampler *qsa, int thread, int num, phi = s[0]*2*M_PI; pz = pow(s[1], blur); - sqr = sqrt(1.0f-pz*pz); + sqr = sqrtf(1.0f - pz * pz); vec[0] = (float)(cosf(phi)*sqr); vec[1] = (float)(sinf(phi)*sqr); @@ -1281,7 +1281,7 @@ static float get_avg_speed(ShadeInput *shi) post_x = (shi->winspeed[2] == PASS_VECTOR_MAX)?0.0f:shi->winspeed[2]; post_y = (shi->winspeed[3] == PASS_VECTOR_MAX)?0.0f:shi->winspeed[3]; - speedavg = (sqrt(pre_x*pre_x + pre_y*pre_y) + sqrt(post_x*post_x + post_y*post_y)) / 2.0; + speedavg = (sqrtf(pre_x * pre_x + pre_y * pre_y) + sqrtf(post_x * post_x + post_y * post_y)) / 2.0; return speedavg; } @@ -1786,10 +1786,10 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys, in sphere= threadsafe_table_sphere(0, thread, xs, ys, tot); /* random rotation */ - ang= BLI_thread_frand(thread); - sinfi= sin(ang); cosfi= cos(ang); - ang= BLI_thread_frand(thread); - sint= sin(ang); cost= cos(ang); + ang = BLI_thread_frand(thread); + sinfi = sinf(ang); cosfi = cosf(ang); + ang = BLI_thread_frand(thread); + sint = sinf(ang); cost = cosf(ang); vec= R.wrld.aosphere; vec1= sphere; @@ -2371,9 +2371,9 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, const float lampco[ mul_m3_v3(lar->mat, vec); /* set start and vec */ - isec->dir[0] = vec[0]+lampco[0]-isec->start[0]; - isec->dir[1] = vec[1]+lampco[1]-isec->start[1]; - isec->dir[2] = vec[2]+lampco[2]-isec->start[2]; + isec->dir[0] = vec[0]+lampco[0]-shi->co[0]; + isec->dir[1] = vec[1]+lampco[1]-shi->co[1]; + isec->dir[2] = vec[2]+lampco[2]-shi->co[2]; RE_instance_rotate_ray_dir(shi->obi, isec); @@ -2406,9 +2406,9 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, const float lampco[ else { /* sqrt makes nice umbra effect */ if (lar->ray_samp_type & LA_SAMP_UMBRA) - shadfac[3]= sqrt(1.0f-fac/div); + shadfac[3] = sqrtf(1.0f - fac / div); else - shadfac[3]= 1.0f-fac/div; + shadfac[3] = 1.0f - fac / div; } } /* extern call from shade_lamp_loop */ diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index d8410fbe257..24797521435 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -48,6 +48,9 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_report.h" +#ifdef WITH_CYCLES_DEBUG +# include "BKE_scene.h" +#endif #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -402,7 +405,7 @@ static int passtype_from_name(const char *str) /********************************** New **************************************/ -static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype) +static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype) { const char *typestr = get_pass_name(passtype, 0); RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr); @@ -438,8 +441,34 @@ static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channel rect[x] = 10e10; } } + return rpass; } +#ifdef WITH_CYCLES_DEBUG +static const char *debug_pass_type_name_get(int debug_type) +{ + switch (debug_type) { + case RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS: + return "BVH Traversal Steps"; + } + return "Unknown"; +} + +static RenderPass *render_layer_add_debug_pass(RenderResult *rr, + RenderLayer *rl, + int channels, + int pass_type, + int debug_type) +{ + RenderPass *rpass = render_layer_add_pass(rr, rl, channels, pass_type); + rpass->debug_type = debug_type; + BLI_strncpy(rpass->name, + debug_pass_type_name_get(debug_type), + sizeof(rpass->name)); + return rpass; +} +#endif + /* called by main render as well for parts */ /* will read info from Render *re to define layers */ /* called in threads */ @@ -578,6 +607,13 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT); if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR) render_layer_add_pass(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR); + +#ifdef WITH_CYCLES_DEBUG + if(BKE_scene_use_new_shading_nodes(re->scene)) { + render_layer_add_debug_pass(rr, rl, 1, SCE_PASS_DEBUG, + RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS); + } +#endif } /* sss, previewrender and envmap don't do layers, so we make a default one */ if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) { diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index dd14c2495e8..0e61c3e796a 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -212,10 +212,10 @@ static int blend(Tex *tex, const float texvec[3], TexResult *texres) texres->tin= (2.0f+x+y)/4.0f; } else if (tex->stype==TEX_RAD) { /* radial */ - texres->tin= (atan2(y, x) / (2*M_PI) + 0.5); + texres->tin = (atan2f(y, x) / (2 * M_PI) + 0.5f); } else { /* sphere TEX_SPHERE */ - texres->tin= 1.0-sqrt(x*x+ y*y+texvec[2]*texvec[2]); + texres->tin = 1.0 - sqrtf(x * x + y * y + texvec[2] * texvec[2]); if (texres->tin<0.0f) texres->tin= 0.0f; if (tex->stype==TEX_HALO) texres->tin*= texres->tin; /* halo */ } @@ -266,8 +266,8 @@ static int clouds(Tex *tex, const float texvec[3], TexResult *texres) /* creates a sine wave */ static float tex_sin(float a) { - a = 0.5 + 0.5*sin(a); - + a = 0.5 + 0.5 * sinf(a); + return a; } @@ -366,10 +366,10 @@ static float marble_int(Tex *tex, float x, float y, float z) if (mt>=TEX_SOFT) { /* TEX_SOFT always true */ mi = waveform[wf](mi); if (mt==TEX_SHARP) { - mi = sqrt(mi); + mi = sqrtf(mi); } else if (mt==TEX_SHARPER) { - mi = sqrt(sqrt(mi)); + mi = sqrtf(sqrtf(mi)); } } @@ -408,41 +408,41 @@ static int magic(Tex *tex, const float texvec[3], TexResult *texres) n= tex->noisedepth; turb= tex->turbul/5.0f; - x= sin( ( texvec[0]+texvec[1]+texvec[2])*5.0f ); - y= cos( (-texvec[0]+texvec[1]-texvec[2])*5.0f ); - z= -cos( (-texvec[0]-texvec[1]+texvec[2])*5.0f ); + x = sinf(( texvec[0] + texvec[1] + texvec[2]) * 5.0f); + y = cosf((-texvec[0] + texvec[1] - texvec[2]) * 5.0f); + z = -cosf((-texvec[0] - texvec[1] + texvec[2]) * 5.0f); if (n>0) { x*= turb; y*= turb; z*= turb; - y= -cos(x-y+z); + y= -cosf(x-y+z); y*= turb; if (n>1) { - x= cos(x-y-z); + x= cosf(x-y-z); x*= turb; if (n>2) { - z= sin(-x-y-z); + z= sinf(-x-y-z); z*= turb; if (n>3) { - x= -cos(-x+y-z); + x= -cosf(-x+y-z); x*= turb; if (n>4) { - y= -sin(-x+y+z); + y= -sinf(-x+y+z); y*= turb; if (n>5) { - y= -cos(-x+y+z); + y= -cosf(-x+y+z); y*= turb; if (n>6) { - x= cos(x+y+z); + x= cosf(x+y+z); x*= turb; if (n>7) { - z= sin(x+y-z); + z= sinf(x+y-z); z*= turb; if (n>8) { - x= -cos(-x-y+z); + x= -cosf(-x-y+z); x*= turb; if (n>9) { - y= -sin(x-y+z); + y= -sinf(x-y+z); y*= turb; } } @@ -2348,8 +2348,8 @@ void do_material_tex(ShadeInput *shi, Render *re) copy_v3_v3(texres.nor, &texres.tr); } else { - float co_nor= 0.5*cos(texres.tin-0.5f); - float si= 0.5*sin(texres.tin-0.5f); + float co_nor= 0.5f * cosf(texres.tin - 0.5f); + float si = 0.5f * sinf(texres.tin - 0.5f); float f1, f2; f1= shi->vn[0]; @@ -3396,8 +3396,11 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r col[0]= texres.tr*la->energy; col[1]= texres.tg*la->energy; col[2]= texres.tb*la->energy; - - texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->colfac, mtex->blendtype); + + if (effect & LA_SHAD_TEX) + texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->shadowfac, mtex->blendtype); + else + texture_rgb_blend(col_r, col, col_r, texres.tin, mtex->colfac, mtex->blendtype); } } } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 27bc449dce3..a67140c6334 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -1906,9 +1906,9 @@ static void renderflare(RenderResult *rr, float *rectf, HaloRen *har) fla.hard= 20.0f + fabsf(70.0f*rc[7]); fla.tex= 0; - type= (int)(fabs(3.9f*rc[6])); + type= (int)(fabsf(3.9f*rc[6])); - fla.rad= ma->subsize*sqrtf(fabs(2.0f*har->rad*rc[4])); + fla.rad = ma->subsize * sqrtf(fabsf(2.0f * har->rad * rc[4])); if (type==3) { fla.rad*= 3.0f; diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 6a3787289d8..46c504aaabf 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -992,10 +992,10 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, xn= har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]); yn= har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]); if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0f; - else zn= atan2(yn, xn); + else zn = atan2f(yn, xn); - har->sin= sin(zn); - har->cos= cos(zn); + har->sin = sinf(zn); + har->cos = cosf(zn); zn= len_v3v3(vec1, vec); har->hasize= vectsize*zn + (1.0f-vectsize)*hasize; @@ -1112,10 +1112,10 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater xn= har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]); yn= har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]); if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0; - else zn= atan2(yn, xn); + else zn = atan2f(yn, xn); - har->sin= sin(zn); - har->cos= cos(zn); + har->sin = sinf(zn); + har->cos = cosf(zn); zn= len_v3v3(vec1, vec)*0.5f; har->hasize= vectsize*zn + (1.0f-vectsize)*hasize; @@ -1284,8 +1284,8 @@ void project_renderdata(Render *re, if (do_pano) { float panophi= xoffs; - re->panosi= sin(panophi); - re->panoco= cos(panophi); + re->panosi = sinf(panophi); + re->panoco = cosf(panophi); } for (obr=re->objecttable.first; obr; obr=obr->next) { diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index aa420d7e7c8..9d83ff1d7e8 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -536,7 +536,7 @@ static void compress_shadowbuf(ShadBuf *shb, int *rectz, int square) if (x< a) minx= x+15-a; else minx= x-a; - dist= sqrt( (float)(minx*minx+miny*miny) ); + dist = sqrtf((float)(minx * minx + miny * miny)); if (square==0 && dist>(float)(a+12)) { /* 12, tested with a onlyshadow lamp */ a= 256; verg= 0; /* 0x80000000; */ /* 0x7FFFFFFF; */ @@ -1685,7 +1685,7 @@ static int point_behind_strand(const float p[3], BSPFace *face) if (face->len==0.0f) { rc[0]= p[0]-face->vec1[0]; rc[1]= p[1]-face->vec1[1]; - dist= (float)(sqrt(rc[0]*rc[0]+ rc[1]*rc[1])); + dist = len_v2(rc); if (dist < face->radline) return 1; @@ -1699,10 +1699,10 @@ static int point_behind_strand(const float p[3], BSPFace *face) pt[0]= lambda*face->rc[0]+face->vec1[0]; pt[1]= lambda*face->rc[1]+face->vec1[1]; - + rc[0]= pt[0]-p[0]; rc[1]= pt[1]-p[1]; - dist= sqrtf(rc[0]*rc[0]+ rc[1]*rc[1]); + dist = len_v2(rc); if (dist < face->radline) { float zval= face->vec1[2] + lambda*face->rc[2]; diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 427d0eeed11..f909c585561 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -144,7 +144,7 @@ float mistfactor(float zcor, float const co[3]) /* pass */ } else { - fac = sqrt(fac); + fac = sqrtf(fac); } } else { @@ -338,9 +338,9 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens) /* now we have 2 points, make three lengths with it */ - a= sqrt(p1[0]*p1[0]+p1[1]*p1[1]+p1[2]*p1[2]); - b= sqrt(p2[0]*p2[0]+p2[1]*p2[1]+p2[2]*p2[2]); - c= len_v3v3(p1, p2); + a = len_v3(p1); + b = len_v3(p2); + c = len_v3v3(p1, p2); a/= ladist; a= sqrt(a); @@ -640,7 +640,7 @@ static float Blinn_Spec(const float n[3], const float l[3], const float v[3], fl /* conversion from 'hardness' (1-255) to 'spec_power' (50 maps at 0.1) */ if (spec_power<100.0f) - spec_power= sqrt(1.0f/spec_power); + spec_power = sqrtf(1.0f / spec_power); else spec_power= 10.0f/spec_power; h[0]= v[0]+l[0]; @@ -731,7 +731,7 @@ static float WardIso_Spec(const float n[3], const float l[3], const float v[3], if (tangent) nl = sasqrt(1.0f - nl*nl); if (nl<=0.0f) nl = 0.001f; - angle = tan(saacos(nh)); + angle = tanf(saacos(nh)); alpha = MAX2(rms, 0.001f); i= nl * (1.0f/(4.0f*(float)M_PI*alpha*alpha)) * (expf( -(angle*angle)/(alpha*alpha))/(sqrtf(nv*nl))); @@ -746,7 +746,7 @@ static float Toon_Diff(const float n[3], const float l[3], const float UNUSED(v[ rslt = n[0]*l[0] + n[1]*l[1] + n[2]*l[2]; - ang = saacos( (double)(rslt) ); + ang = saacos(rslt); if ( ang < size ) rslt = 1.0f; else if ( ang >= (size + smooth) || smooth == 0.0f ) rslt = 0.0f; @@ -1257,7 +1257,7 @@ float lamp_get_visibility(LampRen *lar, const float co[3], float lv[3], float *d x = max_ff(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2])); /* 1.0f/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ - inpr= 1.0f/(sqrt(1.0f+x*x)); + inpr = 1.0f / (sqrtf(1.0f + x * x)); } else inpr= 0.0f; } @@ -1494,11 +1494,14 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int add_to_diffuse(shr->shad, shi, is, lashdw[0]*(i_noshad-i)*lacol[0], lashdw[1]*(i_noshad-i)*lacol[1], lashdw[2]*(i_noshad-i)*lacol[2]); } if (i_noshad>0.0f) { - if (passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW)) { + if (passflag & (SCE_PASS_DIFFUSE|SCE_PASS_SHADOW) || + ((passflag & SCE_PASS_COMBINED) && !(shi->combinedflag & SCE_PASS_SHADOW))) + { add_to_diffuse(shr->diff, shi, is, i_noshad*lacol[0], i_noshad*lacol[1], i_noshad*lacol[2]); } - else + else { copy_v3_v3(shr->diff, shr->shad); + } } } @@ -1648,7 +1651,8 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr) else { /* shadowonly_flag == MA_SO_SHADED */ /* Use shaded value */ accum = 1.0f - shaded; - }} + } + } shr->alpha= (shi->alpha)*(accum); if (shr->alpha<0.0f) shr->alpha=0.0f; @@ -1714,7 +1718,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) */ const int color_passes = SCE_PASS_COMBINED | SCE_PASS_RGBA | SCE_PASS_DIFFUSE | SCE_PASS_SPEC | - SCE_PASS_REFLECT | SCE_PASS_NORMAL | SCE_PASS_REFRACT | SCE_PASS_EMIT; + SCE_PASS_REFLECT | SCE_PASS_NORMAL | SCE_PASS_REFRACT | SCE_PASS_EMIT | SCE_PASS_SHADOW; Material *ma= shi->mat; int passflag= shi->passflag; @@ -1889,7 +1893,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) } if (shi->combinedflag & SCE_PASS_SHADOW) - copy_v3_v3(shr->diffshad, shr->shad); /* note, no ';' ! */ + copy_v3_v3(shr->diffshad, shr->shad); else copy_v3_v3(shr->diffshad, shr->diff); diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index 52d3815c4ad..7e9003aaee7 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -165,7 +165,7 @@ static float f_Rd(float alpha_, float A, float ro) { float sq; - sq= sqrt(3.0f*(1.0f - alpha_)); + sq = sqrtf(3.0f * (1.0f - alpha_)); return (alpha_/2.0f)*(1.0f + expf((-4.0f/3.0f)*A*sq))*expf(-sq) - ro; } @@ -212,8 +212,8 @@ static float Rd_rsquare(ScatterSettings *ss, float rr) { float sr, sv, Rdr, Rdv; - sr= sqrt(rr + ss->zr*ss->zr); - sv= sqrt(rr + ss->zv*ss->zv); + sr = sqrtf(rr + ss->zr * ss->zr); + sv = sqrtf(rr + ss->zv * ss->zv); Rdr= ss->zr*(1.0f + ss->sigma*sr)*expf(-ss->sigma*sr)/(sr*sr*sr); Rdv= ss->zv*(1.0f + ss->sigma*sv)*expf(-ss->sigma*sv)/(sv*sv*sv); @@ -241,7 +241,7 @@ static void approximate_Rd_rgb(ScatterSettings **ss, float rr, float *rd) /* pass */ } else if (rr > RD_TABLE_RANGE) { - rr= sqrt(rr); + rr = sqrtf(rr); indexf= rr*(RD_TABLE_SIZE/RD_TABLE_RANGE_2); index= (int)indexf; idxf= (float)index; @@ -286,7 +286,7 @@ static void build_Rd_table(ScatterSettings *ss) r= i*(RD_TABLE_RANGE/RD_TABLE_SIZE); /*if (r < ss->invsigma_t_*ss->invsigma_t_) r= ss->invsigma_t_*ss->invsigma_t_;*/ - ss->tableRd[i]= Rd(ss, sqrt(r)); + ss->tableRd[i]= Rd(ss, sqrtf(r)); r= i*(RD_TABLE_RANGE_2/RD_TABLE_SIZE); /*if (r < ss->invsigma_t_) diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index 50343cfaa0b..485680da76f 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -145,7 +145,7 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint) w= spoint->co[2]*strandbuf->winmat[2][3] + strandbuf->winmat[3][3]; dx= strandbuf->winx*cross[0]*strandbuf->winmat[0][0]/w; dy= strandbuf->winy*cross[1]*strandbuf->winmat[1][1]/w; - w= sqrt(dx*dx + dy*dy); + w = sqrtf(dx * dx + dy * dy); if (w > 0.0f) { if (strandbuf->flag & R_STRAND_B_UNITS) { diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c index 71ef5b8f62f..1836b3f48a7 100644 --- a/source/blender/render/intern/source/sunsky.c +++ b/source/blender/render/intern/source/sunsky.c @@ -89,14 +89,14 @@ void ClipColor(float c[3]) * */ static float AngleBetween(float thetav, float phiv, float theta, float phi) { - float cospsi = sin(thetav) * sin(theta) * cos(phi - phiv) + cos(thetav) * cos(theta); + float cospsi = sinf(thetav) * sinf(theta) * cosf(phi - phiv) + cosf(thetav) * cosf(theta); if (cospsi > 1.0f) return 0; if (cospsi < -1.0f) return M_PI; - return acos(cospsi); + return acosf(cospsi); } /** @@ -112,7 +112,7 @@ static void DirectionToThetaPhi(float *toSun, float *theta, float *phi) if (fabsf(*theta) < 1e-5f) *phi = 0; else - *phi = atan2(toSun[1], toSun[0]); + *phi = atan2f(toSun[1], toSun[0]); } /** diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 28849ed7686..87e546ef24e 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -2951,7 +2951,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * dvec2[1]= 0.0f; } else { - speedsq= 1.0f - minspeed/sqrt(speedsq); + speedsq = 1.0f - minspeed / sqrtf(speedsq); dvec2[0]= speedsq*dvec1[0]; dvec2[1]= speedsq*dvec1[1]; } @@ -3027,7 +3027,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * if (maxspeed) { float speedsq= dvz[0]*dvz[0] + dvz[1]*dvz[1]; if (speedsq > maxspeedsq) { - speedsq= (float)maxspeed/sqrt(speedsq); + speedsq = (float)maxspeed / sqrtf(speedsq); dvz[0]*= speedsq; dvz[1]*= speedsq; } @@ -3386,7 +3386,7 @@ static int zbuffer_abuf(Render *re, RenderPart *pa, APixstr *APixbuf, ListBase * projectverto(vec, obwinmat, hoco); fval= mul*(1.0f+hoco[2]/hoco[3]); - polygon_offset= (int) fabs(zval - fval ); + polygon_offset= (int)fabsf(zval - fval); } else polygon_offset= 0; diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 748303f9082..1abe000a86c 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -589,8 +589,12 @@ static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km) /* add item */ if (kmdi->add_item) { + /* Do not re-add an already existing keymap item! See T42088. */ + kmi_add = wm_keymap_find_item_equals(km, kmdi->add_item); + if (!kmi_add) + kmi_add = wm_keymap_find_item_equals_result(km, kmdi->add_item); /* only if nothing to remove or item to remove found */ - if (!kmdi->remove_item || kmi_remove) { + if (!kmi_add && (!kmdi->remove_item || kmi_remove)) { kmi_add = wm_keymap_item_copy(kmdi->add_item); kmi_add->flag |= KMI_USER_MODIFIED; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index bc79879f1f4..b9a79a85455 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1893,7 +1893,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar col = uiLayoutColumn(split, false); uiItemL(col, IFACE_("Links"), ICON_NONE); uiItemStringO(col, IFACE_("Support an Open Animation Movie"), ICON_URL, "WM_OT_url_open", "url", - "http://cloud.blender.org/gooseberry"); + "https://cloud.blender.org/join"); uiItemStringO(col, IFACE_("Donations"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/foundation/donation-payment/"); uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url", @@ -2208,7 +2208,7 @@ static void WM_OT_read_homefile(wmOperatorType *ot) "Load user interface setup from the .blend file"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - /* ommit poll to run in background mode */ + /* omit poll to run in background mode */ } static void WM_OT_read_factory_settings(wmOperatorType *ot) @@ -2219,7 +2219,7 @@ static void WM_OT_read_factory_settings(wmOperatorType *ot) ot->invoke = WM_operator_confirm; ot->exec = wm_homefile_read_exec; - /* ommit poll to run in background mode */ + /* omit poll to run in background mode */ } /* *************** open file **************** */ @@ -2372,7 +2372,7 @@ static void WM_OT_open_mainfile(wmOperatorType *ot) ot->exec = wm_open_mainfile_exec; ot->check = wm_open_mainfile_check; ot->ui = wm_open_mainfile_ui; - /* ommit window poll so this can work in background mode */ + /* omit window poll so this can work in background mode */ WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_OPENFILE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); @@ -2860,7 +2860,7 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot) ot->invoke = wm_save_as_mainfile_invoke; ot->exec = wm_save_as_mainfile_exec; ot->check = blend_save_check; - /* ommit window poll so this can work in background mode */ + /* omit window poll so this can work in background mode */ WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); @@ -2936,7 +2936,7 @@ static void WM_OT_save_mainfile(wmOperatorType *ot) ot->invoke = wm_save_mainfile_invoke; ot->exec = wm_save_as_mainfile_exec; ot->check = blend_save_check; - /* ommit window poll so this can work in background mode */ + /* omit window poll so this can work in background mode */ WM_operator_properties_filesel(ot, FOLDERFILE | BLENDERFILE, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); @@ -3749,8 +3749,8 @@ static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *e d[0] = (1 - rc->initial_value) * WM_RADIAL_CONTROL_DISPLAY_WIDTH + WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE; break; case PROP_ANGLE: - d[0] = WM_RADIAL_CONTROL_DISPLAY_SIZE * cos(rc->initial_value); - d[1] = WM_RADIAL_CONTROL_DISPLAY_SIZE * sin(rc->initial_value); + d[0] = WM_RADIAL_CONTROL_DISPLAY_SIZE * cosf(rc->initial_value); + d[1] = WM_RADIAL_CONTROL_DISPLAY_SIZE * sinf(rc->initial_value); break; default: return; @@ -4251,7 +4251,7 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even if (snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f; break; case PROP_ANGLE: - new_value = atan2(delta[1], delta[0]) + M_PI + angle_precision; + new_value = atan2f(delta[1], delta[0]) + M_PI + angle_precision; new_value = fmod(new_value, 2.0f * (float)M_PI); if (new_value < 0.0f) new_value += 2.0f * (float)M_PI; @@ -4354,6 +4354,7 @@ static void redraw_timer_window_swap(bContext *C) { wmWindow *win = CTX_wm_window(C); ScrArea *sa; + CTX_wm_menu_set(C, NULL); for (sa = CTX_wm_screen(C)->areabase.first; sa; sa = sa->next) ED_area_tag_redraw(sa); @@ -4392,7 +4393,8 @@ static int redraw_timer_exec(bContext *C, wmOperator *op) } else if (type == 1) { wmWindow *win = CTX_wm_window(C); - + CTX_wm_menu_set(C, NULL); + ED_region_tag_redraw(ar); wm_draw_update(C); @@ -4405,6 +4407,8 @@ static int redraw_timer_exec(bContext *C, wmOperator *op) ScrArea *sa_back = CTX_wm_area(C); ARegion *ar_back = CTX_wm_region(C); + CTX_wm_menu_set(C, NULL); + for (sa = CTX_wm_screen(C)->areabase.first; sa; sa = sa->next) { ARegion *ar_iter; CTX_wm_area_set(C, sa); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 024135e73e9..76add2f9aac 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -98,6 +98,8 @@ typedef struct PlayState { bool go; /* waiting for images to load */ bool loading; + /* x/y image flip */ + bool draw_flip[2]; int fstep; @@ -168,6 +170,15 @@ static void playanim_window_get_size(int *width_r, int *height_r) GHOST_DisposeRectangle(bounds); } +static void playanim_gl_matrix(void) +{ + /* unified matrix, note it affects offset for drawing */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); + glMatrixMode(GL_MODELVIEW); +} + /* implementation */ static void playanim_event_qual_update(void) { @@ -245,7 +256,8 @@ static int pupdate_time(void) static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep) { - float offsx, offsy; + float offs_x, offs_y; + float span_x, span_y; if (ibuf == NULL) { printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>"); @@ -260,13 +272,17 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); + /* size within window */ + span_x = (ps->zoom * ibuf->x) / (float)ps->win_x; + span_y = (ps->zoom * ibuf->y) / (float)ps->win_y; + /* offset within window */ - offsx = 0.5f * (((float)ps->win_x - ps->zoom * ibuf->x) / (float)ps->win_x); - offsy = 0.5f * (((float)ps->win_y - ps->zoom * ibuf->y) / (float)ps->win_y); + offs_x = 0.5f * (1.0f - span_x); + offs_y = 0.5f * (1.0f - span_y); - CLAMP(offsx, 0.0f, 1.0f); - CLAMP(offsy, 0.0f, 1.0f); - glRasterPos2f(offsx, offsy); + CLAMP(offs_x, 0.0f, 1.0f); + CLAMP(offs_y, 0.0f, 1.0f); + glRasterPos2f(offs_x, offs_y); glClearColor(0.1, 0.1, 0.1, 0.0); glClear(GL_COLOR_BUFFER_BIT); @@ -276,9 +292,15 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - fdrawcheckerboard(offsx, offsy, offsx + (ps->zoom * ibuf->x) / (float)ps->win_x, offsy + (ps->zoom * ibuf->y) / (float)ps->win_y); + fdrawcheckerboard(offs_x, offs_y, offs_x + span_x, offs_y + span_y); } - + + glRasterPos2f(offs_x + (ps->draw_flip[0] ? span_x : 0.0f), + offs_y + (ps->draw_flip[1] ? span_y : 0.0f)); + + glPixelZoom(ps->zoom * ps->draw_flip[0] ? -1.0f : 1.0f, + ps->zoom * ps->draw_flip[1] ? -1.0f : 1.0f); + glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); glDisable(GL_BLEND); @@ -518,6 +540,14 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) case GHOST_kKeyP: if (val) ps->pingpong = !ps->pingpong; break; + case GHOST_kKeyF: + { + if (val) { + int axis = (g_WS.qual & WS_QUAL_SHIFT) ? 1 : 0; + ps->draw_flip[axis] = !ps->draw_flip[axis]; + } + break; + } case GHOST_kKey1: case GHOST_kKeyNumpad1: if (val) swaptime = ps->fstep / 60.0; @@ -780,13 +810,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) glViewport(0, 0, ps->win_x, ps->win_y); glScissor(0, 0, ps->win_x, ps->win_y); - /* unified matrix, note it affects offset for drawing */ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); - glMatrixMode(GL_MODELVIEW); + playanim_gl_matrix(); - glPixelZoom(ps->zoom, ps->zoom); ptottime = 0.0; playanim_toscreen(ps, ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep); @@ -891,6 +916,8 @@ static char *wm_main_playanim_intern(int argc, const char **argv) ps.dropped_file[0] = 0; ps.zoom = 1.0f; /* resetmap = false */ + ps.draw_flip[0] = false; + ps.draw_flip[1] = false; ps.fstep = 1; @@ -1008,11 +1035,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv) playanim_window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y); - /* unified matrix, note it affects offset for drawing */ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); - glMatrixMode(GL_MODELVIEW); + playanim_gl_matrix(); } GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &maxwinx, &maxwiny); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 20e5b1d8353..46a20d3bf88 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -339,6 +339,19 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) } } +float wm_window_pixelsize(wmWindow *win) +{ + float pixelsize = GHOST_GetNativePixelSize(win->ghostwin); + + switch (U.virtual_pixel) { + default: + case VIRTUAL_PIXEL_NATIVE: + return pixelsize; + case VIRTUAL_PIXEL_DOUBLE: + return 2.0f * pixelsize; + } +} + /* belongs to below */ static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wmWindow *win) { @@ -400,7 +413,7 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wm /* displays with larger native pixels, like Macbook. Used to scale dpi with */ /* needed here, because it's used before it reads userdef */ - U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin); + U.pixelsize = wm_window_pixelsize(win); BKE_userdef_state(); wm_window_swap_buffers(win); @@ -688,7 +701,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win) GHOST_ActivateWindowDrawingContext(win->ghostwin); /* this can change per window */ - U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin); + U.pixelsize = wm_window_pixelsize(win); BKE_userdef_state(); } } @@ -1048,7 +1061,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr case GHOST_kEventNativeResolutionChange: // printf("change, pixel size %f\n", GHOST_GetNativePixelSize(win->ghostwin)); - U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin); + U.pixelsize = wm_window_pixelsize(win); BKE_userdef_state(); WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index a71e0fd9fc9..9c9c79d2f54 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -61,6 +61,8 @@ void wm_window_swap_buffers (wmWindow *win); void wm_window_set_swap_interval(wmWindow *win, int interval); bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut); +float wm_window_pixelsize(wmWindow *win); + void wm_get_cursor_position (wmWindow *win, int *x, int *y); wmWindow *wm_window_copy (bContext *C, wmWindow *winorig); diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 97e7d99c802..649ea1f59c7 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -142,6 +142,7 @@ struct wmWindowManager; #include "../../intern/dualcon/dualcon.h" #include "../../intern/elbeem/extern/elbeem.h" #include "../blender/blenkernel/BKE_modifier.h" +#include "../blender/blenkernel/BKE_paint.h" #include "../blender/collada/collada.h" #include "../blender/compositor/COM_compositor.h" #include "../blender/editors/include/ED_armature.h" @@ -168,6 +169,7 @@ struct wmWindowManager; #include "../blender/editors/include/UI_interface_icons.h" #include "../blender/editors/include/UI_resources.h" #include "../blender/editors/include/UI_view2d.h" +#include "../blender/freestyle/FRS_freestyle.h" #include "../blender/python/BPY_extern.h" #include "../blender/render/extern/include/RE_engine.h" #include "../blender/render/extern/include/RE_pipeline.h" @@ -229,6 +231,7 @@ void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, flo /* Freestyle */ bool ED_texture_context_check_linestyle(const struct bContext *C) RET_ZERO +void FRS_free_view_map_cache(void) RET_NONE /* texture.c */ int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool, bool scene_color_manage) RET_ZERO @@ -245,6 +248,9 @@ struct Render *RE_GetRender(const char *name) RET_NULL float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) RET_ZERO /* blenkernel */ +bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil) RET_ZERO + +/* render */ void RE_FreeRenderResult(struct RenderResult *res) RET_NONE void RE_FreeAllRenderResults(void) RET_NONE struct RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty) RET_NULL diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 56b017c14dc..20c2448eed3 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -52,6 +52,11 @@ if(WITH_LIBMV) add_definitions(-DWITH_LIBMV) endif() +if(WITH_CYCLES AND WITH_CYCLES_LOGGING) + blender_include_dirs(../../intern/cycles/blender) + add_definitions(-DWITH_CYCLES_LOGGING) +endif() + if(WITH_CODEC_FFMPEG) add_definitions(-DWITH_FFMPEG) endif() diff --git a/source/creator/creator.c b/source/creator/creator.c index 768a323a169..12ae5c502e4 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -149,6 +149,10 @@ # include "libmv-capi.h" #endif +#ifdef WITH_CYCLES_LOGGING +# include "CCL_api.h" +#endif + /* from buildinfo.c */ #ifdef BUILD_DATE extern char build_date[]; @@ -309,6 +313,9 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data) #ifdef WITH_LIBMV BLI_argsPrintArgDoc(ba, "--debug-libmv"); #endif +#ifdef WITH_CYCLES_LOGGING + BLI_argsPrintArgDoc(ba, "--debug-cycles"); +#endif BLI_argsPrintArgDoc(ba, "--debug-memory"); BLI_argsPrintArgDoc(ba, "--debug-jobs"); BLI_argsPrintArgDoc(ba, "--debug-python"); @@ -450,6 +457,15 @@ static int debug_mode_libmv(int UNUSED(argc), const char **UNUSED(argv), void *U } #endif +#ifdef WITH_CYCLES_LOGGING +static int debug_mode_cycles(int UNUSED(argc), const char **UNUSED(argv), + void *UNUSED(data)) +{ + CCL_start_debug_logging(); + return 0; +} +#endif + static int debug_mode_memory(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data)) { MEM_set_memory_debug(); @@ -887,6 +903,8 @@ static int set_verbosity(int argc, const char **argv, void *UNUSED(data)) #ifdef WITH_LIBMV libmv_setLoggingVerbosity(level); +#elif defined(WITH_CYCLES_LOGGING) + CCL_logging_verbosity_set(level); #else (void)level; #endif @@ -1419,6 +1437,9 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) #ifdef WITH_LIBMV BLI_argsAdd(ba, 1, NULL, "--debug-libmv", "\n\tEnable debug messages from libmv library", debug_mode_libmv, NULL); #endif +#ifdef WITH_CYCLES_LOGGING + BLI_argsAdd(ba, 1, NULL, "--debug-cycles", "\n\tEnable debug messages from Cycles", debug_mode_cycles, NULL); +#endif BLI_argsAdd(ba, 1, NULL, "--debug-memory", "\n\tEnable fully guarded memory allocation and debugging", debug_mode_memory, NULL); BLI_argsAdd(ba, 1, NULL, "--debug-value", "<value>\n\tSet debug value of <value> on startup\n", set_debug_value, NULL); @@ -1508,9 +1529,9 @@ int main( #endif #ifdef WIN32 - /* FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. */ + /* FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. */ # if defined(_MSC_VER) && _MSC_VER >= 1800 && defined(_M_X64) - _set_FMA3_enable(0); + _set_FMA3_enable(0); # endif /* Win32 Unicode Args */ @@ -1583,6 +1604,8 @@ int main( #ifdef WITH_LIBMV libmv_initLogging(argv[0]); +#elif defined(WITH_CYCLES_LOGGING) + CCL_init_logging(argv[0]); #endif setCallbacks(); diff --git a/source/creator/creator_launch_win.c b/source/creator/creator_launch_win.c index a7e04b2dafc..03f28cd4034 100644 --- a/source/creator/creator_launch_win.c +++ b/source/creator/creator_launch_win.c @@ -58,9 +58,14 @@ int main(int argc, const char **UNUSED(argv_c)) wcsncpy(command, BLENDER_BINARY, len - 1); len -= wcslen(BLENDER_BINARY); for (i = 1; i < argc; ++i) { + size_t argument_len = wcslen(argv_16[i]); wcsncat(command, L" \"", len - 2); wcsncat(command, argv_16[i], len - 3); - len -= wcslen(argv_16[i]) + 1; + len -= argument_len + 1; + if (argv_16[i][argument_len - 1] == '\\') { + wcsncat(command, L"\\", len - 1); + len--; + } wcsncat(command, L"\"", len - 1); } diff --git a/source/creator/osx_locals.map b/source/creator/osx_locals.map index a1d7e7fed57..8405be74ab7 100644 --- a/source/creator/osx_locals.map +++ b/source/creator/osx_locals.map @@ -2,4 +2,7 @@ ## (aka visibility=hidden) and will not be global in the output file *boost* *__ZNSt6vector* +*llvm* +*LLVM* +*OSL* diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index a7c98eb9dc1..2a7e631637e 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -67,6 +67,7 @@ extern "C" { + #include "DNA_object_types.h" #include "DNA_view3d_types.h" #include "DNA_screen_types.h" #include "DNA_userdef_types.h" @@ -282,6 +283,10 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c bool mouse_state = startscene->gm.flag & GAME_SHOW_MOUSE; bool restrictAnimFPS = startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES; + short drawtype = v3d->drawtype; + + /* we do not support material mode in game engine, force change to texture mode */ + if (drawtype == OB_MATERIAL) drawtype = OB_TEXTURE; if (animation_record) usefixed= false; /* override since you don't want to run full-speed for sim recording */ // create the canvas and rasterizer @@ -371,7 +376,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c camzoom = 2.0; } - rasterizer->SetDrawingMode(v3d->drawtype); + rasterizer->SetDrawingMode(drawtype); ketsjiengine->SetCameraZoom(camzoom); // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index 8d73e591113..e01130a8970 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -101,7 +101,7 @@ static void game_copy_pose(bPose **dst, bPose *src, int copy_constraint) out->chanhash = NULL; out->agroups.first= out->agroups.last= NULL; out->ikdata = NULL; - out->ikparam = MEM_dupallocN(src->ikparam); + out->ikparam = MEM_dupallocN(src->ikparam); out->flag |= POSE_GAME_ENGINE; BLI_duplicatelist(&out->chanbase, &src->chanbase); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 14772cda113..f76580cd44d 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1734,18 +1734,17 @@ void KX_KetsjiEngine::AddScheduledScenes() bool KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene) { - // Don't allow replacement if the new scene doesn't exists. - // Allows smarter game design (used to have no check here). - // Note that it creates a small backward compatbility issue - // for a game that did a replace followed by a lib load with the - // new scene in the lib => it won't work anymore, the lib - // must be loaded before doing the replace. - if (m_sceneconverter->GetBlenderSceneForName(newscene) != NULL) - { - m_replace_scenes.push_back(std::make_pair(oldscene,newscene)); - return true; - } - return false; + // Don't allow replacement if the new scene doesn't exists. + // Allows smarter game design (used to have no check here). + // Note that it creates a small backward compatbility issue + // for a game that did a replace followed by a lib load with the + // new scene in the lib => it won't work anymore, the lib + // must be loaded before doing the replace. + if (m_sceneconverter->GetBlenderSceneForName(newscene) != NULL) { + m_replace_scenes.push_back(std::make_pair(oldscene,newscene)); + return true; + } + return false; } // replace scene is not the same as removing and adding because the @@ -1767,21 +1766,20 @@ void KX_KetsjiEngine::ReplaceScheduledScenes() int i=0; /* Scenes are not supposed to be included twice... I think */ KX_SceneList::iterator sceneit; - for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++) - { - KX_Scene* scene = *sceneit; - if (scene->GetName() == oldscenename) - { - // avoid crash if the new scene doesn't exist, just do nothing - Scene *blScene = m_sceneconverter->GetBlenderSceneForName(newscenename); - if (blScene) { - m_sceneconverter->RemoveScene(scene); - KX_Scene* tmpscene = CreateScene(blScene); - m_scenes[i]=tmpscene; - PostProcessScene(tmpscene); - } else { - printf("warning: scene %s could not be found, not replaced!\n",newscenename.ReadPtr()); - } + for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++) { + KX_Scene* scene = *sceneit; + if (scene->GetName() == oldscenename) { + // avoid crash if the new scene doesn't exist, just do nothing + Scene *blScene = m_sceneconverter->GetBlenderSceneForName(newscenename); + if (blScene) { + m_sceneconverter->RemoveScene(scene); + KX_Scene* tmpscene = CreateScene(blScene); + m_scenes[i]=tmpscene; + PostProcessScene(tmpscene); + } + else { + printf("warning: scene %s could not be found, not replaced!\n",newscenename.ReadPtr()); + } } i++; } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 625bbee2c8e..d0eab9de1c1 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1577,7 +1577,7 @@ void KX_Scene::AddAnimatedObject(CValue* gameobj) static void update_anim_thread_func(TaskPool *pool, void *taskdata, int UNUSED(threadid)) { - KX_GameObject *gameobj, *child; + KX_GameObject *gameobj, *child, *parent; CListValue *children; bool needs_update; double curtime = *(double*)BLI_task_pool_userdata(pool); @@ -1621,8 +1621,11 @@ static void update_anim_thread_func(TaskPool *pool, void *taskdata, int UNUSED(t if (needs_update) { gameobj->UpdateActionManager(curtime); children = gameobj->GetChildren(); + parent = gameobj->GetParent(); - if (!gameobj->GetParent() && gameobj->GetDeformer()) + // Only do deformers here if they are not parented to an armature, otherwise the armature will + // handle updating its children + if (gameobj->GetDeformer() && (!parent || (parent && parent->GetGameObjectType() != SCA_IObject::OBJ_ARMATURE))) gameobj->GetDeformer()->Update(); for (int j=0; j<children->GetCount(); ++j) { diff --git a/tests/gtests/blenlib/BLI_polyfill2d_test.cc b/tests/gtests/blenlib/BLI_polyfill2d_test.cc new file mode 100644 index 00000000000..785274757aa --- /dev/null +++ b/tests/gtests/blenlib/BLI_polyfill2d_test.cc @@ -0,0 +1,492 @@ +/* Apache License, Version 2.0 */ + +#include "testing/testing.h" + +/* Use to write out OBJ files, handy for checking output */ +// #define USE_OBJ_PREVIEW + +/* test every possible offset and reverse */ +#define USE_COMBINATIONS_ALL + +extern "C" { +#include "BLI_array.h" +#include "BLI_polyfill2d.h" +#include "BLI_math.h" +#include "BLI_edgehash.h" +#include "MEM_guardedalloc.h" + +#ifdef USE_OBJ_PREVIEW +# include "BLI_string.h" +#endif +} + +static void polyfill_to_obj( + const char *id, + const float poly[][2], const unsigned int poly_tot, + const unsigned int tris[][3], const unsigned int tris_tot); + +/* -------------------------------------------------------------------- */ +/* test utility functions */ + +#define TRI_ERROR_VALUE (unsigned int)-1 + +static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tris_tot) +{ + unsigned int i; + for (i = 0; i < tris_tot; i++) { + unsigned int j; + for (j = 0; j < 3; j++) { + tris[i][j] = TRI_ERROR_VALUE; + } + } +} + +/** + * Basic check for face index values: + * + * - no duplicates. + * - all tris set. + * - all verts used at least once. + */ +static void test_polyfill_simple( + const float poly[][2], const unsigned int poly_tot, + const unsigned int tris[][3], const unsigned int tris_tot) +{ + unsigned int i; + int *tot_used = (int *)MEM_callocN(poly_tot * sizeof(int), __func__); + for (i = 0; i < tris_tot; i++) { + unsigned int j; + for (j = 0; j < 3; j++) { + EXPECT_NE(TRI_ERROR_VALUE, tris[i][j]); + tot_used[tris[i][j]] += 1; + } + EXPECT_NE(tris[i][0], tris[i][1]); + EXPECT_NE(tris[i][1], tris[i][2]); + EXPECT_NE(tris[i][2], tris[i][0]); + } + for (i = 0; i < poly_tot; i++) { + EXPECT_NE(0, tot_used[i]); + } + MEM_freeN(tot_used); +} + +static void test_polyfill_topology( + const float poly[][2], const unsigned int poly_tot, + const unsigned int tris[][3], const unsigned int tris_tot) +{ + EdgeHash *edgehash = BLI_edgehash_new(__func__); + EdgeHashIterator *ehi; + unsigned int i; + for (i = 0; i < tris_tot; i++) { + unsigned int j; + for (j = 0; j < 3; j++) { + const unsigned int v1 = tris[i][j]; + const unsigned int v2 = tris[i][(j + 1) % 3]; + void **p = BLI_edgehash_lookup_p(edgehash, v1, v2); + if (p) { + *p = (void *)((intptr_t)*p + (intptr_t)1); + } + else { + BLI_edgehash_insert(edgehash, v1, v2, (void *)(intptr_t)1); + } + } + } + EXPECT_EQ(poly_tot + (poly_tot - 3), BLI_edgehash_size(edgehash)); + + for (i = 0; i < poly_tot; i++) { + const unsigned int v1 = i; + const unsigned int v2 = (i + 1) % poly_tot; + void **p = BLI_edgehash_lookup_p(edgehash, v1, v2); + EXPECT_EQ(1, (void *)p != NULL); + EXPECT_EQ(1, (intptr_t)*p); + } + + for (ehi = BLI_edgehashIterator_new(edgehash), i = 0; + BLI_edgehashIterator_isDone(ehi) == false; + BLI_edgehashIterator_step(ehi), i++) + { + void **p = BLI_edgehashIterator_getValue_p(ehi); + EXPECT_EQ(true, ELEM((intptr_t)*p, 1, 2)); + } + + BLI_edgehash_free(edgehash, NULL); +} + +/** + * Check all faces are flipped the same way + */ +static void test_polyfill_winding( + const float poly[][2], const unsigned int poly_tot, + const unsigned int tris[][3], const unsigned int tris_tot) +{ + unsigned int i; + unsigned int count[2] = {0, 0}; + for (i = 0; i < tris_tot; i++) { + float winding_test = cross_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]); + if (fabsf(winding_test) > FLT_EPSILON) { + count[winding_test < 0.0f] += 1; + } + } + EXPECT_EQ(true, ELEM(0, count[0], count[1])); +} + +/** + * Check the accumulated triangle area is close to the original area. + */ +static void test_polyfill_area( + const float poly[][2], const unsigned int poly_tot, + const unsigned int tris[][3], const unsigned int tris_tot) +{ + unsigned int i; + const float area_tot = area_poly_v2(poly, poly_tot); + float area_tot_tris = 0.0f; + const float eps_abs = 0.00001f; + const float eps = area_tot > 1.0f ? (area_tot * eps_abs) : eps_abs; + for (i = 0; i < tris_tot; i++) { + area_tot_tris += area_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]); + } + EXPECT_NEAR(area_tot, area_tot_tris, eps); +} + + +/* -------------------------------------------------------------------- */ +/* Macro and helpers to manage checking */ +/** + * Main template for polyfill testing. + */ +static void test_polyfill_template_check( + const char *id, bool is_degenerate, + const float poly[][2], const unsigned int poly_tot, + const unsigned int tris[][3], const unsigned int tris_tot) +{ + test_polyfill_simple(poly, poly_tot, tris, tris_tot); + test_polyfill_topology(poly, poly_tot, tris, tris_tot); + if (!is_degenerate) { + test_polyfill_winding(poly, poly_tot, tris, tris_tot); + + test_polyfill_area(poly, poly_tot, tris, tris_tot); + } + polyfill_to_obj(id, poly, poly_tot, tris, tris_tot); +} + +static void test_polyfill_template( + const char *id, bool is_degenerate, + const float poly[][2], const unsigned int poly_tot, + unsigned int tris[][3], const unsigned int tris_tot) +{ + test_valid_polyfill_prepare(tris, tris_tot); + BLI_polyfill_calc(poly, poly_tot, 0, tris); + + /* check all went well */ + test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot); +} + +#ifdef USE_COMBINATIONS_ALL +static void test_polyfill_template_main( + const char *id, bool is_degenerate, + const float poly[][2], const unsigned int poly_tot, + unsigned int tris[][3], const unsigned int tris_tot) +{ + /* overkill? - try at _every_ offset & reverse */ + unsigned int poly_reverse; + float (*poly_copy)[2] = (float (*)[2])MEM_mallocN(sizeof(float[2]) * poly_tot, id); + float tmp[2]; + + memcpy(poly_copy, poly, sizeof(float[2]) * poly_tot); + + for (poly_reverse = 0; poly_reverse < 2; poly_reverse++) { + unsigned int poly_cycle; + + if (poly_reverse) { + BLI_array_reverse(poly_copy, poly_tot); + } + + for (poly_cycle = 0; poly_cycle < poly_tot; poly_cycle++) { + // printf("polytest %s ofs=%d, reverse=%d\n", id, poly_cycle, poly_reverse); + test_polyfill_template(id, is_degenerate, poly, poly_tot, tris, tris_tot); + + /* cycle */ + copy_v2_v2(tmp, poly_copy[0]); + memmove(&poly_copy[0], &poly_copy[1], (poly_tot - 1) * sizeof(float[2])); + copy_v2_v2(poly_copy[poly_tot - 1], tmp); + } + } + + MEM_freeN(poly_copy); +} +#else /* USE_COMBINATIONS_ALL */ +static void test_polyfill_template_main( + const char *id, bool is_degenerate, + const float poly[][2], const unsigned int poly_tot, + unsigned int tris[][3], const unsigned int tris_tot) +{ + test_polyfill_template(id, is_degenerate, poly, poly_tot, tris, tris_tot); +} +#endif /* USE_COMBINATIONS_ALL */ + +#define TEST_POLYFILL_TEMPLATE_STATIC(poly, is_degenerate) \ +{ \ + unsigned int tris[POLY_TRI_COUNT(ARRAY_SIZE(poly))][3]; \ + const unsigned int poly_tot = ARRAY_SIZE(poly); \ + const unsigned int tris_tot = ARRAY_SIZE(tris); \ + const char *id = typeid(*this).name(); \ + \ + test_polyfill_template_main(id, is_degenerate, poly, poly_tot, tris, tris_tot); \ +} (void)0 + +/* -------------------------------------------------------------------- */ +/* visualisation functions (not needed for testing) */ + +#ifdef USE_OBJ_PREVIEW +static void polyfill_to_obj( + const char *id, + const float poly[][2], const unsigned int poly_tot, + const unsigned int tris[][3], const unsigned int tris_tot) +{ + char path[1024]; + FILE *f; + unsigned int i; + + BLI_snprintf(path, sizeof(path), "%s.obj", id); + + f = fopen(path, "w"); + if (!f) { + return; + } + + for (i = 0; i < poly_tot; i++) { + fprintf(f, "v %f %f 0.0\n", UNPACK2(poly[i])); + } + + for (i = 0; i < tris_tot; i++) { + fprintf(f, "f %u %u %u\n", UNPACK3_EX(1 +, tris[i], )); + } + + fclose(f); +} +#else +static void polyfill_to_obj( + const char *id, + const float poly[][2], const unsigned int poly_tot, + const unsigned int tris[][3], const unsigned int tris_tot) +{ + (void)id; + (void)poly, (void)poly_tot; + (void)tris, (void)tris_tot; +} +#endif /* USE_OBJ_PREVIEW */ + + +/* -------------------------------------------------------------------- */ +/* tests */ + +#define POLY_TRI_COUNT(len) ((len) - 2) + + +/* A counterclockwise triangle */ +TEST(polyfill2d, TriangleCCW) +{ + const float poly[][2] = {{0, 0}, {0, 1}, {1, 0}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* A counterclockwise square */ +TEST(polyfill2d, SquareCCW) +{ + const float poly[][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* A clockwise square */ +TEST(polyfill2d, SquareCW) +{ + const float poly[][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Starfleet insigna */ +TEST(polyfill2d, Starfleet) +{ + const float poly[][2] = {{0, 0}, {0.6f, 0.4f}, {1, 0}, {0.5f, 1}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Starfleet insigna with repeated point */ +TEST(polyfill2d, StarfleetDegenerate) +{ + const float poly[][2] = {{0, 0}, {0.6f, 0.4f}, {0.6f, 0.4f}, {1, 0}, {0.5f, 1}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Three collinear points */ +TEST(polyfill2d, 3Colinear) +{ + const float poly[][2] = {{0, 0}, {1, 0}, {2, 0}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Four collinear points */ +TEST(polyfill2d, 4Colinear) +{ + const float poly[][2] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Non-consecutive collinear points */ +TEST(polyfill2d, UnorderedColinear) +{ + const float poly[][2] = {{0, 0}, {1, 1}, {2, 0}, {3, 1}, {4, 0}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Plus shape */ +TEST(polyfill2d, PlusShape) +{ + const float poly[][2] = { + {1, 0}, {2, 0}, {2, 1}, {3, 1}, {3, 2}, {2, 2}, {2, 3}, {1, 3}, {1, 2}, {0, 2}, {0, 1}, {1, 1}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Star shape */ +TEST(polyfill2d, StarShape) +{ + const float poly[][2] = { + {4, 0}, {5, 3}, {8, 4}, {5, 5}, {4, 8}, {3, 5}, {0, 4}, {3, 3}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* U shape */ +TEST(polyfill2d, UShape) +{ + const float poly[][2] = { + {1, 0}, {2, 0}, {3, 1}, {3, 3}, {2, 3}, {2, 1}, {1, 1}, {1, 3}, {0, 3}, {0, 1}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Spiral */ +TEST(polyfill2d, Spiral) +{ + const float poly[][2] = { + {1, 0}, {4, 0}, {5, 1}, {5, 4}, {4, 5}, {1, 5}, {0, 4}, {0, 3}, + {1, 2}, {2, 2}, {3, 3}, {1, 3}, {1, 4}, {4, 4}, {4, 1}, {0, 1}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Test case from http:# www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml */ +TEST(polyfill2d, TestFlipCode) +{ + const float poly[][2] = { + {0, 6}, {0, 0}, {3, 0}, {4, 1}, {6, 1}, {8, 0}, {12, 0}, {13, 2}, + {8, 2}, {8, 4}, {11, 4}, {11, 6}, {6, 6}, {4, 3}, {2, 6}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Self-intersection */ +TEST(polyfill2d, SelfIntersect) +{ + const float poly[][2] = {{0, 0}, {1, 1}, {2, -1}, {3, 1}, {4, 0}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, true); +} + +/* Self-touching */ +TEST(polyfill2d, SelfTouch) +{ + const float poly[][2] = { + {0, 0}, {4, 0}, {4, 4}, {2, 4}, {2, 3}, {3, 3}, {3, 1}, {1, 1}, {1, 3}, {2, 3}, {2, 4}, {0, 4}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Self-overlapping */ +TEST(polyfill2d, SelfOverlap) +{ + const float poly[][2] = { + {0, 0}, {4, 0}, {4, 4}, {1, 4}, {1, 3}, {3, 3}, {3, 1}, {1, 1}, {1, 3}, {3, 3}, {3, 4}, {0, 4}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, true); +} + +/* Test case from http:# www.davdata.nl/math/polygons.html */ +TEST(polyfill2d, TestDavData) +{ + const float poly[][2] = { + {190, 480}, {140, 180}, {310, 100}, {330, 390}, {290, 390}, {280, 260}, {220, 260}, {220, 430}, {370, 430}, + {350, 30}, {50, 30}, {160, 560}, {730, 510}, {710, 20}, {410, 30}, {470, 440}, {640, 410}, {630, 140}, + {590, 140}, {580, 360}, {510, 370}, {510, 60}, {650, 70}, {660, 450}, {190, 480}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Issue 815, http:# code.google.com/p/libgdx/issues/detail?id=815 */ +TEST(polyfill2d, Issue815) +{ + const float poly[][2] = { + {-2.0f, 0.0f}, {-2.0f, 0.5f}, {0.0f, 1.0f}, {0.5f, 2.875f}, + {1.0f, 0.5f}, {1.5f, 1.0f}, {2.0f, 1.0f}, {2.0f, 0.0f}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Issue 207, comment #1, http:# code.google.com/p/libgdx/issues/detail?id=207#c1 */ +TEST(polyfill2d, Issue207_1) +{ + const float poly[][2] = { + {72.42465f, 197.07095f}, {78.485535f, 189.92776f}, {86.12059f, 180.92929f}, {99.68253f, 164.94557f}, + {105.24325f, 165.79604f}, {107.21862f, 166.09814f}, {112.41958f, 162.78253f}, {113.73238f, 161.94562f}, + {123.29477f, 167.93805f}, {126.70667f, 170.07617f}, {73.22717f, 199.51062f}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, true); +} + +/* Issue 207, comment #11, http:# code.google.com/p/libgdx/issues/detail?id=207#c11 */ +/* Also on issue 1081, http:# code.google.com/p/libgdx/issues/detail?id=1081 */ +TEST(polyfill2d, Issue207_11) +{ + const float poly[][2] = { + {2400.0f, 480.0f}, {2400.0f, 176.0f}, {1920.0f, 480.0f}, {1920.0459f, 484.22314f}, + {1920.1797f, 487.91016f}, {1920.3955f, 491.0874f}, {1920.6875f, 493.78125f}, {1921.0498f, 496.01807f}, + {1921.4766f, 497.82422f}, {1921.9619f, 499.22607f}, {1922.5f, 500.25f}, {1923.085f, 500.92236f}, + {1923.7109f, 501.26953f}, {1924.3721f, 501.31787f}, {1925.0625f, 501.09375f}, {1925.7764f, 500.62354f}, + {1926.5078f, 499.9336f}, {1927.251f, 499.0503f}, {1928.0f, 498.0f}, {1928.749f, 496.80908f}, + {1929.4922f, 495.5039f}, {1930.2236f, 494.11084f}, {1930.9375f, 492.65625f}, {1931.6279f, 491.1665f}, + {1932.2891f, 489.66797f}, {1932.915f, 488.187f}, {1933.5f, 486.75f}, {1934.0381f, 485.3833f}, + {1934.5234f, 484.11328f}, {1934.9502f, 482.9663f}, {1935.3125f, 481.96875f}, {1935.6045f, 481.14697f}, + {1935.8203f, 480.52734f}, {1935.9541f, 480.13623f}, {1936.0f, 480.0f}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Issue 1407, http:# code.google.com/p/libgdx/issues/detail?id=1407 */ +TEST(polyfill2d, Issue1407) +{ + const float poly[][2] = { + {3.914329f, 1.9008259f}, {4.414321f, 1.903619f}, {4.8973203f, 1.9063174f}, {5.4979978f, 1.9096732f}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Issue 1407, http:# code.google.com/p/libgdx/issues/detail?id=1407, */ +/* with an additional point to show what is happening. */ +TEST(polyfill2d, Issue1407_pt) +{ + const float poly[][2] = { + {3.914329f, 1.9008259f}, {4.414321f, 1.903619f}, {4.8973203f, 1.9063174f}, {5.4979978f, 1.9096732f}, {4, 4}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Simplified from Blender bug T40777 */ +TEST(polyfill2d, IssueT40777_colinear) +{ + const float poly[][2] = { + {0.7, 0.37}, {0.7, 0}, {0.76, 0}, {0.76, 0.4}, {0.83, 0.4}, {0.83, 0}, {0.88, 0}, {0.88, 0.4}, + {0.94, 0.4}, {0.94, 0}, {1, 0}, {1, 0.4}, {0.03, 0.62}, {0.03, 0.89}, {0.59, 0.89}, {0.03, 1}, + {0, 1}, {0, 0}, {0.03, 0}, {0.03, 0.37}}; + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} + +/* Blender bug T41986 */ +TEST(polyfill2d, IssueT41986_axis_align) +{ + const float poly[][2] = { + {-0.25, -0.07}, {-0.25, 0.27}, {-1.19, 0.14}, {-0.06, 0.73}, {0.17, 1.25}, {-0.25, 1.07}, + {-0.38, 1.02}, {-0.25, 0.94}, {-0.40, 0.90}, {-0.41, 0.86}, {-0.34, 0.83}, {-0.25, 0.82}, + {-0.66, 0.73}, {-0.56, 1.09}, {-0.25, 1.10}, {0.00, 1.31}, {-0.03, 1.47}, {-0.25, 1.53}, + {0.12, 1.62}, {0.36, 1.07}, {0.12, 0.67}, {0.29, 0.57}, {0.44, 0.45}, {0.57, 0.29}, + {0.66, 0.12}, {0.68, 0.06}, {0.57, -0.36}, {-0.25, -0.37}, {0.49, -0.74}, {-0.59, -1.21}, + {-0.25, -0.15}, {-0.46, -0.52}, {-1.08, -0.83}, {-1.45, -0.33}, {-1.25, -0.04}}; + + TEST_POLYFILL_TEMPLATE_STATIC(poly, false); +} diff --git a/tests/gtests/blenlib/BLI_stack_test.cc b/tests/gtests/blenlib/BLI_stack_test.cc index c4884cb8940..08701356816 100644 --- a/tests/gtests/blenlib/BLI_stack_test.cc +++ b/tests/gtests/blenlib/BLI_stack_test.cc @@ -88,6 +88,29 @@ TEST(stack, String) BLI_stack_free(stack); } +TEST(stack, Peek) +{ + const int tot = SIZE; + int i; + + BLI_Stack *stack; + const short in[] = {1, 10, 100, 1000}; + + stack = BLI_stack_new(sizeof(*in), __func__); + + for (i = 0; i < tot; i++) { + BLI_stack_push(stack, &in[i % ARRAY_SIZE(in)]); + } + + for (i = tot - 1; i >= 0; i--, BLI_stack_discard(stack)) { + short *ret = (short *)BLI_stack_peek(stack); + EXPECT_EQ(*ret, in[i % ARRAY_SIZE(in)]); + } + + EXPECT_EQ(BLI_stack_is_empty(stack), true); +} + + TEST(stack, Reuse) { const int sizes[] = {3, 11, 81, 400, 999, 12, 1, 9721, 7, 99, 5, 0}; diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt index 07b89a9042e..c949c1e1f5c 100644 --- a/tests/gtests/blenlib/CMakeLists.txt +++ b/tests/gtests/blenlib/CMakeLists.txt @@ -40,4 +40,5 @@ BLENDER_TEST(BLI_math_color "bf_blenlib") BLENDER_TEST(BLI_math_geom "bf_blenlib") BLENDER_TEST(BLI_string "bf_blenlib") BLENDER_TEST(BLI_path_util "bf_blenlib;extern_wcwidth;${ZLIB_LIBRARIES}") +BLENDER_TEST(BLI_polyfill2d "bf_blenlib") BLENDER_TEST(BLI_listbase "bf_blenlib") diff --git a/tests/python/bl_mesh_modifiers.py b/tests/python/bl_mesh_modifiers.py index 1c05eaafa0d..2db38895f9b 100644 --- a/tests/python/bl_mesh_modifiers.py +++ b/tests/python/bl_mesh_modifiers.py @@ -851,7 +851,7 @@ if __name__ == "__main__": import traceback traceback.print_exc() - import sys + # import sys # sys.exit(1) # comment to debug else: diff --git a/tests/python/rna_array.py b/tests/python/rna_array.py index d3014868bcb..f9777a5b438 100644 --- a/tests/python/rna_array.py +++ b/tests/python/rna_array.py @@ -266,7 +266,7 @@ def prop_to_list(prop): ret= [] for x in prop: - if type(x) not in (bool, int, float): + if type(x) not in {bool, int, float}: ret.append(prop_to_list(x)) else: ret.append(x) |