Merge branch 'master' into xr-dev

This commit is contained in:
Peter Kim 2022-06-09 07:06:03 +09:00
commit 2e66e2c37d
1056 changed files with 16164 additions and 10313 deletions

View File

@ -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)

View File

@ -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\""

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,8 +1,6 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
# <pep8 compliant>
CHECKER_IGNORE_PREFIX = [
"extern",
"intern/moto",

View File

@ -1,8 +1,6 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
# <pep8 compliant>
CHECKER_IGNORE_PREFIX = [
"extern",
"intern/moto",

View File

@ -1,8 +1,6 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
# <pep8 compliant>
CHECKER_IGNORE_PREFIX = [
"extern",
"intern/moto",

View File

@ -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)

View File

@ -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.

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# <pep8 compliant>
__all__ = (
"build_info",
"SOURCE_DIR",

View File

@ -1,8 +1,6 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
# <pep8 compliant>
import os
import shutil
import subprocess

View File

@ -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

View File

@ -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.

View File

@ -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
=====================

View File

@ -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.

View File

@ -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.

View File

@ -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 = []

View File

@ -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.

View File

@ -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}

View File

@ -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);

View File

@ -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)");

View File

@ -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
/** \} */

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2011-2022 Blender Foundation
# <pep8 compliant>
from __future__ import annotations
bl_info = {

View File

@ -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,

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2011-2022 Blender Foundation
# <pep8 compliant>
from __future__ import annotations

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2011-2022 Blender Foundation
# <pep8 compliant>
from __future__ import annotations
import bpy

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2011-2022 Blender Foundation
# <pep8 compliant>
from __future__ import annotations
import bpy

View File

@ -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

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2011-2022 Blender Foundation
# <pep8 compliant>
from __future__ import annotations
import bpy

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2011-2022 Blender Foundation
# <pep8 compliant>
from __future__ import annotations
import bpy

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2011-2022 Blender Foundation
# <pep8 compliant>
from __future__ import annotations
import bpy

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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 &params_,

View File

@ -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 ----------------------------------*/

View File

@ -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)",

View File

@ -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 {

View File

@ -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

View File

@ -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()

View File

@ -14,6 +14,8 @@
# include "util/thread.h"
# define metal_printf VLOG(4) << string_printf
CCL_NAMESPACE_BEGIN
enum MetalGPUVendor {

View File

@ -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.
*/

View File

@ -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 {

View File

@ -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);

View File

@ -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 &params,
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 &params,
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 &params)
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 &params)
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
gl_render_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
need_update_ = false;

View File

@ -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 &params, int texture_width, int texture_height) override;
@ -41,6 +38,11 @@ class HdCyclesDisplayDriver final : public CCL_NS::DisplayDriver {
void draw(const Params &params) 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_;

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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)

View File

@ -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_;

View File

@ -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,

View File

@ -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);
}

View File

@ -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 {

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -194,6 +194,7 @@ class AttributeSet {
void remove(AttributeStandard std);
Attribute *find(AttributeRequest &req);
Attribute *find_matching(const Attribute &other);
void remove(Attribute *attribute);

View File

@ -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;
}
}

View File

@ -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:

View File

@ -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)) {

View File

@ -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)

View File

@ -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)

View File

@ -90,7 +90,7 @@ static vector<ChannelMapping> output_channels()
return map;
}
/* Renderlayer Handling */
/* Render-layer Handling. */
bool DenoiseImageLayer::detect_denoising_channels()
{

View File

@ -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__ */

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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.

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;
/**

View File

@ -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;
}
};

View File

@ -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

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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) {

View File

@ -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);
}

View File

@ -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),

View File

@ -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