Merge branch 'master' into xr-dev
This commit is contained in:
commit
2e66e2c37d
|
@ -300,6 +300,9 @@ option(WITH_USD "Enable Universal Scene Description (USD) Suppor
|
|||
# 3D format support
|
||||
# Disable opencollada when we don't have precompiled libs
|
||||
option(WITH_OPENCOLLADA "Enable OpenCollada Support (http://www.opencollada.org)" ON)
|
||||
option(WITH_IO_WAVEFRONT_OBJ "Enable Wavefront-OBJ 3D file format support (*.obj)" ON)
|
||||
option(WITH_IO_STL "Enable STL 3D file format support (*.stl)" ON)
|
||||
option(WITH_IO_GPENCIL "Enable grease-pencil file format IO (*.svg, *.pdf)" ON)
|
||||
|
||||
# Sound output
|
||||
option(WITH_SDL "Enable SDL for sound" ON)
|
||||
|
|
|
@ -36,19 +36,19 @@ getopt \
|
|||
-o s:i:t:h \
|
||||
--long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,\
|
||||
with-all,with-opencollada,with-jack,with-pulseaudio,with-embree,with-oidn,with-nanovdb,\
|
||||
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,ver-xr-openxr:,\
|
||||
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,ver-xr-openxr:,ver-level-zero:\
|
||||
force-all,force-python,force-boost,force-tbb,\
|
||||
force-ocio,force-imath,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\
|
||||
force-ffmpeg,force-opencollada,force-alembic,force-embree,force-oidn,force-usd,\
|
||||
force-xr-openxr,\
|
||||
force-xr-openxr,force-level-zero,\
|
||||
build-all,build-python,build-boost,build-tbb,\
|
||||
build-ocio,build-imath,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\
|
||||
build-ffmpeg,build-opencollada,build-alembic,build-embree,build-oidn,build-usd,\
|
||||
build-xr-openxr,\
|
||||
build-xr-openxr,build-level-zero,\
|
||||
skip-python,skip-boost,skip-tbb,\
|
||||
skip-ocio,skip-imath,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\
|
||||
skip-ffmpeg,skip-opencollada,skip-alembic,skip-embree,skip-oidn,skip-usd,\
|
||||
skip-xr-openxr \
|
||||
skip-xr-openxr,skip-level-zero \
|
||||
-- "$@" \
|
||||
)
|
||||
|
||||
|
@ -165,6 +165,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
|||
--ver-xr-openxr=<ver>
|
||||
Force version of OpenXR-SDK.
|
||||
|
||||
--ver-level-zero=<ver>
|
||||
Force version of OneAPI Level Zero library.
|
||||
|
||||
Note about the --ver-foo options:
|
||||
It may not always work as expected (some libs are actually checked out from a git rev...), yet it might help
|
||||
to fix some build issues (like LLVM mismatch with the version used by your graphic system).
|
||||
|
@ -226,6 +229,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
|||
--build-xr-openxr
|
||||
Force the build of OpenXR-SDK.
|
||||
|
||||
--build-level-zero=<ver>
|
||||
Force the build of OneAPI Level Zero library.
|
||||
|
||||
Note about the --build-foo options:
|
||||
* They force the script to prefer building dependencies rather than using available packages.
|
||||
This may make things simpler and allow working around some distribution bugs, but on the other hand it will
|
||||
|
@ -293,6 +299,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
|||
--force-xr-openxr
|
||||
Force the rebuild of OpenXR-SDK.
|
||||
|
||||
--force-level-zero=<ver>
|
||||
Force the rebuild of OneAPI Level Zero library.
|
||||
|
||||
Note about the --force-foo options:
|
||||
* They obviously only have an effect if those libraries are built by this script
|
||||
(i.e. if there is no available and satisfactory package)!
|
||||
|
@ -351,7 +360,10 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
|||
Unconditionally skip Universal Scene Description installation/building.
|
||||
|
||||
--skip-xr-openxr
|
||||
Unconditionally skip OpenXR-SDK installation/building.\""
|
||||
Unconditionally skip OpenXR-SDK installation/building.
|
||||
|
||||
--skip-level-zero=<ver>
|
||||
Unconditionally skip OneAPI Level Zero installation/building.\""
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Main Vars
|
||||
|
@ -573,14 +585,13 @@ OIDN_SKIP=false
|
|||
|
||||
ISPC_VERSION="1.17.0"
|
||||
|
||||
FFMPEG_VERSION="4.4"
|
||||
FFMPEG_VERSION_SHORT="4.4"
|
||||
FFMPEG_VERSION_MIN="3.0"
|
||||
FFMPEG_VERSION_MEX="5.0"
|
||||
FFMPEG_FORCE_BUILD=false
|
||||
FFMPEG_FORCE_REBUILD=false
|
||||
FFMPEG_SKIP=false
|
||||
_ffmpeg_list_sep=";"
|
||||
LEVEL_ZERO_VERSION="1.7.15"
|
||||
LEVEL_ZERO_VERSION_SHORT="1.7"
|
||||
LEVEL_ZERO_VERSION_MIN="1.7"
|
||||
LEVEL_ZERO_VERSION_MEX="2.0"
|
||||
LEVEL_ZERO_FORCE_BUILD=false
|
||||
LEVEL_ZERO_FORCE_REBUILD=false
|
||||
LEVEL_ZERO_SKIP=false
|
||||
|
||||
XR_OPENXR_VERSION="1.0.22"
|
||||
XR_OPENXR_VERSION_SHORT="1.0"
|
||||
|
@ -590,6 +601,15 @@ XR_OPENXR_FORCE_BUILD=false
|
|||
XR_OPENXR_FORCE_REBUILD=false
|
||||
XR_OPENXR_SKIP=false
|
||||
|
||||
FFMPEG_VERSION="5.0"
|
||||
FFMPEG_VERSION_SHORT="5.0"
|
||||
FFMPEG_VERSION_MIN="4.0"
|
||||
FFMPEG_VERSION_MEX="6.0"
|
||||
FFMPEG_FORCE_BUILD=false
|
||||
FFMPEG_FORCE_REBUILD=false
|
||||
FFMPEG_SKIP=false
|
||||
_ffmpeg_list_sep=";"
|
||||
|
||||
# FFMPEG optional libs.
|
||||
VORBIS_USE=false
|
||||
VORBIS_DEV=""
|
||||
|
@ -781,6 +801,12 @@ while true; do
|
|||
XR_OPENXR_VERSION_SHORT=$XR_OPENXR_VERSION
|
||||
shift; shift; continue
|
||||
;;
|
||||
--ver-level-zero)
|
||||
LEVEL_ZERO_VERSION="$2"
|
||||
LEVEL_ZERO_VERSION_MIN=$LEVEL_ZERO_VERSION
|
||||
LEVEL_ZERO_VERSION_SHORT=$LEVEL_ZERO_VERSION
|
||||
shift; shift; continue
|
||||
;;
|
||||
--build-all)
|
||||
PYTHON_FORCE_BUILD=true
|
||||
BOOST_FORCE_BUILD=true
|
||||
|
@ -800,6 +826,7 @@ while true; do
|
|||
ALEMBIC_FORCE_BUILD=true
|
||||
USD_FORCE_BUILD=true
|
||||
XR_OPENXR_FORCE_BUILD=true
|
||||
LEVEL_ZERO_FORCE_BUILD=true
|
||||
shift; continue
|
||||
;;
|
||||
--build-python)
|
||||
|
@ -857,6 +884,9 @@ while true; do
|
|||
--build-xr-openxr)
|
||||
XR_OPENXR_FORCE_BUILD=true; shift; continue
|
||||
;;
|
||||
--build-level-zero)
|
||||
LEVEL_ZERO_FORCE_BUILD=true; shift; continue
|
||||
;;
|
||||
--force-all)
|
||||
PYTHON_FORCE_REBUILD=true
|
||||
BOOST_FORCE_REBUILD=true
|
||||
|
@ -876,6 +906,7 @@ while true; do
|
|||
ALEMBIC_FORCE_REBUILD=true
|
||||
USD_FORCE_REBUILD=true
|
||||
XR_OPENXR_FORCE_REBUILD=true
|
||||
LEVEL_ZERO_FORCE_REBUILD=true
|
||||
shift; continue
|
||||
;;
|
||||
--force-python)
|
||||
|
@ -933,6 +964,9 @@ while true; do
|
|||
--force-xr-openxr)
|
||||
XR_OPENXR_FORCE_REBUILD=true; shift; continue
|
||||
;;
|
||||
--force-level-zero)
|
||||
LEVEL_ZERO_FORCE_REBUILD=true; shift; continue
|
||||
;;
|
||||
--skip-python)
|
||||
PYTHON_SKIP=true; shift; continue
|
||||
;;
|
||||
|
@ -987,6 +1021,9 @@ while true; do
|
|||
--skip-xr-openxr)
|
||||
XR_OPENXR_SKIP=true; shift; continue
|
||||
;;
|
||||
--skip-level-zero)
|
||||
LEVEL_ZERO_SKIP=true; shift; continue
|
||||
;;
|
||||
--)
|
||||
# no more arguments to parse
|
||||
break
|
||||
|
@ -1128,14 +1165,16 @@ OIDN_SOURCE=( "https://github.com/OpenImageDenoise/oidn/releases/download/v${OID
|
|||
|
||||
ISPC_BINARY=( "https://github.com/ispc/ispc/releases/download/v${ISPC_VERSION}/ispc-v${ISPC_VERSION}-linux.tar.gz" )
|
||||
|
||||
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
|
||||
|
||||
XR_OPENXR_USE_REPO=false
|
||||
XR_OPENXR_SOURCE=("https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_VERSION}.tar.gz")
|
||||
XR_OPENXR_SOURCE_REPO=("https://github.com/KhronosGroup/OpenXR-SDK.git")
|
||||
XR_OPENXR_REPO_UID="458984d7f59d1ae6dc1b597d94b02e4f7132eaba"
|
||||
XR_OPENXR_REPO_BRANCH="master"
|
||||
|
||||
LEVEL_ZERO_SOURCE=("https://github.com/oneapi-src/level-zero/archive/refs/tags/v${LEVEL_ZERO_VERSION}.tar.gz")
|
||||
|
||||
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
|
||||
|
||||
# C++11 is required now
|
||||
CXXFLAGS_BACK=$CXXFLAGS
|
||||
CXXFLAGS="$CXXFLAGS -std=c++11"
|
||||
|
@ -1187,7 +1226,8 @@ You may also want to build them yourself (optional ones are [between brackets]):
|
|||
* [OpenImageDenoise $OIDN_VERSION] (from $OIDN_SOURCE).
|
||||
* [Alembic $ALEMBIC_VERSION] (from $ALEMBIC_SOURCE).
|
||||
* [Universal Scene Description $USD_VERSION] (from $USD_SOURCE).
|
||||
* [OpenXR-SDK $XR_OPENXR_VERSION] (from $XR_OPENXR_SOURCE).\""
|
||||
* [OpenXR-SDK $XR_OPENXR_VERSION] (from $XR_OPENXR_SOURCE).
|
||||
* [OneAPI Level Zero $LEVEL_ZERO_VERSION] (from $LEVEL_ZERO_SOURCE).\""
|
||||
|
||||
if [ "$DO_SHOW_DEPS" = true ]; then
|
||||
PRINT ""
|
||||
|
@ -3822,6 +3862,103 @@ compile_XR_OpenXR_SDK() {
|
|||
}
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Build OneAPI Level Zero library.
|
||||
|
||||
_init_level_zero() {
|
||||
_src=$SRC/level-zero-$LEVEL_ZERO_VERSION
|
||||
_git=false
|
||||
_inst=$INST/level-zero-$LEVEL_ZERO_VERSION_SHORT
|
||||
_inst_shortcut=$INST/level-zero
|
||||
}
|
||||
|
||||
_update_deps_level_zero() {
|
||||
:
|
||||
}
|
||||
|
||||
clean_Level_Zero() {
|
||||
_init_level_zero
|
||||
if [ -d $_inst ]; then
|
||||
# Force rebuilding the dependencies if needed.
|
||||
_update_deps_level_zero false true
|
||||
fi
|
||||
_clean
|
||||
}
|
||||
|
||||
compile_Level_Zero() {
|
||||
if [ "$NO_BUILD" = true ]; then
|
||||
WARNING "--no-build enabled, Level Zero will not be compiled!"
|
||||
return
|
||||
fi
|
||||
|
||||
# To be changed each time we make edits that would modify the compiled result!
|
||||
level_zero_magic=1
|
||||
_init_level_zero
|
||||
|
||||
# Force having own builds for the dependencies.
|
||||
_update_deps_level_zero true false
|
||||
|
||||
# Clean install if needed!
|
||||
magic_compile_check level-zero-$LEVEL_ZERO_VERSION $level_zero_magic
|
||||
if [ $? -eq 1 -o "$LEVEL_ZERO_FORCE_REBUILD" = true ]; then
|
||||
clean_Level_Zero
|
||||
fi
|
||||
|
||||
if [ ! -d $_inst ]; then
|
||||
INFO "Building Level-Zero-$LEVEL_ZERO_VERSION"
|
||||
|
||||
# Force rebuilding the dependencies.
|
||||
_update_deps_level_zero true true
|
||||
|
||||
prepare_inst
|
||||
|
||||
if [ ! -d $_src ]; then
|
||||
mkdir -p $SRC
|
||||
|
||||
download LEVEL_ZERO_SOURCE[@] "$_src.tar.gz"
|
||||
INFO "Unpacking Level-Zero-$LEVEL_ZERO_VERSION"
|
||||
tar -C $SRC -xf $_src.tar.gz
|
||||
fi
|
||||
|
||||
cd $_src
|
||||
|
||||
# Always refresh the whole build!
|
||||
if [ -d build ]; then
|
||||
rm -rf build
|
||||
fi
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
# Keep flags in sync with LEVEL_ZERO_EXTRA_ARGS in level-zero.cmake!
|
||||
cmake_d="-D CMAKE_BUILD_TYPE=Release"
|
||||
cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst"
|
||||
|
||||
cmake $cmake_d ..
|
||||
|
||||
make -j$THREADS && make install
|
||||
make clean
|
||||
|
||||
if [ ! -d $_inst ]; then
|
||||
ERROR "Level-Zero-$LEVEL_ZERO_VERSION failed to compile, exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
magic_compile_set level-zero-$LEVEL_ZERO_VERSION $level_zero_magic
|
||||
|
||||
cd $CWD
|
||||
INFO "Done compiling Level-Zero-$LEVEL_ZERO_VERSION!"
|
||||
else
|
||||
INFO "Own Level-Zero-$LEVEL_ZERO_VERSION is up to date, nothing to do!"
|
||||
INFO "If you want to force rebuild of this lib, use the --force-level-zero option."
|
||||
fi
|
||||
|
||||
if [ -d $_inst ]; then
|
||||
_create_inst_shortcut
|
||||
fi
|
||||
run_ldconfig "level-zero"
|
||||
}
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Install on DEB-like
|
||||
|
||||
|
@ -4458,6 +4595,18 @@ install_DEB() {
|
|||
PRINT ""
|
||||
compile_XR_OpenXR_SDK
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
if [ "$LEVEL_ZERO_SKIP" = true ]; then
|
||||
WARNING "Skipping Level Zero installation, as requested..."
|
||||
elif [ "$LEVEL_ZERO_FORCE_BUILD" = true ]; then
|
||||
INFO "Forced Level Zero building, as requested..."
|
||||
compile_Level_Zero
|
||||
else
|
||||
# No package currently!
|
||||
PRINT ""
|
||||
compile_Level_Zero
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
@ -5144,6 +5293,18 @@ install_RPM() {
|
|||
# No package currently!
|
||||
compile_XR_OpenXR_SDK
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
if [ "$LEVEL_ZERO_SKIP" = true ]; then
|
||||
WARNING "Skipping Level Zero installation, as requested..."
|
||||
elif [ "$LEVEL_ZERO_FORCE_BUILD" = true ]; then
|
||||
INFO "Forced Level Zero building, as requested..."
|
||||
compile_Level_Zero
|
||||
else
|
||||
# No package currently!
|
||||
PRINT ""
|
||||
compile_Level_Zero
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
@ -5721,6 +5882,18 @@ install_ARCH() {
|
|||
# No package currently!
|
||||
compile_XR_OpenXR_SDK
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
if [ "$LEVEL_ZERO_SKIP" = true ]; then
|
||||
WARNING "Skipping Level Zero installation, as requested..."
|
||||
elif [ "$LEVEL_ZERO_FORCE_BUILD" = true ]; then
|
||||
INFO "Forced Level Zero building, as requested..."
|
||||
compile_Level_Zero
|
||||
else
|
||||
# No package currently!
|
||||
PRINT ""
|
||||
compile_Level_Zero
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
@ -5895,6 +6068,14 @@ install_OTHER() {
|
|||
INFO "Forced OpenXR-SDK building, as requested..."
|
||||
compile_XR_OpenXR_SDK
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
if [ "$LEVEL_ZERO_SKIP" = true ]; then
|
||||
WARNING "Skipping Level Zero installation, as requested..."
|
||||
elif [ "$LEVEL_ZERO_FORCE_BUILD" = true ]; then
|
||||
INFO "Forced Level Zero building, as requested..."
|
||||
compile_Level_Zero
|
||||
fi
|
||||
}
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
@ -6137,6 +6318,18 @@ print_info() {
|
|||
fi
|
||||
fi
|
||||
|
||||
# Not yet available in Blender.
|
||||
#~ if [ "$LEVEL_ZERO_SKIP" = false ]; then
|
||||
#~ _1="-D WITH_LEVEL_ZERO=ON"
|
||||
#~ PRINT " $_1"
|
||||
#~ _buildargs="$_buildargs $_1"
|
||||
#~ if [ -d $INST/level-zero ]; then
|
||||
#~ _1="-D LEVEL_ZERO_ROOT_DIR=$INST/level-zero"
|
||||
#~ PRINT " $_1"
|
||||
#~ _buildargs="$_buildargs $_1"
|
||||
#~ fi
|
||||
#~ fi
|
||||
|
||||
PRINT ""
|
||||
PRINT "Or even simpler, just run (in your blender-source dir):"
|
||||
PRINT " make -j$THREADS BUILD_CMAKE_ARGS=\"$_buildargs\""
|
||||
|
|
|
@ -175,7 +175,9 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibsUnix DEFAULT_MSG
|
|||
IF(PYTHONLIBSUNIX_FOUND)
|
||||
# Assign cache items
|
||||
SET(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIR} ${PYTHON_INCLUDE_CONFIG_DIR})
|
||||
SET(PYTHON_LIBRARIES ${PYTHON_LIBRARY})
|
||||
IF(NOT WITH_PYTHON_MODULE)
|
||||
SET(PYTHON_LIBRARIES ${PYTHON_LIBRARY})
|
||||
ENDIF()
|
||||
|
||||
FIND_FILE(PYTHON_SITE_PACKAGES
|
||||
NAMES
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
"""
|
||||
Example linux usage
|
||||
python3 ~/blender-git/blender/build_files/cmake/cmake_netbeans_project.py ~/blender-git/cmake
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
r"""
|
||||
Example Linux usage:
|
||||
python ~/blender-git/blender/build_files/cmake/cmake_qtcreator_project.py --build-dir ~/blender-git/cmake
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import project_source_info
|
||||
import subprocess
|
||||
import sys
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import project_source_info
|
||||
import subprocess
|
||||
import sys
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
CHECKER_IGNORE_PREFIX = [
|
||||
"extern",
|
||||
"intern/moto",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
CHECKER_IGNORE_PREFIX = [
|
||||
"extern",
|
||||
"intern/moto",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
CHECKER_IGNORE_PREFIX = [
|
||||
"extern",
|
||||
"intern/moto",
|
||||
|
|
|
@ -37,6 +37,9 @@ set(WITH_IMAGE_TIFF OFF CACHE BOOL "" FORCE)
|
|||
set(WITH_IMAGE_WEBP OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_INPUT_NDOF OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_IO_STL OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_IO_WAVEFRONT_OBJ OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_IO_GPENCIL OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_JACK OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_LIBMV OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_LLVM OFF CACHE BOOL "" FORCE)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
"""
|
||||
Module for accessing project file data for Blender.
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
__all__ = (
|
||||
"build_info",
|
||||
"SOURCE_DIR",
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
|
|
|
@ -11,8 +11,6 @@ where <path-to-blender> is the path to the Blender executable,
|
|||
and <output-filename> is where to write the generated man page.
|
||||
'''
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
sphinx==4.1.1
|
||||
sphinx==5.0.1
|
||||
|
||||
# Sphinx dependencies that are important
|
||||
Jinja2==3.0.1
|
||||
Pygments==2.10.0
|
||||
Jinja2==3.1.2
|
||||
Pygments==2.12.0
|
||||
docutils==0.17.1
|
||||
snowballstemmer==2.1.0
|
||||
babel==2.9.1
|
||||
requests==2.26.0
|
||||
snowballstemmer==2.2.0
|
||||
babel==2.10.1
|
||||
requests==2.27.1
|
||||
|
||||
# Only needed to match the theme used for the official documentation.
|
||||
# Without this theme, the default theme will be used.
|
||||
|
|
|
@ -40,15 +40,6 @@ As well as pep8 we have additional conventions used for Blender Python scripts:
|
|||
- pep8 also defines that lines should not exceed 79 characters,
|
||||
we have decided that this is too restrictive so it is optional per script.
|
||||
|
||||
Periodically we run checks for pep8 compliance on Blender scripts,
|
||||
for scripts to be included in this check add this line as a comment at the top of the script:
|
||||
|
||||
``# <pep8 compliant>``
|
||||
|
||||
To enable line length checks use this instead:
|
||||
|
||||
``# <pep8-80 compliant>``
|
||||
|
||||
|
||||
User Interface Layout
|
||||
=====================
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# This is a quite stupid script which extracts bmesh api docs from
|
||||
# 'bmesh_opdefines.c' in order to avoid having to add a lot of introspection
|
||||
# data access into the api.
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
"""
|
||||
Dump the python API into a text file so we can generate changelogs.
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
"""
|
||||
API dump in RST files
|
||||
---------------------
|
||||
|
@ -78,6 +76,27 @@ SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
|
|||
# See: D6261 for reference.
|
||||
USE_ONLY_BUILTIN_RNA_TYPES = True
|
||||
|
||||
# Write a page for each static enum defined in:
|
||||
# `source/blender/makesrna/RNA_enum_items.h` so the enums can be linked to instead of being expanded everywhere.
|
||||
USE_SHARED_RNA_ENUM_ITEMS_STATIC = True
|
||||
|
||||
if USE_SHARED_RNA_ENUM_ITEMS_STATIC:
|
||||
from _bpy import rna_enum_items_static
|
||||
rna_enum_dict = rna_enum_items_static()
|
||||
for key in ("DummyRNA_DEFAULT_items", "DummyRNA_NULL_items"):
|
||||
del rna_enum_dict[key]
|
||||
del key, rna_enum_items_static
|
||||
|
||||
# Build enum `{pointer: identifier}` map, so any enum property pointer can
|
||||
# lookup an identifier using `InfoPropertyRNA.enum_pointer` as the key.
|
||||
rna_enum_pointer_to_id_map = {
|
||||
enum_prop.as_pointer(): key
|
||||
for key, enum_items in rna_enum_dict.items()
|
||||
# It's possible the first item is a heading (which has no identifier).
|
||||
# skip these as the `EnumProperty.enum_items` does not expose them.
|
||||
if (enum_prop := next(iter(enum_prop for enum_prop in enum_items if enum_prop.identifier), None))
|
||||
}
|
||||
|
||||
|
||||
def handle_args():
|
||||
"""
|
||||
|
@ -531,7 +550,7 @@ def import_value_from_module(module_name, import_name):
|
|||
|
||||
def execfile(filepath):
|
||||
global_namespace = {"__file__": filepath, "__name__": "__main__"}
|
||||
with open(filepath) as file_handle:
|
||||
with open(filepath, encoding="utf-8") as file_handle:
|
||||
exec(compile(file_handle.read(), filepath, 'exec'), global_namespace)
|
||||
|
||||
|
||||
|
@ -693,26 +712,6 @@ def write_indented_lines(ident, fn, text, strip=True):
|
|||
fn(ident + l + "\n")
|
||||
|
||||
|
||||
def pymethod2sphinx(ident, fw, identifier, py_func):
|
||||
"""
|
||||
class method to sphinx
|
||||
"""
|
||||
arg_str = inspect.formatargspec(*inspect.getargspec(py_func))
|
||||
if arg_str.startswith("(self, "):
|
||||
arg_str = "(" + arg_str[7:]
|
||||
func_type = "method"
|
||||
elif arg_str.startswith("(cls, "):
|
||||
arg_str = "(" + arg_str[6:]
|
||||
func_type = "classmethod"
|
||||
else:
|
||||
func_type = "staticmethod"
|
||||
|
||||
fw(ident + ".. %s:: %s%s\n\n" % (func_type, identifier, arg_str))
|
||||
if py_func.__doc__:
|
||||
write_indented_lines(ident + " ", fw, py_func.__doc__)
|
||||
fw("\n")
|
||||
|
||||
|
||||
def pyfunc2sphinx(ident, fw, module_name, type_name, identifier, py_func, is_class=True):
|
||||
"""
|
||||
function or class method to sphinx
|
||||
|
@ -1220,15 +1219,23 @@ def pycontext2sphinx(basepath):
|
|||
# No need to check if there are duplicates yet as it's known there wont be.
|
||||
unique.add(prop.identifier)
|
||||
|
||||
enum_descr_override = None
|
||||
if USE_SHARED_RNA_ENUM_ITEMS_STATIC:
|
||||
enum_descr_override = pyrna_enum2sphinx_shared_link(prop)
|
||||
|
||||
type_descr = prop.get_type_description(
|
||||
class_fmt=":class:`bpy.types.%s`", collection_id=_BPY_PROP_COLLECTION_ID)
|
||||
class_fmt=":class:`bpy.types.%s`",
|
||||
collection_id=_BPY_PROP_COLLECTION_ID,
|
||||
enum_descr_override=enum_descr_override,
|
||||
)
|
||||
fw(".. data:: %s\n\n" % prop.identifier)
|
||||
if prop.description:
|
||||
fw(" %s\n\n" % prop.description)
|
||||
|
||||
# Special exception, can't use generic code here for enums.
|
||||
if prop.type == "enum":
|
||||
enum_text = pyrna_enum2sphinx(prop)
|
||||
# If the link has been written, no need to inline the enum items.
|
||||
enum_text = "" if enum_descr_override else pyrna_enum2sphinx(prop)
|
||||
if enum_text:
|
||||
write_indented_lines(" ", fw, enum_text)
|
||||
fw("\n")
|
||||
|
@ -1290,6 +1297,11 @@ def pyrna_enum2sphinx(prop, use_empty_descriptions=False):
|
|||
Write a bullet point list of enum + descriptions.
|
||||
"""
|
||||
|
||||
# Write a link to the enum if this is part of `rna_enum_pointer_map`.
|
||||
if USE_SHARED_RNA_ENUM_ITEMS_STATIC:
|
||||
if (result := pyrna_enum2sphinx_shared_link(prop)) is not None:
|
||||
return result
|
||||
|
||||
if use_empty_descriptions:
|
||||
ok = True
|
||||
else:
|
||||
|
@ -1368,10 +1380,15 @@ def pyrna2sphinx(basepath):
|
|||
|
||||
kwargs["collection_id"] = _BPY_PROP_COLLECTION_ID
|
||||
|
||||
enum_descr_override = None
|
||||
if USE_SHARED_RNA_ENUM_ITEMS_STATIC:
|
||||
enum_descr_override = pyrna_enum2sphinx_shared_link(prop)
|
||||
kwargs["enum_descr_override"] = enum_descr_override
|
||||
|
||||
type_descr = prop.get_type_description(**kwargs)
|
||||
|
||||
enum_text = pyrna_enum2sphinx(prop)
|
||||
|
||||
# If the link has been written, no need to inline the enum items.
|
||||
enum_text = "" if enum_descr_override else pyrna_enum2sphinx(prop)
|
||||
if prop.name or prop.description or enum_text:
|
||||
fw(ident + ":%s%s:\n\n" % (id_name, identifier))
|
||||
|
||||
|
@ -1472,7 +1489,15 @@ def pyrna2sphinx(basepath):
|
|||
if identifier in struct_blacklist:
|
||||
continue
|
||||
|
||||
type_descr = prop.get_type_description(class_fmt=":class:`%s`", collection_id=_BPY_PROP_COLLECTION_ID)
|
||||
enum_descr_override = None
|
||||
if USE_SHARED_RNA_ENUM_ITEMS_STATIC:
|
||||
enum_descr_override = pyrna_enum2sphinx_shared_link(prop)
|
||||
|
||||
type_descr = prop.get_type_description(
|
||||
class_fmt=":class:`%s`",
|
||||
collection_id=_BPY_PROP_COLLECTION_ID,
|
||||
enum_descr_override=enum_descr_override,
|
||||
)
|
||||
# Read-only properties use "data" directive, variables properties use "attribute" directive.
|
||||
if "readonly" in type_descr:
|
||||
fw(" .. data:: %s\n" % identifier)
|
||||
|
@ -1489,7 +1514,8 @@ def pyrna2sphinx(basepath):
|
|||
|
||||
# Special exception, can't use generic code here for enums.
|
||||
if prop.type == "enum":
|
||||
enum_text = pyrna_enum2sphinx(prop)
|
||||
# If the link has been written, no need to inline the enum items.
|
||||
enum_text = "" if enum_descr_override else pyrna_enum2sphinx(prop)
|
||||
if enum_text:
|
||||
write_indented_lines(" ", fw, enum_text)
|
||||
fw("\n")
|
||||
|
@ -1528,8 +1554,16 @@ def pyrna2sphinx(basepath):
|
|||
for prop in func.return_values:
|
||||
# TODO: pyrna_enum2sphinx for multiple return values... actually don't
|
||||
# think we even use this but still!
|
||||
|
||||
enum_descr_override = None
|
||||
if USE_SHARED_RNA_ENUM_ITEMS_STATIC:
|
||||
enum_descr_override = pyrna_enum2sphinx_shared_link(prop)
|
||||
|
||||
type_descr = prop.get_type_description(
|
||||
as_ret=True, class_fmt=":class:`%s`", collection_id=_BPY_PROP_COLLECTION_ID)
|
||||
as_ret=True, class_fmt=":class:`%s`",
|
||||
collection_id=_BPY_PROP_COLLECTION_ID,
|
||||
enum_descr_override=enum_descr_override,
|
||||
)
|
||||
descr = prop.description
|
||||
if not descr:
|
||||
descr = prop.name
|
||||
|
@ -1778,11 +1812,16 @@ def write_sphinx_conf_py(basepath):
|
|||
fw("extensions = ['sphinx.ext.intersphinx']\n\n")
|
||||
fw("intersphinx_mapping = {'blender_manual': ('https://docs.blender.org/manual/en/dev/', None)}\n\n")
|
||||
fw("project = 'Blender %s Python API'\n" % BLENDER_VERSION_STRING)
|
||||
fw("master_doc = 'index'\n")
|
||||
fw("copyright = u'Blender Foundation'\n")
|
||||
fw("root_doc = 'index'\n")
|
||||
fw("copyright = 'Blender Foundation'\n")
|
||||
fw("version = '%s'\n" % BLENDER_VERSION_DOTS)
|
||||
fw("release = '%s'\n" % BLENDER_VERSION_DOTS)
|
||||
|
||||
# Set this as the default is a super-set of Python3.
|
||||
fw("highlight_language = 'python3'\n")
|
||||
# No need to detect encoding.
|
||||
fw("highlight_options = {'default': {'encoding': 'utf-8'}}\n\n")
|
||||
|
||||
# Quiet file not in table-of-contents warnings.
|
||||
fw("exclude_patterns = [\n")
|
||||
fw(" 'include__bmesh.rst',\n")
|
||||
|
@ -1978,6 +2017,14 @@ def write_rst_types_index(basepath):
|
|||
fw(".. toctree::\n")
|
||||
fw(" :glob:\n\n")
|
||||
fw(" bpy.types.*\n\n")
|
||||
|
||||
# This needs to be included somewhere, while it's hidden, list to avoid warnings.
|
||||
if USE_SHARED_RNA_ENUM_ITEMS_STATIC:
|
||||
fw(".. toctree::\n")
|
||||
fw(" :hidden:\n")
|
||||
fw(" :maxdepth: 1\n\n")
|
||||
fw(" Shared Enum Types <bpy_types_enum_items/index>\n\n")
|
||||
|
||||
file.close()
|
||||
|
||||
|
||||
|
@ -2048,6 +2095,81 @@ def write_rst_data(basepath):
|
|||
EXAMPLE_SET_USED.add("bpy.data")
|
||||
|
||||
|
||||
def pyrna_enum2sphinx_shared_link(prop):
|
||||
"""
|
||||
Return a reference to the enum used by ``prop`` or None when not found.
|
||||
"""
|
||||
if (
|
||||
(prop.type == "enum") and
|
||||
(pointer := prop.enum_pointer) and
|
||||
(identifier := rna_enum_pointer_to_id_map.get(pointer))
|
||||
):
|
||||
return ":ref:`%s`" % identifier
|
||||
return None
|
||||
|
||||
|
||||
def write_rst_enum_items(basepath, key, key_no_prefix, enum_items):
|
||||
"""
|
||||
Write a single page for a static enum in RST.
|
||||
|
||||
This helps avoiding very large lists being in-lined in many places which is an issue
|
||||
especially with icons in ``bpy.types.UILayout``. See T87008.
|
||||
"""
|
||||
filepath = os.path.join(basepath, "%s.rst" % key_no_prefix)
|
||||
with open(filepath, "w", encoding="utf-8") as fh:
|
||||
fw = fh.write
|
||||
# fw(".. noindex::\n\n")
|
||||
fw(".. _%s:\n\n" % key)
|
||||
|
||||
fw(title_string(key_no_prefix.replace("_", " ").title(), "#"))
|
||||
# fw(".. rubric:: %s\n\n" % key_no_prefix.replace("_", " ").title())
|
||||
|
||||
for item in enum_items:
|
||||
identifier = item.identifier
|
||||
name = item.name
|
||||
description = item.description
|
||||
if identifier:
|
||||
fw(":%s: %s\n" % (item.identifier, (escape_rst(name) + ".") if name else ""))
|
||||
if description:
|
||||
fw("\n")
|
||||
write_indented_lines(" ", fw, escape_rst(description) + ".")
|
||||
else:
|
||||
fw("\n")
|
||||
else:
|
||||
if name:
|
||||
fw("\n\n**%s**\n\n" % name)
|
||||
else:
|
||||
fw("\n\n----\n\n")
|
||||
|
||||
if description:
|
||||
fw(escape_rst(description) + ".")
|
||||
fw("\n\n")
|
||||
|
||||
|
||||
def write_rst_enum_items_and_index(basepath):
|
||||
"""
|
||||
Write shared enum items.
|
||||
"""
|
||||
subdir = "bpy_types_enum_items"
|
||||
basepath_bpy_types_rna_enum = os.path.join(basepath, subdir)
|
||||
os.makedirs(basepath_bpy_types_rna_enum, exist_ok=True)
|
||||
with open(os.path.join(basepath_bpy_types_rna_enum, "index.rst"), "w", encoding="utf-8") as fh:
|
||||
fw = fh.write
|
||||
fw(title_string("Shared Enum Items", "#"))
|
||||
fw(".. toctree::\n")
|
||||
fw("\n")
|
||||
for key, enum_items in rna_enum_dict.items():
|
||||
if not key.startswith("rna_enum_"):
|
||||
raise Exception("Found RNA enum identifier that doesn't use the 'rna_enum_' prefix, found %r!" % key)
|
||||
key_no_prefix = key.removeprefix("rna_enum_")
|
||||
fw(" %s\n" % key_no_prefix)
|
||||
|
||||
for key, enum_items in rna_enum_dict.items():
|
||||
key_no_prefix = key.removeprefix("rna_enum_")
|
||||
write_rst_enum_items(basepath_bpy_types_rna_enum, key, key_no_prefix, enum_items)
|
||||
fw("\n")
|
||||
|
||||
|
||||
def write_rst_importable_modules(basepath):
|
||||
"""
|
||||
Write the RST files of importable modules.
|
||||
|
@ -2212,6 +2334,10 @@ def rna2sphinx(basepath):
|
|||
write_rst_data(basepath) # bpy.data
|
||||
write_rst_importable_modules(basepath)
|
||||
|
||||
# `bpy_types_enum_items/*` (referenced from `bpy.types`).
|
||||
if USE_SHARED_RNA_ENUM_ITEMS_STATIC:
|
||||
write_rst_enum_items_and_index(basepath)
|
||||
|
||||
# copy the other rsts
|
||||
copy_handwritten_rsts(basepath)
|
||||
|
||||
|
@ -2285,8 +2411,6 @@ def setup_monkey_patch():
|
|||
|
||||
# Avoid adding too many changes here.
|
||||
def setup_blender():
|
||||
import bpy
|
||||
|
||||
# Remove handlers since the functions get included
|
||||
# in the doc-string and don't have meaningful names.
|
||||
lists_to_restore = []
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
bpy_types_Operator_bl_property__doc__ = (
|
||||
"""
|
||||
The name of a property to use as this operators primary property.
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
/* T76453: Prevent Long enum lists */
|
||||
.field-list > dd p {
|
||||
max-height: 245px;
|
||||
overflow-y: auto !important;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* Hide home icon in search area */
|
||||
.wy-side-nav-search > a:hover {background: none; opacity: 0.9}
|
||||
.wy-side-nav-search > a.icon::before {content: none}
|
||||
|
|
|
@ -124,6 +124,8 @@ ATOMIC_INLINE unsigned int atomic_fetch_and_sub_u(unsigned int *p, unsigned int
|
|||
ATOMIC_INLINE unsigned int atomic_cas_u(unsigned int *v, unsigned int old, unsigned int _new);
|
||||
|
||||
ATOMIC_INLINE void *atomic_cas_ptr(void **v, void *old, void *_new);
|
||||
ATOMIC_INLINE void *atomic_load_ptr(void *const *v);
|
||||
ATOMIC_INLINE void atomic_store_ptr(void **p, void *v);
|
||||
|
||||
ATOMIC_INLINE float atomic_cas_float(float *v, float old, float _new);
|
||||
|
||||
|
|
|
@ -205,6 +205,24 @@ ATOMIC_INLINE void *atomic_cas_ptr(void **v, void *old, void *_new)
|
|||
#endif
|
||||
}
|
||||
|
||||
ATOMIC_INLINE void *atomic_load_ptr(void *const *v)
|
||||
{
|
||||
#if (LG_SIZEOF_PTR == 8)
|
||||
return (void *)atomic_load_uint64((const uint64_t *)v);
|
||||
#elif (LG_SIZEOF_PTR == 4)
|
||||
return (void *)atomic_load_uint32((const uint32_t *)v);
|
||||
#endif
|
||||
}
|
||||
|
||||
ATOMIC_INLINE void atomic_store_ptr(void **p, void *v)
|
||||
{
|
||||
#if (LG_SIZEOF_PTR == 8)
|
||||
atomic_store_uint64((uint64_t *)p, (uint64_t)v);
|
||||
#elif (LG_SIZEOF_PTR == 4)
|
||||
atomic_store_uint32((uint32_t *)p, (uint32_t)v);
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* float operations. */
|
||||
ATOMIC_STATIC_ASSERT(sizeof(float) == sizeof(uint32_t), "sizeof(float) != sizeof(uint32_t)");
|
||||
|
|
|
@ -1060,6 +1060,25 @@ TEST(atomic, atomic_cas_ptr)
|
|||
}
|
||||
}
|
||||
|
||||
TEST(atomic, atomic_load_ptr)
|
||||
{
|
||||
{
|
||||
void *value = INT_AS_PTR(0x7f);
|
||||
void *dest = atomic_load_ptr(&value);
|
||||
EXPECT_EQ(dest, INT_AS_PTR(0x7f));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(atomic, atomic_store_ptr)
|
||||
{
|
||||
{
|
||||
void *value = INT_AS_PTR(0x7f);
|
||||
void *dest = nullptr;
|
||||
atomic_store_ptr(&dest, value);
|
||||
EXPECT_EQ(dest, INT_AS_PTR(0x7f));
|
||||
}
|
||||
}
|
||||
|
||||
#undef INT_AS_PTR
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# <pep8 compliant>
|
||||
from __future__ import annotations
|
||||
|
||||
bl_info = {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# Fit to match default projective camera with focal_length 50 and sensor_width 36.
|
||||
default_fisheye_polynomial = [
|
||||
-1.1735143712967577e-05,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# <pep8 compliant>
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# <pep8 compliant>
|
||||
from __future__ import annotations
|
||||
|
||||
import bpy
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# <pep8 compliant>
|
||||
from __future__ import annotations
|
||||
|
||||
import bpy
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# <pep8 compliant>
|
||||
from __future__ import annotations
|
||||
|
||||
from bl_operators.presets import AddPresetBase
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# <pep8 compliant>
|
||||
from __future__ import annotations
|
||||
|
||||
import bpy
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# <pep8 compliant>
|
||||
from __future__ import annotations
|
||||
|
||||
import bpy
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# <pep8 compliant>
|
||||
from __future__ import annotations
|
||||
|
||||
import bpy
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "blender/session.h"
|
||||
#include "blender/util.h"
|
||||
|
||||
#include "util/half.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Packed Images */
|
||||
|
@ -19,17 +21,40 @@ BlenderImageLoader::BlenderImageLoader(BL::Image b_image,
|
|||
frame(frame),
|
||||
tile_number(tile_number),
|
||||
/* Don't free cache for preview render to avoid race condition from T93560, to be fixed
|
||||
properly later as we are close to release. */
|
||||
* properly later as we are close to release. */
|
||||
free_cache(!is_preview_render && !b_image.has_data())
|
||||
{
|
||||
}
|
||||
|
||||
bool BlenderImageLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata)
|
||||
{
|
||||
metadata.width = b_image.size()[0];
|
||||
metadata.height = b_image.size()[1];
|
||||
if (b_image.source() != BL::Image::source_TILED) {
|
||||
/* Image sequence might have different dimensions, and hence needs to be handled in a special
|
||||
* manner.
|
||||
* NOTE: Currently the sequences are not handled by this image loader. */
|
||||
assert(b_image.source() != BL::Image::source_SEQUENCE);
|
||||
|
||||
metadata.width = b_image.size()[0];
|
||||
metadata.height = b_image.size()[1];
|
||||
metadata.channels = b_image.channels();
|
||||
}
|
||||
else {
|
||||
/* Different UDIM tiles might have different resolutions, so get resolution from the actual
|
||||
* tile. */
|
||||
BL::UDIMTile b_udim_tile = b_image.tiles.get(tile_number);
|
||||
if (b_udim_tile) {
|
||||
metadata.width = b_udim_tile.size()[0];
|
||||
metadata.height = b_udim_tile.size()[1];
|
||||
metadata.channels = b_udim_tile.channels();
|
||||
}
|
||||
else {
|
||||
metadata.width = 0;
|
||||
metadata.height = 0;
|
||||
metadata.channels = 0;
|
||||
}
|
||||
}
|
||||
|
||||
metadata.depth = 1;
|
||||
metadata.channels = b_image.channels();
|
||||
|
||||
if (b_image.is_float()) {
|
||||
if (metadata.channels == 1) {
|
||||
|
@ -62,79 +87,133 @@ bool BlenderImageLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaDat
|
|||
}
|
||||
|
||||
bool BlenderImageLoader::load_pixels(const ImageMetaData &metadata,
|
||||
void *pixels,
|
||||
const size_t pixels_size,
|
||||
void *out_pixels,
|
||||
const size_t out_pixels_size,
|
||||
const bool associate_alpha)
|
||||
{
|
||||
const size_t num_pixels = ((size_t)metadata.width) * metadata.height;
|
||||
const int channels = metadata.channels;
|
||||
|
||||
if (b_image.is_float()) {
|
||||
/* image data */
|
||||
float *image_pixels;
|
||||
image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile_number);
|
||||
if (metadata.type == IMAGE_DATA_TYPE_FLOAT || metadata.type == IMAGE_DATA_TYPE_FLOAT4) {
|
||||
/* Float. */
|
||||
float *in_pixels = image_get_float_pixels_for_frame(b_image, frame, tile_number);
|
||||
|
||||
if (image_pixels && num_pixels * channels == pixels_size) {
|
||||
memcpy(pixels, image_pixels, pixels_size * sizeof(float));
|
||||
if (in_pixels && num_pixels * channels == out_pixels_size) {
|
||||
/* Straight copy pixel data. */
|
||||
memcpy(out_pixels, in_pixels, out_pixels_size * sizeof(float));
|
||||
}
|
||||
else {
|
||||
/* Missing or invalid pixel data. */
|
||||
if (channels == 1) {
|
||||
memset(pixels, 0, num_pixels * sizeof(float));
|
||||
memset(out_pixels, 0, num_pixels * sizeof(float));
|
||||
}
|
||||
else {
|
||||
const size_t num_pixels_safe = pixels_size / channels;
|
||||
float *fp = (float *)pixels;
|
||||
for (int i = 0; i < num_pixels_safe; i++, fp += channels) {
|
||||
fp[0] = 1.0f;
|
||||
fp[1] = 0.0f;
|
||||
fp[2] = 1.0f;
|
||||
const size_t num_pixels_safe = out_pixels_size / channels;
|
||||
float *out_pixel = (float *)out_pixels;
|
||||
for (int i = 0; i < num_pixels_safe; i++, out_pixel += channels) {
|
||||
out_pixel[0] = 1.0f;
|
||||
out_pixel[1] = 0.0f;
|
||||
out_pixel[2] = 1.0f;
|
||||
if (channels == 4) {
|
||||
fp[3] = 1.0f;
|
||||
out_pixel[3] = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (image_pixels) {
|
||||
MEM_freeN(image_pixels);
|
||||
if (in_pixels) {
|
||||
MEM_freeN(in_pixels);
|
||||
}
|
||||
}
|
||||
else if (metadata.type == IMAGE_DATA_TYPE_HALF || metadata.type == IMAGE_DATA_TYPE_HALF4) {
|
||||
/* Half float. Blender does not have a half type, but in some cases
|
||||
* we up-sample byte to half to avoid precision loss for colorspace
|
||||
* conversion. */
|
||||
unsigned char *in_pixels = image_get_pixels_for_frame(b_image, frame, tile_number);
|
||||
|
||||
if (in_pixels && num_pixels * channels == out_pixels_size) {
|
||||
/* Convert uchar to half. */
|
||||
const uchar *in_pixel = in_pixels;
|
||||
half *out_pixel = (half *)out_pixels;
|
||||
if (associate_alpha && channels == 4) {
|
||||
for (size_t i = 0; i < num_pixels; i++, in_pixel += 4, out_pixel += 4) {
|
||||
const float alpha = util_image_cast_to_float(in_pixel[3]);
|
||||
out_pixel[0] = float_to_half_image(util_image_cast_to_float(in_pixel[0]) * alpha);
|
||||
out_pixel[1] = float_to_half_image(util_image_cast_to_float(in_pixel[1]) * alpha);
|
||||
out_pixel[2] = float_to_half_image(util_image_cast_to_float(in_pixel[2]) * alpha);
|
||||
out_pixel[3] = float_to_half_image(alpha);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (size_t i = 0; i < num_pixels; i++) {
|
||||
for (int c = 0; c < channels; c++, in_pixel++, out_pixel++) {
|
||||
*out_pixel = float_to_half_image(util_image_cast_to_float(*in_pixel));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Missing or invalid pixel data. */
|
||||
if (channels == 1) {
|
||||
memset(out_pixels, 0, num_pixels * sizeof(half));
|
||||
}
|
||||
else {
|
||||
const size_t num_pixels_safe = out_pixels_size / channels;
|
||||
half *out_pixel = (half *)out_pixels;
|
||||
for (int i = 0; i < num_pixels_safe; i++, out_pixel += channels) {
|
||||
out_pixel[0] = float_to_half_image(1.0f);
|
||||
out_pixel[1] = float_to_half_image(0.0f);
|
||||
out_pixel[2] = float_to_half_image(1.0f);
|
||||
if (channels == 4) {
|
||||
out_pixel[3] = float_to_half_image(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (in_pixels) {
|
||||
MEM_freeN(in_pixels);
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile_number);
|
||||
/* Byte. */
|
||||
unsigned char *in_pixels = image_get_pixels_for_frame(b_image, frame, tile_number);
|
||||
|
||||
if (image_pixels && num_pixels * channels == pixels_size) {
|
||||
memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
|
||||
if (in_pixels && num_pixels * channels == out_pixels_size) {
|
||||
/* Straight copy pixel data. */
|
||||
memcpy(out_pixels, in_pixels, out_pixels_size * sizeof(unsigned char));
|
||||
|
||||
if (associate_alpha && channels == 4) {
|
||||
/* Premultiply, byte images are always straight for Blender. */
|
||||
unsigned char *out_pixel = (unsigned char *)out_pixels;
|
||||
for (size_t i = 0; i < num_pixels; i++, out_pixel += 4) {
|
||||
out_pixel[0] = (out_pixel[0] * out_pixel[3]) / 255;
|
||||
out_pixel[1] = (out_pixel[1] * out_pixel[3]) / 255;
|
||||
out_pixel[2] = (out_pixel[2] * out_pixel[3]) / 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Missing or invalid pixel data. */
|
||||
if (channels == 1) {
|
||||
memset(pixels, 0, pixels_size * sizeof(unsigned char));
|
||||
memset(out_pixels, 0, out_pixels_size * sizeof(unsigned char));
|
||||
}
|
||||
else {
|
||||
const size_t num_pixels_safe = pixels_size / channels;
|
||||
unsigned char *cp = (unsigned char *)pixels;
|
||||
for (size_t i = 0; i < num_pixels_safe; i++, cp += channels) {
|
||||
cp[0] = 255;
|
||||
cp[1] = 0;
|
||||
cp[2] = 255;
|
||||
const size_t num_pixels_safe = out_pixels_size / channels;
|
||||
unsigned char *out_pixel = (unsigned char *)out_pixels;
|
||||
for (size_t i = 0; i < num_pixels_safe; i++, out_pixel += channels) {
|
||||
out_pixel[0] = 255;
|
||||
out_pixel[1] = 0;
|
||||
out_pixel[2] = 255;
|
||||
if (channels == 4) {
|
||||
cp[3] = 255;
|
||||
out_pixel[3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (image_pixels) {
|
||||
MEM_freeN(image_pixels);
|
||||
}
|
||||
|
||||
if (associate_alpha) {
|
||||
/* Premultiply, byte images are always straight for Blender. */
|
||||
unsigned char *cp = (unsigned char *)pixels;
|
||||
for (size_t i = 0; i < num_pixels; i++, cp += channels) {
|
||||
cp[0] = (cp[0] * cp[3]) / 255;
|
||||
cp[1] = (cp[1] * cp[3]) / 255;
|
||||
cp[2] = (cp[2] * cp[3]) / 255;
|
||||
}
|
||||
if (in_pixels) {
|
||||
MEM_freeN(in_pixels);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -811,7 +811,7 @@ BVHNode *BVHBuild::build_node(const BVHRange &range,
|
|||
/* unalignedLeafSAH = params.sah_primitive_cost * split.leafSAH; */
|
||||
unalignedSplitSAH = params.sah_node_cost * unaligned_split.bounds.half_area() +
|
||||
params.sah_primitive_cost * unaligned_split.nodeSAH;
|
||||
/* TOOD(sergey): Check we can create leaf already. */
|
||||
/* TODO(sergey): Check we can create leaf already. */
|
||||
/* Check whether unaligned split is better than the regular one. */
|
||||
if (unalignedSplitSAH < splitSAH) {
|
||||
do_unalinged_split = true;
|
||||
|
|
|
@ -457,6 +457,8 @@ void CUDADevice::reserve_local_memory(const uint kernel_features)
|
|||
/* Use the biggest kernel for estimation. */
|
||||
const DeviceKernel test_kernel = (kernel_features & KERNEL_FEATURE_NODE_RAYTRACE) ?
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE :
|
||||
(kernel_features & KERNEL_FEATURE_MNEE) ?
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE :
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE;
|
||||
|
||||
/* Launch kernel, using just 1 block appears sufficient to reserve memory for all
|
||||
|
|
|
@ -420,6 +420,8 @@ void HIPDevice::reserve_local_memory(const uint kernel_features)
|
|||
/* Use the biggest kernel for estimation. */
|
||||
const DeviceKernel test_kernel = (kernel_features & KERNEL_FEATURE_NODE_RAYTRACE) ?
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE :
|
||||
(kernel_features & KERNEL_FEATURE_MNEE) ?
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE :
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE;
|
||||
|
||||
/* Launch kernel, using just 1 block appears sufficient to reserve memory for all
|
||||
|
|
|
@ -33,6 +33,8 @@ const char *device_kernel_as_string(DeviceKernel kernel)
|
|||
return "integrator_shade_surface";
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE:
|
||||
return "integrator_shade_surface_raytrace";
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE:
|
||||
return "integrator_shade_surface_mnee";
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME:
|
||||
return "integrator_shade_volume";
|
||||
case DEVICE_KERNEL_INTEGRATOR_MEGAKERNEL:
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# include "util/progress.h"
|
||||
|
||||
# include "device/metal/bvh.h"
|
||||
# include "device/metal/util.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -18,6 +19,7 @@ CCL_NAMESPACE_BEGIN
|
|||
{ \
|
||||
string str = string_printf(__VA_ARGS__); \
|
||||
progress.set_substatus(str); \
|
||||
metal_printf("%s\n", str.c_str()); \
|
||||
}
|
||||
|
||||
BVHMetal::BVHMetal(const BVHParams ¶ms_,
|
||||
|
|
|
@ -31,6 +31,8 @@ class MetalDevice : public Device {
|
|||
string source[PSO_NUM];
|
||||
string source_md5[PSO_NUM];
|
||||
|
||||
bool capture_enabled = false;
|
||||
|
||||
KernelParamsMetal launch_params = {0};
|
||||
|
||||
/* MetalRT members ----------------------------------*/
|
||||
|
|
|
@ -86,6 +86,10 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
|
|||
use_metalrt = (atoi(metalrt) != 0);
|
||||
}
|
||||
|
||||
if (getenv("CYCLES_DEBUG_METAL_CAPTURE_KERNEL")) {
|
||||
capture_enabled = true;
|
||||
}
|
||||
|
||||
MTLArgumentDescriptor *arg_desc_params = [[MTLArgumentDescriptor alloc] init];
|
||||
arg_desc_params.dataType = MTLDataTypePointer;
|
||||
arg_desc_params.access = MTLArgumentAccessReadOnly;
|
||||
|
@ -394,7 +398,7 @@ MetalDevice::MetalMem *MetalDevice::generic_alloc(device_memory &mem)
|
|||
}
|
||||
|
||||
if (size > 0) {
|
||||
if (mem.type == MEM_DEVICE_ONLY) {
|
||||
if (mem.type == MEM_DEVICE_ONLY && !capture_enabled) {
|
||||
options = MTLResourceStorageModePrivate;
|
||||
}
|
||||
|
||||
|
@ -697,8 +701,7 @@ void MetalDevice::tex_alloc_as_buffer(device_texture &mem)
|
|||
void MetalDevice::tex_alloc(device_texture &mem)
|
||||
{
|
||||
/* Check that dimensions fit within maximum allowable size.
|
||||
See https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
|
||||
*/
|
||||
* See: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf */
|
||||
if (mem.data_width > 16384 || mem.data_height > 16384) {
|
||||
set_error(string_printf(
|
||||
"Texture exceeds maximum allowed size of 16384 x 16384 (requested: %zu x %zu)",
|
||||
|
|
|
@ -35,7 +35,8 @@ bool kernel_has_intersection(DeviceKernel device_kernel)
|
|||
device_kernel == DEVICE_KERNEL_INTEGRATOR_INTERSECT_SHADOW ||
|
||||
device_kernel == DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE ||
|
||||
device_kernel == DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK ||
|
||||
device_kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE);
|
||||
device_kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE ||
|
||||
device_kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE);
|
||||
}
|
||||
|
||||
struct ShaderCache {
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
# include "device/metal/util.h"
|
||||
# include "kernel/device/metal/globals.h"
|
||||
|
||||
# define metal_printf VLOG(4) << string_printf
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class MetalDevice;
|
||||
|
@ -77,6 +75,38 @@ class MetalDeviceQueue : public DeviceQueue {
|
|||
|
||||
void close_compute_encoder();
|
||||
void close_blit_encoder();
|
||||
|
||||
bool verbose_tracing = false;
|
||||
|
||||
/* Per-kernel profiling (see CYCLES_METAL_PROFILING). */
|
||||
|
||||
struct TimingData {
|
||||
DeviceKernel kernel;
|
||||
int work_size;
|
||||
uint64_t timing_id;
|
||||
};
|
||||
std::vector<TimingData> command_encoder_labels;
|
||||
id<MTLSharedEvent> timing_shared_event = nil;
|
||||
uint64_t timing_shared_event_id;
|
||||
uint64_t command_buffer_start_timing_id;
|
||||
|
||||
struct TimingStats {
|
||||
double total_time = 0.0;
|
||||
uint64_t total_work_size = 0;
|
||||
uint64_t num_dispatches = 0;
|
||||
};
|
||||
TimingStats timing_stats[DEVICE_KERNEL_NUM];
|
||||
double last_completion_time = 0.0;
|
||||
|
||||
/* .gputrace capture (see CYCLES_DEBUG_METAL_CAPTURE_...). */
|
||||
|
||||
id<MTLCaptureScope> mtlCaptureScope = nil;
|
||||
DeviceKernel capture_kernel;
|
||||
int capture_dispatch = 0;
|
||||
int capture_dispatch_counter = 0;
|
||||
bool is_capturing = false;
|
||||
bool is_capturing_to_disk = false;
|
||||
bool has_captured_to_disk = false;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -37,6 +37,61 @@ MetalDeviceQueue::MetalDeviceQueue(MetalDevice *device)
|
|||
}
|
||||
|
||||
wait_semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
if (@available(macos 10.14, *)) {
|
||||
if (getenv("CYCLES_METAL_PROFILING")) {
|
||||
/* Enable per-kernel timing breakdown (shown at end of render). */
|
||||
timing_shared_event = [mtlDevice newSharedEvent];
|
||||
}
|
||||
if (getenv("CYCLES_METAL_DEBUG")) {
|
||||
/* Enable very verbose tracing (shows every dispatch). */
|
||||
verbose_tracing = true;
|
||||
}
|
||||
timing_shared_event_id = 1;
|
||||
}
|
||||
|
||||
capture_kernel = DeviceKernel(-1);
|
||||
if (auto capture_kernel_str = getenv("CYCLES_DEBUG_METAL_CAPTURE_KERNEL")) {
|
||||
/* Enable .gputrace capture for the specified DeviceKernel. */
|
||||
MTLCaptureManager *captureManager = [MTLCaptureManager sharedCaptureManager];
|
||||
mtlCaptureScope = [captureManager newCaptureScopeWithDevice:mtlDevice];
|
||||
mtlCaptureScope.label = [NSString stringWithFormat:@"Cycles kernel dispatch"];
|
||||
[captureManager setDefaultCaptureScope:mtlCaptureScope];
|
||||
|
||||
capture_dispatch = -1;
|
||||
if (auto capture_dispatch_str = getenv("CYCLES_DEBUG_METAL_CAPTURE_DISPATCH")) {
|
||||
capture_dispatch = atoi(capture_dispatch_str);
|
||||
capture_dispatch_counter = 0;
|
||||
}
|
||||
|
||||
capture_kernel = DeviceKernel(atoi(capture_kernel_str));
|
||||
printf("Capture kernel: %d = %s\n", capture_kernel, device_kernel_as_string(capture_kernel));
|
||||
|
||||
if (auto capture_url = getenv("CYCLES_DEBUG_METAL_CAPTURE_URL")) {
|
||||
if (@available(macos 10.15, *)) {
|
||||
if ([captureManager supportsDestination:MTLCaptureDestinationGPUTraceDocument]) {
|
||||
|
||||
MTLCaptureDescriptor *captureDescriptor = [[MTLCaptureDescriptor alloc] init];
|
||||
captureDescriptor.captureObject = mtlCaptureScope;
|
||||
captureDescriptor.destination = MTLCaptureDestinationGPUTraceDocument;
|
||||
captureDescriptor.outputURL = [NSURL fileURLWithPath:@(capture_url)];
|
||||
|
||||
NSError *error;
|
||||
if (![captureManager startCaptureWithDescriptor:captureDescriptor error:&error]) {
|
||||
NSString *err = [error localizedDescription];
|
||||
printf("Start capture failed: %s\n", [err UTF8String]);
|
||||
}
|
||||
else {
|
||||
printf("Capture started (URL: %s)\n", capture_url);
|
||||
is_capturing_to_disk = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Capture to file is not supported\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MetalDeviceQueue::~MetalDeviceQueue()
|
||||
|
@ -58,6 +113,56 @@ MetalDeviceQueue::~MetalDeviceQueue()
|
|||
[mtlCommandQueue release];
|
||||
mtlCommandQueue = nil;
|
||||
}
|
||||
|
||||
if (mtlCaptureScope) {
|
||||
[mtlCaptureScope release];
|
||||
}
|
||||
|
||||
double total_time = 0.0;
|
||||
|
||||
/* Show per-kernel timings, if gathered (see CYCLES_METAL_PROFILING). */
|
||||
int64_t total_work_size = 0;
|
||||
int64_t num_dispatches = 0;
|
||||
for (auto &stat : timing_stats) {
|
||||
total_time += stat.total_time;
|
||||
total_work_size += stat.total_work_size;
|
||||
num_dispatches += stat.num_dispatches;
|
||||
}
|
||||
|
||||
if (num_dispatches) {
|
||||
printf("\nMetal dispatch stats:\n\n");
|
||||
auto header = string_printf("%-40s %16s %12s %12s %7s %7s",
|
||||
"Kernel name",
|
||||
"Total threads",
|
||||
"Dispatches",
|
||||
"Avg. T/D",
|
||||
"Time",
|
||||
"Time%");
|
||||
auto divider = string(header.length(), '-');
|
||||
printf("%s\n%s\n%s\n", divider.c_str(), header.c_str(), divider.c_str());
|
||||
|
||||
for (size_t i = 0; i < DEVICE_KERNEL_NUM; i++) {
|
||||
auto &stat = timing_stats[i];
|
||||
if (stat.num_dispatches > 0) {
|
||||
printf("%-40s %16s %12s %12s %6.2fs %6.2f%%\n",
|
||||
device_kernel_as_string(DeviceKernel(i)),
|
||||
string_human_readable_number(stat.total_work_size).c_str(),
|
||||
string_human_readable_number(stat.num_dispatches).c_str(),
|
||||
string_human_readable_number(stat.total_work_size / stat.num_dispatches).c_str(),
|
||||
stat.total_time,
|
||||
stat.total_time * 100.0 / total_time);
|
||||
}
|
||||
}
|
||||
printf("%s\n", divider.c_str());
|
||||
printf("%-40s %16s %12s %12s %6.2fs %6.2f%%\n",
|
||||
"",
|
||||
"",
|
||||
string_human_readable_number(num_dispatches).c_str(),
|
||||
"",
|
||||
total_time,
|
||||
100.0);
|
||||
printf("%s\n\n", divider.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
int MetalDeviceQueue::num_concurrent_states(const size_t /*state_size*/) const
|
||||
|
@ -101,6 +206,19 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
const int work_size,
|
||||
DeviceKernelArguments const &args)
|
||||
{
|
||||
if (kernel == capture_kernel) {
|
||||
if (capture_dispatch < 0 || capture_dispatch == capture_dispatch_counter) {
|
||||
/* Start gputrace capture. */
|
||||
if (mtlCommandBuffer) {
|
||||
synchronize();
|
||||
}
|
||||
[mtlCaptureScope beginScope];
|
||||
printf("[mtlCaptureScope beginScope]\n");
|
||||
is_capturing = true;
|
||||
}
|
||||
capture_dispatch_counter += 1;
|
||||
}
|
||||
|
||||
if (metal_device->have_error()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -110,6 +228,10 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
|
||||
id<MTLComputeCommandEncoder> mtlComputeCommandEncoder = get_compute_encoder(kernel);
|
||||
|
||||
if (timing_shared_event) {
|
||||
command_encoder_labels.push_back({kernel, work_size, timing_shared_event_id});
|
||||
}
|
||||
|
||||
/* Determine size requirement for argument buffer. */
|
||||
size_t arg_buffer_length = 0;
|
||||
for (size_t i = 0; i < args.count; i++) {
|
||||
|
@ -189,6 +311,14 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
/* Encode KernelParamsMetal buffers */
|
||||
[metal_device->mtlBufferKernelParamsEncoder setArgumentBuffer:arg_buffer offset:globals_offsets];
|
||||
|
||||
if (verbose_tracing || timing_shared_event || is_capturing) {
|
||||
/* Add human-readable labels if we're doing any form of debugging / profiling. */
|
||||
mtlComputeCommandEncoder.label = [[NSString alloc]
|
||||
initWithFormat:@"Metal queue launch %s, work_size %d",
|
||||
device_kernel_as_string(kernel),
|
||||
work_size];
|
||||
}
|
||||
|
||||
/* this relies on IntegratorStateGPU layout being contiguous device_ptrs */
|
||||
const size_t pointer_block_end = offsetof(KernelParamsMetal, __integrator_state) +
|
||||
sizeof(IntegratorStateGPU);
|
||||
|
@ -196,7 +326,7 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
int pointer_index = offset / sizeof(device_ptr);
|
||||
MetalDevice::MetalMem *mmem = *(
|
||||
MetalDevice::MetalMem **)((uint8_t *)&metal_device->launch_params + offset);
|
||||
if (mmem && (mmem->mtlBuffer || mmem->mtlTexture)) {
|
||||
if (mmem && mmem->mem && (mmem->mtlBuffer || mmem->mtlTexture)) {
|
||||
[metal_device->mtlBufferKernelParamsEncoder setBuffer:mmem->mtlBuffer
|
||||
offset:0
|
||||
atIndex:pointer_index];
|
||||
|
@ -270,6 +400,7 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE:
|
||||
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE:
|
||||
break;
|
||||
default:
|
||||
bvhMetalRT = nil;
|
||||
|
@ -343,12 +474,53 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
}
|
||||
}];
|
||||
|
||||
if (verbose_tracing || is_capturing) {
|
||||
/* Force a sync we've enabled step-by-step verbose tracing or if we're capturing. */
|
||||
synchronize();
|
||||
|
||||
/* Show queue counters and dispatch timing. */
|
||||
if (verbose_tracing) {
|
||||
if (kernel == DEVICE_KERNEL_INTEGRATOR_RESET) {
|
||||
printf(
|
||||
"_____________________________________.____________________.______________.___________"
|
||||
"______________________________________\n");
|
||||
}
|
||||
|
||||
printf("%-40s| %7d threads |%5.2fms | buckets [",
|
||||
device_kernel_as_string(kernel),
|
||||
work_size,
|
||||
last_completion_time * 1000.0);
|
||||
std::lock_guard<std::recursive_mutex> lock(metal_device->metal_mem_map_mutex);
|
||||
for (auto &it : metal_device->metal_mem_map) {
|
||||
const string c_integrator_queue_counter = "integrator_queue_counter";
|
||||
if (it.first->name == c_integrator_queue_counter) {
|
||||
/* Workaround "device_copy_from" being protected. */
|
||||
struct MyDeviceMemory : device_memory {
|
||||
void device_copy_from__IntegratorQueueCounter()
|
||||
{
|
||||
device_copy_from(0, data_width, 1, sizeof(IntegratorQueueCounter));
|
||||
}
|
||||
};
|
||||
((MyDeviceMemory *)it.first)->device_copy_from__IntegratorQueueCounter();
|
||||
|
||||
if (IntegratorQueueCounter *queue_counter = (IntegratorQueueCounter *)
|
||||
it.first->host_pointer) {
|
||||
for (int i = 0; i < DEVICE_KERNEL_INTEGRATOR_NUM; i++)
|
||||
printf("%s%d", i == 0 ? "" : ",", int(queue_counter->num_queued[i]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
return !(metal_device->have_error());
|
||||
}
|
||||
|
||||
bool MetalDeviceQueue::synchronize()
|
||||
{
|
||||
if (metal_device->have_error()) {
|
||||
if (has_captured_to_disk || metal_device->have_error()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -358,6 +530,28 @@ bool MetalDeviceQueue::synchronize()
|
|||
close_blit_encoder();
|
||||
|
||||
if (mtlCommandBuffer) {
|
||||
scoped_timer timer;
|
||||
if (timing_shared_event) {
|
||||
/* For per-kernel timing, add event handlers to measure & accumulate dispatch times. */
|
||||
__block double completion_time = 0;
|
||||
for (uint64_t i = command_buffer_start_timing_id; i < timing_shared_event_id; i++) {
|
||||
[timing_shared_event notifyListener:shared_event_listener
|
||||
atValue:i
|
||||
block:^(id<MTLSharedEvent> sharedEvent, uint64_t value) {
|
||||
completion_time = timer.get_time() - completion_time;
|
||||
last_completion_time = completion_time;
|
||||
for (auto label : command_encoder_labels) {
|
||||
if (label.timing_id == value) {
|
||||
TimingStats &stat = timing_stats[label.kernel];
|
||||
stat.num_dispatches++;
|
||||
stat.total_time += completion_time;
|
||||
stat.total_work_size += label.work_size;
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t shared_event_id = this->shared_event_id++;
|
||||
|
||||
if (@available(macos 10.14, *)) {
|
||||
|
@ -373,6 +567,22 @@ bool MetalDeviceQueue::synchronize()
|
|||
dispatch_semaphore_wait(wait_semaphore, DISPATCH_TIME_FOREVER);
|
||||
}
|
||||
|
||||
if (is_capturing) {
|
||||
[mtlCaptureScope endScope];
|
||||
is_capturing = false;
|
||||
printf("[mtlCaptureScope endScope]\n");
|
||||
|
||||
if (is_capturing_to_disk) {
|
||||
if (@available(macos 10.15, *)) {
|
||||
[[MTLCaptureManager sharedCaptureManager] stopCapture];
|
||||
has_captured_to_disk = true;
|
||||
is_capturing_to_disk = false;
|
||||
is_capturing = false;
|
||||
printf("Capture stopped\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[mtlCommandBuffer release];
|
||||
|
||||
for (const CopyBack &mmem : copy_back_mem) {
|
||||
|
@ -384,6 +594,7 @@ bool MetalDeviceQueue::synchronize()
|
|||
metal_device->flush_delayed_free_list();
|
||||
|
||||
mtlCommandBuffer = nil;
|
||||
command_encoder_labels.clear();
|
||||
}
|
||||
|
||||
return !(metal_device->have_error());
|
||||
|
@ -529,6 +740,13 @@ id<MTLComputeCommandEncoder> MetalDeviceQueue::get_compute_encoder(DeviceKernel
|
|||
{
|
||||
bool concurrent = (kernel < DEVICE_KERNEL_INTEGRATOR_NUM);
|
||||
|
||||
if (timing_shared_event) {
|
||||
/* Close the current encoder to ensure we're able to capture per-encoder timing data. */
|
||||
if (mtlComputeEncoder) {
|
||||
close_compute_encoder();
|
||||
}
|
||||
}
|
||||
|
||||
if (@available(macos 10.14, *)) {
|
||||
if (mtlComputeEncoder) {
|
||||
if (mtlComputeEncoder.dispatchType == concurrent ? MTLDispatchTypeConcurrent :
|
||||
|
@ -574,6 +792,7 @@ id<MTLBlitCommandEncoder> MetalDeviceQueue::get_blit_encoder()
|
|||
if (!mtlCommandBuffer) {
|
||||
mtlCommandBuffer = [mtlCommandQueue commandBuffer];
|
||||
[mtlCommandBuffer retain];
|
||||
command_buffer_start_timing_id = timing_shared_event_id;
|
||||
}
|
||||
|
||||
mtlBlitEncoder = [mtlCommandBuffer blitCommandEncoder];
|
||||
|
@ -584,6 +803,10 @@ void MetalDeviceQueue::close_compute_encoder()
|
|||
{
|
||||
[mtlComputeEncoder endEncoding];
|
||||
mtlComputeEncoder = nil;
|
||||
|
||||
if (timing_shared_event) {
|
||||
[mtlCommandBuffer encodeSignalEvent:timing_shared_event value:timing_shared_event_id++];
|
||||
}
|
||||
}
|
||||
|
||||
void MetalDeviceQueue::close_blit_encoder()
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
# include "util/thread.h"
|
||||
|
||||
# define metal_printf VLOG(4) << string_printf
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
enum MetalGPUVendor {
|
||||
|
|
|
@ -452,9 +452,10 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
|
|||
}
|
||||
|
||||
{ /* Load and compile PTX module with OptiX kernels. */
|
||||
string ptx_data, ptx_filename = path_get((kernel_features & KERNEL_FEATURE_NODE_RAYTRACE) ?
|
||||
"lib/kernel_optix_shader_raytrace.ptx" :
|
||||
"lib/kernel_optix.ptx");
|
||||
string ptx_data, ptx_filename = path_get(
|
||||
(kernel_features & (KERNEL_FEATURE_NODE_RAYTRACE | KERNEL_FEATURE_MNEE)) ?
|
||||
"lib/kernel_optix_shader_raytrace.ptx" :
|
||||
"lib/kernel_optix.ptx");
|
||||
if (use_adaptive_compilation() || path_file_size(ptx_filename) == -1) {
|
||||
if (!getenv("OPTIX_ROOT_DIR")) {
|
||||
set_error(
|
||||
|
@ -464,7 +465,9 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
|
|||
}
|
||||
ptx_filename = compile_kernel(
|
||||
kernel_features,
|
||||
(kernel_features & KERNEL_FEATURE_NODE_RAYTRACE) ? "kernel_shader_raytrace" : "kernel",
|
||||
(kernel_features & (KERNEL_FEATURE_NODE_RAYTRACE | KERNEL_FEATURE_MNEE)) ?
|
||||
"kernel_shader_raytrace" :
|
||||
"kernel",
|
||||
"optix",
|
||||
true);
|
||||
}
|
||||
|
@ -550,7 +553,8 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
|
|||
OptixBuiltinISOptions builtin_options = {};
|
||||
# if OPTIX_ABI_VERSION >= 55
|
||||
builtin_options.builtinISModuleType = OPTIX_PRIMITIVE_TYPE_ROUND_CATMULLROM;
|
||||
builtin_options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE;
|
||||
builtin_options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE |
|
||||
OPTIX_BUILD_FLAG_ALLOW_COMPACTION;
|
||||
builtin_options.curveEndcapFlags = OPTIX_CURVE_ENDCAP_DEFAULT; /* Disable end-caps. */
|
||||
# else
|
||||
builtin_options.builtinISModuleType = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE;
|
||||
|
@ -620,6 +624,14 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
|
|||
"__direct_callable__svm_node_bevel";
|
||||
}
|
||||
|
||||
/* MNEE. */
|
||||
if (kernel_features & KERNEL_FEATURE_MNEE) {
|
||||
group_descs[PG_RGEN_SHADE_SURFACE_MNEE].kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
|
||||
group_descs[PG_RGEN_SHADE_SURFACE_MNEE].raygen.module = optix_module;
|
||||
group_descs[PG_RGEN_SHADE_SURFACE_MNEE].raygen.entryFunctionName =
|
||||
"__raygen__kernel_optix_integrator_shade_surface_mnee";
|
||||
}
|
||||
|
||||
optix_assert(optixProgramGroupCreate(
|
||||
context, group_descs, NUM_PROGRAM_GROUPS, &group_options, nullptr, 0, groups));
|
||||
|
||||
|
@ -701,6 +713,46 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
|
|||
pipelines[PIP_SHADE_RAYTRACE], 0, dss, css, motion_blur ? 3 : 2));
|
||||
}
|
||||
|
||||
if (kernel_features & KERNEL_FEATURE_MNEE) {
|
||||
/* Create MNEE pipeline. */
|
||||
vector<OptixProgramGroup> pipeline_groups;
|
||||
pipeline_groups.reserve(NUM_PROGRAM_GROUPS);
|
||||
pipeline_groups.push_back(groups[PG_RGEN_SHADE_SURFACE_MNEE]);
|
||||
pipeline_groups.push_back(groups[PG_MISS]);
|
||||
pipeline_groups.push_back(groups[PG_HITD]);
|
||||
pipeline_groups.push_back(groups[PG_HITS]);
|
||||
pipeline_groups.push_back(groups[PG_HITL]);
|
||||
pipeline_groups.push_back(groups[PG_HITV]);
|
||||
if (motion_blur) {
|
||||
pipeline_groups.push_back(groups[PG_HITD_MOTION]);
|
||||
pipeline_groups.push_back(groups[PG_HITS_MOTION]);
|
||||
}
|
||||
if (kernel_features & KERNEL_FEATURE_POINTCLOUD) {
|
||||
pipeline_groups.push_back(groups[PG_HITD_POINTCLOUD]);
|
||||
pipeline_groups.push_back(groups[PG_HITS_POINTCLOUD]);
|
||||
}
|
||||
pipeline_groups.push_back(groups[PG_CALL_SVM_AO]);
|
||||
pipeline_groups.push_back(groups[PG_CALL_SVM_BEVEL]);
|
||||
|
||||
optix_assert(optixPipelineCreate(context,
|
||||
&pipeline_options,
|
||||
&link_options,
|
||||
pipeline_groups.data(),
|
||||
pipeline_groups.size(),
|
||||
nullptr,
|
||||
0,
|
||||
&pipelines[PIP_SHADE_MNEE]));
|
||||
|
||||
/* Combine ray generation and trace continuation stack size. */
|
||||
const unsigned int css = stack_size[PG_RGEN_SHADE_SURFACE_MNEE].cssRG +
|
||||
link_options.maxTraceDepth * trace_css;
|
||||
const unsigned int dss = 0;
|
||||
|
||||
/* Set stack size depending on pipeline options. */
|
||||
optix_assert(
|
||||
optixPipelineSetStackSize(pipelines[PIP_SHADE_MNEE], 0, dss, css, motion_blur ? 3 : 2));
|
||||
}
|
||||
|
||||
{ /* Create intersection-only pipeline. */
|
||||
vector<OptixProgramGroup> pipeline_groups;
|
||||
pipeline_groups.reserve(NUM_PROGRAM_GROUPS);
|
||||
|
@ -1186,7 +1238,7 @@ bool OptiXDevice::denoise_configure_if_needed(DenoiseContext &context)
|
|||
const OptixResult result = optixDenoiserSetup(
|
||||
denoiser_.optix_denoiser,
|
||||
0, /* Work around bug in r495 drivers that causes artifacts when denoiser setup is called
|
||||
on a stream that is not the default stream */
|
||||
* on a stream that is not the default stream. */
|
||||
tile_size.x + denoiser_.sizes.overlapWindowSizeInPixels * 2,
|
||||
tile_size.y + denoiser_.sizes.overlapWindowSizeInPixels * 2,
|
||||
denoiser_.state.device_pointer,
|
||||
|
@ -1336,7 +1388,10 @@ bool OptiXDevice::build_optix_bvh(BVHOptiX *bvh,
|
|||
OptixAccelBufferSizes sizes = {};
|
||||
OptixAccelBuildOptions options = {};
|
||||
options.operation = operation;
|
||||
if (use_fast_trace_bvh) {
|
||||
if (use_fast_trace_bvh ||
|
||||
/* The build flags have to match the ones used to query the built-in curve intersection
|
||||
program (see optixBuiltinISModuleGet above) */
|
||||
build_input.type == OPTIX_BUILD_INPUT_TYPE_CURVES) {
|
||||
VLOG(2) << "Using fast to trace OptiX BVH";
|
||||
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE | OPTIX_BUILD_FLAG_ALLOW_COMPACTION;
|
||||
}
|
||||
|
@ -1861,7 +1916,7 @@ void OptiXDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
|
|||
{
|
||||
/* Can disable __anyhit__kernel_optix_visibility_test by default (except for thick curves,
|
||||
* since it needs to filter out end-caps there).
|
||||
|
||||
*
|
||||
* It is enabled where necessary (visibility mask exceeds 8 bits or the other any-hit
|
||||
* programs like __anyhit__kernel_optix_shadow_all_hit) via OPTIX_RAY_FLAG_ENFORCE_ANYHIT.
|
||||
*/
|
||||
|
|
|
@ -24,6 +24,7 @@ enum {
|
|||
PG_RGEN_INTERSECT_SUBSURFACE,
|
||||
PG_RGEN_INTERSECT_VOLUME_STACK,
|
||||
PG_RGEN_SHADE_SURFACE_RAYTRACE,
|
||||
PG_RGEN_SHADE_SURFACE_MNEE,
|
||||
PG_MISS,
|
||||
PG_HITD, /* Default hit group. */
|
||||
PG_HITS, /* __SHADOW_RECORD_ALL__ hit group. */
|
||||
|
@ -46,7 +47,7 @@ static const int CALLABLE_PROGRAM_GROUPS_BASE = PG_CALL_SVM_AO;
|
|||
static const int NUM_CALLABLE_PROGRAM_GROUPS = 2;
|
||||
|
||||
/* List of OptiX pipelines. */
|
||||
enum { PIP_SHADE_RAYTRACE, PIP_INTERSECT, NUM_PIPELINES };
|
||||
enum { PIP_SHADE_RAYTRACE, PIP_SHADE_MNEE, PIP_INTERSECT, NUM_PIPELINES };
|
||||
|
||||
/* A single shader binding table entry. */
|
||||
struct SbtRecord {
|
||||
|
|
|
@ -28,6 +28,7 @@ void OptiXDeviceQueue::init_execution()
|
|||
static bool is_optix_specific_kernel(DeviceKernel kernel)
|
||||
{
|
||||
return (kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_INTERSECT_SHADOW ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE ||
|
||||
|
@ -63,7 +64,8 @@ bool OptiXDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
cuda_stream_));
|
||||
|
||||
if (kernel == DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE) {
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE) {
|
||||
cuda_device_assert(
|
||||
cuda_device_,
|
||||
cuMemcpyHtoDAsync(launch_params_ptr + offsetof(KernelParamsOptiX, render_buffer),
|
||||
|
@ -82,6 +84,10 @@ bool OptiXDeviceQueue::enqueue(DeviceKernel kernel,
|
|||
pipeline = optix_device->pipelines[PIP_SHADE_RAYTRACE];
|
||||
sbt_params.raygenRecord = sbt_data_ptr + PG_RGEN_SHADE_SURFACE_RAYTRACE * sizeof(SbtRecord);
|
||||
break;
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE:
|
||||
pipeline = optix_device->pipelines[PIP_SHADE_MNEE];
|
||||
sbt_params.raygenRecord = sbt_data_ptr + PG_RGEN_SHADE_SURFACE_MNEE * sizeof(SbtRecord);
|
||||
break;
|
||||
case DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST:
|
||||
pipeline = optix_device->pipelines[PIP_INTERSECT];
|
||||
sbt_params.raygenRecord = sbt_data_ptr + PG_RGEN_INTERSECT_CLOSEST * sizeof(SbtRecord);
|
||||
|
|
|
@ -23,10 +23,18 @@ HdCyclesDisplayDriver::HdCyclesDisplayDriver(HdCyclesSession *renderParam, Hgi *
|
|||
|
||||
HdCyclesDisplayDriver::~HdCyclesDisplayDriver()
|
||||
{
|
||||
deinit();
|
||||
if (texture_) {
|
||||
_hgi->DestroyTexture(&texture_);
|
||||
}
|
||||
|
||||
if (gl_pbo_id_) {
|
||||
glDeleteBuffers(1, &gl_pbo_id_);
|
||||
}
|
||||
|
||||
gl_context_dispose();
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::init()
|
||||
void HdCyclesDisplayDriver::gl_context_create()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!gl_context_) {
|
||||
|
@ -64,16 +72,42 @@ void HdCyclesDisplayDriver::init()
|
|||
}
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::deinit()
|
||||
bool HdCyclesDisplayDriver::gl_context_enable()
|
||||
{
|
||||
if (texture_) {
|
||||
_hgi->DestroyTexture(&texture_);
|
||||
#ifdef _WIN32
|
||||
if (!hdc_ || !gl_context_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gl_pbo_id_) {
|
||||
glDeleteBuffers(1, &gl_pbo_id_);
|
||||
mutex_.lock();
|
||||
|
||||
// Do not change context if this is called in the main thread
|
||||
if (wglGetCurrentContext() == nullptr) {
|
||||
if (!TF_VERIFY(wglMakeCurrent((HDC)hdc_, (HGLRC)gl_context_))) {
|
||||
mutex_.unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::gl_context_disable()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (wglGetCurrentContext() == gl_context_) {
|
||||
TF_VERIFY(wglMakeCurrent(nullptr, nullptr));
|
||||
}
|
||||
|
||||
mutex_.unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::gl_context_dispose()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (gl_context_) {
|
||||
TF_VERIFY(wglDeleteContext((HGLRC)gl_context_));
|
||||
|
@ -90,13 +124,9 @@ bool HdCyclesDisplayDriver::update_begin(const Params ¶ms,
|
|||
int texture_width,
|
||||
int texture_height)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!hdc_ || !gl_context_) {
|
||||
if (!gl_context_enable()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
graphics_interop_activate();
|
||||
|
||||
if (gl_render_sync_) {
|
||||
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||
|
@ -121,15 +151,14 @@ bool HdCyclesDisplayDriver::update_begin(const Params ¶ms,
|
|||
void HdCyclesDisplayDriver::update_end()
|
||||
{
|
||||
gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
glFlush();
|
||||
|
||||
graphics_interop_deactivate();
|
||||
gl_context_disable();
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::flush()
|
||||
{
|
||||
graphics_interop_activate();
|
||||
gl_context_enable();
|
||||
|
||||
if (gl_upload_sync_) {
|
||||
glWaitSync((GLsync)gl_upload_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||
|
@ -139,7 +168,7 @@ void HdCyclesDisplayDriver::flush()
|
|||
glWaitSync((GLsync)gl_render_sync_, 0, GL_TIMEOUT_IGNORED);
|
||||
}
|
||||
|
||||
graphics_interop_deactivate();
|
||||
gl_context_disable();
|
||||
}
|
||||
|
||||
half4 *HdCyclesDisplayDriver::map_texture_buffer()
|
||||
|
@ -179,25 +208,12 @@ DisplayDriver::GraphicsInterop HdCyclesDisplayDriver::graphics_interop_get()
|
|||
|
||||
void HdCyclesDisplayDriver::graphics_interop_activate()
|
||||
{
|
||||
mutex_.lock();
|
||||
|
||||
#ifdef _WIN32
|
||||
// Do not change context if this is called in the main thread
|
||||
if (wglGetCurrentContext() == nullptr) {
|
||||
TF_VERIFY(wglMakeCurrent((HDC)hdc_, (HGLRC)gl_context_));
|
||||
}
|
||||
#endif
|
||||
gl_context_enable();
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::graphics_interop_deactivate()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (wglGetCurrentContext() == gl_context_) {
|
||||
TF_VERIFY(wglMakeCurrent(nullptr, nullptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
mutex_.unlock();
|
||||
gl_context_disable();
|
||||
}
|
||||
|
||||
void HdCyclesDisplayDriver::clear()
|
||||
|
@ -214,7 +230,11 @@ void HdCyclesDisplayDriver::draw(const Params ¶ms)
|
|||
return;
|
||||
}
|
||||
|
||||
init();
|
||||
if (!renderBuffer->IsResourceUsed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
gl_context_create();
|
||||
|
||||
// Cycles 'DisplayDriver' only supports 'half4' format
|
||||
TF_VERIFY(renderBuffer->GetFormat() == HdFormatFloat16Vec4);
|
||||
|
@ -255,7 +275,6 @@ void HdCyclesDisplayDriver::draw(const Params ¶ms)
|
|||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
glFlush();
|
||||
|
||||
need_update_ = false;
|
||||
|
|
|
@ -19,9 +19,6 @@ class HdCyclesDisplayDriver final : public CCL_NS::DisplayDriver {
|
|||
~HdCyclesDisplayDriver();
|
||||
|
||||
private:
|
||||
void init();
|
||||
void deinit();
|
||||
|
||||
void next_tile_begin() override;
|
||||
|
||||
bool update_begin(const Params ¶ms, int texture_width, int texture_height) override;
|
||||
|
@ -41,6 +38,11 @@ class HdCyclesDisplayDriver final : public CCL_NS::DisplayDriver {
|
|||
|
||||
void draw(const Params ¶ms) override;
|
||||
|
||||
void gl_context_create();
|
||||
bool gl_context_enable();
|
||||
void gl_context_disable();
|
||||
void gl_context_dispose();
|
||||
|
||||
HdCyclesSession *const _renderParam;
|
||||
Hgi *const _hgi;
|
||||
|
||||
|
@ -48,7 +50,6 @@ class HdCyclesDisplayDriver final : public CCL_NS::DisplayDriver {
|
|||
void *hdc_ = nullptr;
|
||||
void *gl_context_ = nullptr;
|
||||
#endif
|
||||
|
||||
CCL_NS::thread_mutex mutex_;
|
||||
|
||||
PXR_NS::HgiTextureHandle texture_;
|
||||
|
|
|
@ -30,11 +30,11 @@ bool HdCyclesOutputDriver::update_render_tile(const Tile &tile)
|
|||
std::vector<float> pixels;
|
||||
|
||||
for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
|
||||
if (aovBinding == _renderParam->GetDisplayAovBinding()) {
|
||||
continue; // Display AOV binding is already updated by Cycles display driver
|
||||
}
|
||||
|
||||
if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) {
|
||||
if (aovBinding == _renderParam->GetDisplayAovBinding() && renderBuffer->IsResourceUsed()) {
|
||||
continue; // Display AOV binding is already updated by Cycles display driver
|
||||
}
|
||||
|
||||
const HdFormat format = renderBuffer->GetFormat();
|
||||
if (format == HdFormatInvalid) {
|
||||
continue; // Skip invalid AOV bindings
|
||||
|
|
|
@ -35,7 +35,7 @@ bool HdCyclesRenderBuffer::Allocate(const GfVec3i &dimensions, HdFormat format,
|
|||
return false;
|
||||
}
|
||||
|
||||
const size_t oldSize = _data.size();
|
||||
const size_t oldSize = _dataSize;
|
||||
const size_t newSize = dimensions[0] * dimensions[1] * HdDataSizeOfFormat(format);
|
||||
if (oldSize == newSize) {
|
||||
return true;
|
||||
|
@ -49,8 +49,8 @@ bool HdCyclesRenderBuffer::Allocate(const GfVec3i &dimensions, HdFormat format,
|
|||
_width = dimensions[0];
|
||||
_height = dimensions[1];
|
||||
_format = format;
|
||||
|
||||
_data.resize(newSize);
|
||||
_dataSize = newSize;
|
||||
_resourceUsed = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ void HdCyclesRenderBuffer::_Deallocate()
|
|||
|
||||
_data.clear();
|
||||
_data.shrink_to_fit();
|
||||
_dataSize = 0;
|
||||
|
||||
_resource = VtValue();
|
||||
}
|
||||
|
@ -74,6 +75,10 @@ void *HdCyclesRenderBuffer::Map()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (_data.size() != _dataSize) {
|
||||
_data.resize(_dataSize);
|
||||
}
|
||||
|
||||
++_mapped;
|
||||
|
||||
return _data.data();
|
||||
|
@ -103,10 +108,17 @@ void HdCyclesRenderBuffer::SetConverged(bool converged)
|
|||
_converged = converged;
|
||||
}
|
||||
|
||||
bool HdCyclesRenderBuffer::IsResourceUsed() const
|
||||
{
|
||||
return _resourceUsed;
|
||||
}
|
||||
|
||||
VtValue HdCyclesRenderBuffer::GetResource(bool multiSampled) const
|
||||
{
|
||||
TF_UNUSED(multiSampled);
|
||||
|
||||
_resourceUsed = true;
|
||||
|
||||
return _resource;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ class HdCyclesRenderBuffer final : public PXR_NS::HdRenderBuffer {
|
|||
|
||||
void SetConverged(bool converged);
|
||||
|
||||
bool IsResourceUsed() const;
|
||||
|
||||
PXR_NS::VtValue GetResource(bool multiSampled = false) const override;
|
||||
|
||||
void SetResource(const PXR_NS::VtValue &resource);
|
||||
|
@ -74,9 +76,11 @@ class HdCyclesRenderBuffer final : public PXR_NS::HdRenderBuffer {
|
|||
unsigned int _width = 0u;
|
||||
unsigned int _height = 0u;
|
||||
PXR_NS::HdFormat _format = PXR_NS::HdFormatInvalid;
|
||||
size_t _dataSize = 0;
|
||||
|
||||
std::vector<uint8_t> _data;
|
||||
PXR_NS::VtValue _resource;
|
||||
mutable std::atomic_bool _resourceUsed = false;
|
||||
|
||||
std::atomic_int _mapped = 0;
|
||||
std::atomic_bool _converged = false;
|
||||
|
|
|
@ -65,6 +65,8 @@ PathTraceWorkGPU::PathTraceWorkGPU(Device *device,
|
|||
integrator_shader_sort_counter_(device, "integrator_shader_sort_counter", MEM_READ_WRITE),
|
||||
integrator_shader_raytrace_sort_counter_(
|
||||
device, "integrator_shader_raytrace_sort_counter", MEM_READ_WRITE),
|
||||
integrator_shader_mnee_sort_counter_(
|
||||
device, "integrator_shader_mnee_sort_counter", MEM_READ_WRITE),
|
||||
integrator_shader_sort_prefix_sum_(
|
||||
device, "integrator_shader_sort_prefix_sum", MEM_READ_WRITE),
|
||||
integrator_next_main_path_index_(device, "integrator_next_main_path_index", MEM_READ_WRITE),
|
||||
|
@ -188,6 +190,9 @@ void PathTraceWorkGPU::alloc_integrator_sorting()
|
|||
integrator_shader_raytrace_sort_counter_.alloc(max_shaders);
|
||||
integrator_shader_raytrace_sort_counter_.zero_to_device();
|
||||
|
||||
integrator_shader_mnee_sort_counter_.alloc(max_shaders);
|
||||
integrator_shader_mnee_sort_counter_.zero_to_device();
|
||||
|
||||
integrator_shader_sort_prefix_sum_.alloc(max_shaders);
|
||||
integrator_shader_sort_prefix_sum_.zero_to_device();
|
||||
|
||||
|
@ -195,6 +200,8 @@ void PathTraceWorkGPU::alloc_integrator_sorting()
|
|||
(int *)integrator_shader_sort_counter_.device_pointer;
|
||||
integrator_state_gpu_.sort_key_counter[DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE] =
|
||||
(int *)integrator_shader_raytrace_sort_counter_.device_pointer;
|
||||
integrator_state_gpu_.sort_key_counter[DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE] =
|
||||
(int *)integrator_shader_mnee_sort_counter_.device_pointer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,6 +334,7 @@ void PathTraceWorkGPU::enqueue_reset()
|
|||
queue_->zero_to_device(integrator_queue_counter_);
|
||||
queue_->zero_to_device(integrator_shader_sort_counter_);
|
||||
queue_->zero_to_device(integrator_shader_raytrace_sort_counter_);
|
||||
queue_->zero_to_device(integrator_shader_mnee_sort_counter_);
|
||||
|
||||
/* Tiles enqueue need to know number of active paths, which is based on this counter. Zero the
|
||||
* counter on the host side because `zero_to_device()` is not doing it. */
|
||||
|
@ -450,6 +458,7 @@ void PathTraceWorkGPU::enqueue_path_iteration(DeviceKernel kernel, const int num
|
|||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE:
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME: {
|
||||
/* Shading kernels with integrator state and render buffer. */
|
||||
DeviceKernelArguments args(&d_path_index, &buffers_->buffer.device_pointer, &work_size);
|
||||
|
@ -1080,13 +1089,15 @@ int PathTraceWorkGPU::shadow_catcher_count_possible_splits()
|
|||
bool PathTraceWorkGPU::kernel_uses_sorting(DeviceKernel kernel)
|
||||
{
|
||||
return (kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE);
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE);
|
||||
}
|
||||
|
||||
bool PathTraceWorkGPU::kernel_creates_shadow_paths(DeviceKernel kernel)
|
||||
{
|
||||
return (kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME);
|
||||
}
|
||||
|
||||
|
@ -1094,7 +1105,8 @@ bool PathTraceWorkGPU::kernel_creates_ao_paths(DeviceKernel kernel)
|
|||
{
|
||||
return (device_scene_->data.kernel_features & KERNEL_FEATURE_AO) &&
|
||||
(kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE);
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE ||
|
||||
kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE);
|
||||
}
|
||||
|
||||
bool PathTraceWorkGPU::kernel_is_shadow_path(DeviceKernel kernel)
|
||||
|
|
|
@ -133,6 +133,7 @@ class PathTraceWorkGPU : public PathTraceWork {
|
|||
/* Shader sorting. */
|
||||
device_vector<int> integrator_shader_sort_counter_;
|
||||
device_vector<int> integrator_shader_raytrace_sort_counter_;
|
||||
device_vector<int> integrator_shader_mnee_sort_counter_;
|
||||
device_vector<int> integrator_shader_sort_prefix_sum_;
|
||||
/* Path split. */
|
||||
device_vector<int> integrator_next_main_path_index_;
|
||||
|
|
|
@ -241,7 +241,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
}
|
||||
ccl_gpu_kernel_postfix
|
||||
|
||||
#ifdef __KERNEL_METAL__
|
||||
#if defined(__KERNEL_METAL_APPLE__) && defined(__METALRT__)
|
||||
constant int __dummy_constant [[function_constant(0)]];
|
||||
#endif
|
||||
|
||||
|
@ -256,7 +256,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
if (global_index < work_size) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
|
||||
#ifdef __KERNEL_METAL__
|
||||
#if defined(__KERNEL_METAL_APPLE__) && defined(__METALRT__)
|
||||
KernelGlobals kg = NULL;
|
||||
/* Workaround Ambient Occlusion and Bevel nodes not working with Metal.
|
||||
* Dummy offset should not affect result, but somehow fixes bug! */
|
||||
|
@ -269,6 +269,21 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
}
|
||||
ccl_gpu_kernel_postfix
|
||||
|
||||
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
||||
ccl_gpu_kernel_signature(integrator_shade_surface_mnee,
|
||||
ccl_global const int *path_index_array,
|
||||
ccl_global float *render_buffer,
|
||||
const int work_size)
|
||||
{
|
||||
const int global_index = ccl_gpu_global_id_x();
|
||||
|
||||
if (global_index < work_size) {
|
||||
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
|
||||
ccl_gpu_kernel_call(integrator_shade_surface_mnee(NULL, state, render_buffer));
|
||||
}
|
||||
}
|
||||
ccl_gpu_kernel_postfix
|
||||
|
||||
ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
||||
ccl_gpu_kernel_signature(integrator_shade_volume,
|
||||
ccl_global const int *path_index_array,
|
||||
|
|
|
@ -15,3 +15,11 @@ extern "C" __global__ void __raygen__kernel_optix_integrator_shade_surface_raytr
|
|||
global_index;
|
||||
integrator_shade_surface_raytrace(nullptr, path_index, __params.render_buffer);
|
||||
}
|
||||
|
||||
extern "C" __global__ void __raygen__kernel_optix_integrator_shade_surface_mnee()
|
||||
{
|
||||
const int global_index = optixGetLaunchIndex().x;
|
||||
const int path_index = (__params.path_index_array) ? __params.path_index_array[global_index] :
|
||||
global_index;
|
||||
integrator_shade_surface_mnee(nullptr, path_index, __params.render_buffer);
|
||||
}
|
||||
|
|
|
@ -243,9 +243,12 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
|
|||
/* Setup next kernel to execute. */
|
||||
const bool use_caustics = kernel_data.integrator.use_caustics &&
|
||||
(object_flag & SD_OBJECT_CAUSTICS);
|
||||
const bool use_raytrace_kernel = (shader_flags & SD_HAS_RAYTRACE) || use_caustics;
|
||||
const bool use_raytrace_kernel = (shader_flags & SD_HAS_RAYTRACE);
|
||||
|
||||
if (use_raytrace_kernel) {
|
||||
if (use_caustics) {
|
||||
INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE, shader_index);
|
||||
}
|
||||
else if (use_raytrace_kernel) {
|
||||
INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader_index);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -125,9 +125,12 @@ ccl_device_forceinline void integrator_split_shadow_catcher(
|
|||
const int flags = kernel_tex_fetch(__shaders, shader).flags;
|
||||
const bool use_caustics = kernel_data.integrator.use_caustics &&
|
||||
(object_flags & SD_OBJECT_CAUSTICS);
|
||||
const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics;
|
||||
const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
|
||||
|
||||
if (use_raytrace_kernel) {
|
||||
if (use_caustics) {
|
||||
INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE, shader);
|
||||
}
|
||||
else if (use_raytrace_kernel) {
|
||||
INTEGRATOR_PATH_INIT_SORTED(DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader);
|
||||
}
|
||||
else {
|
||||
|
@ -150,9 +153,13 @@ ccl_device_forceinline void integrator_intersect_next_kernel_after_shadow_catche
|
|||
const int object_flags = intersection_get_object_flags(kg, &isect);
|
||||
const bool use_caustics = kernel_data.integrator.use_caustics &&
|
||||
(object_flags & SD_OBJECT_CAUSTICS);
|
||||
const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics;
|
||||
const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
|
||||
|
||||
if (use_raytrace_kernel) {
|
||||
if (use_caustics) {
|
||||
INTEGRATOR_PATH_NEXT_SORTED(
|
||||
current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE, shader);
|
||||
}
|
||||
else if (use_raytrace_kernel) {
|
||||
INTEGRATOR_PATH_NEXT_SORTED(
|
||||
current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader);
|
||||
}
|
||||
|
@ -222,8 +229,12 @@ ccl_device_forceinline void integrator_intersect_next_kernel(
|
|||
const int object_flags = intersection_get_object_flags(kg, isect);
|
||||
const bool use_caustics = kernel_data.integrator.use_caustics &&
|
||||
(object_flags & SD_OBJECT_CAUSTICS);
|
||||
const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics;
|
||||
if (use_raytrace_kernel) {
|
||||
const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
|
||||
if (use_caustics) {
|
||||
INTEGRATOR_PATH_NEXT_SORTED(
|
||||
current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE, shader);
|
||||
}
|
||||
else if (use_raytrace_kernel) {
|
||||
INTEGRATOR_PATH_NEXT_SORTED(
|
||||
current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader);
|
||||
}
|
||||
|
@ -272,9 +283,13 @@ ccl_device_forceinline void integrator_intersect_next_kernel_after_volume(
|
|||
const int object_flags = intersection_get_object_flags(kg, isect);
|
||||
const bool use_caustics = kernel_data.integrator.use_caustics &&
|
||||
(object_flags & SD_OBJECT_CAUSTICS);
|
||||
const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE) || use_caustics;
|
||||
const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
|
||||
|
||||
if (use_raytrace_kernel) {
|
||||
if (use_caustics) {
|
||||
INTEGRATOR_PATH_NEXT_SORTED(
|
||||
current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE, shader);
|
||||
}
|
||||
else if (use_raytrace_kernel) {
|
||||
INTEGRATOR_PATH_NEXT_SORTED(
|
||||
current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader);
|
||||
}
|
||||
|
|
|
@ -77,6 +77,9 @@ ccl_device void integrator_megakernel(KernelGlobals kg,
|
|||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE:
|
||||
integrator_shade_surface_raytrace(kg, state, render_buffer);
|
||||
break;
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE:
|
||||
integrator_shade_surface_mnee(kg, state, render_buffer);
|
||||
break;
|
||||
case DEVICE_KERNEL_INTEGRATOR_SHADE_LIGHT:
|
||||
integrator_shade_light(kg, state, render_buffer);
|
||||
break;
|
||||
|
|
|
@ -48,7 +48,7 @@ ccl_device float3 integrator_eval_background_shader(KernelGlobals kg,
|
|||
|
||||
PROFILING_SHADER(emission_sd->object, emission_sd->shader);
|
||||
PROFILING_EVENT(PROFILING_SHADE_LIGHT_EVAL);
|
||||
shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_LIGHT>(
|
||||
shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_BACKGROUND>(
|
||||
kg, state, emission_sd, render_buffer, path_flag | PATH_RAY_EMISSION);
|
||||
|
||||
L = shader_background_eval(emission_sd);
|
||||
|
|
|
@ -137,7 +137,7 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
|||
|
||||
# ifdef __MNEE__
|
||||
int mnee_vertex_count = 0;
|
||||
IF_KERNEL_NODES_FEATURE(RAYTRACE)
|
||||
IF_KERNEL_FEATURE(MNEE)
|
||||
{
|
||||
if (ls.lamp != LAMP_NONE) {
|
||||
/* Is this a caustic light? */
|
||||
|
@ -631,4 +631,12 @@ ccl_device_forceinline void integrator_shade_surface_raytrace(
|
|||
kg, state, render_buffer);
|
||||
}
|
||||
|
||||
ccl_device_forceinline void integrator_shade_surface_mnee(
|
||||
KernelGlobals kg, IntegratorState state, ccl_global float *ccl_restrict render_buffer)
|
||||
{
|
||||
integrator_shade_surface<(KERNEL_FEATURE_NODE_MASK_SURFACE & ~KERNEL_FEATURE_NODE_RAYTRACE) |
|
||||
KERNEL_FEATURE_MNEE,
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE>(kg, state, render_buffer);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -174,9 +174,14 @@ ccl_device_inline bool subsurface_scatter(KernelGlobals kg, IntegratorState stat
|
|||
const int object_flags = intersection_get_object_flags(kg, &ss_isect.hits[0]);
|
||||
const bool use_caustics = kernel_data.integrator.use_caustics &&
|
||||
(object_flags & SD_OBJECT_CAUSTICS);
|
||||
const bool use_raytrace_kernel = (shader_flags & SD_HAS_RAYTRACE) || use_caustics;
|
||||
const bool use_raytrace_kernel = (shader_flags & SD_HAS_RAYTRACE);
|
||||
|
||||
if (use_raytrace_kernel) {
|
||||
if (use_caustics) {
|
||||
INTEGRATOR_PATH_NEXT_SORTED(DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE,
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE,
|
||||
shader);
|
||||
}
|
||||
else if (use_raytrace_kernel) {
|
||||
INTEGRATOR_PATH_NEXT_SORTED(DEVICE_KERNEL_INTEGRATOR_INTERSECT_SUBSURFACE,
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE,
|
||||
shader);
|
||||
|
|
|
@ -1572,6 +1572,7 @@ typedef enum DeviceKernel {
|
|||
DEVICE_KERNEL_INTEGRATOR_SHADE_LIGHT,
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE,
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE,
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE,
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME,
|
||||
DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW,
|
||||
DEVICE_KERNEL_INTEGRATOR_MEGAKERNEL,
|
||||
|
@ -1689,6 +1690,9 @@ enum KernelFeatureFlag : uint32_t {
|
|||
KERNEL_FEATURE_AO_PASS = (1U << 25U),
|
||||
KERNEL_FEATURE_AO_ADDITIVE = (1U << 26U),
|
||||
KERNEL_FEATURE_AO = (KERNEL_FEATURE_AO_PASS | KERNEL_FEATURE_AO_ADDITIVE),
|
||||
|
||||
/* MNEE. */
|
||||
KERNEL_FEATURE_MNEE = (1U << 27U),
|
||||
};
|
||||
|
||||
/* Shader node feature mask, to specialize shader evaluation for kernels. */
|
||||
|
@ -1696,6 +1700,8 @@ enum KernelFeatureFlag : uint32_t {
|
|||
#define KERNEL_FEATURE_NODE_MASK_SURFACE_LIGHT \
|
||||
(KERNEL_FEATURE_NODE_EMISSION | KERNEL_FEATURE_NODE_VORONOI_EXTRA | \
|
||||
KERNEL_FEATURE_NODE_LIGHT_PATH)
|
||||
#define KERNEL_FEATURE_NODE_MASK_SURFACE_BACKGROUND \
|
||||
(KERNEL_FEATURE_NODE_MASK_SURFACE_LIGHT | KERNEL_FEATURE_NODE_AOV)
|
||||
#define KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW \
|
||||
(KERNEL_FEATURE_NODE_BSDF | KERNEL_FEATURE_NODE_EMISSION | KERNEL_FEATURE_NODE_VOLUME | \
|
||||
KERNEL_FEATURE_NODE_BUMP | KERNEL_FEATURE_NODE_BUMP_STATE | \
|
||||
|
@ -1714,9 +1720,12 @@ enum KernelFeatureFlag : uint32_t {
|
|||
* are different depending on the main, shadow or null path. For GPU we don't have
|
||||
* C++17 everywhere so can't use it. */
|
||||
#ifdef __KERNEL_CPU__
|
||||
# define IF_KERNEL_FEATURE(feature) \
|
||||
if constexpr ((node_feature_mask & (KERNEL_FEATURE_##feature)) != 0U)
|
||||
# define IF_KERNEL_NODES_FEATURE(feature) \
|
||||
if constexpr ((node_feature_mask & (KERNEL_FEATURE_NODE_##feature)) != 0U)
|
||||
#else
|
||||
# define IF_KERNEL_FEATURE(feature) if ((node_feature_mask & (KERNEL_FEATURE_##feature)) != 0U)
|
||||
# define IF_KERNEL_NODES_FEATURE(feature) \
|
||||
if ((node_feature_mask & (KERNEL_FEATURE_NODE_##feature)) != 0U)
|
||||
#endif
|
||||
|
|
|
@ -661,6 +661,26 @@ Attribute *AttributeSet::find(AttributeStandard std) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
Attribute *AttributeSet::find_matching(const Attribute &other)
|
||||
{
|
||||
for (Attribute &attr : attributes) {
|
||||
if (attr.name != other.name) {
|
||||
continue;
|
||||
}
|
||||
if (attr.std != other.std) {
|
||||
continue;
|
||||
}
|
||||
if (attr.type != other.type) {
|
||||
continue;
|
||||
}
|
||||
if (attr.element != other.element) {
|
||||
continue;
|
||||
}
|
||||
return &attr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AttributeSet::remove(AttributeStandard std)
|
||||
{
|
||||
Attribute *attr = find(std);
|
||||
|
@ -729,32 +749,24 @@ void AttributeSet::clear(bool preserve_voxel_data)
|
|||
|
||||
void AttributeSet::update(AttributeSet &&new_attributes)
|
||||
{
|
||||
/* add or update old_attributes based on the new_attributes */
|
||||
/* Remove any attributes not on new_attributes. */
|
||||
list<Attribute>::iterator it;
|
||||
for (it = attributes.begin(); it != attributes.end();) {
|
||||
const Attribute &old_attr = *it;
|
||||
if (new_attributes.find_matching(old_attr) == nullptr) {
|
||||
remove(it++);
|
||||
continue;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
/* Add or update old_attributes based on the new_attributes. */
|
||||
foreach (Attribute &attr, new_attributes.attributes) {
|
||||
Attribute *nattr = add(attr.name, attr.type, attr.element);
|
||||
nattr->std = attr.std;
|
||||
nattr->set_data_from(std::move(attr));
|
||||
}
|
||||
|
||||
/* remove any attributes not on new_attributes */
|
||||
list<Attribute>::iterator it;
|
||||
for (it = attributes.begin(); it != attributes.end();) {
|
||||
if (it->std != ATTR_STD_NONE) {
|
||||
if (new_attributes.find(it->std) == nullptr) {
|
||||
remove(it++);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (it->name != "") {
|
||||
if (new_attributes.find(it->name) == nullptr) {
|
||||
remove(it++);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
|
||||
/* If all attributes were replaced, transform is no longer applied. */
|
||||
geometry->transform_applied = false;
|
||||
}
|
||||
|
|
|
@ -194,6 +194,7 @@ class AttributeSet {
|
|||
void remove(AttributeStandard std);
|
||||
|
||||
Attribute *find(AttributeRequest &req);
|
||||
Attribute *find_matching(const Attribute &other);
|
||||
|
||||
void remove(Attribute *attribute);
|
||||
|
||||
|
|
|
@ -272,17 +272,12 @@ void ImageMetaData::detect_colorspace()
|
|||
compress_as_srgb = true;
|
||||
}
|
||||
else {
|
||||
/* Always compress non-raw 8bit images as scene linear + sRGB, as a
|
||||
* heuristic to keep memory usage the same without too much data loss
|
||||
* due to quantization in common cases. */
|
||||
compress_as_srgb = (type == IMAGE_DATA_TYPE_BYTE || type == IMAGE_DATA_TYPE_BYTE4);
|
||||
|
||||
/* If colorspace conversion needed, use half instead of short so we can
|
||||
* represent HDR values that might result from conversion. */
|
||||
if (type == IMAGE_DATA_TYPE_USHORT) {
|
||||
if (type == IMAGE_DATA_TYPE_BYTE || type == IMAGE_DATA_TYPE_USHORT) {
|
||||
type = IMAGE_DATA_TYPE_HALF;
|
||||
}
|
||||
else if (type == IMAGE_DATA_TYPE_USHORT4) {
|
||||
else if (type == IMAGE_DATA_TYPE_BYTE4 || type == IMAGE_DATA_TYPE_USHORT4) {
|
||||
type = IMAGE_DATA_TYPE_HALF4;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,10 +94,11 @@ bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures & /*features*/,
|
|||
template<TypeDesc::BASETYPE FileFormat, typename StorageType>
|
||||
static void oiio_load_pixels(const ImageMetaData &metadata,
|
||||
const unique_ptr<ImageInput> &in,
|
||||
const bool associate_alpha,
|
||||
StorageType *pixels)
|
||||
{
|
||||
const int width = metadata.width;
|
||||
const int height = metadata.height;
|
||||
const size_t width = metadata.width;
|
||||
const size_t height = metadata.height;
|
||||
const int depth = metadata.depth;
|
||||
const int components = metadata.channels;
|
||||
|
||||
|
@ -105,12 +106,12 @@ static void oiio_load_pixels(const ImageMetaData &metadata,
|
|||
StorageType *readpixels = pixels;
|
||||
vector<StorageType> tmppixels;
|
||||
if (components > 4) {
|
||||
tmppixels.resize(((size_t)width) * height * components);
|
||||
tmppixels.resize(width * height * components);
|
||||
readpixels = &tmppixels[0];
|
||||
}
|
||||
|
||||
if (depth <= 1) {
|
||||
size_t scanlinesize = ((size_t)width) * components * sizeof(StorageType);
|
||||
size_t scanlinesize = width * components * sizeof(StorageType);
|
||||
in->read_image(FileFormat,
|
||||
(uchar *)readpixels + (height - 1) * scanlinesize,
|
||||
AutoStride,
|
||||
|
@ -122,7 +123,7 @@ static void oiio_load_pixels(const ImageMetaData &metadata,
|
|||
}
|
||||
|
||||
if (components > 4) {
|
||||
size_t dimensions = ((size_t)width) * height;
|
||||
size_t dimensions = width * height;
|
||||
for (size_t i = dimensions - 1, pixel = 0; pixel < dimensions; pixel++, i--) {
|
||||
pixels[i * 4 + 3] = tmppixels[i * components + 3];
|
||||
pixels[i * 4 + 2] = tmppixels[i * components + 2];
|
||||
|
@ -137,7 +138,7 @@ static void oiio_load_pixels(const ImageMetaData &metadata,
|
|||
if (cmyk) {
|
||||
const StorageType one = util_image_cast_from_float<StorageType>(1.0f);
|
||||
|
||||
const size_t num_pixels = ((size_t)width) * height * depth;
|
||||
const size_t num_pixels = width * height * depth;
|
||||
for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
|
||||
float c = util_image_cast_to_float(pixels[i * 4 + 0]);
|
||||
float m = util_image_cast_to_float(pixels[i * 4 + 1]);
|
||||
|
@ -149,6 +150,16 @@ static void oiio_load_pixels(const ImageMetaData &metadata,
|
|||
pixels[i * 4 + 3] = one;
|
||||
}
|
||||
}
|
||||
|
||||
if (components == 4 && associate_alpha) {
|
||||
size_t dimensions = width * height;
|
||||
for (size_t i = dimensions - 1, pixel = 0; pixel < dimensions; pixel++, i--) {
|
||||
const StorageType alpha = pixels[i * 4 + 3];
|
||||
pixels[i * 4 + 0] = util_image_multiply_native(pixels[i * 4 + 0], alpha);
|
||||
pixels[i * 4 + 1] = util_image_multiply_native(pixels[i * 4 + 1], alpha);
|
||||
pixels[i * 4 + 2] = util_image_multiply_native(pixels[i * 4 + 2], alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OIIOImageLoader::load_pixels(const ImageMetaData &metadata,
|
||||
|
@ -172,30 +183,36 @@ bool OIIOImageLoader::load_pixels(const ImageMetaData &metadata,
|
|||
ImageSpec spec = ImageSpec();
|
||||
ImageSpec config = ImageSpec();
|
||||
|
||||
if (!associate_alpha) {
|
||||
config.attribute("oiio:UnassociatedAlpha", 1);
|
||||
}
|
||||
/* Load without automatic OIIO alpha conversion, we do it ourselves. OIIO
|
||||
* will associate alpha in the the 8bit buffer for PNGs, which leads to too
|
||||
* much precision loss when we load it as half float to do a colorspace
|
||||
* transform. */
|
||||
config.attribute("oiio:UnassociatedAlpha", 1);
|
||||
|
||||
if (!in->open(filepath.string(), spec, config)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool do_associate_alpha = associate_alpha &&
|
||||
spec.get_int_attribute("oiio:UnassociatedAlpha", 0);
|
||||
|
||||
switch (metadata.type) {
|
||||
case IMAGE_DATA_TYPE_BYTE:
|
||||
case IMAGE_DATA_TYPE_BYTE4:
|
||||
oiio_load_pixels<TypeDesc::UINT8, uchar>(metadata, in, (uchar *)pixels);
|
||||
oiio_load_pixels<TypeDesc::UINT8, uchar>(metadata, in, do_associate_alpha, (uchar *)pixels);
|
||||
break;
|
||||
case IMAGE_DATA_TYPE_USHORT:
|
||||
case IMAGE_DATA_TYPE_USHORT4:
|
||||
oiio_load_pixels<TypeDesc::USHORT, uint16_t>(metadata, in, (uint16_t *)pixels);
|
||||
oiio_load_pixels<TypeDesc::USHORT, uint16_t>(
|
||||
metadata, in, do_associate_alpha, (uint16_t *)pixels);
|
||||
break;
|
||||
case IMAGE_DATA_TYPE_HALF:
|
||||
case IMAGE_DATA_TYPE_HALF4:
|
||||
oiio_load_pixels<TypeDesc::HALF, half>(metadata, in, (half *)pixels);
|
||||
oiio_load_pixels<TypeDesc::HALF, half>(metadata, in, do_associate_alpha, (half *)pixels);
|
||||
break;
|
||||
case IMAGE_DATA_TYPE_FLOAT:
|
||||
case IMAGE_DATA_TYPE_FLOAT4:
|
||||
oiio_load_pixels<TypeDesc::FLOAT, float>(metadata, in, (float *)pixels);
|
||||
oiio_load_pixels<TypeDesc::FLOAT, float>(metadata, in, do_associate_alpha, (float *)pixels);
|
||||
break;
|
||||
case IMAGE_DATA_TYPE_NANOVDB_FLOAT:
|
||||
case IMAGE_DATA_TYPE_NANOVDB_FLOAT3:
|
||||
|
|
|
@ -114,9 +114,11 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
|
|||
# ifdef WITH_NANOVDB
|
||||
if (features.has_nanovdb) {
|
||||
/* NanoVDB expects no inactive leaf nodes. */
|
||||
/*openvdb::FloatGrid &pruned_grid = *openvdb::gridPtrCast<openvdb::FloatGrid>(grid);
|
||||
# if 0
|
||||
openvdb::FloatGrid &pruned_grid = *openvdb::gridPtrCast<openvdb::FloatGrid>(grid);
|
||||
openvdb::tools::pruneInactive(pruned_grid.tree());
|
||||
nanogrid = nanovdb::openToNanoVDB(pruned_grid);*/
|
||||
nanogrid = nanovdb::openToNanoVDB(pruned_grid);
|
||||
# endif
|
||||
ToNanoOp op;
|
||||
op.precision = precision;
|
||||
if (!openvdb::grid_type_operation(grid, op)) {
|
||||
|
|
|
@ -550,7 +550,7 @@ void Scene::update_kernel_features()
|
|||
dscene.data.integrator.use_caustics = false;
|
||||
if (has_caustics_caster && has_caustics_receiver && has_caustics_light) {
|
||||
dscene.data.integrator.use_caustics = true;
|
||||
kernel_features |= KERNEL_FEATURE_NODE_RAYTRACE;
|
||||
kernel_features |= KERNEL_FEATURE_MNEE;
|
||||
}
|
||||
|
||||
if (bake_manager->get_baking()) {
|
||||
|
@ -597,6 +597,7 @@ static void log_kernel_features(const uint features)
|
|||
<< "\n";
|
||||
VLOG(2) << "Use Shader Raytrace " << string_from_bool(features & KERNEL_FEATURE_NODE_RAYTRACE)
|
||||
<< "\n";
|
||||
VLOG(2) << "Use MNEE" << string_from_bool(features & KERNEL_FEATURE_MNEE) << "\n";
|
||||
VLOG(2) << "Use Transparent " << string_from_bool(features & KERNEL_FEATURE_TRANSPARENT) << "\n";
|
||||
VLOG(2) << "Use Denoising " << string_from_bool(features & KERNEL_FEATURE_DENOISING) << "\n";
|
||||
VLOG(2) << "Use Path Tracing " << string_from_bool(features & KERNEL_FEATURE_PATH_TRACING)
|
||||
|
|
|
@ -888,7 +888,7 @@ void ShaderGraph::default_inputs(bool do_osl)
|
|||
|
||||
void ShaderGraph::refine_bump_nodes()
|
||||
{
|
||||
/* we transverse the node graph looking for bump nodes, when we find them,
|
||||
/* We transverse the node graph looking for bump nodes, when we find them,
|
||||
* like in bump_from_displacement(), we copy the sub-graph defined from "bump"
|
||||
* input to the inputs "center","dx" and "dy" What is in "bump" input is moved
|
||||
* to "center" input. */
|
||||
|
@ -898,18 +898,18 @@ void ShaderGraph::refine_bump_nodes()
|
|||
ShaderInput *bump_input = node->input("Height");
|
||||
ShaderNodeSet nodes_bump;
|
||||
|
||||
/* make 2 extra copies of the subgraph defined in Bump input */
|
||||
/* Make 2 extra copies of the subgraph defined in Bump input. */
|
||||
ShaderNodeMap nodes_dx;
|
||||
ShaderNodeMap nodes_dy;
|
||||
|
||||
/* find dependencies for the given input */
|
||||
/* Find dependencies for the given input. */
|
||||
find_dependencies(nodes_bump, bump_input);
|
||||
|
||||
copy_nodes(nodes_bump, nodes_dx);
|
||||
copy_nodes(nodes_bump, nodes_dy);
|
||||
|
||||
/* mark nodes to indicate they are use for bump computation, so
|
||||
that any texture coordinates are shifted by dx/dy when sampling */
|
||||
/* Mark nodes to indicate they are use for bump computation, so
|
||||
* that any texture coordinates are shifted by dx/dy when sampling. */
|
||||
foreach (ShaderNode *node, nodes_bump)
|
||||
node->bump = SHADER_BUMP_CENTER;
|
||||
foreach (NodePair &pair, nodes_dx)
|
||||
|
@ -924,7 +924,7 @@ void ShaderGraph::refine_bump_nodes()
|
|||
connect(out_dx, node->input("SampleX"));
|
||||
connect(out_dy, node->input("SampleY"));
|
||||
|
||||
/* add generated nodes */
|
||||
/* Add generated nodes. */
|
||||
foreach (NodePair &pair, nodes_dx)
|
||||
add(pair.second);
|
||||
foreach (NodePair &pair, nodes_dy)
|
||||
|
|
|
@ -90,7 +90,7 @@ static vector<ChannelMapping> output_channels()
|
|||
return map;
|
||||
}
|
||||
|
||||
/* Renderlayer Handling */
|
||||
/* Render-layer Handling. */
|
||||
|
||||
bool DenoiseImageLayer::detect_denoising_channels()
|
||||
{
|
||||
|
|
|
@ -78,6 +78,26 @@ template<> inline half util_image_cast_from_float(float value)
|
|||
return float_to_half_image(value);
|
||||
}
|
||||
|
||||
/* Multiply image pixels in native data format. */
|
||||
template<typename T> inline T util_image_multiply_native(T a, T b);
|
||||
|
||||
template<> inline float util_image_multiply_native(float a, float b)
|
||||
{
|
||||
return a * b;
|
||||
}
|
||||
template<> inline uchar util_image_multiply_native(uchar a, uchar b)
|
||||
{
|
||||
return ((uint32_t)a * (uint32_t)b) / 255;
|
||||
}
|
||||
template<> inline uint16_t util_image_multiply_native(uint16_t a, uint16_t b)
|
||||
{
|
||||
return ((uint32_t)a * (uint32_t)b) / 65535;
|
||||
}
|
||||
template<> inline half util_image_multiply_native(half a, half b)
|
||||
{
|
||||
return float_to_half_image(half_to_float_image(a) * half_to_float_image(b));
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __UTIL_IMAGE_H__ */
|
||||
|
|
|
@ -402,6 +402,10 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
|
|||
int32_t x,
|
||||
int32_t y);
|
||||
|
||||
GHOST_TSuccess GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TAxisFlag *r_wrap_axis,
|
||||
int r_bounds[4]);
|
||||
|
||||
/**
|
||||
* Grabs the cursor for a modal operation, to keep receiving
|
||||
* events when the mouse is outside the window. X11 only, others
|
||||
|
@ -414,7 +418,7 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
|
|||
*/
|
||||
extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TGrabCursorMode mode,
|
||||
GHOST_TAxisFlag warp_axis,
|
||||
GHOST_TAxisFlag wrap_axis,
|
||||
int bounds[4],
|
||||
const int mouse_ungrab_xy[2]);
|
||||
|
||||
|
@ -727,7 +731,7 @@ extern unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle
|
|||
/**
|
||||
* Get the OpenGL frame-buffer handle that serves as a default frame-buffer.
|
||||
*/
|
||||
extern unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windwHandle);
|
||||
extern unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
|
||||
|
@ -896,6 +900,11 @@ extern int setConsoleWindowState(GHOST_TConsoleWindowState action);
|
|||
*/
|
||||
extern int GHOST_UseNativePixels(void);
|
||||
|
||||
/**
|
||||
* Warp the cursor, if supported.
|
||||
*/
|
||||
extern int GHOST_SupportsCursorWarp(void);
|
||||
|
||||
/**
|
||||
* Focus window after opening, or put them in the background.
|
||||
*/
|
||||
|
|
|
@ -304,6 +304,11 @@ class GHOST_ISystem {
|
|||
*/
|
||||
virtual bool useNativePixel(void) = 0;
|
||||
|
||||
/**
|
||||
* Return true when warping the cursor is supported.
|
||||
*/
|
||||
virtual bool supportsCursorWarp() = 0;
|
||||
|
||||
/**
|
||||
* Focus window after opening, or put them in the background.
|
||||
*/
|
||||
|
|
|
@ -254,6 +254,10 @@ class GHOST_IWindow {
|
|||
*/
|
||||
virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0;
|
||||
|
||||
virtual GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) = 0;
|
||||
|
||||
virtual GHOST_TSuccess getCursorGrabState(GHOST_TAxisFlag &axis_flag, GHOST_Rect &bounds) = 0;
|
||||
|
||||
/**
|
||||
* Test if the standard cursor shape is supported by current platform.
|
||||
* \return Indication of success.
|
||||
|
|
|
@ -403,6 +403,8 @@ typedef enum {
|
|||
GHOST_kGrabHide,
|
||||
} GHOST_TGrabCursorMode;
|
||||
|
||||
#define GHOST_GRAB_NEEDS_SOFTWARE_CURSOR_FOR_WARP(grab) ((grab) == GHOST_kGrabWrap)
|
||||
|
||||
typedef enum {
|
||||
/** Axis that cursor grab will wrap. */
|
||||
GHOST_kGrabAxisNone = 0,
|
||||
|
@ -521,7 +523,7 @@ typedef struct {
|
|||
} GHOST_TEventNDOFMotionData;
|
||||
|
||||
typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction;
|
||||
/* Good for mouse or other buttons too, hmmm? */
|
||||
/* Good for mouse or other buttons too? */
|
||||
|
||||
typedef struct {
|
||||
GHOST_TButtonAction action;
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
* C Api for GHOST
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
#include "GHOST_IEvent.h"
|
||||
|
@ -206,13 +206,15 @@ GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle,
|
|||
const int stereoVisual)
|
||||
{
|
||||
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
|
||||
GHOST_IWindow *window = NULL;
|
||||
GHOST_IWindow *window = nullptr;
|
||||
bool bstereoVisual;
|
||||
|
||||
if (stereoVisual)
|
||||
if (stereoVisual) {
|
||||
bstereoVisual = true;
|
||||
else
|
||||
}
|
||||
else {
|
||||
bstereoVisual = false;
|
||||
}
|
||||
|
||||
system->beginFullScreen(*setting, &window, bstereoVisual);
|
||||
|
||||
|
@ -371,7 +373,24 @@ GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
|
|||
}
|
||||
|
||||
return window->setCursorGrab(
|
||||
mode, wrap_axis, bounds ? &bounds_rect : NULL, mouse_ungrab_xy ? mouse_xy : NULL);
|
||||
mode, wrap_axis, bounds ? &bounds_rect : nullptr, mouse_ungrab_xy ? mouse_xy : nullptr);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TAxisFlag *r_axis_flag,
|
||||
int r_bounds[4])
|
||||
{
|
||||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||
GHOST_Rect bounds_rect;
|
||||
if (!window->getCursorGrabState(*r_axis_flag, bounds_rect)) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
r_bounds[0] = bounds_rect.m_l;
|
||||
r_bounds[1] = bounds_rect.m_t;
|
||||
r_bounds[2] = bounds_rect.m_r;
|
||||
r_bounds[3] = bounds_rect.m_b;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle,
|
||||
|
@ -509,8 +528,8 @@ char *GHOST_GetTitle(GHOST_WindowHandle windowhandle)
|
|||
|
||||
char *ctitle = (char *)malloc(title.size() + 1);
|
||||
|
||||
if (ctitle == NULL) {
|
||||
return NULL;
|
||||
if (ctitle == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
strcpy(ctitle, title.c_str());
|
||||
|
@ -521,7 +540,7 @@ char *GHOST_GetTitle(GHOST_WindowHandle windowhandle)
|
|||
GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||
GHOST_Rect *rectangle = NULL;
|
||||
GHOST_Rect *rectangle = nullptr;
|
||||
|
||||
rectangle = new GHOST_Rect();
|
||||
window->getWindowBounds(*rectangle);
|
||||
|
@ -532,7 +551,7 @@ GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle)
|
|||
GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||
GHOST_Rect *rectangle = NULL;
|
||||
GHOST_Rect *rectangle = nullptr;
|
||||
|
||||
rectangle = new GHOST_Rect();
|
||||
window->getClientBounds(*rectangle);
|
||||
|
@ -646,10 +665,8 @@ GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
|
|||
if (context) {
|
||||
return context->activateDrawingContext();
|
||||
}
|
||||
else {
|
||||
GHOST_PRINTF("%s: Context not valid\n", __func__);
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
GHOST_PRINTF("%s: Context not valid\n", __func__);
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle)
|
||||
|
@ -717,9 +734,9 @@ GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle)
|
|||
{
|
||||
GHOST_TSuccess result = GHOST_kFailure;
|
||||
|
||||
if (((GHOST_Rect *)rectanglehandle)->isEmpty())
|
||||
if (((GHOST_Rect *)rectanglehandle)->isEmpty()) {
|
||||
result = GHOST_kSuccess;
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -727,9 +744,9 @@ GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle)
|
|||
{
|
||||
GHOST_TSuccess result = GHOST_kFailure;
|
||||
|
||||
if (((GHOST_Rect *)rectanglehandle)->isValid())
|
||||
if (((GHOST_Rect *)rectanglehandle)->isValid()) {
|
||||
result = GHOST_kSuccess;
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -753,9 +770,9 @@ GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle, in
|
|||
{
|
||||
GHOST_TSuccess result = GHOST_kFailure;
|
||||
|
||||
if (((GHOST_Rect *)rectanglehandle)->isInside(x, y))
|
||||
if (((GHOST_Rect *)rectanglehandle)->isInside(x, y)) {
|
||||
result = GHOST_kSuccess;
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -785,9 +802,9 @@ GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle,
|
|||
{
|
||||
GHOST_TSuccess result = GHOST_kFailure;
|
||||
|
||||
if (((GHOST_Rect *)rectanglehandle)->clip(*(GHOST_Rect *)anotherrectanglehandle))
|
||||
if (((GHOST_Rect *)rectanglehandle)->clip(*(GHOST_Rect *)anotherrectanglehandle)) {
|
||||
result = GHOST_kSuccess;
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -815,6 +832,12 @@ int GHOST_UseNativePixels(void)
|
|||
return system->useNativePixel();
|
||||
}
|
||||
|
||||
int GHOST_SupportsCursorWarp(void)
|
||||
{
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
return system->supportsCursorWarp();
|
||||
}
|
||||
|
||||
void GHOST_UseWindowFocus(int use_focus)
|
||||
{
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
|
@ -824,8 +847,9 @@ void GHOST_UseWindowFocus(int use_focus)
|
|||
float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||
if (window)
|
||||
if (window) {
|
||||
return window->getNativePixelSize();
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ static const char *get_egl_error_enum_string(EGLint error)
|
|||
CASE_CODE_RETURN_STR(EGL_BAD_NATIVE_WINDOW)
|
||||
CASE_CODE_RETURN_STR(EGL_CONTEXT_LOST)
|
||||
default:
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,11 +106,14 @@ static const char *get_egl_error_message_string(EGLint error)
|
|||
"and objects to continue rendering.");
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static bool egl_chk(bool result, const char *file = NULL, int line = 0, const char *text = NULL)
|
||||
static bool egl_chk(bool result,
|
||||
const char *file = nullptr,
|
||||
int line = 0,
|
||||
const char *text = nullptr)
|
||||
{
|
||||
if (!result) {
|
||||
const EGLint error = eglGetError();
|
||||
|
@ -158,7 +161,7 @@ static inline bool bindAPI(EGLenum api)
|
|||
}
|
||||
|
||||
#ifdef WITH_GL_ANGLE
|
||||
HMODULE GHOST_ContextEGL::s_d3dcompiler = NULL;
|
||||
HMODULE GHOST_ContextEGL::s_d3dcompiler = nullptr;
|
||||
#endif
|
||||
|
||||
EGLContext GHOST_ContextEGL::s_gl_sharedContext = EGL_NO_CONTEXT;
|
||||
|
@ -170,7 +173,9 @@ EGLint GHOST_ContextEGL::s_gles_sharedCount = 0;
|
|||
EGLContext GHOST_ContextEGL::s_vg_sharedContext = EGL_NO_CONTEXT;
|
||||
EGLint GHOST_ContextEGL::s_vg_sharedCount = 0;
|
||||
|
||||
#pragma warning(disable : 4715)
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable : 4715)
|
||||
#endif
|
||||
|
||||
template<typename T> T &choose_api(EGLenum api, T &a, T &b, T &c)
|
||||
{
|
||||
|
@ -223,23 +228,24 @@ GHOST_ContextEGL::~GHOST_ContextEGL()
|
|||
bindAPI(m_api);
|
||||
|
||||
if (m_context != EGL_NO_CONTEXT) {
|
||||
if (m_context == ::eglGetCurrentContext())
|
||||
if (m_context == ::eglGetCurrentContext()) {
|
||||
EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
|
||||
|
||||
}
|
||||
if (m_context != m_sharedContext || m_sharedCount == 1) {
|
||||
assert(m_sharedCount > 0);
|
||||
|
||||
m_sharedCount--;
|
||||
|
||||
if (m_sharedCount == 0)
|
||||
if (m_sharedCount == 0) {
|
||||
m_sharedContext = EGL_NO_CONTEXT;
|
||||
|
||||
}
|
||||
EGL_CHK(::eglDestroyContext(m_display, m_context));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_surface != EGL_NO_SURFACE)
|
||||
if (m_surface != EGL_NO_SURFACE) {
|
||||
EGL_CHK(::eglDestroySurface(m_display, m_surface));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,13 +262,9 @@ GHOST_TSuccess GHOST_ContextEGL::setSwapInterval(int interval)
|
|||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ContextEGL::getSwapInterval(int &intervalOut)
|
||||
|
@ -293,13 +295,10 @@ GHOST_TSuccess GHOST_ContextEGL::activateDrawingContext()
|
|||
{
|
||||
if (m_display) {
|
||||
bindAPI(m_api);
|
||||
|
||||
return EGL_CHK(::eglMakeCurrent(m_display, m_surface, m_surface, m_context)) ? GHOST_kSuccess :
|
||||
GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ContextEGL::releaseDrawingContext()
|
||||
|
@ -311,9 +310,7 @@ GHOST_TSuccess GHOST_ContextEGL::releaseDrawingContext()
|
|||
GHOST_kSuccess :
|
||||
GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
bool GHOST_ContextEGL::initContextEGLEW()
|
||||
|
@ -322,7 +319,7 @@ bool GHOST_ContextEGL::initContextEGLEW()
|
|||
* it requires a display argument. glewInit() does the same, but we only want
|
||||
* to initialize EGLEW here. */
|
||||
eglGetDisplay = (PFNEGLGETDISPLAYPROC)eglGetProcAddress("eglGetDisplay");
|
||||
if (eglGetDisplay == NULL) {
|
||||
if (eglGetDisplay == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -353,9 +350,9 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||
std::vector<EGLint> attrib_list;
|
||||
EGLint num_config = 0;
|
||||
|
||||
if (m_stereoVisual)
|
||||
if (m_stereoVisual) {
|
||||
fprintf(stderr, "Warning! Stereo OpenGL ES contexts are not supported.\n");
|
||||
|
||||
}
|
||||
m_stereoVisual = false; /* It doesn't matter what the Window wants. */
|
||||
|
||||
if (!initContextEGLEW()) {
|
||||
|
@ -364,12 +361,12 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||
|
||||
#ifdef WITH_GL_ANGLE
|
||||
/* `d3dcompiler_XX.dll` needs to be loaded before ANGLE will work. */
|
||||
if (s_d3dcompiler == NULL) {
|
||||
if (s_d3dcompiler == nullptr) {
|
||||
s_d3dcompiler = LoadLibrary(D3DCOMPILER);
|
||||
|
||||
WIN32_CHK(s_d3dcompiler != NULL);
|
||||
WIN32_CHK(s_d3dcompiler != nullptr);
|
||||
|
||||
if (s_d3dcompiler == NULL) {
|
||||
if (s_d3dcompiler == nullptr) {
|
||||
fprintf(stderr, "LoadLibrary(\"" D3DCOMPILER "\") failed!\n");
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
@ -383,18 +380,19 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||
|
||||
EGLint egl_major, egl_minor;
|
||||
|
||||
if (!EGL_CHK(::eglInitialize(m_display, &egl_major, &egl_minor)))
|
||||
if (!EGL_CHK(::eglInitialize(m_display, &egl_major, &egl_minor))) {
|
||||
goto error;
|
||||
|
||||
}
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
fprintf(stderr, "EGL Version %d.%d\n", egl_major, egl_minor);
|
||||
#endif
|
||||
|
||||
if (!EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)))
|
||||
if (!EGL_CHK(::eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))) {
|
||||
goto error;
|
||||
|
||||
if (!bindAPI(m_api))
|
||||
}
|
||||
if (!bindAPI(m_api)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Build attribute list. */
|
||||
|
||||
|
@ -462,15 +460,17 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||
|
||||
attrib_list.push_back(EGL_NONE);
|
||||
|
||||
if (!EGL_CHK(::eglChooseConfig(m_display, &(attrib_list[0]), &m_config, 1, &num_config)))
|
||||
if (!EGL_CHK(::eglChooseConfig(m_display, &(attrib_list[0]), &m_config, 1, &num_config))) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* A common error is to assume that ChooseConfig worked because it returned EGL_TRUE. */
|
||||
if (num_config != 1) /* `num_config` should be exactly 1. */
|
||||
if (num_config != 1) { /* `num_config` should be exactly 1. */
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (m_nativeWindow != 0) {
|
||||
m_surface = ::eglCreateWindowSurface(m_display, m_config, m_nativeWindow, NULL);
|
||||
m_surface = ::eglCreateWindowSurface(m_display, m_config, m_nativeWindow, nullptr);
|
||||
}
|
||||
else {
|
||||
static const EGLint pb_attrib_list[] = {
|
||||
|
@ -483,9 +483,9 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||
m_surface = ::eglCreatePbufferSurface(m_display, m_config, pb_attrib_list);
|
||||
}
|
||||
|
||||
if (!EGL_CHK(m_surface != EGL_NO_SURFACE))
|
||||
if (!EGL_CHK(m_surface != EGL_NO_SURFACE)) {
|
||||
goto error;
|
||||
|
||||
}
|
||||
attrib_list.clear();
|
||||
|
||||
if (EGLEW_VERSION_1_5 || EGLEW_KHR_create_context) {
|
||||
|
@ -524,9 +524,10 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (m_contextProfileMask != 0)
|
||||
if (m_contextProfileMask != 0) {
|
||||
fprintf(
|
||||
stderr, "Warning! Cannot select profile for %s contexts.", api_string(m_api).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_api == EGL_OPENGL_API || EGLEW_VERSION_1_5) {
|
||||
|
@ -583,16 +584,19 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||
|
||||
m_context = ::eglCreateContext(m_display, m_config, m_sharedContext, &(attrib_list[0]));
|
||||
|
||||
if (!EGL_CHK(m_context != EGL_NO_CONTEXT))
|
||||
if (!EGL_CHK(m_context != EGL_NO_CONTEXT)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (m_sharedContext == EGL_NO_CONTEXT)
|
||||
if (m_sharedContext == EGL_NO_CONTEXT) {
|
||||
m_sharedContext = m_context;
|
||||
}
|
||||
|
||||
m_sharedCount++;
|
||||
|
||||
if (!EGL_CHK(::eglMakeCurrent(m_display, m_surface, m_surface, m_context)))
|
||||
if (!EGL_CHK(::eglMakeCurrent(m_display, m_surface, m_surface, m_context))) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
initContextGLEW();
|
||||
|
||||
|
@ -602,16 +606,16 @@ GHOST_TSuccess GHOST_ContextEGL::initializeDrawingContext()
|
|||
return GHOST_kSuccess;
|
||||
|
||||
error:
|
||||
if (prev_display != EGL_NO_DISPLAY)
|
||||
if (prev_display != EGL_NO_DISPLAY) {
|
||||
EGL_CHK(eglMakeCurrent(prev_display, prev_draw, prev_read, prev_context));
|
||||
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ContextEGL::releaseNativeHandles()
|
||||
{
|
||||
m_nativeWindow = 0;
|
||||
m_nativeDisplay = NULL;
|
||||
m_nativeDisplay = nullptr;
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
|
|
@ -47,23 +47,24 @@ GHOST_ContextGLX::GHOST_ContextGLX(bool stereoVisual,
|
|||
m_contextResetNotificationStrategy(contextResetNotificationStrategy),
|
||||
m_context(None)
|
||||
{
|
||||
assert(m_display != NULL);
|
||||
assert(m_display != nullptr);
|
||||
}
|
||||
|
||||
GHOST_ContextGLX::~GHOST_ContextGLX()
|
||||
{
|
||||
if (m_display != NULL) {
|
||||
if (m_display != nullptr) {
|
||||
if (m_context != None) {
|
||||
if (m_window != 0 && m_context == ::glXGetCurrentContext())
|
||||
::glXMakeCurrent(m_display, None, NULL);
|
||||
|
||||
if (m_window != 0 && m_context == ::glXGetCurrentContext()) {
|
||||
::glXMakeCurrent(m_display, None, nullptr);
|
||||
}
|
||||
if (m_context != s_sharedContext || s_sharedCount == 1) {
|
||||
assert(s_sharedCount > 0);
|
||||
|
||||
s_sharedCount--;
|
||||
|
||||
if (s_sharedCount == 0)
|
||||
s_sharedContext = NULL;
|
||||
if (s_sharedCount == 0) {
|
||||
s_sharedContext = nullptr;
|
||||
}
|
||||
|
||||
::glXDestroyContext(m_display, m_context);
|
||||
}
|
||||
|
@ -80,22 +81,18 @@ GHOST_TSuccess GHOST_ContextGLX::swapBuffers()
|
|||
|
||||
GHOST_TSuccess GHOST_ContextGLX::activateDrawingContext()
|
||||
{
|
||||
if (m_display) {
|
||||
return ::glXMakeCurrent(m_display, m_window, m_context) ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
if (m_display == nullptr) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return ::glXMakeCurrent(m_display, m_window, m_context) ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ContextGLX::releaseDrawingContext()
|
||||
{
|
||||
if (m_display) {
|
||||
return ::glXMakeCurrent(m_display, None, NULL) ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
if (m_display == nullptr) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return ::glXMakeCurrent(m_display, None, nullptr) ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
void GHOST_ContextGLX::initContextGLXEW()
|
||||
|
@ -113,15 +110,15 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
|
|||
#ifdef USE_GLXEW_INIT_WORKAROUND
|
||||
const GLubyte *extStart = (GLubyte *)"";
|
||||
const GLubyte *extEnd;
|
||||
if (glXQueryExtension(m_display, NULL, NULL)) {
|
||||
if (glXQueryExtension(m_display, nullptr, nullptr)) {
|
||||
extStart = (const GLubyte *)glXGetClientString(m_display, GLX_EXTENSIONS);
|
||||
if ((extStart == NULL) ||
|
||||
if ((extStart == nullptr) ||
|
||||
(glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddressARB(
|
||||
(const GLubyte *)"glXChooseFBConfig")) == NULL ||
|
||||
(const GLubyte *)"glXChooseFBConfig")) == nullptr ||
|
||||
(glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddressARB(
|
||||
(const GLubyte *)"glXCreateContextAttribsARB")) == NULL ||
|
||||
(const GLubyte *)"glXCreateContextAttribsARB")) == nullptr ||
|
||||
(glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC)glXGetProcAddressARB(
|
||||
(const GLubyte *)"glXCreatePbuffer")) == NULL) {
|
||||
(const GLubyte *)"glXCreatePbuffer")) == nullptr) {
|
||||
extStart = (GLubyte *)"";
|
||||
}
|
||||
}
|
||||
|
@ -161,11 +158,12 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
|
|||
int profileBitES = m_contextProfileMask & GLX_CONTEXT_ES_PROFILE_BIT_EXT;
|
||||
#endif
|
||||
|
||||
if (!GLXEW_ARB_create_context_profile && profileBitCore)
|
||||
if (!GLXEW_ARB_create_context_profile && profileBitCore) {
|
||||
fprintf(stderr, "Warning! OpenGL core profile not available.\n");
|
||||
|
||||
if (!GLXEW_ARB_create_context_profile && profileBitCompat)
|
||||
}
|
||||
if (!GLXEW_ARB_create_context_profile && profileBitCompat) {
|
||||
fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");
|
||||
}
|
||||
|
||||
#ifdef WITH_GLEW_ES
|
||||
if (!GLXEW_EXT_create_context_es_profile && profileBitES && m_contextMajorVersion == 1)
|
||||
|
@ -177,20 +175,21 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
|
|||
|
||||
int profileMask = 0;
|
||||
|
||||
if (GLXEW_ARB_create_context_profile && profileBitCore)
|
||||
if (GLXEW_ARB_create_context_profile && profileBitCore) {
|
||||
profileMask |= profileBitCore;
|
||||
|
||||
if (GLXEW_ARB_create_context_profile && profileBitCompat)
|
||||
}
|
||||
if (GLXEW_ARB_create_context_profile && profileBitCompat) {
|
||||
profileMask |= profileBitCompat;
|
||||
}
|
||||
|
||||
#ifdef WITH_GLEW_ES
|
||||
if (GLXEW_EXT_create_context_es_profile && profileBitES)
|
||||
profileMask |= profileBitES;
|
||||
#endif
|
||||
|
||||
if (profileMask != m_contextProfileMask)
|
||||
if (profileMask != m_contextProfileMask) {
|
||||
fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");
|
||||
|
||||
}
|
||||
/* max 10 attributes plus terminator */
|
||||
int attribs[11];
|
||||
int i = 0;
|
||||
|
@ -238,7 +237,7 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
|
|||
}
|
||||
}
|
||||
else {
|
||||
GLXFBConfig *framebuffer_config = NULL;
|
||||
GLXFBConfig *framebuffer_config = nullptr;
|
||||
{
|
||||
int glx_attribs[64];
|
||||
int fbcount = 0;
|
||||
|
@ -269,12 +268,12 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
|
|||
|
||||
GHOST_TSuccess success;
|
||||
|
||||
if (m_context != NULL) {
|
||||
if (m_context != nullptr) {
|
||||
const unsigned char *version;
|
||||
|
||||
if (!s_sharedContext)
|
||||
if (!s_sharedContext) {
|
||||
s_sharedContext = m_context;
|
||||
|
||||
}
|
||||
s_sharedCount++;
|
||||
|
||||
glXMakeCurrent(m_display, m_window, m_context);
|
||||
|
@ -319,14 +318,11 @@ GHOST_TSuccess GHOST_ContextGLX::releaseNativeHandles()
|
|||
|
||||
GHOST_TSuccess GHOST_ContextGLX::setSwapInterval(int interval)
|
||||
{
|
||||
if (GLXEW_EXT_swap_control) {
|
||||
if (!GLXEW_EXT_swap_control) {
|
||||
::glXSwapIntervalEXT(m_display, m_window, interval);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ContextGLX::getSwapInterval(int &intervalOut)
|
||||
|
@ -340,9 +336,7 @@ GHOST_TSuccess GHOST_ContextGLX::getSwapInterval(int &intervalOut)
|
|||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -406,30 +400,36 @@ int GHOST_X11_GL_GetAttributes(
|
|||
static GLuint _glewStrLen(const GLubyte *s)
|
||||
{
|
||||
GLuint i = 0;
|
||||
if (s == NULL)
|
||||
if (s == nullptr) {
|
||||
return 0;
|
||||
while (s[i] != '\0')
|
||||
}
|
||||
while (s[i] != '\0') {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static GLuint _glewStrCLen(const GLubyte *s, GLubyte c)
|
||||
{
|
||||
GLuint i = 0;
|
||||
if (s == NULL)
|
||||
if (s == nullptr) {
|
||||
return 0;
|
||||
while (s[i] != '\0' && s[i] != c)
|
||||
}
|
||||
while (s[i] != '\0' && s[i] != c) {
|
||||
i++;
|
||||
}
|
||||
return (s[i] == '\0' || s[i] == c) ? i : 0;
|
||||
}
|
||||
|
||||
static GLboolean _glewStrSame(const GLubyte *a, const GLubyte *b, GLuint n)
|
||||
{
|
||||
GLuint i = 0;
|
||||
if (a == NULL || b == NULL)
|
||||
return (a == NULL && b == NULL && n == 0) ? GL_TRUE : GL_FALSE;
|
||||
while (i < n && a[i] != '\0' && b[i] != '\0' && a[i] == b[i])
|
||||
if (a == nullptr || b == nullptr) {
|
||||
return (a == nullptr && b == nullptr && n == 0) ? GL_TRUE : GL_FALSE;
|
||||
}
|
||||
while (i < n && a[i] != '\0' && b[i] != '\0' && a[i] == b[i]) {
|
||||
i++;
|
||||
}
|
||||
return i == n ? GL_TRUE : GL_FALSE;
|
||||
}
|
||||
|
||||
|
@ -440,8 +440,9 @@ static GLboolean _glewSearchExtension(const char *name, const GLubyte *start, co
|
|||
p = start;
|
||||
while (p < end) {
|
||||
GLuint n = _glewStrCLen(p, ' ');
|
||||
if (len == n && _glewStrSame((const GLubyte *)name, p, n))
|
||||
if (len == n && _glewStrSame((const GLubyte *)name, p, n)) {
|
||||
return GL_TRUE;
|
||||
}
|
||||
p += n + 1;
|
||||
}
|
||||
return GL_FALSE;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
SDL_GLContext GHOST_ContextSDL::s_sharedContext = NULL;
|
||||
SDL_GLContext GHOST_ContextSDL::s_sharedContext = nullptr;
|
||||
int GHOST_ContextSDL::s_sharedCount = 0;
|
||||
|
||||
GHOST_ContextSDL::GHOST_ContextSDL(bool stereoVisual,
|
||||
|
@ -27,36 +27,39 @@ GHOST_ContextSDL::GHOST_ContextSDL(bool stereoVisual,
|
|||
int contextResetNotificationStrategy)
|
||||
: GHOST_Context(stereoVisual),
|
||||
m_window(window),
|
||||
m_hidden_window(NULL),
|
||||
m_hidden_window(nullptr),
|
||||
m_contextProfileMask(contextProfileMask),
|
||||
m_contextMajorVersion(contextMajorVersion),
|
||||
m_contextMinorVersion(contextMinorVersion),
|
||||
m_contextFlags(contextFlags),
|
||||
m_contextResetNotificationStrategy(contextResetNotificationStrategy),
|
||||
m_context(NULL)
|
||||
m_context(nullptr)
|
||||
{
|
||||
// assert(m_window != NULL);
|
||||
// assert(m_window != nullptr);
|
||||
}
|
||||
|
||||
GHOST_ContextSDL::~GHOST_ContextSDL()
|
||||
{
|
||||
if (m_context != NULL) {
|
||||
if (m_window != NULL && m_context == SDL_GL_GetCurrentContext())
|
||||
SDL_GL_MakeCurrent(m_window, NULL);
|
||||
if (m_context == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_context != s_sharedContext || s_sharedCount == 1) {
|
||||
assert(s_sharedCount > 0);
|
||||
if (m_window != nullptr && m_context == SDL_GL_GetCurrentContext()) {
|
||||
SDL_GL_MakeCurrent(m_window, nullptr);
|
||||
}
|
||||
if (m_context != s_sharedContext || s_sharedCount == 1) {
|
||||
assert(s_sharedCount > 0);
|
||||
|
||||
s_sharedCount--;
|
||||
s_sharedCount--;
|
||||
|
||||
if (s_sharedCount == 0)
|
||||
s_sharedContext = NULL;
|
||||
|
||||
SDL_GL_DeleteContext(m_context);
|
||||
if (s_sharedCount == 0) {
|
||||
s_sharedContext = nullptr;
|
||||
}
|
||||
SDL_GL_DeleteContext(m_context);
|
||||
}
|
||||
|
||||
if (m_hidden_window != NULL)
|
||||
SDL_DestroyWindow(m_hidden_window);
|
||||
if (m_hidden_window != nullptr) {
|
||||
SDL_DestroyWindow(m_hidden_window);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,23 +72,19 @@ GHOST_TSuccess GHOST_ContextSDL::swapBuffers()
|
|||
|
||||
GHOST_TSuccess GHOST_ContextSDL::activateDrawingContext()
|
||||
{
|
||||
if (m_context) {
|
||||
return SDL_GL_MakeCurrent(m_window, m_context) ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
if (m_context == nullptr) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return SDL_GL_MakeCurrent(m_window, m_context) ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ContextSDL::releaseDrawingContext()
|
||||
{
|
||||
if (m_context) {
|
||||
/* Untested, may not work */
|
||||
return SDL_GL_MakeCurrent(NULL, NULL) ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
if (m_context == nullptr) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
/* Untested, may not work. */
|
||||
return SDL_GL_MakeCurrent(nullptr, nullptr) ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext()
|
||||
|
@ -115,7 +114,7 @@ GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext()
|
|||
SDL_GL_SetAttribute(SDL_GL_STEREO, 1);
|
||||
}
|
||||
|
||||
if (m_window == NULL) {
|
||||
if (m_window == nullptr) {
|
||||
m_hidden_window = SDL_CreateWindow("Offscreen Context Windows",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
|
@ -131,10 +130,10 @@ GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext()
|
|||
|
||||
GHOST_TSuccess success;
|
||||
|
||||
if (m_context != NULL) {
|
||||
if (!s_sharedContext)
|
||||
if (m_context != nullptr) {
|
||||
if (!s_sharedContext) {
|
||||
s_sharedContext = m_context;
|
||||
|
||||
}
|
||||
s_sharedCount++;
|
||||
|
||||
success = (SDL_GL_MakeCurrent(m_window, m_context) < 0) ? GHOST_kFailure : GHOST_kSuccess;
|
||||
|
@ -155,19 +154,17 @@ GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext()
|
|||
|
||||
GHOST_TSuccess GHOST_ContextSDL::releaseNativeHandles()
|
||||
{
|
||||
m_window = NULL;
|
||||
m_window = nullptr;
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ContextSDL::setSwapInterval(int interval)
|
||||
{
|
||||
if (SDL_GL_SetSwapInterval(interval) != -1) {
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
if (SDL_GL_SetSwapInterval(interval) == -1) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ContextSDL::getSwapInterval(int &intervalOut)
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
#include "GHOST_DisplayManager.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
GHOST_DisplayManager::GHOST_DisplayManager(void) : m_settingsInitialized(false)
|
||||
GHOST_DisplayManager::GHOST_DisplayManager() : m_settingsInitialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
GHOST_DisplayManager::~GHOST_DisplayManager(void)
|
||||
GHOST_DisplayManager::~GHOST_DisplayManager()
|
||||
{
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManager::initialize(void)
|
||||
GHOST_TSuccess GHOST_DisplayManager::initialize()
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (!m_settingsInitialized) {
|
||||
|
@ -139,7 +139,7 @@ GHOST_TSuccess GHOST_DisplayManager::findMatch(uint8_t display,
|
|||
return success;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManager::initializeSettings(void)
|
||||
GHOST_TSuccess GHOST_DisplayManager::initializeSettings()
|
||||
{
|
||||
uint8_t numDisplays;
|
||||
GHOST_TSuccess success = getNumDisplays(numDisplays);
|
||||
|
|
|
@ -109,7 +109,7 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::setCurrentDisplaySetting(
|
|||
|
||||
SDL_GetDisplayMode(display, i, &mode);
|
||||
|
||||
if (setting.xPixels > mode.w || setting.yPixels > mode.h) {
|
||||
if ((int)setting.xPixels > mode.w || (int)setting.yPixels > mode.h) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -122,9 +122,9 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::setCurrentDisplaySetting(
|
|||
}
|
||||
}
|
||||
|
||||
if (best_fit == -1)
|
||||
if (best_fit == -1) {
|
||||
return GHOST_kFailure;
|
||||
|
||||
}
|
||||
SDL_GetDisplayMode(display, best_fit, &mode);
|
||||
}
|
||||
|
||||
|
@ -142,12 +142,10 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::setCurrentDisplaySetting(
|
|||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
/* this is a problem for the BGE player :S, perhaps SDL2 will resolve at some point.
|
||||
* we really need SDL_SetDisplayModeForDisplay() to become an API func! - campbell */
|
||||
printf("no windows available, can't fullscreen\n");
|
||||
/* This is a problem for the BGE player :S, perhaps SDL2 will resolve at some point.
|
||||
* we really need SDL_SetDisplayModeForDisplay() to become an API func! - campbell. */
|
||||
printf("no windows available, can't fullscreen\n");
|
||||
|
||||
/* do not fail, we will try again later when the window is created - wander */
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
/* do not fail, we will try again later when the window is created - wander */
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
|
|
@ -39,8 +39,9 @@ GHOST_TSuccess GHOST_DisplayManagerX11::getNumDisplaySettings(uint8_t display,
|
|||
|
||||
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
|
||||
|
||||
if (dpy == NULL)
|
||||
if (dpy == nullptr) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
majorVersion = minorVersion = 0;
|
||||
if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
|
||||
|
@ -77,8 +78,9 @@ GHOST_TSuccess GHOST_DisplayManagerX11::getDisplaySetting(uint8_t display,
|
|||
{
|
||||
Display *dpy = m_system->getXDisplay();
|
||||
|
||||
if (dpy == NULL)
|
||||
if (dpy == nullptr) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
(void)display;
|
||||
|
||||
|
@ -143,8 +145,9 @@ GHOST_TSuccess GHOST_DisplayManagerX11::setCurrentDisplaySetting(
|
|||
Display *dpy = m_system->getXDisplay();
|
||||
int scrnum, num_vidmodes;
|
||||
|
||||
if (dpy == NULL)
|
||||
if (dpy == nullptr) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
scrnum = DefaultScreen(dpy);
|
||||
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
#include "GHOST_DropTargetX11.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
bool GHOST_DropTargetX11::m_xdndInitialized = false;
|
||||
DndClass GHOST_DropTargetX11::m_dndClass;
|
||||
Atom *GHOST_DropTargetX11::m_dndTypes = NULL;
|
||||
Atom *GHOST_DropTargetX11::m_dndActions = NULL;
|
||||
Atom *GHOST_DropTargetX11::m_dndTypes = nullptr;
|
||||
Atom *GHOST_DropTargetX11::m_dndActions = nullptr;
|
||||
const char *GHOST_DropTargetX11::m_dndMimeTypes[] = {
|
||||
"url/url", "text/uri-list", "text/plain", "application/octet-stream"};
|
||||
int GHOST_DropTargetX11::m_refCounter = 0;
|
||||
|
@ -180,12 +180,12 @@ char *GHOST_DropTargetX11::FileUrlDecode(char *fileUrl)
|
|||
return decodedPath;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *GHOST_DropTargetX11::getURIListGhostData(unsigned char *dropBuffer, int dropBufferSize)
|
||||
{
|
||||
GHOST_TStringArray *strArray = NULL;
|
||||
GHOST_TStringArray *strArray = nullptr;
|
||||
int totPaths = 0, curLength = 0;
|
||||
|
||||
/* Count total number of file paths in buffer. */
|
||||
|
@ -196,8 +196,9 @@ void *GHOST_DropTargetX11::getURIListGhostData(unsigned char *dropBuffer, int dr
|
|||
curLength = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
curLength++;
|
||||
}
|
||||
}
|
||||
|
||||
strArray = (GHOST_TStringArray *)malloc(sizeof(GHOST_TStringArray));
|
||||
|
@ -224,8 +225,9 @@ void *GHOST_DropTargetX11::getURIListGhostData(unsigned char *dropBuffer, int dr
|
|||
curLength = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
curLength++;
|
||||
}
|
||||
}
|
||||
|
||||
return strArray;
|
||||
|
@ -235,11 +237,11 @@ void *GHOST_DropTargetX11::getGhostData(Atom dropType,
|
|||
unsigned char *dropBuffer,
|
||||
int dropBufferSize)
|
||||
{
|
||||
void *data = NULL;
|
||||
void *data = nullptr;
|
||||
unsigned char *tmpBuffer = (unsigned char *)malloc(dropBufferSize + 1);
|
||||
bool needsFree = true;
|
||||
|
||||
/* ensure NULL-terminator */
|
||||
/* Ensure nil-terminator. */
|
||||
memcpy(tmpBuffer, dropBuffer, dropBufferSize);
|
||||
tmpBuffer[dropBufferSize] = 0;
|
||||
|
||||
|
@ -265,8 +267,9 @@ void *GHOST_DropTargetX11::getGhostData(Atom dropType,
|
|||
m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
|
||||
}
|
||||
|
||||
if (needsFree)
|
||||
if (needsFree) {
|
||||
free(tmpBuffer);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -288,9 +291,10 @@ bool GHOST_DropTargetX11::GHOST_HandleClientMessage(XEvent *event)
|
|||
&dropY)) {
|
||||
void *data = getGhostData(dropType, dropBuffer, dropBufferSize);
|
||||
|
||||
if (data)
|
||||
if (data) {
|
||||
m_system->pushDragDropEvent(
|
||||
GHOST_kEventDraggingDropDone, m_draggedObjectType, m_window, dropX, dropY, data);
|
||||
}
|
||||
|
||||
free(dropBuffer);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
# include "GHOST_SystemCocoa.h"
|
||||
#endif
|
||||
|
||||
GHOST_ISystem *GHOST_ISystem::m_system = NULL;
|
||||
GHOST_ISystem *GHOST_ISystem::m_system = nullptr;
|
||||
|
||||
GHOST_TSuccess GHOST_ISystem::createSystem()
|
||||
{
|
||||
|
@ -61,7 +61,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem()
|
|||
#elif defined(__APPLE__)
|
||||
m_system = new GHOST_SystemCocoa();
|
||||
#endif
|
||||
success = m_system != NULL ? GHOST_kSuccess : GHOST_kFailure;
|
||||
success = m_system != nullptr ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
|
@ -77,7 +77,7 @@ GHOST_TSuccess GHOST_ISystem::disposeSystem()
|
|||
GHOST_TSuccess success = GHOST_kSuccess;
|
||||
if (m_system) {
|
||||
delete m_system;
|
||||
m_system = NULL;
|
||||
m_system = nullptr;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* just for NULL */
|
||||
|
||||
#include "GHOST_ISystemPaths.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -23,7 +21,7 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
GHOST_ISystemPaths *GHOST_ISystemPaths::m_systemPaths = NULL;
|
||||
GHOST_ISystemPaths *GHOST_ISystemPaths::m_systemPaths = nullptr;
|
||||
|
||||
GHOST_TSuccess GHOST_ISystemPaths::create()
|
||||
{
|
||||
|
@ -38,7 +36,7 @@ GHOST_TSuccess GHOST_ISystemPaths::create()
|
|||
m_systemPaths = new GHOST_SystemPathsUnix();
|
||||
# endif
|
||||
#endif
|
||||
success = m_systemPaths != NULL ? GHOST_kSuccess : GHOST_kFailure;
|
||||
success = m_systemPaths != nullptr ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
|
@ -51,7 +49,7 @@ GHOST_TSuccess GHOST_ISystemPaths::dispose()
|
|||
GHOST_TSuccess success = GHOST_kSuccess;
|
||||
if (m_systemPaths) {
|
||||
delete m_systemPaths;
|
||||
m_systemPaths = NULL;
|
||||
m_systemPaths = nullptr;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
|
|
|
@ -25,25 +25,28 @@ GHOST_TSuccess GHOST_DisposeSystemPaths(void)
|
|||
const char *GHOST_getSystemDir(int version, const char *versionstr)
|
||||
{
|
||||
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
|
||||
return systemPaths ? systemPaths->getSystemDir(version, versionstr) : NULL;
|
||||
return systemPaths ? systemPaths->getSystemDir(version, versionstr) : nullptr;
|
||||
}
|
||||
|
||||
const char *GHOST_getUserDir(int version, const char *versionstr)
|
||||
{
|
||||
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
|
||||
return systemPaths ? systemPaths->getUserDir(version, versionstr) : NULL; /* shouldn't be NULL */
|
||||
/* Shouldn't be `nullptr`. */
|
||||
return systemPaths ? systemPaths->getUserDir(version, versionstr) : nullptr;
|
||||
}
|
||||
|
||||
const char *GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type)
|
||||
{
|
||||
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
|
||||
return systemPaths ? systemPaths->getUserSpecialDir(type) : NULL; /* shouldn't be NULL */
|
||||
/* Shouldn't be `nullptr`. */
|
||||
return systemPaths ? systemPaths->getUserSpecialDir(type) : nullptr;
|
||||
}
|
||||
|
||||
const char *GHOST_getBinaryDir()
|
||||
{
|
||||
GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get();
|
||||
return systemPaths ? systemPaths->getBinaryDir() : NULL; /* shouldn't be NULL */
|
||||
/* Shouldn't be `nullptr`. */
|
||||
return systemPaths ? systemPaths->getBinaryDir() : nullptr;
|
||||
}
|
||||
|
||||
void GHOST_addToSystemRecentFiles(const char *filename)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "GHOST_System.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <stdio.h> /* just for printf */
|
||||
#include <cstdio> /* just for printf */
|
||||
|
||||
#include "GHOST_DisplayManager.h"
|
||||
#include "GHOST_EventManager.h"
|
||||
|
@ -23,10 +23,10 @@
|
|||
GHOST_System::GHOST_System()
|
||||
: m_nativePixel(false),
|
||||
m_windowFocus(true),
|
||||
m_displayManager(NULL),
|
||||
m_timerManager(NULL),
|
||||
m_windowManager(NULL),
|
||||
m_eventManager(NULL),
|
||||
m_displayManager(nullptr),
|
||||
m_timerManager(nullptr),
|
||||
m_windowManager(nullptr),
|
||||
m_eventManager(nullptr),
|
||||
#ifdef WITH_INPUT_NDOF
|
||||
m_ndofManager(0),
|
||||
#endif
|
||||
|
@ -61,7 +61,7 @@ GHOST_ITimerTask *GHOST_System::installTimer(uint64_t delay,
|
|||
}
|
||||
else {
|
||||
delete timer;
|
||||
timer = NULL;
|
||||
timer = nullptr;
|
||||
}
|
||||
}
|
||||
return timer;
|
||||
|
@ -205,7 +205,7 @@ GHOST_IWindow *GHOST_System::getWindowUnderCursor(int32_t x, int32_t y)
|
|||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GHOST_System::dispatchEvents()
|
||||
|
@ -331,20 +331,20 @@ GHOST_TSuccess GHOST_System::exit()
|
|||
}
|
||||
|
||||
delete m_displayManager;
|
||||
m_displayManager = NULL;
|
||||
m_displayManager = nullptr;
|
||||
|
||||
delete m_windowManager;
|
||||
m_windowManager = NULL;
|
||||
m_windowManager = nullptr;
|
||||
|
||||
delete m_timerManager;
|
||||
m_timerManager = NULL;
|
||||
m_timerManager = nullptr;
|
||||
|
||||
delete m_eventManager;
|
||||
m_eventManager = NULL;
|
||||
m_eventManager = nullptr;
|
||||
|
||||
#ifdef WITH_INPUT_NDOF
|
||||
delete m_ndofManager;
|
||||
m_ndofManager = NULL;
|
||||
m_ndofManager = nullptr;
|
||||
#endif
|
||||
|
||||
return GHOST_kSuccess;
|
||||
|
@ -376,13 +376,13 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
|
|||
GHOST_kDrawingContextTypeOpenGL,
|
||||
glSettings,
|
||||
true /* exclusive */);
|
||||
return (*window == NULL) ? GHOST_kFailure : GHOST_kSuccess;
|
||||
return (*window == nullptr) ? GHOST_kFailure : GHOST_kSuccess;
|
||||
}
|
||||
|
||||
bool GHOST_System::useNativePixel(void)
|
||||
bool GHOST_System::useNativePixel()
|
||||
{
|
||||
m_nativePixel = true;
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GHOST_System::useWindowFocus(const bool use_focus)
|
||||
|
@ -390,6 +390,11 @@ void GHOST_System::useWindowFocus(const bool use_focus)
|
|||
m_windowFocus = use_focus;
|
||||
}
|
||||
|
||||
bool GHOST_System::supportsCursorWarp()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void GHOST_System::initDebug(GHOST_Debug debug)
|
||||
{
|
||||
m_is_debug_enabled = debug.flags & GHOST_kDebugDefault;
|
||||
|
|
|
@ -151,10 +151,13 @@ class GHOST_System : public GHOST_ISystem {
|
|||
bool useNativePixel(void);
|
||||
bool m_nativePixel;
|
||||
|
||||
bool supportsCursorWarp(void);
|
||||
|
||||
/**
|
||||
* Focus window after opening, or put them in the background.
|
||||
*/
|
||||
void useWindowFocus(const bool use_focus);
|
||||
|
||||
bool m_windowFocus;
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,7 +40,7 @@ class GHOST_SystemNULL : public GHOST_System {
|
|||
}
|
||||
char *getClipboard(bool selection) const
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
void putClipboard(const char *buffer, bool selection) const
|
||||
{ /* nop */
|
||||
|
@ -69,7 +69,7 @@ class GHOST_SystemNULL : public GHOST_System {
|
|||
}
|
||||
GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings)
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
GHOST_TSuccess disposeContext(GHOST_IContext *context)
|
||||
{
|
||||
|
@ -117,6 +117,6 @@ class GHOST_SystemNULL : public GHOST_System {
|
|||
|
||||
GHOST_IWindow *getWindowUnderCursor(int32_t x, int32_t y)
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstdio> /* for fprintf only */
|
||||
#include <cstdlib> /* for exit */
|
||||
#include <stdio.h> /* for fprintf only */
|
||||
|
||||
#include <pwd.h> /* for get home without use getenv() */
|
||||
#include <string>
|
||||
|
@ -28,7 +28,7 @@ using std::string;
|
|||
#ifdef PREFIX
|
||||
static const char *static_path = PREFIX "/share";
|
||||
#else
|
||||
static const char *static_path = NULL;
|
||||
static const char *static_path = nullptr;
|
||||
#endif
|
||||
|
||||
GHOST_SystemPathsUnix::GHOST_SystemPathsUnix()
|
||||
|
@ -39,7 +39,7 @@ GHOST_SystemPathsUnix::~GHOST_SystemPathsUnix()
|
|||
{
|
||||
}
|
||||
|
||||
const char *GHOST_SystemPathsUnix::getSystemDir(int, const char *versionstr) const
|
||||
const char *GHOST_SystemPathsUnix::getSystemDir(int /*version*/, const char *versionstr) const
|
||||
{
|
||||
/* no prefix assumes a portable build which only uses bundled scripts */
|
||||
if (static_path) {
|
||||
|
@ -47,7 +47,7 @@ const char *GHOST_SystemPathsUnix::getSystemDir(int, const char *versionstr) con
|
|||
return system_path.c_str();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *GHOST_SystemPathsUnix::getUserDir(int version, const char *versionstr) const
|
||||
|
@ -67,32 +67,29 @@ const char *GHOST_SystemPathsUnix::getUserDir(int version, const char *versionst
|
|||
user_path = string(home) + "/.blender/" + versionstr;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return user_path.c_str();
|
||||
}
|
||||
else {
|
||||
if (user_path.empty() || last_version != version) {
|
||||
const char *home = getenv("XDG_CONFIG_HOME");
|
||||
if (user_path.empty() || last_version != version) {
|
||||
const char *home = getenv("XDG_CONFIG_HOME");
|
||||
|
||||
last_version = version;
|
||||
last_version = version;
|
||||
|
||||
if (home) {
|
||||
user_path = string(home) + "/blender/" + versionstr;
|
||||
}
|
||||
else {
|
||||
home = getenv("HOME");
|
||||
|
||||
if (home == NULL)
|
||||
home = getpwuid(getuid())->pw_dir;
|
||||
|
||||
user_path = string(home) + "/.config/blender/" + versionstr;
|
||||
}
|
||||
if (home) {
|
||||
user_path = string(home) + "/blender/" + versionstr;
|
||||
}
|
||||
else {
|
||||
home = getenv("HOME");
|
||||
if (home == nullptr) {
|
||||
home = getpwuid(getuid())->pw_dir;
|
||||
}
|
||||
user_path = string(home) + "/.config/blender/" + versionstr;
|
||||
}
|
||||
|
||||
return user_path.c_str();
|
||||
}
|
||||
|
||||
return user_path.c_str();
|
||||
}
|
||||
|
||||
const char *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const
|
||||
|
@ -135,7 +132,7 @@ const char *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes
|
|||
GHOST_ASSERT(
|
||||
false,
|
||||
"GHOST_SystemPathsUnix::getUserSpecialDir(): Invalid enum value for type parameter");
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static string path = "";
|
||||
|
@ -143,8 +140,8 @@ const char *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes
|
|||
string command = string("xdg-user-dir ") + type_str + " 2> /dev/null";
|
||||
|
||||
FILE *fstream = popen(command.c_str(), "r");
|
||||
if (fstream == NULL) {
|
||||
return NULL;
|
||||
if (fstream == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
std::stringstream path_stream;
|
||||
while (!feof(fstream)) {
|
||||
|
@ -157,7 +154,7 @@ const char *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes
|
|||
}
|
||||
if (pclose(fstream) == -1) {
|
||||
perror("GHOST_SystemPathsUnix::getUserSpecialDir failed at pclose()");
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!add_path.empty()) {
|
||||
|
@ -165,12 +162,12 @@ const char *GHOST_SystemPathsUnix::getUserSpecialDir(GHOST_TUserSpecialDirTypes
|
|||
}
|
||||
|
||||
path = path_stream.str();
|
||||
return path[0] ? path.c_str() : NULL;
|
||||
return path[0] ? path.c_str() : nullptr;
|
||||
}
|
||||
|
||||
const char *GHOST_SystemPathsUnix::getBinaryDir() const
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GHOST_SystemPathsUnix::addToSystemRecentFiles(const char * /*filename*/) const
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
|
||||
#include "GHOST_ContextSDL.h"
|
||||
#include "GHOST_SystemSDL.h"
|
||||
|
@ -47,7 +47,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
|
|||
const bool /* is_dialog */,
|
||||
const GHOST_IWindow *parentWindow)
|
||||
{
|
||||
GHOST_WindowSDL *window = NULL;
|
||||
GHOST_WindowSDL *window = nullptr;
|
||||
|
||||
window = new GHOST_WindowSDL(this,
|
||||
title,
|
||||
|
@ -79,7 +79,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
|
|||
}
|
||||
else {
|
||||
delete window;
|
||||
window = NULL;
|
||||
window = nullptr;
|
||||
}
|
||||
}
|
||||
return window;
|
||||
|
@ -127,20 +127,20 @@ uint8_t GHOST_SystemSDL::getNumDisplays() const
|
|||
|
||||
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GLSettings /*glSettings*/)
|
||||
{
|
||||
GHOST_Context *context = new GHOST_ContextSDL(0,
|
||||
NULL,
|
||||
GHOST_Context *context = new GHOST_ContextSDL(false,
|
||||
nullptr,
|
||||
0, /* Profile bit. */
|
||||
3,
|
||||
3,
|
||||
GHOST_OPENGL_SDL_CONTEXT_FLAGS,
|
||||
GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY);
|
||||
|
||||
if (context->initializeDrawingContext())
|
||||
if (context->initializeDrawingContext()) {
|
||||
return context;
|
||||
else
|
||||
delete context;
|
||||
}
|
||||
delete context;
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemSDL::disposeContext(GHOST_IContext *context)
|
||||
|
@ -286,7 +286,7 @@ static GHOST_TKey convertSDLKey(SDL_Scancode key)
|
|||
static SDL_Window *SDL_GetWindowFromID_fallback(Uint32 id)
|
||||
{
|
||||
SDL_Window *sdl_win = SDL_GetWindowFromID(id);
|
||||
if (sdl_win == NULL) {
|
||||
if (sdl_win == nullptr) {
|
||||
sdl_win = SDL_GL_GetCurrentWindow();
|
||||
}
|
||||
return sdl_win;
|
||||
|
@ -294,16 +294,16 @@ static SDL_Window *SDL_GetWindowFromID_fallback(Uint32 id)
|
|||
|
||||
void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
|
||||
{
|
||||
GHOST_Event *g_event = NULL;
|
||||
GHOST_Event *g_event = nullptr;
|
||||
|
||||
switch (sdl_event->type) {
|
||||
case SDL_WINDOWEVENT: {
|
||||
SDL_WindowEvent &sdl_sub_evt = sdl_event->window;
|
||||
GHOST_WindowSDL *window = findGhostWindow(
|
||||
SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID));
|
||||
/* Can be NULL on close window. */
|
||||
/* Can be nullptr on close window. */
|
||||
#if 0
|
||||
assert(window != NULL);
|
||||
assert(window != nullptr);
|
||||
#endif
|
||||
|
||||
switch (sdl_sub_evt.event) {
|
||||
|
@ -340,7 +340,7 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
|
|||
SDL_MouseMotionEvent &sdl_sub_evt = sdl_event->motion;
|
||||
SDL_Window *sdl_win = SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID);
|
||||
GHOST_WindowSDL *window = findGhostWindow(sdl_win);
|
||||
assert(window != NULL);
|
||||
assert(window != nullptr);
|
||||
|
||||
int x_win, y_win;
|
||||
SDL_GetWindowPosition(sdl_win, &x_win, &y_win);
|
||||
|
@ -416,22 +416,28 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
|
|||
|
||||
GHOST_WindowSDL *window = findGhostWindow(
|
||||
SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID));
|
||||
assert(window != NULL);
|
||||
assert(window != nullptr);
|
||||
|
||||
/* process rest of normal mouse buttons */
|
||||
if (sdl_sub_evt.button == SDL_BUTTON_LEFT)
|
||||
if (sdl_sub_evt.button == SDL_BUTTON_LEFT) {
|
||||
gbmask = GHOST_kButtonMaskLeft;
|
||||
else if (sdl_sub_evt.button == SDL_BUTTON_MIDDLE)
|
||||
}
|
||||
else if (sdl_sub_evt.button == SDL_BUTTON_MIDDLE) {
|
||||
gbmask = GHOST_kButtonMaskMiddle;
|
||||
else if (sdl_sub_evt.button == SDL_BUTTON_RIGHT)
|
||||
}
|
||||
else if (sdl_sub_evt.button == SDL_BUTTON_RIGHT) {
|
||||
gbmask = GHOST_kButtonMaskRight;
|
||||
/* these buttons are untested! */
|
||||
else if (sdl_sub_evt.button == SDL_BUTTON_X1)
|
||||
/* these buttons are untested! */
|
||||
}
|
||||
else if (sdl_sub_evt.button == SDL_BUTTON_X1) {
|
||||
gbmask = GHOST_kButtonMaskButton4;
|
||||
else if (sdl_sub_evt.button == SDL_BUTTON_X2)
|
||||
}
|
||||
else if (sdl_sub_evt.button == SDL_BUTTON_X2) {
|
||||
gbmask = GHOST_kButtonMaskButton5;
|
||||
else
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
g_event = new GHOST_EventButton(
|
||||
getMilliSeconds(), type, window, gbmask, GHOST_TABLET_DATA_NONE);
|
||||
|
@ -441,7 +447,7 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
|
|||
SDL_MouseWheelEvent &sdl_sub_evt = sdl_event->wheel;
|
||||
GHOST_WindowSDL *window = findGhostWindow(
|
||||
SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID));
|
||||
assert(window != NULL);
|
||||
assert(window != nullptr);
|
||||
g_event = new GHOST_EventWheel(getMilliSeconds(), window, sdl_sub_evt.y);
|
||||
break;
|
||||
}
|
||||
|
@ -454,7 +460,7 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
|
|||
|
||||
GHOST_WindowSDL *window = findGhostWindow(
|
||||
SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID));
|
||||
assert(window != NULL);
|
||||
assert(window != nullptr);
|
||||
|
||||
GHOST_TKey gkey = convertSDLKey(sdl_sub_evt.keysym.scancode);
|
||||
/* NOTE: the `sdl_sub_evt.keysym.sym` is truncated,
|
||||
|
@ -590,7 +596,7 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
|
|||
}
|
||||
}
|
||||
|
||||
g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sym, NULL, false);
|
||||
g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sym, nullptr, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -660,14 +666,14 @@ bool GHOST_SystemSDL::processEvents(bool waitForEvent)
|
|||
uint64_t next = timerMgr->nextFireTime();
|
||||
|
||||
if (next == GHOST_kFireTimeNever) {
|
||||
SDL_WaitEventTimeout(NULL, -1);
|
||||
SDL_WaitEventTimeout(nullptr, -1);
|
||||
// SleepTillEvent(m_display, -1);
|
||||
}
|
||||
else {
|
||||
int64_t maxSleep = next - getMilliSeconds();
|
||||
|
||||
if (maxSleep >= 0) {
|
||||
SDL_WaitEventTimeout(NULL, next - getMilliSeconds());
|
||||
SDL_WaitEventTimeout(nullptr, next - getMilliSeconds());
|
||||
// SleepTillEvent(m_display, next - getMilliSeconds()); /* X11. */
|
||||
}
|
||||
}
|
||||
|
@ -693,9 +699,9 @@ bool GHOST_SystemSDL::processEvents(bool waitForEvent)
|
|||
|
||||
GHOST_WindowSDL *GHOST_SystemSDL::findGhostWindow(SDL_Window *sdl_win)
|
||||
{
|
||||
if (sdl_win == NULL)
|
||||
return NULL;
|
||||
|
||||
if (sdl_win == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
/* It is not entirely safe to do this as the backptr may point
|
||||
* to a window that has recently been removed.
|
||||
* We should always check the window manager's list of windows
|
||||
|
@ -712,19 +718,19 @@ GHOST_WindowSDL *GHOST_SystemSDL::findGhostWindow(SDL_Window *sdl_win)
|
|||
return window;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GHOST_SystemSDL::addDirtyWindow(GHOST_WindowSDL *bad_wind)
|
||||
{
|
||||
GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)");
|
||||
GHOST_ASSERT((bad_wind != nullptr), "addDirtyWindow() nullptr ptr trapped (window)");
|
||||
|
||||
m_dirty_windows.push_back(bad_wind);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemSDL::getButtons(GHOST_Buttons &buttons) const
|
||||
{
|
||||
Uint8 state = SDL_GetMouseState(NULL, NULL);
|
||||
Uint8 state = SDL_GetMouseState(nullptr, nullptr);
|
||||
buttons.set(GHOST_kButtonMaskLeft, (state & SDL_BUTTON_LMASK) != 0);
|
||||
buttons.set(GHOST_kButtonMaskMiddle, (state & SDL_BUTTON_MMASK) != 0);
|
||||
buttons.set(GHOST_kButtonMaskRight, (state & SDL_BUTTON_RMASK) != 0);
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
|
||||
#include <cstring>
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Private Types & Defines
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Selected input event code defines from `linux/input-event-codes.h`
|
||||
* We include some of the button input event codes here, since the header is
|
||||
|
@ -112,6 +116,7 @@ struct input_t {
|
|||
|
||||
struct zwp_relative_pointer_v1 *relative_pointer;
|
||||
struct zwp_locked_pointer_v1 *locked_pointer;
|
||||
struct zwp_confined_pointer_v1 *confined_pointer;
|
||||
|
||||
struct xkb_context *xkb_context;
|
||||
struct xkb_state *xkb_state;
|
||||
|
@ -156,6 +161,12 @@ struct display_t {
|
|||
std::vector<struct wl_egl_window *> os_egl_windows;
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Private Utility Functions
|
||||
* \{ */
|
||||
|
||||
static GHOST_WindowManager *window_manager = nullptr;
|
||||
|
||||
static void display_destroy(display_t *d)
|
||||
|
@ -429,8 +440,10 @@ static const std::vector<std::string> mime_send = {
|
|||
"text/plain",
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Interface Callbacks
|
||||
/** \name Listener (Relative Motion), #zwp_relative_pointer_v1_listener
|
||||
*
|
||||
* These callbacks are registered for Wayland interfaces and called when
|
||||
* an event is received from the compositor.
|
||||
|
@ -466,6 +479,12 @@ static const zwp_relative_pointer_v1_listener relative_pointer_listener = {
|
|||
relative_pointer_relative_motion,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (Data Source), #wl_data_source_listener
|
||||
* \{ */
|
||||
|
||||
static void dnd_events(const input_t *const input, const GHOST_TEventType event)
|
||||
{
|
||||
const uint64_t time = input->system->getMilliSeconds();
|
||||
|
@ -507,7 +526,7 @@ static std::string read_pipe(data_offer_t *data_offer, const std::string mime_re
|
|||
* A target accepts an offered mime type.
|
||||
*
|
||||
* Sent when a target accepts pointer_focus or motion events. If
|
||||
* a target does not accept any of the offered types, type is NULL.
|
||||
* a target does not accept any of the offered types, type is nullptr.
|
||||
*/
|
||||
static void data_source_target(void * /*data*/,
|
||||
struct wl_data_source * /*wl_data_source*/,
|
||||
|
@ -581,6 +600,12 @@ static const struct wl_data_source_listener data_source_listener = {
|
|||
data_source_action,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (Data Offer), #wl_data_offer_listener
|
||||
* \{ */
|
||||
|
||||
static void data_offer_offer(void *data,
|
||||
struct wl_data_offer * /*wl_data_offer*/,
|
||||
const char *mime_type)
|
||||
|
@ -608,6 +633,12 @@ static const struct wl_data_offer_listener data_offer_listener = {
|
|||
data_offer_action,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (Data Device), #wl_data_device_listener
|
||||
* \{ */
|
||||
|
||||
static void data_device_data_offer(void * /*data*/,
|
||||
struct wl_data_device * /*wl_data_device*/,
|
||||
struct wl_data_offer *id)
|
||||
|
@ -794,6 +825,12 @@ static const struct wl_data_device_listener data_device_listener = {
|
|||
data_device_selection,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (Pointer), #wl_pointer_listener
|
||||
* \{ */
|
||||
|
||||
static void cursor_buffer_release(void *data, struct wl_buffer *wl_buffer)
|
||||
{
|
||||
cursor_t *cursor = static_cast<cursor_t *>(data);
|
||||
|
@ -828,8 +865,9 @@ static bool update_cursor_scale(cursor_t &cursor, wl_shm *shm)
|
|||
{
|
||||
int scale = 0;
|
||||
for (const output_t *output : cursor.outputs) {
|
||||
if (output->scale > scale)
|
||||
if (output->scale > scale) {
|
||||
scale = output->scale;
|
||||
}
|
||||
}
|
||||
|
||||
if (scale > 0 && cursor.scale != scale) {
|
||||
|
@ -1030,6 +1068,12 @@ static const struct wl_pointer_listener pointer_listener = {
|
|||
pointer_axis,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (Keyboard), #wl_keyboard_listener
|
||||
* \{ */
|
||||
|
||||
static void keyboard_keymap(
|
||||
void *data, struct wl_keyboard * /*wl_keyboard*/, uint32_t format, int32_t fd, uint32_t size)
|
||||
{
|
||||
|
@ -1235,6 +1279,12 @@ static const struct wl_keyboard_listener keyboard_listener = {
|
|||
keyboard_repeat_info,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (Seat), #wl_seat_listener
|
||||
* \{ */
|
||||
|
||||
static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities)
|
||||
{
|
||||
input_t *input = static_cast<input_t *>(data);
|
||||
|
@ -1271,6 +1321,12 @@ static const struct wl_seat_listener seat_listener = {
|
|||
seat_name,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (Output), #wl_output_listener
|
||||
* \{ */
|
||||
|
||||
static void output_geometry(void *data,
|
||||
struct wl_output * /*wl_output*/,
|
||||
int32_t /*x*/,
|
||||
|
@ -1326,6 +1382,12 @@ static const struct wl_output_listener output_listener = {
|
|||
output_scale,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (XDG WM Base), #xdg_wm_base_listener
|
||||
* \{ */
|
||||
|
||||
static void shell_ping(void * /*data*/, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
|
||||
{
|
||||
xdg_wm_base_pong(xdg_wm_base, serial);
|
||||
|
@ -1335,6 +1397,12 @@ static const struct xdg_wm_base_listener shell_listener = {
|
|||
shell_ping,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Listener (Registry), #wl_registry_listener
|
||||
* \{ */
|
||||
|
||||
static void global_add(void *data,
|
||||
struct wl_registry *wl_registry,
|
||||
uint32_t name,
|
||||
|
@ -1375,6 +1443,7 @@ static void global_add(void *data,
|
|||
input->data_source->buffer_out = nullptr;
|
||||
input->relative_pointer = nullptr;
|
||||
input->locked_pointer = nullptr;
|
||||
input->confined_pointer = nullptr;
|
||||
input->seat = static_cast<wl_seat *>(
|
||||
wl_registry_bind(wl_registry, name, &wl_seat_interface, 4));
|
||||
display->inputs.push_back(input);
|
||||
|
@ -1538,8 +1607,9 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c
|
|||
data_source_t *data_source = d->inputs[0]->data_source;
|
||||
|
||||
/* Copy buffer. */
|
||||
data_source->buffer_out = static_cast<char *>(malloc(strlen(buffer) + 1));
|
||||
std::strcpy(data_source->buffer_out, buffer);
|
||||
const size_t buffer_size = strlen(buffer) + 1;
|
||||
data_source->buffer_out = static_cast<char *>(malloc(buffer_size));
|
||||
std::memcpy(data_source->buffer_out, buffer, buffer_size);
|
||||
|
||||
data_source->data_source = wl_data_device_manager_create_data_source(d->data_device_manager);
|
||||
|
||||
|
@ -1563,14 +1633,13 @@ uint8_t GHOST_SystemWayland::getNumDisplays() const
|
|||
|
||||
GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) const
|
||||
{
|
||||
if (!d->inputs.empty() && (d->inputs[0]->focus_pointer != nullptr)) {
|
||||
x = d->inputs[0]->x;
|
||||
y = d->inputs[0]->y;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
if (d->inputs.empty() || (d->inputs[0]->focus_pointer == nullptr)) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
x = d->inputs[0]->x;
|
||||
y = d->inputs[0]->y;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(int32_t /*x*/, int32_t /*y*/)
|
||||
|
@ -1615,10 +1684,10 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*g
|
|||
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
|
||||
EGL_OPENGL_API);
|
||||
|
||||
if (context->initializeDrawingContext())
|
||||
if (context->initializeDrawingContext()) {
|
||||
return context;
|
||||
else
|
||||
delete context;
|
||||
}
|
||||
delete context;
|
||||
}
|
||||
|
||||
context = new GHOST_ContextEGL(this,
|
||||
|
@ -1635,9 +1704,7 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*g
|
|||
if (context->initializeDrawingContext()) {
|
||||
return context;
|
||||
}
|
||||
else {
|
||||
delete context;
|
||||
}
|
||||
delete context;
|
||||
|
||||
GHOST_PRINT("Cannot create off-screen EGL context" << std::endl);
|
||||
|
||||
|
@ -1806,7 +1873,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
|
|||
cursor_t *cursor = &d->inputs[0]->cursor;
|
||||
|
||||
static const int32_t stride = sizex * 4; /* ARGB */
|
||||
cursor->file_buffer->size = size_t(stride * sizey);
|
||||
cursor->file_buffer->size = (size_t)stride * sizey;
|
||||
|
||||
#ifdef HAVE_MEMFD_CREATE
|
||||
const int fd = memfd_create("blender-cursor-custom", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||
|
@ -1919,6 +1986,11 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible)
|
|||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
bool GHOST_SystemWayland::supportsCursorWarp()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode,
|
||||
const GHOST_TGrabCursorMode mode_current,
|
||||
|
||||
|
@ -1940,15 +2012,32 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo
|
|||
|
||||
input_t *input = d->inputs[0];
|
||||
|
||||
if (mode_current == GHOST_kGrabHide) {
|
||||
#define MODE_NEEDS_LOCK(m) ((m) == GHOST_kGrabWrap || (m) == GHOST_kGrabHide)
|
||||
#define MODE_NEEDS_HIDE(m) ((m) == GHOST_kGrabHide)
|
||||
#define MODE_NEEDS_CONFINE(m) ((m) == GHOST_kGrabNormal)
|
||||
|
||||
const bool was_lock = MODE_NEEDS_LOCK(mode_current);
|
||||
const bool use_lock = MODE_NEEDS_LOCK(mode);
|
||||
|
||||
/* Check for wrap as #supportsCursorWarp isn't supproted. */
|
||||
const bool was_hide = MODE_NEEDS_HIDE(mode_current) || (mode_current == GHOST_kGrabWrap);
|
||||
const bool use_hide = MODE_NEEDS_HIDE(mode) || (mode == GHOST_kGrabWrap);
|
||||
|
||||
const bool was_confine = MODE_NEEDS_CONFINE(mode_current);
|
||||
const bool use_confine = MODE_NEEDS_CONFINE(mode);
|
||||
|
||||
#undef MODE_NEEDS_LOCK
|
||||
#undef MODE_NEEDS_HIDE
|
||||
#undef MODE_NEEDS_CONFINE
|
||||
|
||||
if (!use_hide) {
|
||||
setCursorVisibility(true);
|
||||
}
|
||||
|
||||
if ((mode == GHOST_kGrabDisable) ||
|
||||
/* Switching from one grab mode to another,
|
||||
* in this case disable the current locks as it makes logic confusing,
|
||||
* postpone changing the cursor to avoid flickering. */
|
||||
(mode_current != GHOST_kGrabDisable)) {
|
||||
/* Switching from one grab mode to another,
|
||||
* in this case disable the current locks as it makes logic confusing,
|
||||
* postpone changing the cursor to avoid flickering. */
|
||||
if (!use_lock) {
|
||||
if (input->relative_pointer) {
|
||||
zwp_relative_pointer_v1_destroy(input->relative_pointer);
|
||||
input->relative_pointer = nullptr;
|
||||
|
@ -1959,23 +2048,44 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo
|
|||
}
|
||||
}
|
||||
|
||||
if (mode != GHOST_kGrabDisable) {
|
||||
/* TODO(@campbellbarton): As WAYLAND does not support warping the pointer it may not be
|
||||
* possible to support #GHOST_kGrabWrap by pragmatically settings it's coordinates.
|
||||
* An alternative could be to draw the cursor in software (and hide the real cursor),
|
||||
* or just accept a locked cursor on WAYLAND. */
|
||||
input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
|
||||
d->relative_pointer_manager, input->pointer);
|
||||
zwp_relative_pointer_v1_add_listener(
|
||||
input->relative_pointer, &relative_pointer_listener, input);
|
||||
input->locked_pointer = zwp_pointer_constraints_v1_lock_pointer(
|
||||
d->pointer_constraints,
|
||||
surface,
|
||||
input->pointer,
|
||||
nullptr,
|
||||
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
|
||||
if (!use_confine) {
|
||||
if (input->confined_pointer) {
|
||||
zwp_confined_pointer_v1_destroy(input->confined_pointer);
|
||||
input->confined_pointer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == GHOST_kGrabHide) {
|
||||
if (mode != GHOST_kGrabDisable) {
|
||||
if (use_lock) {
|
||||
if (!was_lock) {
|
||||
/* TODO(@campbellbarton): As WAYLAND does not support warping the pointer it may not be
|
||||
* possible to support #GHOST_kGrabWrap by pragmatically settings it's coordinates.
|
||||
* An alternative could be to draw the cursor in software (and hide the real cursor),
|
||||
* or just accept a locked cursor on WAYLAND. */
|
||||
input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
|
||||
d->relative_pointer_manager, input->pointer);
|
||||
zwp_relative_pointer_v1_add_listener(
|
||||
input->relative_pointer, &relative_pointer_listener, input);
|
||||
input->locked_pointer = zwp_pointer_constraints_v1_lock_pointer(
|
||||
d->pointer_constraints,
|
||||
surface,
|
||||
input->pointer,
|
||||
nullptr,
|
||||
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
|
||||
}
|
||||
}
|
||||
else if (use_confine) {
|
||||
if (!was_confine) {
|
||||
input->confined_pointer = zwp_pointer_constraints_v1_confine_pointer(
|
||||
d->pointer_constraints,
|
||||
surface,
|
||||
input->pointer,
|
||||
nullptr,
|
||||
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
|
||||
}
|
||||
}
|
||||
|
||||
if (use_hide && !was_hide) {
|
||||
setCursorVisibility(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ struct display_t;
|
|||
|
||||
struct output_t {
|
||||
struct wl_output *output;
|
||||
int32_t width_pxl, height_pxl; // dimensions in pixel
|
||||
int32_t width_mm, height_mm; // dimensions in millimeter
|
||||
int32_t width_pxl, height_pxl; /* Dimensions in pixel. */
|
||||
int32_t width_mm, height_mm; /* Dimensions in millimeter. */
|
||||
int transform;
|
||||
int scale;
|
||||
std::string make;
|
||||
|
@ -103,6 +103,8 @@ class GHOST_SystemWayland : public GHOST_System {
|
|||
|
||||
GHOST_TSuccess setCursorVisibility(bool visible);
|
||||
|
||||
bool supportsCursorWarp();
|
||||
|
||||
GHOST_TSuccess setCursorGrab(const GHOST_TGrabCursorMode mode,
|
||||
const GHOST_TGrabCursorMode mode_current,
|
||||
wl_surface *surface);
|
||||
|
|
|
@ -58,9 +58,9 @@
|
|||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstdio> /* for fprintf only */
|
||||
#include <cstdlib> /* for exit */
|
||||
#include <iostream>
|
||||
#include <stdio.h> /* for fprintf only */
|
||||
#include <vector>
|
||||
|
||||
/* For debugging, so we can break-point X11 errors. */
|
||||
|
@ -89,8 +89,8 @@ static GHOST_TKey ghost_key_from_keysym_or_keycode(const KeySym key,
|
|||
const KeyCode keycode);
|
||||
|
||||
/* these are for copy and select copy */
|
||||
static char *txt_cut_buffer = NULL;
|
||||
static char *txt_select_buffer = NULL;
|
||||
static char *txt_cut_buffer = nullptr;
|
||||
static char *txt_select_buffer = nullptr;
|
||||
|
||||
#ifdef WITH_XWAYLAND_HACK
|
||||
static bool use_xwayland_hack = false;
|
||||
|
@ -98,10 +98,10 @@ static bool use_xwayland_hack = false;
|
|||
|
||||
using namespace std;
|
||||
|
||||
GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_time(0)
|
||||
GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(nullptr), m_start_time(0)
|
||||
{
|
||||
XInitThreads();
|
||||
m_display = XOpenDisplay(NULL);
|
||||
m_display = XOpenDisplay(nullptr);
|
||||
|
||||
if (!m_display) {
|
||||
std::cerr << "Unable to open a display" << std::endl;
|
||||
|
@ -117,7 +117,7 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_
|
|||
/* NOTE: Don't open connection to XIM server here, because the locale has to be
|
||||
* set before opening the connection but `setlocale()` has not been called yet.
|
||||
* the connection will be opened after entering the event loop. */
|
||||
m_xim = NULL;
|
||||
m_xim = nullptr;
|
||||
#endif
|
||||
|
||||
#define GHOST_INTERN_ATOM_IF_EXISTS(atom) \
|
||||
|
@ -165,7 +165,7 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_
|
|||
|
||||
/* compute the initial time */
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv, NULL) == -1) {
|
||||
if (gettimeofday(&tv, nullptr) == -1) {
|
||||
GHOST_ASSERT(false, "Could not instantiate timer!");
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_
|
|||
use_xkb = XkbQueryExtension(
|
||||
m_display, &xkb_opcode, &xkb_event, &xkb_error, &xkb_major, &xkb_minor);
|
||||
if (use_xkb) {
|
||||
XkbSetDetectableAutoRepeat(m_display, true, NULL);
|
||||
XkbSetDetectableAutoRepeat(m_display, true, nullptr);
|
||||
|
||||
m_xkb_descr = XkbGetMap(m_display, 0, XkbUseCoreKbd);
|
||||
if (m_xkb_descr) {
|
||||
|
@ -190,7 +190,7 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_
|
|||
}
|
||||
|
||||
#ifdef WITH_XWAYLAND_HACK
|
||||
use_xwayland_hack = getenv("WAYLAND_DISPLAY") != NULL;
|
||||
use_xwayland_hack = getenv("WAYLAND_DISPLAY") != nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_X11_XINPUT
|
||||
|
@ -266,7 +266,7 @@ GHOST_TSuccess GHOST_SystemX11::init()
|
|||
uint64_t GHOST_SystemX11::getMilliSeconds() const
|
||||
{
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv, NULL) == -1) {
|
||||
if (gettimeofday(&tv, nullptr) == -1) {
|
||||
GHOST_ASSERT(false, "Could not compute time!");
|
||||
}
|
||||
|
||||
|
@ -334,10 +334,11 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
|
|||
const bool is_dialog,
|
||||
const GHOST_IWindow *parentWindow)
|
||||
{
|
||||
GHOST_WindowX11 *window = NULL;
|
||||
GHOST_WindowX11 *window = nullptr;
|
||||
|
||||
if (!m_display)
|
||||
return 0;
|
||||
if (!m_display) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
window = new GHOST_WindowX11(this,
|
||||
m_display,
|
||||
|
@ -367,7 +368,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
|
|||
}
|
||||
else {
|
||||
delete window;
|
||||
window = NULL;
|
||||
window = nullptr;
|
||||
}
|
||||
}
|
||||
return window;
|
||||
|
@ -395,7 +396,7 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
|
|||
#if defined(WITH_GL_PROFILE_CORE)
|
||||
{
|
||||
const char *version_major = (char *)glewGetString(GLEW_VERSION_MAJOR);
|
||||
if (version_major != NULL && version_major[0] == '1') {
|
||||
if (version_major != nullptr && version_major[0] == '1') {
|
||||
fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
|
||||
abort();
|
||||
}
|
||||
|
@ -438,9 +439,9 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
|
|||
EGL_OPENGL_API);
|
||||
#else
|
||||
context = new GHOST_ContextGLX(false,
|
||||
(Window)NULL,
|
||||
(Window) nullptr,
|
||||
m_display,
|
||||
(GLXFBConfig)NULL,
|
||||
(GLXFBConfig) nullptr,
|
||||
profile_mask,
|
||||
4,
|
||||
minor,
|
||||
|
@ -449,10 +450,10 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
|
|||
GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
|
||||
#endif
|
||||
|
||||
if (context->initializeDrawingContext())
|
||||
if (context->initializeDrawingContext()) {
|
||||
return context;
|
||||
else
|
||||
delete context;
|
||||
}
|
||||
delete context;
|
||||
}
|
||||
|
||||
#if defined(WITH_GL_EGL)
|
||||
|
@ -469,9 +470,9 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
|
|||
EGL_OPENGL_API);
|
||||
#else
|
||||
context = new GHOST_ContextGLX(false,
|
||||
(Window)NULL,
|
||||
(Window) nullptr,
|
||||
m_display,
|
||||
(GLXFBConfig)NULL,
|
||||
(GLXFBConfig) nullptr,
|
||||
profile_mask,
|
||||
3,
|
||||
3,
|
||||
|
@ -480,12 +481,12 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
|
|||
GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
|
||||
#endif
|
||||
|
||||
if (context->initializeDrawingContext())
|
||||
if (context->initializeDrawingContext()) {
|
||||
return context;
|
||||
else
|
||||
delete context;
|
||||
}
|
||||
delete context;
|
||||
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -506,7 +507,7 @@ static void destroyIMCallback(XIM /*xim*/, XPointer ptr, XPointer /*data*/)
|
|||
GHOST_PRINT("XIM server died\n");
|
||||
|
||||
if (ptr)
|
||||
*(XIM *)ptr = NULL;
|
||||
*(XIM *)ptr = nullptr;
|
||||
}
|
||||
|
||||
bool GHOST_SystemX11::openX11_IM()
|
||||
|
@ -517,14 +518,14 @@ bool GHOST_SystemX11::openX11_IM()
|
|||
/* set locale modifiers such as `@im=ibus` specified by XMODIFIERS. */
|
||||
XSetLocaleModifiers("");
|
||||
|
||||
m_xim = XOpenIM(m_display, NULL, (char *)GHOST_X11_RES_NAME, (char *)GHOST_X11_RES_CLASS);
|
||||
m_xim = XOpenIM(m_display, nullptr, (char *)GHOST_X11_RES_NAME, (char *)GHOST_X11_RES_CLASS);
|
||||
if (!m_xim)
|
||||
return false;
|
||||
|
||||
XIMCallback destroy;
|
||||
destroy.callback = (XIMProc)destroyIMCallback;
|
||||
destroy.client_data = (XPointer)&m_xim;
|
||||
XSetIMValues(m_xim, XNDestroyCallback, &destroy, NULL);
|
||||
XSetIMValues(m_xim, XNDestroyCallback, &destroy, nullptr);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -532,8 +533,9 @@ bool GHOST_SystemX11::openX11_IM()
|
|||
GHOST_WindowX11 *GHOST_SystemX11::findGhostWindow(Window xwind) const
|
||||
{
|
||||
|
||||
if (xwind == 0)
|
||||
return NULL;
|
||||
if (xwind == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* It is not entirely safe to do this as the backptr may point
|
||||
* to a window that has recently been removed.
|
||||
|
@ -551,7 +553,7 @@ GHOST_WindowX11 *GHOST_SystemX11::findGhostWindow(Window xwind) const
|
|||
return window;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void SleepTillEvent(Display *display, int64_t maxSleep)
|
||||
|
@ -563,7 +565,7 @@ static void SleepTillEvent(Display *display, int64_t maxSleep)
|
|||
FD_SET(fd, &fds);
|
||||
|
||||
if (maxSleep == -1) {
|
||||
select(fd + 1, &fds, NULL, NULL, NULL);
|
||||
select(fd + 1, &fds, nullptr, nullptr, nullptr);
|
||||
}
|
||||
else {
|
||||
timeval tv;
|
||||
|
@ -571,7 +573,7 @@ static void SleepTillEvent(Display *display, int64_t maxSleep)
|
|||
tv.tv_sec = maxSleep / 1000;
|
||||
tv.tv_usec = (maxSleep - tv.tv_sec * 1000) * 1000;
|
||||
|
||||
select(fd + 1, &fds, NULL, NULL, &tv);
|
||||
select(fd + 1, &fds, nullptr, nullptr, &tv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -677,7 +679,7 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent)
|
|||
}
|
||||
|
||||
/* dispatch event to XIM server */
|
||||
if ((XFilterEvent(&xevent, (Window)NULL) == True)) {
|
||||
if ((XFilterEvent(&xevent, (Window) nullptr) == True)) {
|
||||
/* do nothing now, the event is consumed by XIM. */
|
||||
continue;
|
||||
}
|
||||
|
@ -739,7 +741,7 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent)
|
|||
window,
|
||||
ghost_key_from_keysym(modifiers[i]),
|
||||
'\0',
|
||||
NULL,
|
||||
nullptr,
|
||||
false));
|
||||
}
|
||||
}
|
||||
|
@ -773,7 +775,7 @@ static bool checkTabletProximity(Display *display, XDevice *device)
|
|||
/* see: state.c from xinput, to get more data out of the device */
|
||||
XDeviceState *state;
|
||||
|
||||
if (device == NULL) {
|
||||
if (device == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -812,7 +814,7 @@ static bool checkTabletProximity(Display *display, XDevice *device)
|
|||
void GHOST_SystemX11::processEvent(XEvent *xe)
|
||||
{
|
||||
GHOST_WindowX11 *window = findGhostWindow(xe->xany.window);
|
||||
GHOST_Event *g_event = NULL;
|
||||
GHOST_Event *g_event = nullptr;
|
||||
|
||||
/* Detect auto-repeat. */
|
||||
bool is_repeat = false;
|
||||
|
@ -822,7 +824,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
|
|||
/* Set to true if this key will repeat. */
|
||||
bool is_repeat_keycode = false;
|
||||
|
||||
if (m_xkb_descr != NULL) {
|
||||
if (m_xkb_descr != nullptr) {
|
||||
/* Use XKB support. */
|
||||
is_repeat_keycode = (
|
||||
/* Should always be true, check just in case. */
|
||||
|
@ -954,8 +956,9 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
|
|||
GHOST_Rect bounds;
|
||||
|
||||
/* fallback to window bounds */
|
||||
if (window->getCursorGrabBounds(bounds) == GHOST_kFailure)
|
||||
if (window->getCursorGrabBounds(bounds) == GHOST_kFailure) {
|
||||
window->getClientBounds(bounds);
|
||||
}
|
||||
|
||||
/* Could also clamp to screen bounds wrap with a window outside the view will
|
||||
* fail at the moment. Use offset of 8 in case the window is at screen bounds. */
|
||||
|
@ -1019,7 +1022,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
|
|||
char *utf8_buf = utf8_array;
|
||||
int len = 1; /* at least one null character will be stored */
|
||||
#else
|
||||
char *utf8_buf = NULL;
|
||||
char *utf8_buf = nullptr;
|
||||
#endif
|
||||
|
||||
GHOST_TEventType type = (xke->type == KeyPress) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
|
||||
|
@ -1065,7 +1068,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
|
|||
key_sym = XLookupKeysym(xke, 0);
|
||||
}
|
||||
|
||||
if (!XLookupString(xke, &ascii, 1, &key_sym_str, NULL)) {
|
||||
if (!XLookupString(xke, &ascii, 1, &key_sym_str, nullptr)) {
|
||||
ascii = '\0';
|
||||
}
|
||||
|
||||
|
@ -1135,7 +1138,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
|
|||
|
||||
gkey = ghost_key_from_keysym_or_keycode(key_sym, m_xkb_descr, xke->keycode);
|
||||
|
||||
if (!XLookupString(xke, &ascii, 1, NULL, NULL)) {
|
||||
if (!XLookupString(xke, &ascii, 1, nullptr, nullptr)) {
|
||||
ascii = '\0';
|
||||
}
|
||||
#endif
|
||||
|
@ -1715,7 +1718,7 @@ GHOST_TSuccess GHOST_SystemX11::setCursorPosition(int32_t x, int32_t y)
|
|||
|
||||
void GHOST_SystemX11::addDirtyWindow(GHOST_WindowX11 *bad_wind)
|
||||
{
|
||||
GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)");
|
||||
GHOST_ASSERT((bad_wind != nullptr), "addDirtyWindow() nullptr ptr trapped (window)");
|
||||
|
||||
m_dirty_windows.push_back(bad_wind);
|
||||
}
|
||||
|
@ -2157,8 +2160,9 @@ char *GHOST_SystemX11::getClipboard(bool selection) const
|
|||
return sel_buf;
|
||||
}
|
||||
}
|
||||
else if (owner == None)
|
||||
return NULL;
|
||||
else if (owner == None) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Restore events so copy doesn't swallow other event types (keyboard/mouse). */
|
||||
vector<XEvent> restore_events;
|
||||
|
@ -2224,7 +2228,7 @@ char *GHOST_SystemX11::getClipboard(bool selection) const
|
|||
|
||||
return tmp_data;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GHOST_SystemX11::putClipboard(const char *buffer, bool selection) const
|
||||
|
@ -2352,14 +2356,16 @@ static void split(const char *text, const char *seps, char ***str, int *count)
|
|||
*count = 0;
|
||||
|
||||
data = strdup(text);
|
||||
for (tok = strtok(data, seps); tok != NULL; tok = strtok(NULL, seps))
|
||||
for (tok = strtok(data, seps); tok != nullptr; tok = strtok(nullptr, seps)) {
|
||||
(*count)++;
|
||||
}
|
||||
free(data);
|
||||
|
||||
data = strdup(text);
|
||||
*str = (char **)malloc((size_t)(*count) * sizeof(char *));
|
||||
for (i = 0, tok = strtok(data, seps); tok != NULL; tok = strtok(NULL, seps), i++)
|
||||
for (i = 0, tok = strtok(data, seps); tok != nullptr; tok = strtok(nullptr, seps), i++) {
|
||||
(*str)[i] = strdup(tok);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
|
@ -2370,7 +2376,7 @@ GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title,
|
|||
const char *link,
|
||||
GHOST_DialogOptions) const
|
||||
{
|
||||
char **text_splitted = NULL;
|
||||
char **text_splitted = nullptr;
|
||||
int textLines = 0;
|
||||
split(message, "\n", &text_splitted, &textLines);
|
||||
|
||||
|
@ -2433,7 +2439,7 @@ GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title,
|
|||
XSelectInput(m_display, window, ExposureMask | ButtonPressMask | ButtonReleaseMask);
|
||||
XMapWindow(m_display, window);
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
XNextEvent(m_display, &e);
|
||||
if (e.type == Expose) {
|
||||
for (int i = 0; i < textLines; i++) {
|
||||
|
@ -2454,7 +2460,7 @@ GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title,
|
|||
if (dialog_data.isInsideButton(e, 1)) {
|
||||
break;
|
||||
}
|
||||
else if (dialog_data.isInsideButton(e, 2)) {
|
||||
if (dialog_data.isInsideButton(e, 2)) {
|
||||
if (strlen(link)) {
|
||||
string cmd = "xdg-open \"" + string(link) + "\"";
|
||||
if (system(cmd.c_str()) != 0) {
|
||||
|
@ -2580,19 +2586,19 @@ static bool match_token(const char *haystack, const char *needle)
|
|||
static GHOST_TTabletMode tablet_mode_from_name(const char *name, const char *type)
|
||||
{
|
||||
int i;
|
||||
static const char *tablet_stylus_whitelist[] = {"stylus", "wizardpen", "acecad", "pen", NULL};
|
||||
static const char *tablet_stylus_whitelist[] = {"stylus", "wizardpen", "acecad", "pen", nullptr};
|
||||
|
||||
static const char *type_blacklist[] = {"pad", "cursor", "touch", NULL};
|
||||
static const char *type_blacklist[] = {"pad", "cursor", "touch", nullptr};
|
||||
|
||||
/* Skip some known unsupported types. */
|
||||
for (i = 0; type_blacklist[i] != NULL; i++) {
|
||||
for (i = 0; type_blacklist[i] != nullptr; i++) {
|
||||
if (type && (strcasecmp(type, type_blacklist[i]) == 0)) {
|
||||
return GHOST_kTabletModeNone;
|
||||
}
|
||||
}
|
||||
|
||||
/* First check device type to avoid cases where name is "Pen and Eraser" and type is "ERASER" */
|
||||
for (i = 0; tablet_stylus_whitelist[i] != NULL; i++) {
|
||||
for (i = 0; tablet_stylus_whitelist[i] != nullptr; i++) {
|
||||
if (type && match_token(type, tablet_stylus_whitelist[i])) {
|
||||
return GHOST_kTabletModeStylus;
|
||||
}
|
||||
|
@ -2600,7 +2606,7 @@ static GHOST_TTabletMode tablet_mode_from_name(const char *name, const char *typ
|
|||
if (type && match_token(type, "eraser")) {
|
||||
return GHOST_kTabletModeEraser;
|
||||
}
|
||||
for (i = 0; tablet_stylus_whitelist[i] != NULL; i++) {
|
||||
for (i = 0; tablet_stylus_whitelist[i] != nullptr; i++) {
|
||||
if (name && match_token(name, tablet_stylus_whitelist[i])) {
|
||||
return GHOST_kTabletModeStylus;
|
||||
}
|
||||
|
@ -2629,7 +2635,7 @@ void GHOST_SystemX11::refreshXInputDevices()
|
|||
|
||||
for (int i = 0; i < device_count; ++i) {
|
||||
char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) :
|
||||
NULL;
|
||||
nullptr;
|
||||
GHOST_TTabletMode tablet_mode = tablet_mode_from_name(device_info[i].name, device_type);
|
||||
|
||||
// printf("Tablet type:'%s', name:'%s', index:%d\n", device_type, device_info[i].name, i);
|
||||
|
@ -2646,15 +2652,15 @@ void GHOST_SystemX11::refreshXInputDevices()
|
|||
xtablet.ID = device_info[i].id;
|
||||
xtablet.Device = XOpenDevice(m_display, xtablet.ID);
|
||||
|
||||
if (xtablet.Device != NULL) {
|
||||
if (xtablet.Device != nullptr) {
|
||||
/* Find how many pressure levels tablet has */
|
||||
XAnyClassPtr ici = device_info[i].inputclassinfo;
|
||||
|
||||
if (ici != NULL) {
|
||||
if (ici != nullptr) {
|
||||
for (int j = 0; j < device_info[i].num_classes; ++j) {
|
||||
if (ici->c_class == ValuatorClass) {
|
||||
XValuatorInfo *xvi = (XValuatorInfo *)ici;
|
||||
if (xvi->axes != NULL) {
|
||||
if (xvi->axes != nullptr) {
|
||||
xtablet.PressureLevels = xvi->axes[2].max_value;
|
||||
|
||||
if (xvi->num_axes > 3) {
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
#include <cstdlib>
|
||||
#include <dlfcn.h>
|
||||
|
||||
typedef void *(*unity_get_entry_t)(const char *);
|
||||
typedef void (*unity_set_progress_t)(void *, double);
|
||||
typedef void (*unity_set_progress_visible_t)(void *, int);
|
||||
typedef int (*unity_event_loop_t)(void *, int);
|
||||
using unity_get_entry_t = void *(*)(const char *);
|
||||
using unity_set_progress_t = void (*)(void *, double);
|
||||
using unity_set_progress_visible_t = void (*)(void *, int);
|
||||
using unity_event_loop_t = int (*)(void *, int);
|
||||
|
||||
static unity_get_entry_t unity_get_entry;
|
||||
static unity_set_progress_t unity_set_progress;
|
||||
|
@ -23,13 +23,13 @@ static unity_event_loop_t unity_event_loop;
|
|||
|
||||
static bool libunity_initialized = false;
|
||||
static bool libunity_available = false;
|
||||
static void *libunity_handle = NULL;
|
||||
static void *libunity_handle = nullptr;
|
||||
|
||||
void GHOST_TaskBarX11::free()
|
||||
{
|
||||
if (libunity_handle) {
|
||||
dlclose(libunity_handle);
|
||||
libunity_handle = NULL;
|
||||
libunity_handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ bool GHOST_TaskBarX11::init()
|
|||
libunity_initialized = true;
|
||||
|
||||
const char *libunity_names[] = {
|
||||
"libunity.so.4", "libunity.so.6", "libunity.so.9", "libunity.so", NULL};
|
||||
"libunity.so.4", "libunity.so.6", "libunity.so.9", "libunity.so", nullptr};
|
||||
for (int i = 0; libunity_names[i]; i++) {
|
||||
libunity_handle = dlopen(libunity_names[i], RTLD_LAZY);
|
||||
if (libunity_handle) {
|
||||
|
@ -90,13 +90,13 @@ GHOST_TaskBarX11::GHOST_TaskBarX11(const char *name)
|
|||
handle = unity_get_entry(name);
|
||||
}
|
||||
else {
|
||||
handle = NULL;
|
||||
handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool GHOST_TaskBarX11::is_valid()
|
||||
{
|
||||
return (handle != NULL);
|
||||
return (handle != nullptr);
|
||||
}
|
||||
|
||||
void GHOST_TaskBarX11::set_progress(double progress)
|
||||
|
@ -109,5 +109,5 @@ void GHOST_TaskBarX11::set_progress_enabled(bool enabled)
|
|||
{
|
||||
assert(is_valid());
|
||||
unity_set_progress_visible(handle, enabled ? 1 : 0);
|
||||
unity_event_loop(NULL, 0);
|
||||
unity_event_loop(nullptr, 0);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class GHOST_TimerTask : public GHOST_ITimerTask {
|
|||
GHOST_TimerTask(uint64_t start,
|
||||
uint64_t interval,
|
||||
GHOST_TimerProcPtr timerProc,
|
||||
GHOST_TUserDataPtr userData = NULL)
|
||||
GHOST_TUserDataPtr userData = nullptr)
|
||||
: m_start(start),
|
||||
m_interval(interval),
|
||||
m_next(start),
|
||||
|
|
|
@ -28,7 +28,7 @@ static DBusMessage *get_setting_sync(DBusConnection *const connection,
|
|||
message, DBUS_TYPE_STRING, &key, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID);
|
||||
|
||||
if (!success) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
reply = dbus_connection_send_with_reply_and_block(
|
||||
|
@ -37,7 +37,7 @@ static DBusMessage *get_setting_sync(DBusConnection *const connection,
|
|||
dbus_message_unref(message);
|
||||
|
||||
if (dbus_error_is_set(&error)) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reply;
|
||||
|
@ -76,7 +76,7 @@ static bool get_cursor_settings(std::string &theme, int &size)
|
|||
DBusError error;
|
||||
DBusConnection *connection;
|
||||
DBusMessage *reply;
|
||||
const char *value_theme = NULL;
|
||||
const char *value_theme = nullptr;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue