Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Open Toontown 2022-09-18 20:45:47 -04:00
commit c0887f457a
432 changed files with 13471 additions and 4663 deletions

View File

@ -333,7 +333,7 @@ jobs:
if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')"
strategy:
matrix:
os: [ubuntu-18.04, windows-2016, macOS-11]
os: [ubuntu-18.04, windows-2019, macOS-11]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v1
@ -365,7 +365,7 @@ jobs:
- name: Build Python 3.9
shell: bash
run: |
python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4
python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10
- name: Test Python 3.9
shell: bash
run: |
@ -378,7 +378,7 @@ jobs:
- name: Build Python 3.8
shell: bash
run: |
python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4
python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10
- name: Test Python 3.8
shell: bash
run: |
@ -391,7 +391,7 @@ jobs:
- name: Build Python 3.7
shell: bash
run: |
python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4
python makepanda/makepanda.py --git-commit=${{github.sha}} --outputdir=built --everything --no-eigen --python-incdir="$pythonLocation/include" --python-libdir="$pythonLocation/lib" --verbose --threads=4 --windows-sdk=10
- name: Test Python 3.7
shell: bash
run: |

View File

@ -1,36 +1,14 @@
cmake_minimum_required(VERSION 3.0.2)
cmake_minimum_required(VERSION 3.13)
set(CMAKE_DISABLE_SOURCE_CHANGES ON) # Must go before project() below
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) # Must go before project() below
if(CMAKE_VERSION VERSION_GREATER "3.11" OR POLICY CMP0072)
# Prefer GLVND over libGL when available; this will be enabled by default
# once the minimum CMake version is at least 3.11.
cmake_policy(SET CMP0072 NEW)
endif()
if(CMAKE_VERSION VERSION_GREATER "3.12" OR POLICY CMP0074)
# Needed for THIRDPARTY_DIRECTORY support; this will be enabled by default
# once the minimum CMake version is at least 3.12.
cmake_policy(SET CMP0074 NEW)
endif()
if(POLICY CMP0091)
# Needed for CMake to pass /MD flag properly with non-VC generators.
cmake_policy(SET CMP0091 NEW)
endif()
# Determine whether we are using a multi-config generator.
if(CMAKE_VERSION VERSION_GREATER "3.8")
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
else()
message(WARNING "Multi-configuration builds may not work properly when using
a CMake < 3.9. Making a guess if this is a multi-config generator.")
if(DEFINED CMAKE_CONFIGURATION_TYPES)
set(IS_MULTICONFIG ON)
else()
set(IS_MULTICONFIG OFF)
endif()
endif()
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
# Set the default CMAKE_BUILD_TYPE before calling project().
if(IS_MULTICONFIG)
@ -89,11 +67,9 @@ string(REPLACE "$(EFFECTIVE_PLATFORM_NAME)" "" PANDA_CFG_INTDIR "${CMAKE_CFG_INT
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros/")
if(CMAKE_VERSION VERSION_GREATER "3.8")
# When using the Xcode generator, don't append the platform name to the
# intermediate configuration directory.
set_property(GLOBAL PROPERTY XCODE_EMIT_EFFECTIVE_PLATFORM_NAME OFF)
endif()
# When using the Xcode generator, don't append the platform name to the
# intermediate configuration directory.
set_property(GLOBAL PROPERTY XCODE_EMIT_EFFECTIVE_PLATFORM_NAME OFF)
# Include modules builtin to CMake
include(GNUInstallDirs) # Defines CMAKE_INSTALL_<dir> variables

View File

@ -24,7 +24,7 @@ Installing Panda3D
==================
The latest Panda3D SDK can be downloaded from
[this page](https://www.panda3d.org/download/sdk-1-10-11/).
[this page](https://www.panda3d.org/download/sdk-1-10-12/).
If you are familiar with installing Python packages, you can use
the following command:
@ -58,14 +58,14 @@ You will also need to install the [Windows SDK](https://developer.microsoft.com/
and if you intend to target Windows Vista, you will also need the
[Windows 8.1 SDK](https://go.microsoft.com/fwlink/p/?LinkId=323507).
You will also need to have the third-party dependency libraries available for
You will also need the thirdparty dependency libraries available for
the build scripts to use. These are available from one of these two URLs,
depending on whether you are on a 32-bit or 64-bit system, or you can
[click here](https://github.com/rdb/panda3d-thirdparty) for instructions on
building them from source.
- https://www.panda3d.org/download/panda3d-1.10.11/panda3d-1.10.11-tools-win64.zip
- https://www.panda3d.org/download/panda3d-1.10.11/panda3d-1.10.11-tools-win32.zip
- https://www.panda3d.org/download/panda3d-1.10.12/panda3d-1.10.12-tools-win64.zip
- https://www.panda3d.org/download/panda3d-1.10.12/panda3d-1.10.12-tools-win32.zip
After acquiring these dependencies, you can build Panda3D from the command
prompt using the following command. Change the `--msvc-version` option based
@ -136,7 +136,7 @@ macOS
-----
On macOS, you will need to download a set of precompiled thirdparty packages in order to
compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.11/panda3d-1.10.11-tools-mac.tar.gz).
compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.10.12/panda3d-1.10.12-tools-mac.tar.gz).
After placing the thirdparty directory inside the panda3d source directory,
you may build Panda3D using a command like the following:
@ -177,35 +177,32 @@ directory which you can install using `pkg install`.
Android
-------
Note: building on Android is very experimental and not guaranteed to work.
Although it's possible to build Panda3D on an Android device using the
[termux](https://termux.com/) shell, the recommended route is to cross-compile
.whl files using the SDK and NDK, which can then be used by the `build_apps`
command to build a Python application into an .apk or .aab bundle. You will
need to get the latest thirdparty packages, which can be obtained from the
artifacts page of the last successful run here:
You can experimentally build the Android Python runner via the [termux](https://termux.com/)
shell. You will need to install [Termux](https://play.google.com/store/apps/details?id=com.termux)
and [Termux API](https://play.google.com/store/apps/details?id=com.termux.api)
from the Play Store. Many of the dependencies can be installed by running the
following command in the Termux shell:
https://github.com/rdb/panda3d-thirdparty/actions?query=branch%3Amain+is%3Asuccess+event%3Apush
This does not include Python at the moment, which can be extracted from
[this archive](https://rdb.name/thirdparty-android.tar.gz) instead.
These commands show how to compile wheels for the supported Android ABIs:
```bash
pkg install python ndk-sysroot clang bison freetype harfbuzz libpng eigen openal-soft opusfile libvorbis assimp libopus ecj dx patchelf aapt apksigner libcrypt openssl pkg-config
export ANDROID_SDK_ROOT=/home/rdb/local/android
python3.8 makepanda/makepanda.py --everything --outputdir built-droid-arm64 --arch arm64 --target android-21 --threads 6 --wheel
python3.8 makepanda/makepanda.py --everything --outputdir built-droid-armv7a --arch armv7a --target android-19 --threads 6 --wheel
python3.8 makepanda/makepanda.py --everything --outputdir built-droid-x86_64 --arch x86_64 --target android-21 --threads 6 --wheel
python3.8 makepanda/makepanda.py --everything --outputdir built-droid-x86 --arch x86 --target android-19 --threads 6 --wheel
```
Then, you can build the .apk using this command:
It is now possible to use the generated wheels with `build_apps`, as explained
on this page:
```bash
python makepanda/makepanda.py --everything --target android-21 --no-tiff --installer
```
You can install the generated panda3d.apk by browsing to the panda3d folder
using a file manager. You may need to copy it to `/sdcard` to be able to
access it from other apps.
To launch a Python program from Termux, you can use the `run_python.sh` script
inside the `panda/src/android` directory. It will launch Python in a separate
activity, load it with the Python script you passed as argument, and use a
socket for returning the command-line output to the Termux shell. Do note
that this requires the Python application to reside on the SD card and that
Termux needs to be set up with access to the SD card (using the
`termux-setup-storage` command).
https://discourse.panda3d.org/t/deployment-for-android/28226
Running Tests
=============

View File

@ -5,83 +5,6 @@
# instead just an agglomeration of the various component libraries that get
# linked into them. A library of libraries - a "metalibrary."
#
# Function: target_link_libraries(...)
#
# Overrides CMake's target_link_libraries() to support "linking" object
# libraries. This is a partial reimplementation of CMake commit dc38970f83,
# which is only available in CMake 3.12+
#
if(CMAKE_VERSION VERSION_LESS "3.12")
function(target_link_libraries target)
get_target_property(target_type "${target}" TYPE)
if(NOT target_type STREQUAL "OBJECT_LIBRARY")
_target_link_libraries("${target}" ${ARGN})
return()
endif()
foreach(library ${ARGN})
# This is a quick and dirty regex to tell targets apart from other stuff.
# It just checks if it's alphanumeric and starts with p3/panda.
if(library MATCHES "^(PKG::|p3|panda)[A-Za-z0-9]*$")
# We need to add "library"'s include directories to "target"
# (and transitively to INTERFACE_INCLUDE_DIRECTORIES so further
# dependencies will work)
set(include_directories "$<TARGET_PROPERTY:${library},INTERFACE_INCLUDE_DIRECTORIES>")
set_property(TARGET "${target}" APPEND PROPERTY INCLUDE_DIRECTORIES "${include_directories}")
set_property(TARGET "${target}" APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${include_directories}")
# SYSTEM include directories should still be reported as SYSTEM, so
# that warnings from those includes are suppressed
set(sys_include_directories
"$<TARGET_PROPERTY:${library},INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>")
target_include_directories("${target}" SYSTEM PUBLIC "${sys_include_directories}")
# And for INTERFACE_COMPILE_DEFINITIONS as well
set(compile_definitions "$<TARGET_PROPERTY:${library},INTERFACE_COMPILE_DEFINITIONS>")
set_property(TARGET "${target}" APPEND PROPERTY COMPILE_DEFINITIONS "${compile_definitions}")
set_property(TARGET "${target}" APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS "${compile_definitions}")
# Build up some generator expressions for determining whether `library`
# is a component library or not.
if(library MATCHES ".*::.*")
# "::" messes up CMake's genex parser; fortunately, a library whose
# name contains that is either an interface library or alias, and
# definitely not a component
set(is_component 0)
set(name_of_component "")
set(name_of_non_component "${library}")
else()
set(is_component "$<TARGET_PROPERTY:${library},IS_COMPONENT>")
# CMake complains if we lookup IS_COMPONENT on an INTERFACE library :(
set(is_object "$<STREQUAL:$<TARGET_PROPERTY:${library},TYPE>,OBJECT_LIBRARY>")
set(is_component "$<BOOL:$<${is_object}:${is_component}>>")
set(name_of_component "$<${is_component}:$<TARGET_NAME:${library}>>")
set(name_of_non_component "$<$<NOT:${is_component}>:$<TARGET_NAME:${library}>>")
endif()
# Libraries are only linked transitively if they aren't components.
set_property(TARGET "${target}" APPEND PROPERTY
INTERFACE_LINK_LIBRARIES "${name_of_non_component}")
else()
# This is a file path to an out-of-tree library - this needs to be
# recorded so that the metalib can link them. (They aren't needed at
# all for the object libraries themselves, so they don't have to work
# transitively.)
set_property(TARGET "${target}" APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${library}")
endif()
endforeach(library)
endfunction(target_link_libraries)
endif()
#
# Function: add_component_library(target [SYMBOL building_symbol]
# [SOURCES] [[NOINIT]/[INIT func [header]]])
@ -305,6 +228,7 @@ function(add_metalib target_name)
set(interface_defines)
set(includes)
set(libs)
set(link_options)
set(component_init_funcs "")
foreach(component ${components})
if(NOT TARGET "${component}")
@ -392,6 +316,16 @@ function(add_metalib target_name)
endif()
endforeach(component_library)
# All the linker options applied to an individual component get applied
# when building the metalib (for things like --exclude-libs).
get_target_property(component_link_options "${component}" LINK_OPTIONS)
foreach(component_link_option ${component_link_options})
if(component_link_option)
list(APPEND link_options "${component_link_option}")
endif()
endforeach(component_link_option)
# Consume this component's objects
list(APPEND sources "$<TARGET_OBJECTS:${component}>")
@ -419,6 +353,7 @@ function(add_metalib target_name)
PRIVATE ${private_defines}
INTERFACE ${interface_defines})
target_link_libraries("${target_name}" ${libs})
target_link_options("${target_name}" PRIVATE ${link_options})
target_include_directories("${target_name}"
PUBLIC ${includes}
INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}/panda3d>")

View File

@ -176,18 +176,6 @@ function(package_option name)
# Create the INTERFACE library used to depend on this package.
add_library(PKG::${name} INTERFACE IMPORTED GLOBAL)
# Explicitly record the package's include directories as system include
# directories. CMake does do this automatically for INTERFACE libraries, but
# it does it by discovering all transitive links first, then reading
# INTERFACE_INCLUDE_DIRECTORIES for those which are INTERFACE libraries. So,
# this would be broken for the metalib system (pre CMake 3.12) which doesn't
# "link" the object libraries.
if(CMAKE_VERSION VERSION_LESS "3.12")
set_target_properties(PKG::${name} PROPERTIES
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
"$<TARGET_PROPERTY:PKG::${name},INTERFACE_INCLUDE_DIRECTORIES>")
endif()
# If the option actually is enabled, populate the INTERFACE library created above
if(HAVE_${name})
set(use_variables ON)
@ -412,9 +400,8 @@ function(export_packages filename)
endforeach(config)
endif()
elseif(CMAKE_VERSION VERSION_GREATER "3.8")
# This is an INTERFACE_LIBRARY, and CMake is new enough to support
# IMPORTED_IMPLIB
else()
# This is an INTERFACE_LIBRARY.
get_target_property(imported_libname "${head}" IMPORTED_LIBNAME)
if(imported_libname)
list(APPEND libraries ${imported_libname})

View File

@ -0,0 +1,12 @@
find_package(PkgConfig QUIET)
set(__gtk3_required_version "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}")
if(__gtk3_required_version)
set(__gtk3_required_version " >= ${__gtk3_required_version}")
endif()
pkg_check_modules(GTK3 QUIET "gtk+-3.0${__gtk3_required_version}" IMPORTED_TARGET)
if (NOT TARGET PkgConfig::GTK3)
set(GTK3_FOUND 0)
endif()
unset(__gtk3_required_version)

View File

@ -14,42 +14,62 @@
# LIBSQUISH_DEBUG_LIBRARY - the filepath of the libsquish debug library
#
# Find the libsquish include files
find_path(LIBSQUISH_INCLUDE_DIR
NAMES "squish.h"
PATHS "/usr/include"
"/usr/local/include"
"/sw/include"
"/opt/include"
"/opt/local/include"
"/opt/csw/include"
PATH_SUFFIXES "" "cppunit"
)
if(LibSquish_ROOT)
# Search exclusively under the root
find_path(LIBSQUISH_INCLUDE_DIR
NAMES "squish.h"
PATHS ${LibSquish_ROOT}
PATH_SUFFIXES "include"
)
# Find the libsquish library built for release
find_library(LIBSQUISH_RELEASE_LIBRARY
NAMES "squish" "libsquish"
PATHS "/usr"
"/usr/local"
"/usr/freeware"
"/sw"
"/opt"
"/opt/csw"
PATH_SUFFIXES "lib" "lib32" "lib64"
)
find_library(LIBSQUISH_RELEASE_LIBRARY
NAMES "squish" "libsquish"
PATHS ${LibSquish_ROOT}
PATH_SUFFIXES "lib"
)
# Find the libsquish library built for debug
find_library(LIBSQUISH_DEBUG_LIBRARY
NAMES "squishd" "libsquishd"
PATHS "/usr"
"/usr/local"
"/usr/freeware"
"/sw"
"/opt"
"/opt/csw"
PATH_SUFFIXES "lib" "lib32" "lib64"
)
find_library(LIBSQUISH_DEBUG_LIBRARY
NAMES "squishd" "libsquishd"
PATHS ${LibSquish_ROOT}
PATH_SUFFIXES "lib"
)
else()
# Find the libsquish include files
find_path(LIBSQUISH_INCLUDE_DIR
NAMES "squish.h"
PATHS "/usr/include"
"/usr/local/include"
"/sw/include"
"/opt/include"
"/opt/local/include"
"/opt/csw/include"
PATH_SUFFIXES "" "cppunit"
)
# Find the libsquish library built for release
find_library(LIBSQUISH_RELEASE_LIBRARY
NAMES "squish" "libsquish"
PATHS "/usr"
"/usr/local"
"/usr/freeware"
"/sw"
"/opt"
"/opt/csw"
PATH_SUFFIXES "lib" "lib32" "lib64"
)
# Find the libsquish library built for debug
find_library(LIBSQUISH_DEBUG_LIBRARY
NAMES "squishd" "libsquishd"
PATHS "/usr"
"/usr/local"
"/usr/freeware"
"/sw"
"/opt"
"/opt/csw"
PATH_SUFFIXES "lib" "lib32" "lib64"
)
endif()
mark_as_advanced(LIBSQUISH_INCLUDE_DIR)
mark_as_advanced(LIBSQUISH_RELEASE_LIBRARY)

View File

@ -1,88 +0,0 @@
# Filename: FindOpenEXR.cmake
# Authors: CFSworks (5 Nov, 2018)
#
# Usage:
# find_package(OpenEXR [REQUIRED] [QUIET])
#
# Once done this will define:
# OPENEXR_FOUND - system has OpenEXR
# OPENEXR_INCLUDE_DIR - the include directory containing OpenEXR header files
# OPENEXR_LIBRARIES - the path to the OpenEXR libraries
#
find_path(OPENEXR_INCLUDE_DIR
"ImfVersion.h"
PATH_SUFFIXES "OpenEXR")
mark_as_advanced(OPENEXR_INCLUDE_DIR)
find_library(OPENEXR_imf_LIBRARY
NAMES "IlmImf")
if(OPENEXR_imf_LIBRARY)
get_filename_component(_imf_dir "${OPENEXR_imf_LIBRARY}" DIRECTORY)
find_library(OPENEXR_imfutil_LIBRARY
NAMES "IlmImfUtil"
PATHS "${_imf_dir}"
NO_DEFAULT_PATH)
find_library(OPENEXR_ilmthread_LIBRARY
NAMES "IlmThread"
PATHS "${_imf_dir}"
NO_DEFAULT_PATH)
find_library(OPENEXR_iex_LIBRARY
NAMES "Iex"
PATHS "${_imf_dir}"
NO_DEFAULT_PATH)
find_library(OPENEXR_iexmath_LIBRARY
NAMES "IexMath"
PATHS "${_imf_dir}"
NO_DEFAULT_PATH)
find_library(OPENEXR_imath_LIBRARY
NAMES "Imath"
PATHS "${_imf_dir}"
NO_DEFAULT_PATH)
find_library(OPENEXR_half_LIBRARY
NAMES "Half"
PATHS "${_imf_dir}"
NO_DEFAULT_PATH)
unset(_imf_dir)
endif()
mark_as_advanced(
OPENEXR_imf_LIBRARY
OPENEXR_imfutil_LIBRARY
OPENEXR_ilmthread_LIBRARY
OPENEXR_iex_LIBRARY
OPENEXR_iexmath_LIBRARY
OPENEXR_imath_LIBRARY
OPENEXR_half_LIBRARY
)
set(OPENEXR_LIBRARIES
${OPENEXR_imf_LIBRARY}
${OPENEXR_imfutil_LIBRARY}
${OPENEXR_ilmthread_LIBRARY}
${OPENEXR_iex_LIBRARY}
${OPENEXR_iexmath_LIBRARY}
${OPENEXR_imath_LIBRARY}
${OPENEXR_half_LIBRARY}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenEXR DEFAULT_MSG
OPENEXR_INCLUDE_DIR OPENEXR_LIBRARIES
OPENEXR_imf_LIBRARY
OPENEXR_imfutil_LIBRARY
OPENEXR_ilmthread_LIBRARY
OPENEXR_iex_LIBRARY
OPENEXR_iexmath_LIBRARY
OPENEXR_imath_LIBRARY
OPENEXR_half_LIBRARY
)

View File

@ -30,6 +30,7 @@
#include "pandabase.h"
#include "luse.h"
#include "memoryBase.h"
#include "transformState.h"
#include "look_at.h"
#include "compose_matrix.h"
@ -48,7 +49,7 @@
* and a view-projection matrix. The shadow manager regenerates the shadow maps
* using the data from the shadow sources.
*/
class ShadowSource {
class ShadowSource : public MemoryBase {
public:
ShadowSource();
@ -78,14 +79,13 @@ public:
inline const BoundingSphere& get_bounds() const;
private:
int _slot;
bool _needs_update;
size_t _resolution;
LMatrix4 _mvp;
LVecBase4i _region;
LVecBase4 _region_uv;
BoundingSphere _bounds;
int _slot;
bool _needs_update;
size_t _resolution;
};
#include "shadowSource.I"

View File

@ -80,6 +80,13 @@ defaultHiddenImports = {
],
'pandas.compat': ['lzma', 'cmath'],
'pandas._libs.tslibs.conversion': ['pandas._libs.tslibs.base'],
'plyer': ['plyer.platforms'],
'scipy.linalg': ['scipy.linalg.cython_blas', 'scipy.linalg.cython_lapack'],
'scipy.sparse.csgraph': ['scipy.sparse.csgraph._validation'],
'scipy.spatial._qhull': ['scipy._lib.messagestream'],
'scipy.spatial.transform._rotation': ['scipy.spatial.transform._rotation_groups'],
'scipy.special._ufuncs': ['scipy.special._ufuncs_cxx'],
'scipy.stats._stats': ['scipy.special.cython_special'],
}
@ -791,10 +798,6 @@ class Freezer:
# default object will be created when it is needed.
self.cenv = None
# This is the search path to use for Python modules. Leave it
# to the default value of None to use sys.path.
self.path = path
# The filename extension to append to the source file before
# compiling.
self.sourceExtension = '.c'
@ -843,32 +846,44 @@ class Freezer:
# builds. It can be explicitly included if desired.
self.modules['doctest'] = self.ModuleDef('doctest', exclude = True)
self.mf = None
# Actually, make sure we know how to find all of the
# already-imported modules. (Some of them might do their own
# special path mangling.)
for moduleName, module in list(sys.modules.items()):
if module and getattr(module, '__path__', None) is not None:
path = list(getattr(module, '__path__'))
if path:
modulefinder.AddPackagePath(moduleName, path[0])
modPath = list(getattr(module, '__path__'))
if modPath:
modulefinder.AddPackagePath(moduleName, modPath[0])
# Module with non-obvious dependencies
self.hiddenImports = defaultHiddenImports.copy()
if hiddenImports is not None:
self.hiddenImports.update(hiddenImports)
# Special hack for plyer, which has platform-specific hidden imports
plyer_platform = None
if self.platform.startswith('android'):
plyer_platform = 'android'
elif self.platform.startswith('linux'):
plyer_platform = 'linux'
elif self.platform.startswith('mac'):
plyer_platform = 'macosx'
elif self.platform.startswith('win'):
plyer_platform = 'win'
if plyer_platform:
self.hiddenImports['plyer'].append(f'plyer.platforms.{plyer_platform}.*')
# Suffix/extension for Python C extension modules
if self.platform == PandaSystem.getPlatform():
self.moduleSuffixes = imp.get_suffixes()
suffixes = imp.get_suffixes()
# Set extension for Python files to binary mode
for i, suffix in enumerate(self.moduleSuffixes):
for i, suffix in enumerate(suffixes):
if suffix[2] == imp.PY_SOURCE:
self.moduleSuffixes[i] = (suffix[0], 'rb', imp.PY_SOURCE)
suffixes[i] = (suffix[0], 'rb', imp.PY_SOURCE)
else:
self.moduleSuffixes = [('.py', 'rb', 1), ('.pyc', 'rb', 2)]
suffixes = [('.py', 'rb', 1), ('.pyc', 'rb', 2)]
abi_version = '{0}{1}'.format(*sys.version_info)
abi_flags = ''
@ -876,7 +891,7 @@ class Freezer:
abi_flags += 'm'
if 'linux' in self.platform:
self.moduleSuffixes += [
suffixes += [
('.cpython-{0}{1}-x86_64-linux-gnu.so'.format(abi_version, abi_flags), 'rb', 3),
('.cpython-{0}{1}-i686-linux-gnu.so'.format(abi_version, abi_flags), 'rb', 3),
('.abi{0}.so'.format(sys.version_info[0]), 'rb', 3),
@ -884,24 +899,26 @@ class Freezer:
]
elif 'win' in self.platform:
# ABI flags are not appended on Windows.
self.moduleSuffixes += [
suffixes += [
('.cp{0}-win_amd64.pyd'.format(abi_version), 'rb', 3),
('.cp{0}-win32.pyd'.format(abi_version), 'rb', 3),
('.pyd', 'rb', 3),
]
elif 'mac' in self.platform:
self.moduleSuffixes += [
suffixes += [
('.cpython-{0}{1}-darwin.so'.format(abi_version, abi_flags), 'rb', 3),
('.abi{0}.so'.format(sys.version_info[0]), 'rb', 3),
('.so', 'rb', 3),
]
else: # FreeBSD et al.
self.moduleSuffixes += [
suffixes += [
('.cpython-{0}{1}.so'.format(abi_version, abi_flags), 'rb', 3),
('.abi{0}.so'.format(sys.version_info[0]), 'rb', 3),
('.so', 'rb', 3),
]
self.mf = PandaModuleFinder(excludes=['doctest'], suffixes=suffixes, path=path)
def excludeFrom(self, freezer):
""" Excludes all modules that have already been processed by
the indicated FreezeTool. This is equivalent to passing the
@ -921,8 +938,6 @@ class Freezer:
allowChildren is true, the children of the indicated module
may still be included."""
assert self.mf is None
self.modules[moduleName] = self.ModuleDef(
moduleName, exclude = True,
forbid = forbid, allowChildren = allowChildren,
@ -947,24 +962,6 @@ class Freezer:
files can be found. If the module is a .py file and not a
directory, returns None. """
# First, try to import the module directly. That's the most
# reliable answer, if it works.
try:
module = __import__(moduleName)
except:
print("couldn't import %s" % (moduleName))
module = None
if module is not None:
for symbol in moduleName.split('.')[1:]:
module = getattr(module, symbol)
if hasattr(module, '__path__'):
return module.__path__
# If it didn't work--maybe the module is unimportable because
# it makes certain assumptions about the builtins, or
# whatever--then just look for file on disk. That's usually
# good enough.
path = None
baseName = moduleName
if '.' in baseName:
@ -974,34 +971,20 @@ class Freezer:
return None
try:
file, pathname, description = imp.find_module(baseName, path)
file, pathname, description = self.mf.find_module(baseName, path)
except ImportError:
return None
if not os.path.isdir(pathname):
if not self.mf._dir_exists(pathname):
return None
return [pathname]
def getModuleStar(self, moduleName):
""" Looks for the indicated directory module and returns the
__all__ member: the list of symbols within the module. """
# First, try to import the module directly. That's the most
# reliable answer, if it works.
try:
module = __import__(moduleName)
except:
print("couldn't import %s" % (moduleName))
module = None
if module is not None:
for symbol in moduleName.split('.')[1:]:
module = getattr(module, symbol)
if hasattr(module, '__all__'):
return module.__all__
# If it didn't work, just open the directory and scan for *.py
# files.
# Open the directory and scan for *.py files.
path = None
baseName = moduleName
if '.' in baseName:
@ -1011,16 +994,16 @@ class Freezer:
return None
try:
file, pathname, description = imp.find_module(baseName, path)
file, pathname, description = self.mf.find_module(baseName, path)
except ImportError:
return None
if not os.path.isdir(pathname):
if not self.mf._dir_exists(pathname):
return None
# Scan the directory, looking for .py files.
modules = []
for basename in sorted(os.listdir(pathname)):
for basename in sorted(self.mf._listdir(pathname)):
if basename.endswith('.py') and basename != '__init__.py':
modules.append(basename[:-3])
@ -1054,8 +1037,8 @@ class Freezer:
modulePath = self.getModulePath(topName)
if modulePath:
for dirname in modulePath:
for basename in sorted(os.listdir(dirname)):
if os.path.exists(os.path.join(dirname, basename, '__init__.py')):
for basename in sorted(self.mf._listdir(dirname)):
if self.mf._file_exists(os.path.join(dirname, basename, '__init__.py')):
parentName = '%s.%s' % (topName, basename)
newParentName = '%s.%s' % (newTopName, basename)
if self.getModulePath(parentName):
@ -1100,8 +1083,6 @@ class Freezer:
directories within a particular directory.
"""
assert self.mf is None
if not newName:
newName = moduleName
@ -1122,8 +1103,6 @@ class Freezer:
to done(), you may not add any more modules until you call
reset(). """
assert self.mf is None
# If we are building an exe, we also need to implicitly
# bring in Python's startup modules.
if addStartupModules:
@ -1165,7 +1144,9 @@ class Freezer:
else:
includes.append(mdef)
self.mf = PandaModuleFinder(excludes=list(excludeDict.keys()), suffixes=self.moduleSuffixes, path=self.path)
# Add the excludes to the ModuleFinder.
for exclude in excludeDict:
self.mf.excludes.append(exclude)
# Attempt to import the explicit modules into the modulefinder.
@ -1212,12 +1193,33 @@ class Freezer:
else:
self.__loadModule(self.ModuleDef(modname, implicit = True))
# Special case for sysconfig, which depends on a platform-specific
# sysconfigdata module on POSIX systems.
missing = []
if 'sysconfig' in self.mf.modules and \
('linux' in self.platform or 'mac' in self.platform):
modname = '_sysconfigdata'
if sys.version_info >= (3, 6):
modname += '_'
if sys.version_info < (3, 8):
modname += 'm'
if 'linux' in self.platform:
arch = self.platform.split('_', 1)[1]
modname += '_linux_' + arch + '-linux-gnu'
elif 'mac' in self.platform:
modname += '_darwin_darwin'
try:
self.__loadModule(self.ModuleDef(modname, implicit=True))
except:
missing.append(modname)
# Now, any new modules we found get added to the export list.
for origName in list(self.mf.modules.keys()):
if origName not in origToNewName:
self.modules[origName] = self.ModuleDef(origName, implicit = True)
missing = []
for origName in self.mf.any_missing_maybe()[0]:
if origName in startupModules:
continue
@ -2428,6 +2430,17 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
return None
def _file_exists(self, path):
if os.path.exists(path):
return os.path.isfile(path)
fh = self._open_file(path, 'rb')
if fh:
fh.close()
return True
return False
def _dir_exists(self, path):
"""Returns True if the given directory exists, either on disk or inside
a wheel."""
@ -2466,6 +2479,43 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
return False
def _listdir(self, path):
"""Lists files in the given directory if it exists."""
if os.path.isdir(path):
return os.listdir(path)
# Is there a zip file along the path?
dir, dirname = os.path.split(path.rstrip(os.path.sep + '/'))
fn = dirname
while dirname:
if os.path.isfile(dir):
# Okay, this is actually a file. Is it a zip file?
if dir in self._zip_files:
# Yes, and we've previously opened this.
zip = self._zip_files[dir]
elif zipfile.is_zipfile(dir):
zip = zipfile.ZipFile(dir)
self._zip_files[dir] = zip
else:
# It's not a directory or zip file.
return []
# List files whose path start with our directory name.
prefix = fn.replace(os.path.sep, '/') + '/'
result = []
for name in zip.namelist():
if name.startswith(prefix) and '/' not in name[len(prefix):]:
result.append(name[len(prefix):])
return result
# Look at the parent directory.
dir, dirname = os.path.split(dir)
fn = os.path.join(dirname, fn)
return []
def load_module(self, fqname, fp, pathname, file_info):
"""Copied from ModuleFinder.load_module with fixes to handle sending bytes
to compile() for PY_SOURCE types. Sending bytes to compile allows it to
@ -2712,7 +2762,7 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
modules = {}
for dir in m.__path__:
try:
names = os.listdir(dir)
names = self._listdir(dir)
except OSError:
self.msg(2, "can't list directory", dir)
continue

View File

@ -169,9 +169,11 @@ ANDROID_ATTRIBUTES = {
'alwaysRetainTaskState': bool_resource(0x1010203),
'clearTaskOnLaunch': bool_resource(0x1010015),
'debuggable': bool_resource(0x0101000f),
'documentLaunchMode': enum_resource(0x1010445, "none", "intoExisting", "always", "never"),
'configChanges': flag_resource(0x0101001f, mcc=0x0001, mnc=0x0002, locale=0x0004, touchscreen=0x0008, keyboard=0x0010, keyboardHidden=0x0020, navigation=0x0040, orientation=0x0080, screenLayout=0x0100, uiMode=0x0200, screenSize=0x0400, smallestScreenSize=0x0800, layoutDirection=0x2000, fontScale=0x40000000),
'enabled': bool_resource(0x101000e),
'excludeFromRecents': bool_resource(0x1010017),
'exported': bool_resource(0x1010010),
'extractNativeLibs': bool_resource(0x10104ea),
'finishOnTaskLaunch': bool_resource(0x1010014),
'fullBackupContent': bool_resource(0x10104eb),
@ -189,9 +191,12 @@ ANDROID_ATTRIBUTES = {
'minSdkVersion': int_resource(0x101020c),
'multiprocess': bool_resource(0x1010013),
'name': str_resource(0x1010003),
'noHistory': bool_resource(0x101022d),
'pathPattern': str_resource(0x101002c),
'resizeableActivity': bool_resource(0x10104f6),
'required': bool_resource(0x101028e),
'scheme': str_resource(0x1010027),
'screenOrientation': enum_resource(0x101001e, 'landscape', 'portrait', 'user', 'behind', 'sensor', 'nosensor', 'sensorLandscape', 'sensorPortrait', 'reverseLandscape', 'reversePortrait', 'fullSensor', 'userLandscape', 'userPortrait', 'fullUser', 'locked'),
'stateNotNeeded': bool_resource(0x1010016),
'supportsRtl': bool_resource(0x010103af),
'supportsUploading': bool_resource(0x101029b),

View File

@ -116,7 +116,7 @@ from _frozen_importlib import _imp, FrozenImporter
sys.frozen = True
if sys.platform == 'win32':
if sys.platform == 'win32' and sys.version_info < (3, 10):
# Make sure the preferred encoding is something we actually support.
import _bootlocale
enc = _bootlocale.getpreferredencoding().lower()
@ -155,7 +155,9 @@ from android_log import write as android_log_write
sys.frozen = True
sys.platform = "android"
# Temporary hack for plyer to detect Android, see kivy/plyer#670
os.environ['ANDROID_ARGUMENT'] = ''
# Replace stdout/stderr with something that writes to the Android log.
@ -465,6 +467,12 @@ class build_apps(setuptools.Command):
elif not self.android_abis:
self.android_abis = ['arm64-v8a', 'armeabi-v7a', 'x86_64', 'x86']
supported_abis = 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
unsupported_abis = set(self.android_abis) - set(supported_abis)
if unsupported_abis:
raise ValueError(f'Unrecognized value(s) for android_abis: {", ".join(unsupported_abis)}\n'
f'Valid ABIs are: {", ".join(supported_abis)}')
self.icon_objects = {}
for app, iconpaths in self.icons.items():
if not isinstance(iconpaths, list) and not isinstance(iconpaths, tuple):
@ -513,7 +521,9 @@ class build_apps(setuptools.Command):
else: # e.g. x86, x86_64, mips, mips64
suffix = '_' + abi.replace('-', '_')
self.build_binaries(lib_dir, platform + suffix)
# We end up copying the data multiple times to the same
# directory, but that's probably fine for now.
self.build_binaries(platform + suffix, lib_dir, data_dir)
# Write out the icons to the res directory.
for appname, icon in self.icon_objects.items():
@ -532,13 +542,13 @@ class build_apps(setuptools.Command):
if icon.getLargestSize() >= 192:
icon.writeSize(192, os.path.join(res_dir, 'mipmap-xxxhdpi-v4', basename))
self.build_data(data_dir, platform)
self.build_assets(platform, data_dir)
# Generate an AndroidManifest.xml
self.generate_android_manifest(os.path.join(build_dir, 'AndroidManifest.xml'))
else:
self.build_binaries(build_dir, platform)
self.build_data(build_dir, platform)
self.build_binaries(platform, build_dir, build_dir)
self.build_assets(platform, build_dir)
# Bundle into an .app on macOS
if self.macos_main_app and 'macosx' in platform:
@ -727,7 +737,7 @@ class build_apps(setuptools.Command):
for appname in self.gui_apps:
activity = ET.SubElement(application, 'activity')
activity.set('android:name', 'org.panda3d.android.PandaActivity')
activity.set('android:name', 'org.panda3d.android.PythonActivity')
activity.set('android:label', appname)
activity.set('android:theme', '@android:style/Theme.NoTitleBar')
activity.set('android:configChanges', 'orientation|keyboardHidden')
@ -750,7 +760,7 @@ class build_apps(setuptools.Command):
with open(path, 'wb') as fh:
tree.write(fh, encoding='utf-8', xml_declaration=True)
def build_binaries(self, binary_dir, platform):
def build_binaries(self, platform, binary_dir, data_dir=None):
""" Builds the binary data for the given platform. """
use_wheels = True
@ -1015,7 +1025,7 @@ class build_apps(setuptools.Command):
freezer_extras.update(freezer.extras)
freezer_modules.update(freezer.getAllModuleNames())
for suffix in freezer.moduleSuffixes:
for suffix in freezer.mf.suffixes:
if suffix[2] == imp.C_EXTENSION:
ext_suffixes.add(suffix[0])
@ -1030,12 +1040,9 @@ class build_apps(setuptools.Command):
self.warn("Detected use of tkinter, but tkinter is not specified in requirements.txt!")
# Copy extension modules
whl_modules = []
whl_modules_ext = ''
whl_modules = {}
if use_wheels:
# Get the module libs
whl_modules = []
for i in p3dwhl.namelist():
if not i.startswith('deploy_libs/'):
continue
@ -1050,8 +1057,7 @@ class build_apps(setuptools.Command):
base = os.path.basename(i)
module, _, ext = base.partition('.')
whl_modules.append(module)
whl_modules_ext = ext
whl_modules[module] = i
# Make sure to copy any builtins that have shared objects in the
# deploy libs, assuming they are not already in freezer_extras.
@ -1103,7 +1109,7 @@ class build_apps(setuptools.Command):
else:
# Builtin module, but might not be builtin in wheel libs, so double check
if module in whl_modules:
source_path = os.path.join(p3dwhlfn, 'deploy_libs/{}.{}'.format(module, whl_modules_ext))#'{0}/deploy_libs/{1}.{2}'.format(p3dwhlfn, module, whl_modules_ext)
source_path = os.path.join(p3dwhlfn, whl_modules[module])
basename = os.path.basename(source_path)
#XXX should we remove python version string here too?
else:
@ -1125,6 +1131,9 @@ class build_apps(setuptools.Command):
os.path.join(binary_dir, '..', '..', 'classes.dex'))
# Extract any other data files from dependency packages.
if data_dir is None:
return
for module, datadesc in self.package_data_dirs.items():
if module not in freezer_modules:
continue
@ -1165,11 +1174,11 @@ class build_apps(setuptools.Command):
else:
self.copy(source_path, target_path)
def build_data(self, data_dir, platform):
def build_assets(self, platform, data_dir):
""" Builds the data files for the given platform. """
# Copy Game Files
self.announce('Copying game files for platform: {}'.format(platform), distutils.log.INFO)
self.announce('Copying assets for platform: {}'.format(platform), distutils.log.INFO)
ignore_copy_list = [
'**/__pycache__/**',
'**/*.pyc',

View File

@ -9,7 +9,6 @@ from direct.showbase import GarbageReport
from direct.showbase.MessengerGlobal import messenger
from .PyDatagramIterator import PyDatagramIterator
import inspect
import gc
__all__ = ["ConnectionRepository", "GCTrigger"]
@ -311,6 +310,8 @@ class ConnectionRepository(
# Now get the class definition for the classes named in the DC
# file.
import inspect
for i in range(dcFile.getNumClasses()):
dclass = dcFile.getClass(i)
number = dclass.getNumber()

View File

@ -30,6 +30,19 @@ class PyDatagramIterator(DatagramIterator):
getChannel = DatagramIterator.getUint64
def __init__(self, datagram=None, offset=0):
if datagram is not None:
super().__init__(datagram, offset)
# Retain a reference to it so that it doesn't get deleted.
self.__initialDatagram = datagram
else:
super().__init__()
def assign(self, datagram, offset = 0):
super().assign(datagram, offset)
self.__initialDatagram = datagram
def getArg(self, subatomicType, divisor=1):
# Import the type numbers
if divisor == 1:

View File

@ -58,19 +58,18 @@ CConnectionRepository(bool has_owner_view, bool threaded_net) :
_bdc(4096000,4096000,1400),
_native(false),
#endif
_has_owner_view(has_owner_view),
_handle_c_updates(true),
_client_datagram(true),
_handle_datagrams_internally(handle_datagrams_internally),
_simulated_disconnect(false),
_verbose(distributed_cat.is_spam()),
_in_quiet_zone(0),
_time_warning(0.0),
// _msg_channels(),
_msg_sender(0),
_msg_type(0),
_has_owner_view(has_owner_view),
_handle_c_updates(true),
_want_message_bundling(true),
_bundling_msgs(0),
_in_quiet_zone(0)
_bundling_msgs(0)
{
#if defined(HAVE_NET) && defined(SIMULATE_NETWORK_DELAY)
if (min_lag != 0.0 || max_lag != 0.0) {

View File

@ -20,6 +20,7 @@ from panda3d.core import LVecBase4, LPoint2
from panda3d.core import AuxBitplaneAttrib
from panda3d.core import Texture, Shader, ATSNone
from panda3d.core import FrameBufferProperties
from panda3d.core import getDefaultCoordinateSystem, CS_zup_right, CS_zup_left
from direct.task.TaskManagerGlobal import taskMgr
@ -52,6 +53,7 @@ o_color = lerp(o_color, k_cartooncolor, cartoon_thresh);
SSAO_BODY = """//Cg
void vshader(float4 vtx_position : POSITION,
float2 vtx_texcoord : TEXCOORD0,
out float4 l_position : POSITION,
out float2 l_texcoord : TEXCOORD0,
out float2 l_texcoordD : TEXCOORD1,
@ -61,9 +63,9 @@ void vshader(float4 vtx_position : POSITION,
uniform float4x4 mat_modelproj)
{
l_position = mul(mat_modelproj, vtx_position);
l_texcoord = vtx_position.xz;
l_texcoordD = (vtx_position.xz * texpad_depth.xy) + texpad_depth.xy;
l_texcoordN = (vtx_position.xz * texpad_normal.xy) + texpad_normal.xy;
l_texcoord = vtx_texcoord;
l_texcoordD = vtx_texcoord * texpad_depth.xy * 2;
l_texcoordN = vtx_texcoord * texpad_normal.xy * 2;
}
float3 sphere[16] = float3[](float3(0.53812504, 0.18565957, -0.43192),float3(0.13790712, 0.24864247, 0.44301823),float3(0.33715037, 0.56794053, -0.005789503),float3(-0.6999805, -0.04511441, -0.0019965635),float3(0.06896307, -0.15983082, -0.85477847),float3(0.056099437, 0.006954967, -0.1843352),float3(-0.014653638, 0.14027752, 0.0762037),float3(0.010019933, -0.1924225, -0.034443386),float3(-0.35775623, -0.5301969, -0.43581226),float3(-0.3169221, 0.106360726, 0.015860917),float3(0.010350345, -0.58698344, 0.0046293875),float3(-0.08972908, -0.49408212, 0.3287904),float3(0.7119986, -0.0154690035, -0.09183723),float3(-0.053382345, 0.059675813, -0.5411899),float3(0.035267662, -0.063188605, 0.54602677),float3(-0.47761092, 0.2847911, -0.0271716));
@ -292,11 +294,19 @@ class CommonFilters:
text += "{\n"
text += " l_position = mul(mat_modelproj, vtx_position);\n"
# The card is oriented differently depending on our chosen
# coordinate system. We could just use vtx_texcoord, but this
# saves on an additional variable.
if getDefaultCoordinateSystem() in (CS_zup_right, CS_zup_left):
pos = "vtx_position.xz"
else:
pos = "vtx_position.xy"
for texcoord, padTex in texcoordPadding.items():
if padTex is None:
text += " %s = vtx_position.xz * float2(0.5, 0.5) + float2(0.5, 0.5);\n" % (texcoord)
text += " %s = %s * float2(0.5, 0.5) + float2(0.5, 0.5);\n" % (texcoord, pos)
else:
text += " %s = (vtx_position.xz * texpad_tx%s.xy) + texpad_tx%s.xy;\n" % (texcoord, padTex, padTex)
text += " %s = (%s * texpad_tx%s.xy) + texpad_tx%s.xy;\n" % (texcoord, pos, padTex, padTex)
if "HalfPixelShift" in configuration:
text += " %s += texpix_tx%s.xy * 0.5;\n" % (texcoord, padTex)

View File

@ -323,7 +323,7 @@ class FilterManager(DirectObject):
props.setAuxRgba(1)
if auxtex1 is not None:
props.setAuxRgba(2)
buffer=base.graphicsEngine.makeOutput(
buffer=self.engine.makeOutput(
self.win.getPipe(), name, -1,
props, winprops, GraphicsPipe.BFRefuseWindow | GraphicsPipe.BFResizeable,
self.win.getGsg(), self.win)

View File

@ -32,6 +32,7 @@ BLOOM_I = """
void vshader(float4 vtx_position : POSITION,
float2 vtx_texcoord : TEXCOORD0,
out float4 l_position : POSITION,
out float2 l_texcoordNW : TEXCOORD0,
out float2 l_texcoordNE : TEXCOORD1,
@ -42,7 +43,7 @@ void vshader(float4 vtx_position : POSITION,
uniform float4x4 mat_modelproj)
{
l_position=mul(mat_modelproj, vtx_position);
float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
float2 c = vtx_texcoord * texpad_src.xy * 2;
float4 offs = texpix_src * 0.5;
l_texcoordNW = c + float2( offs.x, -offs.y);
l_texcoordNE = c + float2( offs.x, offs.y);

View File

@ -2,6 +2,7 @@ BLOOM_X = """
//Cg
void vshader(float4 vtx_position : POSITION,
float2 vtx_texcoord : TEXCOORD0,
out float4 l_position : POSITION,
out float4 l_texcoord0 : TEXCOORD0,
out float4 l_texcoord1 : TEXCOORD1,
@ -10,8 +11,8 @@ void vshader(float4 vtx_position : POSITION,
uniform float4 texpix_src,
uniform float4x4 mat_modelproj)
{
l_position=mul(mat_modelproj, vtx_position);
float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
l_position = mul(mat_modelproj, vtx_position);
float2 c = vtx_texcoord * texpad_src.xy * 2;
float offset = texpix_src.x;
float pad = texpad_src.x * 2;
l_texcoord0 = float4(min(c.x-offset* -4, pad), min(c.x-offset* -3, pad), min(c.x-offset* -2, pad), c.y);

View File

@ -2,6 +2,7 @@ BLOOM_Y = """
//Cg
void vshader(float4 vtx_position : POSITION,
float2 vtx_texcoord : TEXCOORD0,
out float4 l_position : POSITION,
out float4 l_texcoord0 : TEXCOORD0,
out float4 l_texcoord1 : TEXCOORD1,
@ -11,7 +12,7 @@ void vshader(float4 vtx_position : POSITION,
uniform float4x4 mat_modelproj)
{
l_position=mul(mat_modelproj, vtx_position);
float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
float2 c = vtx_texcoord * texpad_src.xy * 2;
float offset = texpix_src.y;
float pad = texpad_src.y * 2;
l_texcoord0 = float4(min(c.y-offset* -4, pad), min(c.y-offset* -3, pad), min(c.y-offset* -2, pad), c.x);

View File

@ -4,14 +4,14 @@ BLUR_X = """
//Cg profile arbvp1 arbfp1
void vshader(float4 vtx_position : POSITION,
float2 vtx_texcoord0 : TEXCOORD0,
float2 vtx_texcoord : TEXCOORD0,
out float4 l_position : POSITION,
out float2 l_texcoord0 : TEXCOORD0,
out float2 l_texcoord0 : TEXCOORD0,
uniform float4 texpad_src,
uniform float4x4 mat_modelproj)
{
l_position=mul(mat_modelproj, vtx_position);
l_texcoord0 = (vtx_position.xz * texpad_src.xy) + texpad_src.xy;
l_position = mul(mat_modelproj, vtx_position);
l_texcoord0 = vtx_texcoord * texpad_src.xy * 2;
}

View File

@ -4,14 +4,14 @@ BLUR_Y = """
//Cg profile arbvp1 arbfp1
void vshader(float4 vtx_position : POSITION,
float2 vtx_texcoord0 : TEXCOORD0,
float2 vtx_texcoord : TEXCOORD0,
out float4 l_position : POSITION,
out float2 l_texcoord0 : TEXCOORD0,
out float2 l_texcoord0 : TEXCOORD0,
uniform float4 texpad_src,
uniform float4x4 mat_modelproj)
{
l_position=mul(mat_modelproj, vtx_position);
l_texcoord0 = (vtx_position.xz * texpad_src.xy) + texpad_src.xy;
l_position = mul(mat_modelproj, vtx_position);
l_texcoord0 = vtx_texcoord * texpad_src.xy * 2;
}

View File

@ -3,13 +3,14 @@ COPY = """
void vshader(float4 vtx_position : POSITION,
float2 vtx_texcoord : TEXCOORD0,
out float4 l_position : POSITION,
out float2 l_texcoord : TEXCOORD0,
uniform float4 texpad_src,
uniform float4x4 mat_modelproj)
{
l_position=mul(mat_modelproj, vtx_position);
l_texcoord = (vtx_position.xz * texpad_src.xy) + texpad_src.xy;
l_position = mul(mat_modelproj, vtx_position);
l_texcoord = vtx_texcoord * texpad_src.xy * 2;
}
void fshader(float2 l_texcoord : TEXCOORD0,

View File

@ -2,6 +2,7 @@ DOWN_4 = """
//Cg
void vshader(float4 vtx_position : POSITION,
float2 vtx_texcoord : TEXCOORD0,
out float4 l_position : POSITION,
out float2 l_texcoordNW : TEXCOORD0,
out float2 l_texcoordNE : TEXCOORD1,
@ -11,8 +12,8 @@ void vshader(float4 vtx_position : POSITION,
uniform float4 texpix_src,
uniform float4x4 mat_modelproj)
{
l_position=mul(mat_modelproj, vtx_position);
float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy;
l_position = mul(mat_modelproj, vtx_position);
float2 c = vtx_texcoord * texpad_src.xy * 2;
l_texcoordNW = c + float2( texpix_src.x, -texpix_src.y);
l_texcoordNE = c + float2( texpix_src.x, texpix_src.y);
l_texcoordSW = c + float2(-texpix_src.x, -texpix_src.y);

View File

@ -100,8 +100,6 @@ from direct.showbase import DirectObject
from direct.task import Task
from direct.task.TaskManagerGlobal import taskMgr
guiObjectCollector = PStatCollector("Client::GuiObjects")
_track_gui_items = ConfigVariableBool('track-gui-items', False)
@ -732,8 +730,6 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
self.guiId = self.guiItem.getId()
if ShowBaseGlobal.__dev__:
guiObjectCollector.addLevel(1)
guiObjectCollector.flushLevel()
# track gui items by guiId for tracking down leaks
if _track_gui_items:
if not hasattr(ShowBase, 'guiItems'):
@ -1033,8 +1029,6 @@ class DirectGuiWidget(DirectGuiBase, NodePath):
def destroy(self):
if hasattr(self, "frameStyle"):
if ShowBaseGlobal.__dev__:
guiObjectCollector.subLevel(1)
guiObjectCollector.flushLevel()
if hasattr(ShowBase, 'guiItems'):
ShowBase.guiItems.pop(self.guiId, None)

View File

@ -21,11 +21,12 @@
#include "geomVertexWriter.h"
#include "geomTriangles.h"
#include "luse.h"
#include "memoryBase.h"
#include "nurbsCurveEvaluator.h"
#include "plist.h"
#include "epvector.h"
class CMotionTrailVertex {
class CMotionTrailVertex : public MemoryBase {
public:
LPoint4 _vertex;
LVecBase4 _start_color;

View File

@ -240,10 +240,10 @@ class BufferViewer(DirectObject):
offsetx = (ringoffset[ring]*2.0) / float(sizex)
offsety = (ringoffset[ring]*2.0) / float(sizey)
bright = ringbright[ring]
vwriter.addData3f(-1-offsetx, 0, -1-offsety)
vwriter.addData3f(1+offsetx, 0, -1-offsety)
vwriter.addData3f(1+offsetx, 0, 1+offsety)
vwriter.addData3f(-1-offsetx, 0, 1+offsety)
vwriter.addData3f(Vec3F.rfu(-1 - offsetx, 0, -1 - offsety))
vwriter.addData3f(Vec3F.rfu( 1 + offsetx, 0, -1 - offsety))
vwriter.addData3f(Vec3F.rfu( 1 + offsetx, 0, 1 + offsety))
vwriter.addData3f(Vec3F.rfu(-1 - offsetx, 0, 1 + offsety))
cwriter.addData3f(bright, bright, bright)
cwriter.addData3f(bright, bright, bright)
cwriter.addData3f(bright, bright, bright)

View File

@ -44,14 +44,14 @@ class DirectObject:
def addTask(self, *args, **kwargs):
if not hasattr(self, "_taskList"):
self._taskList = {}
kwargs['owner']=self
kwargs['owner'] = self
task = taskMgr.add(*args, **kwargs)
return task
def doMethodLater(self, *args, **kwargs):
if not hasattr(self, "_taskList"):
self._taskList = {}
kwargs['owner']=self
kwargs['owner'] = self
task = taskMgr.doMethodLater(*args, **kwargs)
return task

View File

@ -11,7 +11,7 @@ __all__ = [
'boolEqual', 'lineupPos', 'formatElapsedSeconds', 'solveQuadratic',
'findPythonModule', 'mostDerivedLast', 'clampScalar', 'weightedChoice',
'randFloat', 'normalDistrib', 'weightedRand', 'randUint31', 'randInt32',
'SerialNumGen', 'serialNum', 'uniqueName', 'Enum', 'Singleton',
'SerialNumGen', 'serialNum', 'uniqueName', 'Singleton',
'SingletonError', 'printListEnum', 'safeRepr', 'fastRepr',
'isDefaultValue', 'ScratchPad', 'Sync', 'itype', 'getNumberedTypedString',
'getNumberedTypedSortedString', 'printNumberedTyped', 'DelayedCall',
@ -1223,111 +1223,6 @@ def uniqueName(name):
global _serialGen
return '%s-%s' % (name, _serialGen.next())
class EnumIter:
def __init__(self, enum):
self._values = tuple(enum._stringTable.keys())
self._index = 0
def __iter__(self):
return self
def __next__(self):
if self._index >= len(self._values):
raise StopIteration
self._index += 1
return self._values[self._index-1]
class Enum:
"""Pass in list of strings or string of comma-separated strings.
Items are accessible as instance.item, and are assigned unique,
increasing integer values. Pass in integer for 'start' to override
starting value.
Example:
>>> colors = Enum('red, green, blue')
>>> colors.red
0
>>> colors.green
1
>>> colors.blue
2
>>> colors.getString(colors.red)
'red'
"""
if __debug__:
# chars that cannot appear within an item string.
def _checkValidIdentifier(item):
import string
invalidChars = string.whitespace + string.punctuation
invalidChars = invalidChars.replace('_', '')
invalidFirstChars = invalidChars+string.digits
if item[0] in invalidFirstChars:
raise SyntaxError("Enum '%s' contains invalid first char" %
item)
if not disjoint(item, invalidChars):
for char in item:
if char in invalidChars:
raise SyntaxError(
"Enum\n'%s'\ncontains illegal char '%s'" %
(item, char))
return 1
_checkValidIdentifier = staticmethod(_checkValidIdentifier)
def __init__(self, items, start=0):
if isinstance(items, str):
items = items.split(',')
self._stringTable = {}
# make sure we don't overwrite an existing element of the class
assert self._checkExistingMembers(items)
assert uniqueElements(items)
i = start
for item in items:
# remove leading/trailing whitespace
item = item.strip()
# is there anything left?
if len(item) == 0:
continue
# make sure there are no invalid characters
assert Enum._checkValidIdentifier(item)
self.__dict__[item] = i
self._stringTable[i] = item
i += 1
def __iter__(self):
return EnumIter(self)
def hasString(self, string):
return string in set(self._stringTable.values())
def fromString(self, string):
if self.hasString(string):
return self.__dict__[string]
# throw an error
{}[string]
def getString(self, value):
return self._stringTable[value]
def __contains__(self, value):
return value in self._stringTable
def __len__(self):
return len(self._stringTable)
def copyTo(self, obj):
# copies all members onto obj
for name, value in self._stringTable:
setattr(obj, name, value)
if __debug__:
def _checkExistingMembers(self, items):
for item in items:
if hasattr(self, item):
return 0
return 1
############################################################
# class: Singleton
@ -2635,7 +2530,6 @@ class PriorityCallbacks:
builtins.Functor = Functor
builtins.Stack = Stack
builtins.Queue = Queue
builtins.Enum = Enum
builtins.SerialNumGen = SerialNumGen
builtins.SerialMaskedGen = SerialMaskedGen
builtins.ScratchPad = ScratchPad

View File

@ -1930,7 +1930,11 @@ class ShowBase(DirectObject.DirectObject):
if port is None:
port = -1
PStatClient.connect(hostname, port)
return PStatClient.isConnected()
if PStatClient.isConnected():
PStatClient.mainTick()
return True
else:
return False
def addSfxManager(self, extraSfxManager):
"""

View File

@ -216,8 +216,8 @@ class RLock(core.ReMutex):
core.ReMutex.__init__(self, name)
class Condition(core.ConditionVarFull):
""" This class provides a wrapper around Panda's ConditionVarFull
class Condition(core.ConditionVar):
""" This class provides a wrapper around Panda's ConditionVar
object. The wrapper is designed to emulate Python's own
threading.Condition object. """
@ -230,7 +230,7 @@ class Condition(core.ConditionVarFull):
assert isinstance(lock, Lock)
self.__lock = lock
core.ConditionVarFull.__init__(self, self.__lock)
core.ConditionVar.__init__(self, self.__lock)
def acquire(self, *args, **kw):
return self.__lock.acquire(*args, **kw)
@ -240,12 +240,12 @@ class Condition(core.ConditionVarFull):
def wait(self, timeout = None):
if timeout is None:
core.ConditionVarFull.wait(self)
core.ConditionVar.wait(self)
else:
core.ConditionVarFull.wait(self, timeout)
core.ConditionVar.wait(self, timeout)
def notifyAll(self):
core.ConditionVarFull.notifyAll(self)
core.ConditionVar.notifyAll(self)
notify_all = notifyAll
@ -295,7 +295,7 @@ class Event:
def __init__(self):
self.__lock = core.Mutex("Python Event")
self.__cvar = core.ConditionVarFull(self.__lock)
self.__cvar = core.ConditionVar(self.__lock)
self.__flag = False
def is_set(self):

View File

@ -16,11 +16,17 @@ from direct.showbase.MessengerGlobal import messenger
import types
import random
import importlib
import sys
try:
import _signal as signal
except ImportError:
# On Android, there's no use handling SIGINT, and in fact we can't, since we
# run the application in a separate thread from the main thread.
if hasattr(sys, 'getandroidapilevel'):
signal = None
else:
try:
import _signal as signal
except ImportError:
signal = None
from panda3d.core import *
from direct.extensions_native import HTTPChannel_extensions
@ -31,7 +37,6 @@ def print_exc_plus():
Print the usual traceback information, followed by a listing of all the
local variables in each frame.
"""
import sys
import traceback
tb = sys.exc_info()[2]
@ -1271,7 +1276,6 @@ class TaskManager:
if __debug__:
def checkLeak():
import sys
import gc
gc.enable()
from direct.showbase.DirectObject import DirectObject

View File

@ -186,7 +186,7 @@ it will show you the available command-line options:
--use-opencv --no-opencv (enable/disable use of OPENCV)
--use-directcam --no-directcam (enable/disable use of DIRECTCAM)
--use-vision --no-vision (enable/disable use of VISION)
--use-gtk2 --no-gtk2 (enable/disable use of GTK2)
--use-gtk3 --no-gtk3 (enable/disable use of GTK3)
--use-npapi --no-npapi (enable/disable use of NPAPI)
--use-mfc --no-mfc (enable/disable use of MFC)
--use-wx --no-wx (enable/disable use of WX)

View File

@ -1,3 +1,59 @@
----------------------- RELEASE 1.10.12 -----------------------
Recommended maintenance release containing primarily bug fixes.
Windowing
* Windows: Fix origin not respected when switching to windowed mode
* macOS: Fix origin not being updated when resizing window
* macOS: Fix off-by-one errors with mouse cursor position
* macOS: Fix issues with confined mouse mode
* macOS: Fix events being suppressed when moving the mouse pointer
* macOS: Invert horizontal scroll, set `cocoa-invert-wheel-x true` to revert
Rendering
* Add `shadow-cube-map-filter` setting to enable cube map shadow filtering
* Support floating-point FBOs in OpenGL ES 2+
* Fix texture format selection in OpenGL with T_half_float component type
* Added `egl-device-index` config var to select EGL device
* Offscreen windows in tinydisplay renderer are now resizeable
* CommonFilters now supports alternative coordinate systems
* Fix BufferViewer frame when using a different coordinate system
Deployment
* Fix _bootlocale error in deployed application on Windows with Python 3.10
* Include _sysconfigdata module properly when using sysconfig module
* Fix building deploy-stub on platforms that use DT_RUNPATH instead of DT_RPATH
* `sys.flags.optimize` is now set to 2 in Python 3.2 and above
* Fix import errors when using scipy
Miscellaneous
* `Texture::get_ram_image_as()` fixed for 3D textures
* Fix PStats GPU timing not working with newer NVIDIA drivers
* Fix false negative in collision test when sphere is fully inside box
* Resolve segmentation fault when statically linking ffmpeg module
* Fix issue with failed mmap when using WebcamVideo on Linux
* macOS: Keyboard/mouse devices are no longer enumerated by default
* Fix repr of LPlane class
* Remove dependency on ShowBase in FilterManager
* Many new functions added to interrogatedb module to query additional info
* Interrogate no longer writes wrappers with rvalue references to interrogatedb
* PStats on Linux: Fix mouse motion detected outside strip chart graph area
* Fix assertion when reading bam file with Bullet convex hull shape
* Fix memory leak when specifying owner of a task
* Add additional helpful debug/spam prints to display code
Build
* Support building with Python 3.11
* Support building with OpenSSL 1.1.1 on Windows
* Support building with OpenEXR 3.0 or 3.1 on Windows
* Fix errors when compiling Panda headers with MinGW
* Allow compiling Panda headers on Windows without NOMINMAX set
* Fix wheel platform tag on manylinux aarch64
* Experimentally allow building with mimalloc on Windows
* Makepanda records cache timestamps as integers instead of floats
* Makepanda can now also build tinydisplay on Linux without X11
* Fix naming of built wheels when building for macOS 12
----------------------- RELEASE 1.10.11 -----------------------
Maintenance release containing assorted bug fixes and minor improvements.

View File

@ -48,21 +48,9 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GCC")
endif()
# Panda3D is now a C++11 project. Newer versions of CMake support this out of
# the box; for older versions we take a shot in the dark:
if(CMAKE_VERSION VERSION_LESS "3.1")
check_cxx_compiler_flag("-std=gnu++11" COMPILER_SUPPORTS_CXX11)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
endif()
else()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
# Panda3D is now a C++11 project.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Set certain CMake flags we expect
set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
@ -110,21 +98,6 @@ if(APPLE)
set(CMAKE_SHARED_MODULE_SUFFIX ".dylib")
endif()
# We want the output structured like build/CONFIG/bin, not build/bin/CONFIG per
# the default for multi-configuration generators. In CMake 3.4+, it switches
# automatically if the *_OUTPUT_DIRECTORY property contains a generator
# expresssion, but as of this writing we support as early as CMake 3.0.2.
#
# So, let's just do this:
if(CMAKE_VERSION VERSION_LESS "3.4")
foreach(_type RUNTIME ARCHIVE LIBRARY)
foreach(_config ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER "${_config}" _config)
set(CMAKE_${_type}_OUTPUT_DIRECTORY_${_config} "${CMAKE_${_type}_OUTPUT_DIRECTORY}")
endforeach(_config)
endforeach(_type)
endif()
# Set warning levels
if(MSVC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3")
@ -138,7 +111,7 @@ endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
set(global_flags
"-Wno-unused-function -Wno-unused-parameter -fno-strict-aliasing")
"-Wno-unused-function -Wno-unused-parameter -fno-strict-aliasing -Werror=return-type")
set(release_flags "-Wno-unused-variable")
if(NOT MSVC)
@ -154,7 +127,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${global_flags}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${global_flags} -Wno-reorder")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${global_flags}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${release_flags}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${release_flags}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${release_flags}")
@ -245,3 +218,10 @@ if(NOT MSVC)
add_compile_options("-fvisibility=hidden")
endif()
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
check_cxx_compiler_flag("-fno-semantic-interposition" COMPILER_SUPPORTS_FNO_SEMANTIC_INTERPOSITION)
if(COMPILER_SUPPORTS_FNO_SEMANTIC_INTERPOSITION)
add_compile_options("-fno-semantic-interposition")
endif()
endif()

View File

@ -288,6 +288,26 @@ mark_as_advanced(SIMULATE_NETWORK_DELAY DO_MEMORY_USAGE DO_DCAST)
# The following options have to do with the memory allocation system.
#
find_package(MIMALLOC 1.0 QUIET)
package_option(MIMALLOC
"The mimalloc allocator. See also USE_MEMORY_MIMALLOC, which
you will need to use to activate it by default. If you do not set
USE_MEMORY_MIMALLOC, Panda will decide whether to use it."
IMPORTED_AS mimalloc-static)
if (WIN32 AND HAVE_MIMALLOC)
set(_prefer_mimalloc ON)
else()
set(_prefer_mimalloc OFF)
endif()
option(USE_MEMORY_MIMALLOC
"This is an optional memory allocator with good multi-threading
support. It is recommended on Windows, where it gives much better
performance than the built-in malloc. However, it does not appear
to be significantly faster on glibc-based systems." ${_prefer_mimalloc})
option(USE_MEMORY_DLMALLOC
"This is an optional alternative memory-allocation scheme
available within Panda. You can experiment with it to see
@ -307,16 +327,33 @@ if 16-byte alignment must be performed on top of it, wasting up to
is required and not provided by the system malloc library, then an
alternative malloc system (above) will be used instead." OFF)
option(USE_DELETED_CHAIN
"Define this true to use the DELETED_CHAIN macros, which support
if (WIN32 AND NOT HAVE_MIMALLOC)
option(USE_DELETED_CHAIN
"Define this true to use the DELETED_CHAIN macros, which support
fast re-use of existing allocated blocks, minimizing the low-level
calls to malloc() and free() for frequently-created and -deleted
objects. There's usually no reason to set this false, unless you
suspect a bug in Panda's memory management code." ON)
objects. This is significantly better than built-in malloc on Windows
but suffers with multiple threads, where mimalloc performs better, so
it is preferred to get mimalloc instead and turn this OFF." ON)
else()
option(USE_DELETED_CHAIN
"Define this true to use the DELETED_CHAIN macros, which support
fast re-use of existing allocated blocks, minimizing the low-level
calls to malloc() and free() for frequently-created and -deleted
objects. However, modern memory allocators generally perform as good,
especially with threading, so best leave this OFF." OFF)
endif()
mark_as_advanced(USE_MEMORY_DLMALLOC USE_MEMORY_PTMALLOC2
MEMORY_HOOK_DO_ALIGN USE_DELETED_CHAIN)
USE_MEMORY_MIMALLOC MEMORY_HOOK_DO_ALIGN USE_DELETED_CHAIN)
if(USE_MEMORY_MIMALLOC)
package_status(MIMALLOC "mimalloc memory allocator")
else()
package_status(MIMALLOC "mimalloc memory allocator (not used)")
endif()
unset(_prefer_mimalloc)
#
# This section relates to mobile-device/phone support and options

View File

@ -1,5 +1,5 @@
set(_thirdparty_dir_default "${PROJECT_SOURCE_DIR}/thirdparty")
if(NOT (APPLE OR WIN32) OR NOT IS_DIRECTORY "${_thirdparty_dir_default}")
if(NOT IS_DIRECTORY "${_thirdparty_dir_default}")
set(_thirdparty_dir_default "")
endif()
@ -47,6 +47,27 @@ if(THIRDPARTY_DIRECTORY)
set(BISON_ROOT "${THIRDPARTY_DIRECTORY}/win-util")
set(FLEX_ROOT "${THIRDPARTY_DIRECTORY}/win-util")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
set(_package_dir ${THIRDPARTY_DIRECTORY}/linux-libs-arm64)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_package_dir ${THIRDPARTY_DIRECTORY}/linux-libs-x64)
else()
set(_package_dir ${THIRDPARTY_DIRECTORY}/linux-libs-a)
endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
set(_package_dir ${THIRDPARTY_DIRECTORY}/freebsd-libs-arm64)
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_package_dir ${THIRDPARTY_DIRECTORY}/freebsd-libs-x64)
else()
set(_package_dir ${THIRDPARTY_DIRECTORY}/freebsd-libs-a)
endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
set(_package_dir ${THIRDPARTY_DIRECTORY}/android-libs-${CMAKE_ANDROID_ARCH})
else()
message(FATAL_ERROR
"You can't use THIRDPARTY_DIRECTORY on this platform. Unset it to continue.")
@ -190,19 +211,6 @@ if(Python_FOUND)
set(PYTHON_INCLUDE_DIRS ${Python_INCLUDE_DIRS})
set(PYTHON_LIBRARY_DIRS ${Python_LIBRARY_DIRS})
set(PYTHON_VERSION_STRING ${Python_VERSION})
elseif(CMAKE_VERSION VERSION_LESS "3.12")
find_package(PythonInterp ${WANT_PYTHON_VERSION} QUIET)
find_package(PythonLibs ${PYTHON_VERSION_STRING} QUIET)
if(PYTHONLIBS_FOUND)
set(PYTHON_FOUND ON)
if(NOT PYTHON_VERSION_STRING)
set(PYTHON_VERSION_STRING ${PYTHONLIBS_VERSION_STRING})
endif()
endif()
endif()
if(CMAKE_VERSION VERSION_LESS "3.15")
@ -369,14 +377,22 @@ package_option(TIFF "Enable support for loading .tif images.")
package_status(TIFF "libtiff")
# OpenEXR
find_package(OpenEXR QUIET MODULE)
find_package(OpenEXR QUIET)
package_option(OpenEXR "Enable support for loading .exr images.")
if (TARGET OpenEXR::IlmImf AND NOT TARGET OpenEXR::OpenEXR)
package_option(OpenEXR
"Enable support for loading .exr images."
IMPORTED_AS OpenEXR::IlmImf)
else()
package_option(OpenEXR
"Enable support for loading .exr images."
IMPORTED_AS OpenEXR::OpenEXR)
endif()
package_status(OpenEXR "OpenEXR")
# libsquish
find_package(LibSquish QUIET)
find_package(LibSquish QUIET MODULE)
package_option(SQUISH
"Enables support for automatic compression of DXT textures."
@ -556,16 +572,17 @@ package_option(HarfBuzz
package_status(HarfBuzz "HarfBuzz")
# GTK2
# GTK3
set(Freetype_FIND_QUIETLY TRUE) # Fix for builtin FindGTK2
set(GTK2_GTK_FIND_QUIETLY TRUE) # Fix for builtin FindGTK2
find_package(GTK2 QUIET COMPONENTS gtk)
if(NOT WIN32)
find_package(GTK3 QUIET)
endif()
package_option(GTK2)
package_status(GTK2 "gtk+-2")
package_option(GTK3
"This is necessary to build the PStats performance analysis tool on platforms
other than Windows.")
package_status(GTK3 "gtk+-3")
#
# ------------ Physics engines ------------

View File

@ -46,10 +46,6 @@ math(EXPR PANDA_NUMERIC_VERSION "${PROJECT_VERSION_MAJOR}*1000000 + ${PROJECT_VE
# If SOURCE_DATE_EPOCH is set, it affects PandaSystem::get_build_date()
if(DEFINED ENV{SOURCE_DATE_EPOCH})
if(CMAKE_VERSION VERSION_LESS "3.8")
message(FATAL_ERROR "CMake 3.8 is required to support SOURCE_DATE_EPOCH properly.")
endif()
string(TIMESTAMP _build_date "%b %d %Y %H:%M:%S" UTC)
# CMake doesn't support %e, replace leading zero in day with space

View File

@ -130,8 +130,12 @@
/* Define if we want to support fixed-function OpenGL rendering. */
#cmakedefine SUPPORT_FIXED_FUNCTION
/* Define for either of the alternative malloc schemes. */
/* Define if we have mimalloc available. */
#cmakedefine HAVE_MIMALLOC
/* Define for one of the alternative malloc schemes. */
#cmakedefine USE_MEMORY_DLMALLOC
#cmakedefine USE_MEMORY_MIMALLOC
#cmakedefine USE_MEMORY_PTMALLOC2
/* Define if we want to compile in support for pipelining. */

File diff suppressed because it is too large Load Diff

View File

@ -226,8 +226,8 @@ output(std::ostream &out) const {
out << "$1";
}
for (int i = 1; i < _num_parameters; ++i) {
if (_variadic_param == i) {
for (size_t i = 1; i < _num_parameters; ++i) {
if (_variadic_param == (int)i) {
out << ", ...";
} else {
out << ", $" << i + 1;

View File

@ -43,7 +43,7 @@ public:
std::string _name;
bool _has_parameters;
int _num_parameters;
size_t _num_parameters;
int _variadic_param;
cppyyltype _loc;
CPPExpression *_expr;

View File

@ -22,9 +22,9 @@
CPPNamespace::
CPPNamespace(CPPIdentifier *ident, CPPScope *scope, const CPPFile &file) :
CPPDeclaration(file),
_is_inline(false),
_ident(ident),
_scope(scope),
_is_inline(false)
_scope(scope)
{
}

View File

@ -58,8 +58,8 @@ CPPStructType(const CPPStructType &copy) :
CPPExtensionType(copy),
_scope(copy._scope),
_incomplete(copy._incomplete),
_derivation(copy._derivation),
_final(copy._final)
_final(copy._final),
_derivation(copy._derivation)
{
_subst_decl_recursive_protect = false;
}

View File

@ -46,6 +46,7 @@ set(P3DTOOLBASE_HEADERS
typeRegistryNode.I typeRegistryNode.h
typedObject.I typedObject.h
pallocator.T pallocator.h
patomic.h patomic.I
pdeque.h plist.h pmap.h pset.h
pvector.h epvector.h
lookup3.h
@ -70,6 +71,7 @@ set(P3DTOOLBASE_SOURCES
mutexWin32Impl.cxx
mutexSpinlockImpl.cxx
neverFreeMemory.cxx
patomic.cxx
pdtoa.cxx
pstrtod.cxx
register_type.cxx
@ -92,9 +94,14 @@ add_component_library(p3dtoolbase NOINIT SYMBOL BUILDING_DTOOL_DTOOLBASE
target_include_directories(p3dtoolbase PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
$<BUILD_INTERFACE:${PANDA_OUTPUT_DIR}/include>)
target_link_libraries(p3dtoolbase PKG::EIGEN PKG::THREADS)
target_link_libraries(p3dtoolbase PKG::EIGEN PKG::THREADS PKG::MIMALLOC)
target_interrogate(p3dtoolbase ${P3DTOOLBASE_SOURCES} EXTENSIONS ${P3DTOOLBASE_IGATEEXT})
if(HAVE_MIMALLOC AND CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang)$")
# Do not re-export symbols from these libraries.
target_link_options(p3dtoolbase PRIVATE "LINKER:--exclude-libs,libmimalloc.a")
endif()
if(NOT BUILD_METALIBS)
install(TARGETS p3dtoolbase
EXPORT Core COMPONENT Core

View File

@ -27,7 +27,7 @@ validate(void *ptr) {
#if defined(USE_DELETEDCHAINFLAG) && defined(USE_DELETED_CHAIN)
const ObjectNode *obj = buffer_to_node(ptr);
return AtomicAdjust::get(obj->_flag) == DCF_alive;
return obj->_flag.load(std::memory_order_relaxed) == DCF_alive;
#else
return true;
#endif // USE_DELETEDCHAINFLAG

View File

@ -50,8 +50,8 @@ allocate(size_t size, TypeHandle type_handle) {
_lock.unlock();
#ifdef USE_DELETEDCHAINFLAG
assert(obj->_flag == (AtomicAdjust::Integer)DCF_deleted);
obj->_flag = DCF_alive;
DeletedChainFlag orig_flag = obj->_flag.exchange(DCF_alive, std::memory_order_relaxed);
assert(orig_flag == DCF_deleted);
#endif // USE_DELETEDCHAINFLAG
void *ptr = node_to_buffer(obj);
@ -75,7 +75,7 @@ allocate(size_t size, TypeHandle type_handle) {
obj = (ObjectNode *)(aligned - flag_reserved_bytes);
#ifdef USE_DELETEDCHAINFLAG
obj->_flag = DCF_alive;
obj->_flag.store(DCF_alive, std::memory_order_relaxed);
#endif // USE_DELETEDCHAINFLAG
void *ptr = node_to_buffer(obj);
@ -116,14 +116,16 @@ deallocate(void *ptr, TypeHandle type_handle) {
ObjectNode *obj = buffer_to_node(ptr);
#ifdef USE_DELETEDCHAINFLAG
AtomicAdjust::Integer orig_flag = AtomicAdjust::compare_and_exchange(obj->_flag, DCF_alive, DCF_deleted);
DeletedChainFlag orig_flag = DCF_alive;
if (UNLIKELY(!obj->_flag.compare_exchange_strong(orig_flag, DCF_deleted,
std::memory_order_relaxed))) {
// If this assertion is triggered, you double-deleted an object.
assert(orig_flag != DCF_deleted);
// If this assertion is triggered, you double-deleted an object.
assert(orig_flag != (AtomicAdjust::Integer)DCF_deleted);
// If this assertion is triggered, you tried to delete an object that was
// never allocated, or you have heap corruption.
assert(orig_flag == (AtomicAdjust::Integer)DCF_alive);
// If this assertion is triggered, you tried to delete an object that was
// never allocated, or you have heap corruption.
assert(orig_flag == DCF_alive);
}
#endif // USE_DELETEDCHAINFLAG
_lock.lock();

View File

@ -20,6 +20,7 @@
#include "atomicAdjust.h"
#include "numeric_types.h"
#include "typeHandle.h"
#include "patomic.h"
#include <assert.h>
// Though it's tempting, it doesn't seem to be possible to implement
@ -37,7 +38,7 @@
#endif // NDEBUG
#ifdef USE_DELETEDCHAINFLAG
enum DeletedChainFlag {
enum DeletedChainFlag : unsigned int {
DCF_deleted = 0xfeedba0f,
DCF_alive = 0x12487654,
};
@ -73,7 +74,7 @@ private:
// In development mode, we piggyback this extra data. This is maintained
// out-of-band from the actual pointer returned, so we can safely use this
// flag to indicate the difference between allocated and freed pointers.
TVOLATILE AtomicAdjust::Integer _flag;
patomic<DeletedChainFlag> _flag;
#endif
// This pointer sits within the buffer, in the same space referenced by

View File

@ -375,6 +375,10 @@ typedef struct _object PyObject;
// This specialized malloc implementation can perform the required alignment.
#undef MEMORY_HOOK_DO_ALIGN
#elif defined(USE_MEMORY_MIMALLOC)
// This one does, too.
#undef MEMORY_HOOK_DO_ALIGN
#elif defined(USE_MEMORY_PTMALLOC2)
// But not this one. For some reason it crashes when we try to build it with
// alignment 16. So if we're using ptmalloc2, we need to enforce alignment
@ -385,6 +389,12 @@ typedef struct _object PyObject;
// The OS-provided malloc implementation will do the required alignment.
#undef MEMORY_HOOK_DO_ALIGN
#elif defined(HAVE_MIMALLOC) && defined(_WIN32)
// Prefer mimalloc on Windows, if we have it. It is significantly faster than
// standard malloc, supports multi-threading well and does the alignment too.
#undef MEMORY_HOOK_DO_ALIGN
#define USE_MEMORY_MIMALLOC 1
#elif defined(MEMORY_HOOK_DO_ALIGN)
// We need memory alignment, and we're willing to provide it ourselves.
@ -426,7 +436,7 @@ typedef struct _object PyObject;
#endif
/* Determine our memory-allocation requirements. */
#if defined(USE_MEMORY_PTMALLOC2) || defined(USE_MEMORY_DLMALLOC) || defined(DO_MEMORY_USAGE) || defined(MEMORY_HOOK_DO_ALIGN)
#if defined(USE_MEMORY_MIMALLOC) || defined(USE_MEMORY_PTMALLOC2) || defined(USE_MEMORY_DLMALLOC) || defined(DO_MEMORY_USAGE) || defined(MEMORY_HOOK_DO_ALIGN)
/* In this case we have some custom memory management requirements. */
#else
/* Otherwise, if we have no custom memory management needs at all, we

View File

@ -49,8 +49,6 @@
// interrogate pass (CPPPARSER isn't defined), this maps to public.
#define PUBLISHED __published
#define PHAVE_ATOMIC 1
typedef int ios_openmode;
typedef int ios_fmtflags;
typedef int ios_iostate;
@ -112,9 +110,6 @@ typedef std::ios::seekdir ios_seekdir;
#define INLINE inline
#endif
// Expect that we have access to the <atomic> header.
#define PHAVE_ATOMIC 1
// Determine the availability of C++11 features.
#if defined(_MSC_VER) && _MSC_VER < 1900 // Visual Studio 2015
#error Microsoft Visual C++ 2015 or later is required to compile Panda3D.

View File

@ -51,6 +51,18 @@ static_assert((MEMORY_HOOK_ALIGNMENT & (MEMORY_HOOK_ALIGNMENT - 1)) == 0,
#if defined(CPPPARSER)
#elif defined(USE_MEMORY_MIMALLOC)
// mimalloc is a modern memory manager by Microsoft that is very fast as well
// as thread-safe.
#include "mimalloc.h"
#define call_malloc mi_malloc
#define call_realloc mi_realloc
#define call_free mi_free
#undef MEMORY_HOOK_MALLOC_LOCK
#elif defined(USE_MEMORY_DLMALLOC)
// Memory manager: DLMALLOC This is Doug Lea's memory manager. It is very

View File

@ -19,9 +19,7 @@
#ifdef MUTEX_SPINLOCK
#ifdef PHAVE_ATOMIC
#include <atomic>
#endif
/**
* Uses a simple user-space spinlock to implement a mutex. It is usually not

View File

@ -13,7 +13,7 @@
#include "selectThreadImpl.h"
#if defined(_WIN32) && !defined(CPPPARSER)
#ifdef _WIN32
#include "mutexWin32Impl.h"

View File

@ -1,3 +1,4 @@
#include "patomic.cxx"
#include "mutexPosixImpl.cxx"
#include "mutexWin32Impl.cxx"
#include "mutexSpinlockImpl.cxx"

View File

@ -0,0 +1,472 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file patomic.I
* @author rdb
* @date 2022-01-28
*/
#if defined(THREAD_DUMMY_IMPL) || defined(THREAD_SIMPLE_IMPL)
/**
* Value initializer.
*/
template<class T>
constexpr patomic<T>::
patomic(T desired) noexcept : _value(desired) {
}
/**
* Returns true if this is a lock free type (which it always is).
*/
template<class T>
ALWAYS_INLINE bool patomic<T>::
is_lock_free() const noexcept {
return true;
}
/**
* Returns the stored value.
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
load(std::memory_order order) const noexcept {
return _value;
}
/**
* Returns the stored value.
*/
template<class T>
ALWAYS_INLINE patomic<T>::
operator T() const noexcept {
return _value;
}
/**
* Changes the stored value.
*/
template<class T>
ALWAYS_INLINE void patomic<T>::
store(T desired, std::memory_order order) noexcept {
_value = desired;
}
/**
* Changes the stored value.
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
operator=(T desired) noexcept {
_value = desired;
}
/**
* Changes the stored value, returning the previous value.
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
exchange(T desired, std::memory_order) noexcept {
T current = _value;
_value = desired;
return current;
}
/**
* Sets the desired value if the current value is as the first argument.
* If it is not, the current value is written to expected.
*/
template<class T>
ALWAYS_INLINE bool patomic<T>::
compare_exchange_weak(T &expected, T desired,
std::memory_order, std::memory_order) noexcept {
T current = _value;
if (_value == expected) {
_value = desired;
return true;
} else {
expected = current;
return false;
}
}
/**
* Sets the desired value if the current value is as the first argument.
* If it is not, the current value is written to expected.
*/
template<class T>
ALWAYS_INLINE bool patomic<T>::
compare_exchange_strong(T &expected, T desired,
std::memory_order, std::memory_order) noexcept {
T current = _value;
if (_value == expected) {
_value = desired;
return true;
} else {
expected = current;
return false;
}
}
/**
* Adds to the stored value, returns the old value.
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
fetch_add(T arg, std::memory_order) noexcept {
T old = _value;
_value += arg;
return old;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
fetch_sub(T arg, std::memory_order) noexcept {
T old = _value;
_value -= arg;
return old;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
fetch_and(T arg, std::memory_order) noexcept {
T old = _value;
_value &= arg;
return old;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
fetch_or(T arg, std::memory_order) noexcept {
T old = _value;
_value |= arg;
return old;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
fetch_xor(T arg, std::memory_order) noexcept {
T old = _value;
_value ^= arg;
return old;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
operator ++(int) noexcept {
return _value++;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
operator --(int) noexcept {
return _value--;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
operator ++() noexcept {
return ++_value;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
operator --() noexcept {
return --_value;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
operator +=(T arg) noexcept {
return _value += arg;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
operator -=(T arg) noexcept {
return _value -= arg;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
operator &=(T arg) noexcept {
return _value &= arg;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
operator |=(T arg) noexcept {
return _value |= arg;
}
/**
*
*/
template<class T>
ALWAYS_INLINE T patomic<T>::
operator ^=(T arg) noexcept {
return _value ^= arg;
}
#endif // defined(THREAD_DUMMY_IMPL) || defined(THREAD_SIMPLE_IMPL)
/**
* Initializes the variable to zero (according to C++20 semantics, NOT C++11
* semantics!)
*/
constexpr patomic_unsigned_lock_free::
patomic_unsigned_lock_free() noexcept :
patomic<uint32_t>(0u) {
}
/**
* Initializes the variable to the given value.
*/
constexpr patomic_unsigned_lock_free::
patomic_unsigned_lock_free(uint32_t desired) noexcept :
patomic<uint32_t>(desired) {
}
/**
* Waits until the value is no longer equal to the given value.
*/
ALWAYS_INLINE void patomic_unsigned_lock_free::
wait(uint32_t old, std::memory_order order) const noexcept {
if (load(order) == old) {
patomic_wait((const volatile uint32_t *)this, old);
}
}
/**
* Wakes up at least one thread waiting for the value to change.
*/
ALWAYS_INLINE void patomic_unsigned_lock_free::
notify_one() noexcept {
patomic_notify_one((volatile uint32_t *)this);
}
/**
* Wakes up at least one thread waiting for the value to change.
*/
ALWAYS_INLINE void patomic_unsigned_lock_free::
notify_all() noexcept {
patomic_notify_all((volatile uint32_t *)this);
}
/**
* Initializes the variable to zero (according to C++20 semantics, NOT C++11
* semantics!)
*/
constexpr patomic_signed_lock_free::
patomic_signed_lock_free() noexcept :
patomic<int32_t>(0) {
}
/**
* Initializes the variable to the given value.
*/
constexpr patomic_signed_lock_free::
patomic_signed_lock_free(int32_t desired) noexcept :
patomic<int32_t>(desired) {
}
/**
* Waits until the value is no longer equal to the given value.
*/
ALWAYS_INLINE void patomic_signed_lock_free::
wait(int32_t old, std::memory_order order) const noexcept {
if (load(order) == old) {
patomic_wait((const volatile int32_t *)this, old);
}
}
/**
* Wakes up at least one thread waiting for the value to change.
*/
ALWAYS_INLINE void patomic_signed_lock_free::
notify_one() noexcept {
patomic_notify_one((volatile int32_t *)this);
}
/**
* Wakes up at least one thread waiting for the value to change.
*/
ALWAYS_INLINE void patomic_signed_lock_free::
notify_all() noexcept {
patomic_notify_all((volatile int32_t *)this);
}
/**
* Allows assignment from ATOMIC_FLAG_INIT.
*/
constexpr patomic_flag::
patomic_flag(bool desired) noexcept : _value(desired) {
}
/**
* Sets the flag to false.
*/
ALWAYS_INLINE void patomic_flag::
clear(std::memory_order order) noexcept {
_value.store(0u, order);
}
/**
* Sets the flag to true and returns the previous value.
*/
ALWAYS_INLINE bool patomic_flag::
test_and_set(std::memory_order order) noexcept {
return _value.exchange(1u, order) != 0u;
}
/**
* Returns the current value of the flag.
*/
ALWAYS_INLINE bool patomic_flag::
test(std::memory_order order) const noexcept {
return _value.load(order) != 0u;
}
/**
* Waits until the value is no longer equal to the given value.
*/
ALWAYS_INLINE void patomic_flag::
wait(bool old, std::memory_order order) const noexcept {
_value.wait(old, order);
}
/**
* Wakes up at least one thread waiting for the value to change.
*/
ALWAYS_INLINE void patomic_flag::
notify_one() noexcept {
_value.notify_one();
}
/**
* Wakes up at least one thread waiting for the value to change.
*/
ALWAYS_INLINE void patomic_flag::
notify_all() noexcept {
_value.notify_all();
}
/**
*
*/
ALWAYS_INLINE void
patomic_wait(const volatile int32_t *value, int32_t old) {
patomic_wait((const volatile uint32_t *)value, (uint32_t)old);
}
/**
*
*/
ALWAYS_INLINE void
patomic_notify_one(volatile int32_t *value) {
patomic_notify_one((volatile uint32_t *)value);
}
/**
*
*/
ALWAYS_INLINE void
patomic_notify_all(volatile int32_t *value) {
patomic_notify_all((volatile uint32_t *)value);
}
/**
*
*/
ALWAYS_INLINE void
patomic_wait(const volatile uint32_t *value, uint32_t old) {
#ifdef __linux__
while (__atomic_load_n(value, __ATOMIC_SEQ_CST) == old) {
syscall(SYS_futex, old, FUTEX_WAIT_PRIVATE, old, 0, 0, 0);
}
//#elif _WIN32_WINNT >= _WIN32_WINNT_WIN8
// while (*value == old) {
// WaitOnAddress((volatile void *)value, &old, sizeof(uint32_t), INFINITE);
// }
#elif defined(_WIN32)
while (*value == old) {
_patomic_wait_func((volatile void *)value, &old, sizeof(uint32_t), INFINITE);
}
#elif defined(HAVE_POSIX_THREADS)
_patomic_wait(value, old);
#else
while (*value == old);
#endif
}
/**
*
*/
ALWAYS_INLINE void
patomic_notify_one(volatile uint32_t *value) {
#ifdef __linux__
syscall(SYS_futex, value, FUTEX_WAKE_PRIVATE, 1, 0, 0, 0);
//#elif _WIN32_WINNT >= _WIN32_WINNT_WIN8
// WakeByAddressSingle((void *)value);
#elif defined(_WIN32)
_patomic_wake_one_func((void *)value);
#elif defined(HAVE_POSIX_THREADS)
_patomic_notify_all(value);
#endif
}
/**
*
*/
ALWAYS_INLINE void
patomic_notify_all(volatile uint32_t *value) {
#ifdef __linux__
syscall(SYS_futex, value, FUTEX_WAKE_PRIVATE, INT_MAX, 0, 0, 0);
//#elif _WIN32_WINNT >= _WIN32_WINNT_WIN8
// WakeByAddressAll((void *)value);
#elif defined(_WIN32)
_patomic_wake_all_func((void *)value);
#elif defined(HAVE_POSIX_THREADS)
_patomic_notify_all(value);
#endif
}

View File

@ -0,0 +1,168 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file patomic.cxx
* @author rdb
* @date 2022-02-23
*/
#include "patomic.h"
#include <functional>
static_assert(sizeof(patomic_unsigned_lock_free) == sizeof(uint32_t),
"expected atomic uint32_t to have same size as uint32_t");
static_assert(sizeof(patomic_signed_lock_free) == sizeof(int32_t),
"expected atomic int32_t to have same size as int32_t");
static_assert(sizeof(uint32_t) == sizeof(int32_t),
"expected int32_t to have same size as uint32_t");
#if !defined(CPPPARSER) && defined(_WIN32)
// On Windows 7, we try to load the Windows 8 functions dynamically, and
// fall back to a condition variable table if they aren't available.
static BOOL __stdcall initialize_wait(volatile VOID *addr, PVOID cmp, SIZE_T size, DWORD timeout);
static void __stdcall dummy_wake(PVOID addr) {}
BOOL (__stdcall *_patomic_wait_func)(volatile VOID *, PVOID, SIZE_T, DWORD) = &initialize_wait;
void (__stdcall *_patomic_wake_one_func)(PVOID) = &dummy_wake;
void (__stdcall *_patomic_wake_all_func)(PVOID) = &dummy_wake;
// Randomly pick an entry into the wait table based on the hash of the address.
// It's possible to get hash collision, but that's not so bad, it just means
// that the other thread will get a spurious wakeup.
struct alignas(64) WaitTableEntry {
SRWLOCK _lock = SRWLOCK_INIT;
CONDITION_VARIABLE _cvar = CONDITION_VARIABLE_INIT;
DWORD _waiters = 0;
};
static WaitTableEntry _wait_table[64] = {};
static const size_t _wait_hash_mask = 63;
/**
* Emulates WakeByAddressSingle for Windows Vista and 7.
*/
static void __stdcall
emulated_wake(PVOID addr) {
size_t i = std::hash<volatile void *>{}(addr) & (sizeof(_wait_table) / sizeof(WaitTableEntry) - 1);
WaitTableEntry &entry = _wait_table[i];
AcquireSRWLockExclusive(&entry._lock);
DWORD num_waiters = entry._waiters;
ReleaseSRWLockExclusive(&entry._lock);
if (num_waiters > 0) {
// We have to wake up all the threads, even if only one of them is for this
// address. Some of them will get a spurious wakeup, but that's OK.
WakeAllConditionVariable(&entry._cvar);
}
}
/**
* Emulates WaitOnAddress for Windows Vista and 7. Only supports aligned
* 32-bit values.
*/
static BOOL __stdcall
emulated_wait(volatile VOID *addr, PVOID cmp, SIZE_T size, DWORD timeout) {
assert(size == sizeof(LONG));
LONG cmpval = *(LONG *)cmp;
if (*(LONG *)addr != cmpval) {
return TRUE;
}
size_t i = std::hash<volatile void *>{}(addr) & _wait_hash_mask;
WaitTableEntry &entry = _wait_table[i];
AcquireSRWLockExclusive(&entry._lock);
++entry._waiters;
while (*(LONG *)addr == cmpval) {
if (SleepConditionVariableSRW(&entry._cvar, &entry._lock, timeout, 0) != 0) {
// Timeout.
--entry._waiters;
ReleaseSRWLockExclusive(&entry._lock);
return FALSE;
}
}
--entry._waiters;
ReleaseSRWLockExclusive(&entry._lock);
return TRUE;
}
/**
* Initially assigned to the wait function slot to initialize the function
* pointers.
*/
static BOOL __stdcall
initialize_wait(volatile VOID *addr, PVOID cmp, SIZE_T size, DWORD timeout) {
// There's a chance of a race here, with two threads trying to initialize the
// functions at the same time. That's OK, because they should all produce
// the same results, and the stores to the function pointers are atomic.
HMODULE lib = GetModuleHandleW(L"api-ms-win-core-synch-l1-2-0.dll");
if (lib) {
auto wait_func = (decltype(_patomic_wait_func))GetProcAddress(lib, "WaitOnAddress");
auto wake_one_func = (decltype(_patomic_wake_one_func))GetProcAddress(lib, "WakeByAddressSingle");
auto wake_all_func = (decltype(_patomic_wake_all_func))GetProcAddress(lib, "WakeByAddressAll");
if (wait_func && wake_one_func && wake_all_func) {
// Make sure that the wake function is guaranteed to be visible to other
// threads by the time we assign the wait function.
_patomic_wake_one_func = wake_one_func;
_patomic_wake_all_func = wake_all_func;
patomic_thread_fence(std::memory_order_release);
_patomic_wait_func = wait_func;
return wait_func(addr, cmp, size, timeout);
}
}
// We don't have Windows 8's functions, use the emulated wait and wake funcs.
_patomic_wake_one_func = &emulated_wake;
_patomic_wake_all_func = &emulated_wake;
patomic_thread_fence(std::memory_order_release);
_patomic_wait_func = &emulated_wait;
return emulated_wait(addr, cmp, size, timeout);
}
#elif !defined(CPPPARSER) && !defined(__linux__) && defined(HAVE_POSIX_THREADS)
// Same as above, but using pthreads.
struct alignas(64) WaitTableEntry {
pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t _cvar = PTHREAD_COND_INITIALIZER;
unsigned int _waiters = 0;
};
static WaitTableEntry _wait_table[64];
static const size_t _wait_hash_mask = 63;
/**
*
*/
void
_patomic_wait(const volatile uint32_t *value, uint32_t old) {
WaitTableEntry &entry = _wait_table[std::hash<const volatile void *>{}(value) & _wait_hash_mask];
pthread_mutex_lock(&entry._lock);
++entry._waiters;
while (__atomic_load_n(value, __ATOMIC_SEQ_CST) == old) {
pthread_cond_wait(&entry._cvar, &entry._lock);
}
--entry._waiters;
pthread_mutex_unlock(&entry._lock);
}
/**
*
*/
void
_patomic_notify_all(volatile uint32_t *value) {
WaitTableEntry &entry = _wait_table[std::hash<const volatile void *>{}(value) & _wait_hash_mask];
pthread_mutex_lock(&entry._lock);
unsigned int num_waiters = entry._waiters;
pthread_mutex_unlock(&entry._lock);
if (num_waiters > 0) {
pthread_cond_broadcast(&entry._cvar);
}
}
#endif

View File

@ -0,0 +1,175 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file patomic.h
* @author rdb
* @date 2022-01-28
*/
#ifndef PATOMIC_H
#define PATOMIC_H
#include "dtoolbase.h"
#include "selectThreadImpl.h"
#include <atomic>
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#endif
#ifdef __linux__
#include <linux/futex.h>
#include <sys/syscall.h>
#include <unistd.h>
#endif
#if defined(THREAD_DUMMY_IMPL) || defined(THREAD_SIMPLE_IMPL)
/**
* Dummy implementation of std::atomic that does not do any atomic operations,
* used when compiling without HAVE_THREADS or with SIMPLE_THREADS.
*/
template<class T>
struct patomic {
using value_type = T;
constexpr patomic() noexcept = default;
constexpr patomic(T desired) noexcept;
ALWAYS_INLINE patomic(const patomic &) = delete;
ALWAYS_INLINE patomic &operator=(const patomic &) = delete;
static constexpr bool is_always_lock_free = true;
ALWAYS_INLINE bool is_lock_free() const noexcept;
ALWAYS_INLINE T load(std::memory_order order = std::memory_order_seq_cst) const noexcept;
ALWAYS_INLINE operator T() const noexcept;
ALWAYS_INLINE void store(T desired, std::memory_order order = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE T operator=(T desired) noexcept;
ALWAYS_INLINE T exchange(T desired, std::memory_order order = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE bool compare_exchange_weak(T &expected, T desired,
std::memory_order success = std::memory_order_seq_cst,
std::memory_order failure = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE bool compare_exchange_strong(T &expected, T desired,
std::memory_order success = std::memory_order_seq_cst,
std::memory_order failure = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE T operator ++(int) noexcept;
ALWAYS_INLINE T operator --(int) noexcept;
ALWAYS_INLINE T operator ++() noexcept;
ALWAYS_INLINE T operator --() noexcept;
ALWAYS_INLINE T operator +=(T arg) noexcept;
ALWAYS_INLINE T operator -=(T arg) noexcept;
ALWAYS_INLINE T operator &=(T arg) noexcept;
ALWAYS_INLINE T operator |=(T arg) noexcept;
ALWAYS_INLINE T operator ^=(T arg) noexcept;
private:
T _value;
};
#define patomic_thread_fence(order) (std::atomic_signal_fence((order)))
#else
// We're using real threading, so use the real implementation.
template<class T>
using patomic = std::atomic<T>;
#define patomic_thread_fence(order) (std::atomic_thread_fence((order)))
#endif
/**
* Implementation of atomic_unsigned_lock_free with C++20 semantics.
*/
class EXPCL_DTOOL_DTOOLBASE patomic_unsigned_lock_free : public patomic<uint32_t> {
public:
typedef uint32_t value_type;
constexpr patomic_unsigned_lock_free() noexcept;
constexpr patomic_unsigned_lock_free(uint32_t desired) noexcept;
INLINE void wait(uint32_t old, std::memory_order order = std::memory_order_seq_cst) const noexcept;
ALWAYS_INLINE void notify_one() noexcept;
ALWAYS_INLINE void notify_all() noexcept;
};
/**
* Implementation of atomic_signed_lock_free with C++20 semantics.
*/
class EXPCL_DTOOL_DTOOLBASE patomic_signed_lock_free : public patomic<int32_t> {
public:
typedef int32_t value_type;
constexpr patomic_signed_lock_free() noexcept;
constexpr patomic_signed_lock_free(int32_t desired) noexcept;
INLINE void wait(int32_t old, std::memory_order order = std::memory_order_seq_cst) const noexcept;
ALWAYS_INLINE void notify_one() noexcept;
ALWAYS_INLINE void notify_all() noexcept;
};
/**
* Implementation of atomic_flag with C++20 semantics.
*/
class EXPCL_DTOOL_DTOOLBASE patomic_flag {
public:
constexpr patomic_flag() noexcept = default;
constexpr patomic_flag(bool desired) noexcept;
patomic_flag(const patomic_flag &) = delete;
patomic_flag &operator=(const patomic_flag &) = delete;
ALWAYS_INLINE void clear(std::memory_order order = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE bool test_and_set(std::memory_order order = std::memory_order_seq_cst) noexcept;
ALWAYS_INLINE bool test(std::memory_order order = std::memory_order_seq_cst) const noexcept;
ALWAYS_INLINE void wait(bool old, std::memory_order order = std::memory_order_seq_cst) const noexcept;
ALWAYS_INLINE void notify_one() noexcept;
ALWAYS_INLINE void notify_all() noexcept;
private:
patomic_unsigned_lock_free _value { 0u };
};
#ifndef CPPPARSER
ALWAYS_INLINE void patomic_wait(const volatile int32_t *value, int32_t old);
ALWAYS_INLINE void patomic_notify_one(volatile int32_t *value);
ALWAYS_INLINE void patomic_notify_all(volatile int32_t *value);
ALWAYS_INLINE void patomic_wait(const volatile uint32_t *value, uint32_t old);
ALWAYS_INLINE void patomic_notify_one(volatile uint32_t *value);
ALWAYS_INLINE void patomic_notify_all(volatile uint32_t *value);
#ifdef _WIN32
EXPCL_DTOOL_DTOOLBASE extern BOOL (__stdcall *_patomic_wait_func)(volatile VOID *, PVOID, SIZE_T, DWORD);
EXPCL_DTOOL_DTOOLBASE extern void (__stdcall *_patomic_wake_one_func)(PVOID);
EXPCL_DTOOL_DTOOLBASE extern void (__stdcall *_patomic_wake_all_func)(PVOID);
#elif !defined(__linux__) && defined(HAVE_POSIX_THREADS)
EXPCL_DTOOL_DTOOLBASE void _patomic_wait(const volatile uint32_t *value, uint32_t old);
EXPCL_DTOOL_DTOOLBASE void _patomic_notify_all(volatile uint32_t *value);
#endif
#include "patomic.I"
#endif // CPPPARSER
#endif

View File

@ -13,7 +13,6 @@
#include "typeHandle.h"
#include "typeRegistryNode.h"
#include "atomicAdjust.h"
/**
* Returns the total allocated memory used by objects of this type, for the
@ -29,7 +28,7 @@ get_memory_usage(MemoryClass memory_class) const {
} else {
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, nullptr);
assert(rnode != nullptr);
return (size_t)AtomicAdjust::get(rnode->_memory_usage[memory_class]);
return rnode->_memory_usage[memory_class].load(std::memory_order_relaxed);
}
#endif // DO_MEMORY_USAGE
return 0;
@ -48,10 +47,8 @@ inc_memory_usage(MemoryClass memory_class, size_t size) {
if ((*this) != TypeHandle::none()) {
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, nullptr);
assert(rnode != nullptr);
AtomicAdjust::add(rnode->_memory_usage[memory_class], (AtomicAdjust::Integer)size);
// cerr << *this << ".inc(" << memory_class << ", " << size << ") -> " <<
// rnode->_memory_usage[memory_class] << "\n";
if (rnode->_memory_usage[memory_class] < 0) {
size_t prev = rnode->_memory_usage[memory_class].fetch_add(size, std::memory_order_relaxed);
if (prev + size < prev) {
std::cerr << "Memory usage overflow for type " << rnode->_name << ".\n";
abort();
}
@ -72,10 +69,8 @@ dec_memory_usage(MemoryClass memory_class, size_t size) {
if ((*this) != TypeHandle::none()) {
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, nullptr);
assert(rnode != nullptr);
AtomicAdjust::add(rnode->_memory_usage[memory_class], -(AtomicAdjust::Integer)size);
// cerr << *this << ".dec(" << memory_class << ", " << size << ") -> " <<
// rnode->_memory_usage[memory_class] << "\n";
assert(rnode->_memory_usage[memory_class] >= 0);
size_t prev = rnode->_memory_usage[memory_class].fetch_sub(size, std::memory_order_relaxed);
assert(prev - size <= prev);
}
#endif // DO_MEMORY_USAGE
}
@ -97,8 +92,8 @@ allocate_array(size_t size) {
#endif
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, nullptr);
assert(rnode != nullptr);
AtomicAdjust::add(rnode->_memory_usage[MC_array], (AtomicAdjust::Integer)alloc_size);
if (rnode->_memory_usage[MC_array] < 0) {
size_t prev = rnode->_memory_usage[MC_array].fetch_add(alloc_size, std::memory_order_relaxed);
if (prev + size < prev) {
std::cerr << "Memory usage overflow for type " << rnode->_name << ".\n";
abort();
}
@ -124,8 +119,11 @@ reallocate_array(void *old_ptr, size_t size) {
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, nullptr);
assert(rnode != nullptr);
AtomicAdjust::add(rnode->_memory_usage[MC_array], (AtomicAdjust::Integer)new_size - (AtomicAdjust::Integer)old_size);
assert(rnode->_memory_usage[MC_array] >= 0);
if (new_size > old_size) {
rnode->_memory_usage[MC_array].fetch_add(new_size - old_size, std::memory_order_relaxed);
} else {
rnode->_memory_usage[MC_array].fetch_sub(old_size - new_size, std::memory_order_relaxed);
}
}
#else
void *new_ptr = PANDA_REALLOC_ARRAY(old_ptr, size);
@ -146,8 +144,8 @@ deallocate_array(void *ptr) {
if ((*this) != TypeHandle::none()) {
TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, nullptr);
assert(rnode != nullptr);
AtomicAdjust::add(rnode->_memory_usage[MC_array], -(AtomicAdjust::Integer)alloc_size);
assert(rnode->_memory_usage[MC_array] >= 0);
size_t prev = rnode->_memory_usage[MC_array].fetch_sub(alloc_size, std::memory_order_relaxed);
assert(prev - alloc_size <= prev);
}
#endif // DO_MEMORY_USAGE
PANDA_FREE_ARRAY(ptr);

View File

@ -38,7 +38,6 @@ make(PyTypeObject *tp) {
PyObject *Extension<TypeHandle>::
__reduce__() const {
extern struct Dtool_PyTypedObject Dtool_TypeHandle;
extern struct Dtool_PyTypedObject Dtool_TypeRegistry;
if (!*_this) {
PyObject *func = PyObject_GetAttrString((PyObject *)&Dtool_TypeHandle, "none");

View File

@ -23,10 +23,9 @@ bool TypeRegistryNode::_paranoid_inheritance = false;
*/
TypeRegistryNode::
TypeRegistryNode(TypeHandle handle, const std::string &name, TypeHandle &ref) :
_handle(handle), _name(name), _ref(ref)
_handle(handle), _name(name), _ref(ref), _memory_usage{}
{
clear_subtree();
memset(_memory_usage, 0, sizeof(_memory_usage));
}
/**

View File

@ -18,6 +18,7 @@
#include "typeHandle.h"
#include "numeric_types.h"
#include "patomic.h"
#include <assert.h>
#include <vector>
@ -50,7 +51,7 @@ public:
Classes _child_classes;
PyObject *_python_type = nullptr;
AtomicAdjust::Integer _memory_usage[TypeHandle::MC_limit];
patomic<size_t> _memory_usage[TypeHandle::MC_limit];
static bool _paranoid_inheritance;

View File

@ -259,10 +259,14 @@ ns_has_environment_variable(const string &var) const {
return true;
}
#ifndef PREREAD_ENVIRONMENT
return getenv(var.c_str()) != nullptr;
#else
#ifdef PREREAD_ENVIRONMENT
return false;
#elif defined(_MSC_VER)
size_t size = 0;
getenv_s(&size, nullptr, 0, var.c_str());
return size != 0;
#else
return getenv(var.c_str()) != nullptr;
#endif
}
@ -301,11 +305,24 @@ ns_get_environment_variable(const string &var) const {
}
#ifndef PREREAD_ENVIRONMENT
#ifdef _MSC_VER
std::string value(128, '\0');
size_t size = value.size();
while (getenv_s(&size, &value[0], size, var.c_str()) == ERANGE) {
value.resize(size);
}
if (size != 0) {
// Strip off the trailing null byte.
value.resize(size - 1);
return value;
}
#else
const char *def = getenv(var.c_str());
if (def != nullptr) {
return def;
}
#endif
#endif
#ifdef _WIN32
// On Windows only, we also simulate several standard folder names as
@ -414,14 +431,15 @@ ns_get_environment_variable(const string &var) const {
void ExecutionEnvironment::
ns_set_environment_variable(const string &var, const string &value) {
_variables[var] = value;
#ifdef _MSC_VER
_putenv_s(var.c_str(), value.c_str());
#else
string putstr = var + "=" + value;
// putenv() requires us to malloc a new C-style string.
char *put = (char *)malloc(putstr.length() + 1);
strcpy(put, putstr.c_str());
#ifdef _MSC_VER
_putenv(put);
#else
putenv(put);
#endif
}
@ -447,12 +465,27 @@ ns_clear_shadow(const string &var) {
#ifdef PREREAD_ENVIRONMENT
// Now we have to replace the value in the table.
#ifdef _MSC_VER
std::string value(128, '\0');
size_t size = value.size();
while (getenv_s(&size, &value[0], size, var.c_str()) == ERANGE) {
value.resize(size);
}
if (size != 0) {
// Strip off the trailing null byte.
value.resize(size - 1);
(*vi).second = std::move(value);
} else {
_variables.erase(vi);
}
#else
const char *def = getenv(var.c_str());
if (def != nullptr) {
(*vi).second = def;
} else {
_variables.erase(vi);
}
#endif
#endif // PREREAD_ENVIRONMENT
}

View File

@ -152,10 +152,22 @@ get_panda_root() {
if (panda_root == nullptr) {
panda_root = new string;
#ifdef _MSC_VER
char *envvar = nullptr;
size_t size = 0;
while (getenv_s(&size, envvar, size, "PANDA_ROOT") == ERANGE) {
envvar = (char *)alloca(size);
}
if (size != 0) {
(*panda_root) = front_to_back_slash(envvar);
}
#else
const char *envvar = getenv("PANDA_ROOT");
if (envvar != nullptr) {
(*panda_root) = front_to_back_slash(envvar);
}
#endif
// Ensure the string ends in a backslash. If PANDA_ROOT is empty or
// undefined, this function must return a single backslash--not an empty
@ -477,7 +489,8 @@ get_home_directory() {
if (AtomicAdjust::get_ptr(_home_directory) == nullptr) {
Filename home_directory;
// In all environments, check $HOME first.
// In all environments except Windows, check $HOME first.
#ifndef _WIN32
char *home = getenv("HOME");
if (home != nullptr) {
Filename dirname = from_os_specific(home);
@ -487,6 +500,7 @@ get_home_directory() {
}
}
}
#endif
if (home_directory.empty()) {
#ifdef _WIN32

View File

@ -53,6 +53,8 @@ PandaSystem() :
set_system_tag("system", "malloc", "dlmalloc");
#elif defined(USE_MEMORY_PTMALLOC2)
set_system_tag("system", "malloc", "ptmalloc2");
#elif defined(USE_MEMORY_MIMALLOC)
set_system_tag("system", "malloc", "mimalloc");
#else
set_system_tag("system", "malloc", "malloc");
#endif

View File

@ -140,6 +140,10 @@ PandaGetopt(int argc, char *const argv[], const char *optstring,
// _options[0] is used for invalid characters.
_options.push_back(Option('?', no_argument));
#ifdef _MSC_VER
size_t size;
#endif
if (optstring[0] == '-') {
// RETURN_IN_ORDER: Non-option arguments (operands) are handled as if they
// were the argument to an option with the value 1 ('\001').
@ -154,8 +158,12 @@ PandaGetopt(int argc, char *const argv[], const char *optstring,
// argument is reached, or when the element of argv is "--".
++optstring;
_require_order = true;
} else if (getenv("POSIXLY_CORRECT") != nullptr) {
}
#ifdef _MSC_VER
else if (getenv_s(&size, nullptr, 0, "POSIXLY_CORRECT") == 0 && size != 0) {
#else
else if (getenv("POSIXLY_CORRECT") != nullptr) {
#endif
// REQUIRE_ORDER.
_require_order = true;

View File

@ -331,8 +331,9 @@ open_pipe(const string &cmd) {
// Both WinExec() and CreateProcess() want a non-const char pointer. Maybe
// they change it, and maybe they don't. I'm not taking chances.
char *cmdline = new char[cmd.length() + 1];
strcpy(cmdline, cmd.c_str());
char *cmdline = (char *)alloca(cmd.size() + 1);
memcpy(cmdline, cmd.data(), cmd.size());
cmdline[cmd.size()] = 0;
// We should be using CreateProcess() instead of WinExec(), but that seems
// to be likely to crash Win98. WinExec() seems better behaved, and it's
@ -345,8 +346,6 @@ open_pipe(const string &cmd) {
// Don't return yet, since we still need to clean up.
}
delete[] cmdline;
// Now restore our own stdout, up here in the parent process.
if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) {
#ifndef NDEBUG

View File

@ -327,6 +327,9 @@ make_wrapper_entry(FunctionIndex function_index) {
if ((*pi)._has_name) {
param._parameter_flags |= InterrogateFunctionWrapper::PF_has_name;
}
if ((*pi)._remap->has_default_value()) {
param._parameter_flags |= InterrogateFunctionWrapper::PF_is_optional;
}
iwrapper._parameters.push_back(param);
}

View File

@ -77,8 +77,8 @@ InterfaceMaker::Function::
*/
InterfaceMaker::MakeSeq::
MakeSeq(const string &name, const InterrogateMakeSeq &imake_seq) :
_name(name),
_imake_seq(imake_seq),
_name(name),
_length_getter(nullptr),
_element_getter(nullptr)
{
@ -237,7 +237,7 @@ generate_wrappers() {
int num_global_elements = idb->get_num_global_elements();
for (int gi = 0; gi < num_global_elements; ++gi) {
printf(" Global Type = %d", gi);
//printf(" Global Type = %d", gi);
TypeIndex type_index = idb->get_global_element(gi);
record_object(type_index);
}
@ -256,12 +256,12 @@ generate_wrappers() {
FunctionIndex func_index = iman.get_getter();
record_function(dummy_type, func_index);
}
printf(" Manifests %d\n", mi);
//printf(" Manifests %d\n", mi);
}
int num_elements = idb->get_num_global_elements();
for (int ei = 0; ei < num_elements; ei++) {
printf(" Element %d\n", ei);
//printf(" Element %d\n", ei);
ElementIndex element_index = idb->get_global_element(ei);
const InterrogateElement &ielement = idb->get_element(element_index);

View File

@ -2510,11 +2510,11 @@ write_module_class(ostream &out, Object *obj) {
out << " if (arg2 != nullptr && arg2 != Py_None) {\n";
out << " PyObject *args = PyTuple_Pack(2, arg, arg2);\n";
write_function_forset(out, two_param_remaps, 2, 2, expected_params, 4,
true, true, AT_varargs, RF_pyobject | RF_err_null | RF_decref_args, true);
true, true, AT_varargs, return_flags | RF_decref_args, true);
out << " Py_DECREF(args);\n";
out << " } else {\n";
write_function_forset(out, one_param_remaps, 1, 1, expected_params, 4,
true, true, AT_single_arg, RF_pyobject | RF_err_null, true);
true, true, AT_single_arg, return_flags, true);
out << " }\n\n";
out << " if (!_PyErr_OCCURRED()) {\n";

View File

@ -102,10 +102,10 @@ write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
++fi) {
Function *func = (*fi);
out << " { \"" << func->_ifunc.get_name() << "\", &" << func->_name
<< ", METH_VARARGS },\n";
<< ", METH_VARARGS, nullptr },\n";
}
}
out << " { nullptr, nullptr }\n"
out << " { nullptr, nullptr, 0, nullptr }\n"
<< "};\n\n"
<< "#if PY_MAJOR_VERSION >= 3\n"

View File

@ -89,10 +89,10 @@ write_module(ostream &out,ostream *out_h, InterrogateModuleDef *def) {
for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
FunctionRemap *remap = (*ri);
out << " { \"" << remap->_reported_name << "\", &"
<< remap->_wrapper_name << ", METH_VARARGS },\n";
<< remap->_wrapper_name << ", METH_VARARGS, nullptr },\n";
}
}
out << " { nullptr, nullptr }\n"
out << " { nullptr, nullptr, 0, nullptr }\n"
<< "};\n\n"
<< "#if PY_MAJOR_VERSION >= 3\n"

View File

@ -547,8 +547,15 @@ main(int argc, char **argv) {
// We allow overriding this value by setting SOURCE_DATE_EPOCH to support
// reproducible builds.
int file_identifier;
#ifdef _MSC_VER
char source_date_epoch[64];
size_t source_date_epoch_size = 0;
if (getenv_s(&source_date_epoch_size, source_date_epoch,
sizeof(source_date_epoch), "SOURCE_DATE_EPOCH"), source_date_epoch_size > 1) {
#else
const char *source_date_epoch = getenv("SOURCE_DATE_EPOCH");
if (source_date_epoch != nullptr && source_date_epoch[0] != 0) {
#endif
file_identifier = atoi(source_date_epoch);
} else {
file_identifier = time(nullptr);

View File

@ -1071,6 +1071,10 @@ scan_function(CPPInstance *function) {
return;
}
if (TypeManager::involves_rvalue_reference(ftype)) {
return;
}
get_function(function, "",
nullptr, scope,
InterrogateFunction::F_global);
@ -1770,6 +1774,16 @@ get_function(CPPInstance *function, string description,
ifunction->_flags |= InterrogateFunction::F_operator_typecast;
}
if (ftype->_flags & CPPFunctionType::F_constructor) {
// This is a constructor.
ifunction->_flags |= InterrogateFunction::F_constructor;
}
if (ftype->_flags & CPPFunctionType::F_destructor) {
// This is a destructor.
ifunction->_flags |= InterrogateFunction::F_destructor;
}
if (function->_storage_class & CPPInstance::SC_virtual) {
// This is a virtual function.
ifunction->_flags |= InterrogateFunction::F_virtual;
@ -2747,7 +2761,8 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
function->_storage_class |= CPPInstance::SC_inline | CPPInstance::SC_defaulted;
function->_vis = V_published;
FunctionIndex index = get_function(function, "", cpptype, cpptype->get_scope(), 0);
FunctionIndex index = get_function(function, "", cpptype, cpptype->get_scope(),
InterrogateFunction::F_constructor);
if (find(itype._constructors.begin(), itype._constructors.end(),
index) == itype._constructors.end()) {
itype._constructors.push_back(index);
@ -2773,7 +2788,8 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
function->_storage_class |= CPPInstance::SC_inline | CPPInstance::SC_defaulted;
function->_vis = V_published;
FunctionIndex index = get_function(function, "", cpptype, cpptype->get_scope(), 0);
FunctionIndex index = get_function(function, "", cpptype, cpptype->get_scope(),
InterrogateFunction::F_constructor);
if (find(itype._constructors.begin(), itype._constructors.end(),
index) == itype._constructors.end()) {
itype._constructors.push_back(index);
@ -2814,7 +2830,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
itype._destructor = get_function(function, "",
cpptype, cpptype->get_scope(),
0);
InterrogateFunction::F_destructor);
itype._flags |= InterrogateType::F_implicit_destructor;
}
}
@ -2988,6 +3004,9 @@ define_method(CPPInstance *function, InterrogateType &itype,
// If it isn't, we should publish this method anyway.
}
if (TypeManager::involves_rvalue_reference(ftype)) {
return;
}
FunctionIndex index = get_function(function, "", struct_type, scope, 0);
if (index != 0) {

View File

@ -2017,6 +2017,46 @@ involves_protected(CPPType *type) {
}
}
/**
* Returns true if the type involves an rvalue reference.
*/
bool TypeManager::
involves_rvalue_reference(CPPType *type) {
switch (type->get_subtype()) {
case CPPDeclaration::ST_const:
return involves_rvalue_reference(type->as_const_type()->_wrapped_around);
case CPPDeclaration::ST_reference:
return type->as_reference_type()->_value_category == CPPReferenceType::VC_rvalue;
case CPPDeclaration::ST_pointer:
return involves_rvalue_reference(type->as_pointer_type()->_pointing_at);
case CPPDeclaration::ST_function:
{
CPPFunctionType *ftype = type->as_function_type();
if (involves_rvalue_reference(ftype->_return_type)) {
return true;
}
const CPPParameterList::Parameters &params =
ftype->_parameters->_parameters;
CPPParameterList::Parameters::const_iterator pi;
for (pi = params.begin(); pi != params.end(); ++pi) {
if (involves_rvalue_reference((*pi)->_type)) {
return true;
}
}
return false;
}
case CPPDeclaration::ST_typedef:
return involves_rvalue_reference(type->as_typedef_type()->_type);
default:
return false;
}
}
/**
* Returns the type this pointer type points to.
*/

View File

@ -118,6 +118,7 @@ public:
static bool is_handle(CPPType *type);
static bool involves_unpublished(CPPType *type);
static bool involves_protected(CPPType *type);
static bool involves_rvalue_reference(CPPType *type);
static bool is_ostream(CPPType *type);
static bool is_pointer_to_ostream(CPPType *type);

View File

@ -968,6 +968,17 @@ read_new(std::istream &in, InterrogateModuleDef *def) {
add_type(index, type);
num_types--;
// Older versions of interrogate were not setting these flags.
const InterrogateType &itype = get_type(index);
FunctionIndex dtor = itype.get_destructor();
if (dtor != 0) {
update_function(dtor)._flags |= InterrogateFunction::F_destructor;
}
for (int i = 0; i < itype.number_of_constructors(); ++i) {
FunctionIndex ctor = itype.get_constructor(i);
update_function(ctor)._flags |= InterrogateFunction::F_constructor;
}
}
}

View File

@ -54,6 +54,22 @@ is_operator_typecast() const {
return (_flags & F_operator_typecast) != 0;
}
/**
* Returns true if the function is a constructor.
*/
INLINE bool InterrogateFunction::
is_constructor() const {
return (_flags & F_constructor) != 0;
}
/**
* Returns true if the function is a destructor.
*/
INLINE bool InterrogateFunction::
is_destructor() const {
return (_flags & F_destructor) != 0;
}
/**
* Return the class that owns the method, if is_method() returns true.
*/

View File

@ -38,6 +38,8 @@ public:
INLINE bool is_method() const;
INLINE bool is_unary_op() const;
INLINE bool is_operator_typecast() const;
INLINE bool is_constructor() const;
INLINE bool is_destructor() const;
INLINE TypeIndex get_class() const;
INLINE bool has_scoped_name() const;
@ -70,7 +72,9 @@ private:
F_setter = 0x0020,
F_unary_op = 0x0040,
F_operator_typecast = 0x0080,
F_item_assignment = 0x0100,
F_constructor = 0x0100,
F_destructor = 0x0200,
F_item_assignment = 0x0400,
};
int _flags;
@ -98,6 +102,7 @@ public:
std::string _expression;
friend class InterrogateBuilder;
friend class InterrogateDatabase;
friend class InterfaceMakerC;
friend class InterfaceMakerPythonSimple;
friend class InterfaceMakerPythonNative;

View File

@ -148,6 +148,17 @@ parameter_is_this(int n) const {
return false;
}
/**
*
*/
INLINE bool InterrogateFunctionWrapper::
parameter_is_optional(int n) const {
if (n >= 0 && n < (int)_parameters.size()) {
return (_parameters[n]._parameter_flags & PF_is_optional) != 0;
}
return false;
}
/**
*
*/

View File

@ -45,6 +45,7 @@ public:
INLINE bool parameter_has_name(int n) const;
INLINE const std::string &parameter_get_name(int n) const;
INLINE bool parameter_is_this(int n) const;
INLINE bool parameter_is_optional(int n) const;
INLINE const std::string &get_unique_name() const;
@ -66,6 +67,7 @@ private:
enum ParameterFlags {
PF_has_name = 0x0001,
PF_is_this = 0x0002,
PF_is_optional = 0x0004,
};
int _flags;

View File

@ -266,6 +266,31 @@ interrogate_function_class(FunctionIndex function) {
return InterrogateDatabase::get_ptr()->get_function(function).get_class();
}
bool
interrogate_function_is_unary_op(FunctionIndex function) {
// cerr << "interrogate_function_is_unary_op(" << function << ")\n";
return InterrogateDatabase::get_ptr()->get_function(function).is_unary_op();
}
bool
interrogate_function_is_operator_typecast(FunctionIndex function) {
// cerr << "interrogate_function_is_operator_typecast(" << function <<
// ")\n";
return InterrogateDatabase::get_ptr()->get_function(function).is_operator_typecast();
}
bool
interrogate_function_is_constructor(FunctionIndex function) {
// cerr << "interrogate_function_is_constructor(" << function << ")\n";
return InterrogateDatabase::get_ptr()->get_function(function).is_constructor();
}
bool
interrogate_function_is_destructor(FunctionIndex function) {
// cerr << "interrogate_function_is_destructor(" << function << ")\n";
return InterrogateDatabase::get_ptr()->get_function(function).is_destructor();
}
bool
interrogate_function_has_module_name(FunctionIndex function) {
// cerr << "interrogate_function_has_module_name(" << function << ")\n";
@ -411,6 +436,12 @@ interrogate_wrapper_parameter_is_this(FunctionWrapperIndex wrapper, int n) {
return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).parameter_is_this(n);
}
bool
interrogate_wrapper_parameter_is_optional(FunctionWrapperIndex wrapper, int n) {
// cerr << "interrogate_wrapper_is_optional(" << wrapper << ", " << n << ")\n";
return InterrogateDatabase::get_ptr()->get_wrapper(wrapper).parameter_is_optional(n);
}
bool
interrogate_wrapper_has_pointer(FunctionWrapperIndex wrapper) {
// cerr << "interrogate_wrapper_has_pointer(" << wrapper << ")\n";
@ -476,11 +507,22 @@ interrogate_make_seq_num_name(MakeSeqIndex make_seq) {
const char *
interrogate_make_seq_element_name(MakeSeqIndex make_seq) {
// cerr << "interrogate_make_seq_element_name(" << make_seq << ")\n";
static string result;
FunctionIndex function = InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_element_getter();
return interrogate_function_name(function);
}
FunctionIndex
interrogate_make_seq_num_getter(MakeSeqIndex make_seq) {
// cerr << "interrogate_make_seq_num_getter(" << make_seq << ")\n";
return InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_length_getter();
}
FunctionIndex
interrogate_make_seq_element_getter(MakeSeqIndex make_seq) {
// cerr << "interrogate_make_seq_element_getter(" << make_seq << ")\n";
return InterrogateDatabase::get_ptr()->get_make_seq(make_seq).get_element_getter();
}
int
interrogate_number_of_global_types() {
// cerr << "interrogate_number_of_global_types()\n";
@ -668,12 +710,30 @@ interrogate_type_wrapped_type(TypeIndex type) {
return InterrogateDatabase::get_ptr()->get_type(type).get_wrapped_type();
}
bool
interrogate_type_is_array(TypeIndex type) {
// cerr << "interrogate_type_is_array(" << type << ")\n";
return InterrogateDatabase::get_ptr()->get_type(type).is_array();
}
int
interrogate_type_array_size(TypeIndex type) {
// cerr << "interrogate_type_array_size(" << type << ")\n";
return InterrogateDatabase::get_ptr()->get_type(type).get_array_size();
}
bool
interrogate_type_is_enum(TypeIndex type) {
// cerr << "interrogate_type_is_enum(" << type << ")\n";
return InterrogateDatabase::get_ptr()->get_type(type).is_enum();
}
bool
interrogate_type_is_scoped_enum(TypeIndex type) {
// cerr << "interrogate_type_is_scoped_enum(" << type << ")\n";
return InterrogateDatabase::get_ptr()->get_type(type).is_scoped_enum();
}
int
interrogate_type_number_of_enum_values(TypeIndex type) {
// cerr << "interrogate_type_number_of_enum_values(" << type << ")\n";
@ -828,6 +888,12 @@ interrogate_type_get_derivation(TypeIndex type, int n) {
return InterrogateDatabase::get_ptr()->get_type(type).get_derivation(n);
}
bool
interrogate_type_is_final(TypeIndex type) {
// cerr << "interrogate_type_is_final(" << type << ")\n";
return InterrogateDatabase::get_ptr()->get_type(type).is_final();
}
bool
interrogate_type_derivation_has_upcast(TypeIndex type, int n) {
// cerr << "interrogate_type_derivation_has_upcast(" << type << ", " << n <<

View File

@ -210,6 +210,10 @@ EXPCL_INTERROGATEDB const char *interrogate_function_prototype(FunctionIndex fun
// if the function is a class method.
EXPCL_INTERROGATEDB bool interrogate_function_is_method(FunctionIndex function);
EXPCL_INTERROGATEDB TypeIndex interrogate_function_class(FunctionIndex function);
EXPCL_INTERROGATEDB bool interrogate_function_is_unary_op(FunctionIndex function);
EXPCL_INTERROGATEDB bool interrogate_function_is_operator_typecast(FunctionIndex function);
EXPCL_INTERROGATEDB bool interrogate_function_is_constructor(FunctionIndex function);
EXPCL_INTERROGATEDB bool interrogate_function_is_destructor(FunctionIndex function);
// This returns the module name reported for the function, if available.
EXPCL_INTERROGATEDB bool interrogate_function_has_module_name(FunctionIndex function);
@ -299,6 +303,7 @@ EXPCL_INTERROGATEDB TypeIndex interrogate_wrapper_parameter_type(FunctionWrapper
EXPCL_INTERROGATEDB bool interrogate_wrapper_parameter_has_name(FunctionWrapperIndex wrapper, int n);
EXPCL_INTERROGATEDB const char *interrogate_wrapper_parameter_name(FunctionWrapperIndex wrapper, int n);
EXPCL_INTERROGATEDB bool interrogate_wrapper_parameter_is_this(FunctionWrapperIndex wrapper, int n);
EXPCL_INTERROGATEDB bool interrogate_wrapper_parameter_is_optional(FunctionWrapperIndex wrapper, int n);
// This returns a pointer to a function that may be called to invoke the
// function, if the -fptrs option to return function pointers was specified to
@ -345,7 +350,8 @@ EXPCL_INTERROGATEDB const char *interrogate_make_seq_comment(ElementIndex elemen
EXPCL_INTERROGATEDB const char *interrogate_make_seq_num_name(MakeSeqIndex make_seq);
// The name of the real method that returns the nth element, e.g. "get_thing"
EXPCL_INTERROGATEDB const char *interrogate_make_seq_element_name(MakeSeqIndex make_seq);
EXPCL_INTERROGATEDB FunctionIndex interrogate_make_seq_num_getter(MakeSeqIndex make_seq);
EXPCL_INTERROGATEDB FunctionIndex interrogate_make_seq_element_getter(MakeSeqIndex make_seq);
// Types
@ -420,9 +426,14 @@ EXPCL_INTERROGATEDB bool interrogate_type_is_const(TypeIndex type);
EXPCL_INTERROGATEDB bool interrogate_type_is_typedef(TypeIndex type);
EXPCL_INTERROGATEDB TypeIndex interrogate_type_wrapped_type(TypeIndex type);
// If interrogate_type_is_array() returns true, this is an array type.
EXPCL_INTERROGATEDB bool interrogate_type_is_array(TypeIndex type);
EXPCL_INTERROGATEDB int interrogate_type_array_size(TypeIndex type);
// If interrogate_type_is_enum() returns true, this is an enumerated type,
// which means it may take any one of a number of named integer values.
EXPCL_INTERROGATEDB bool interrogate_type_is_enum(TypeIndex type);
EXPCL_INTERROGATEDB bool interrogate_type_is_scoped_enum(TypeIndex type);
EXPCL_INTERROGATEDB int interrogate_type_number_of_enum_values(TypeIndex type);
EXPCL_INTERROGATEDB const char *interrogate_type_enum_value_name(TypeIndex type, int n);
EXPCL_INTERROGATEDB const char *interrogate_type_enum_value_scoped_name(TypeIndex type, int n);
@ -499,6 +510,7 @@ EXPCL_INTERROGATEDB FunctionIndex interrogate_type_get_cast(TypeIndex type, int
// list of base classes for this particular type.
EXPCL_INTERROGATEDB int interrogate_type_number_of_derivations(TypeIndex type);
EXPCL_INTERROGATEDB TypeIndex interrogate_type_get_derivation(TypeIndex type, int n);
EXPCL_INTERROGATEDB bool interrogate_type_is_final(TypeIndex type);
// For each base class, we might need to define an explicit upcast or downcast
// operation to convert the pointer to the derived class to an appropriate

View File

@ -744,7 +744,7 @@ PyObject *copy_from_make_copy(PyObject *self, PyObject *noargs) {
if (callable == nullptr) {
return nullptr;
}
PyObject *result = _PyObject_CallNoArg(callable);
PyObject *result = PyObject_CallNoArgs(callable);
Py_DECREF(callable);
return result;
}
@ -768,7 +768,7 @@ PyObject *map_deepcopy_to_copy(PyObject *self, PyObject *args) {
if (callable == nullptr) {
return nullptr;
}
PyObject *result = _PyObject_CallNoArg(callable);
PyObject *result = PyObject_CallNoArgs(callable);
Py_DECREF(callable);
return result;
}

View File

@ -94,6 +94,12 @@ if(ANDROID)
target_link_libraries(p3prc log)
endif()
if(HAVE_OPENSSL AND CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang)$")
# Do not re-export symbols from these libraries.
target_link_options(p3prc PRIVATE "LINKER:--exclude-libs,libssl.a")
target_link_options(p3prc PRIVATE "LINKER:--exclude-libs,libcrypto.a")
endif()
install(TARGETS p3prc
EXPORT Core COMPONENT Core
DESTINATION ${CMAKE_INSTALL_LIBDIR}

View File

@ -17,6 +17,7 @@
#include "dtoolbase.h"
#include "numeric_types.h"
#include "atomicAdjust.h"
#include "memoryBase.h"
/**
* This class is the base class of both ConfigVariable and ConfigVariableCore.

View File

@ -21,6 +21,7 @@
#include "configVariableManager.h"
#include "vector_string.h"
#include "pset.h"
#include "memoryBase.h"
// Use this macro to wrap around a description passed to a ConfigVariable
// constructor. This allows the description to be completely compiled out, so
@ -42,7 +43,7 @@
* and/or ConfigDeclaration, more or less duplicating the interface presented
* there.
*/
class EXPCL_DTOOL_PRC ConfigVariableBase : public ConfigFlags {
class EXPCL_DTOOL_PRC ConfigVariableBase : public ConfigFlags, public MemoryBase {
protected:
INLINE ConfigVariableBase(const std::string &name, ValueType type);
ConfigVariableBase(const std::string &name, ValueType type,

View File

@ -18,6 +18,7 @@
#include "configFlags.h"
#include "configPageManager.h"
#include "pnotify.h"
#include "memoryBase.h"
#include <vector>
@ -31,7 +32,7 @@ class ConfigDeclaration;
* make() method, which may return a shared instance. Once created, these
* objects are never destructed.
*/
class EXPCL_DTOOL_PRC ConfigVariableCore : public ConfigFlags {
class EXPCL_DTOOL_PRC ConfigVariableCore : public ConfigFlags, public MemoryBase {
private:
ConfigVariableCore(const std::string &name);
ConfigVariableCore(const ConfigVariableCore &templ, const std::string &name);

View File

@ -18,13 +18,10 @@
#include "configVariableBool.h"
#include "filename.h"
#include "config_prc.h"
#include "patomic.h"
#include <ctype.h>
#ifdef PHAVE_ATOMIC
#include <atomic>
#endif
#ifdef BUILD_IPHONE
#include <fcntl.h>
#endif
@ -439,7 +436,7 @@ config_initialized() {
"The filename to which to write all the output of notify");
// We use this to ensure that only one thread can initialize the output.
static std::atomic_flag initialized = ATOMIC_FLAG_INIT;
static patomic_flag initialized = ATOMIC_FLAG_INIT;
std::string value = notify_output.get_value();
if (!value.empty() && !initialized.test_and_set()) {

View File

@ -49,7 +49,7 @@ set_severity(NotifySeverity severity) {
_severity = severity;
#else
// enforce the no-debug, no-spam rule.
_severity = std::max(severity, NS_info);
_severity = (std::max)(severity, NS_info);
#endif
invalidate_cache();
}

View File

@ -189,31 +189,65 @@ def MakeInstallerNSIS(version, file, title, installdir, compressor="lzma", **kwa
oscmd(cmd)
def MakeDebugSymbolArchive(zipname, dirname):
outputdir = GetOutputDir()
def MakeDebugSymbolZipArchive(zipname):
import zipfile
zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
outputdir = GetOutputDir()
zip = zipfile.ZipFile(zipname + '.zip', 'w', zipfile.ZIP_DEFLATED)
for fn in glob.glob(os.path.join(outputdir, 'bin', '*.pdb')):
zip.write(fn, dirname + '/bin/' + os.path.basename(fn))
zip.write(fn, 'bin/' + os.path.basename(fn))
for fn in glob.glob(os.path.join(outputdir, 'panda3d', '*.pdb')):
zip.write(fn, dirname + '/panda3d/' + os.path.basename(fn))
zip.write(fn, 'panda3d/' + os.path.basename(fn))
for fn in glob.glob(os.path.join(outputdir, 'plugins', '*.pdb')):
zip.write(fn, dirname + '/plugins/' + os.path.basename(fn))
zip.write(fn, 'plugins/' + os.path.basename(fn))
for fn in glob.glob(os.path.join(outputdir, 'python', '*.pdb')):
zip.write(fn, dirname + '/python/' + os.path.basename(fn))
zip.write(fn, 'python/' + os.path.basename(fn))
for fn in glob.glob(os.path.join(outputdir, 'python', 'DLLs', '*.pdb')):
zip.write(fn, dirname + '/python/DLLs/' + os.path.basename(fn))
zip.write(fn, 'python/DLLs/' + os.path.basename(fn))
zip.close()
def MakeDebugSymbolSevenZipArchive(zipname, compressor):
zipname += '.7z'
flags = ['-t7z', '-y']
if compressor == 'zlib':
# This will still build an LZMA2 archive by default,
# but will complete significantly faster.
flags.extend(['-mx=3'])
# Remove the old archive before proceeding.
if os.path.exists(zipname):
os.remove(zipname)
outputdir = GetOutputDir()
# We'll be creating the archive inside the output
# directory, so we need the relative path to the archive
zipname = os.path.relpath(zipname, outputdir)
# Create a 7-zip archive, including all *.pdb files
# that are not in the tmp folder
cmd = [GetSevenZip(), 'a']
cmd.extend(flags)
cmd.extend(['-ir!*.pdb', '-x!' + os.path.join('tmp', '*'), zipname])
subprocess.call(cmd, stdout=subprocess.DEVNULL, cwd=outputdir)
def MakeDebugSymbolArchive(zipname, compressor):
if HasSevenZip():
MakeDebugSymbolSevenZipArchive(zipname, compressor)
else:
MakeDebugSymbolZipArchive(zipname)
def MakeInstallerLinux(version, debversion=None, rpmversion=None, rpmrelease=1,
python_versions=[], **kwargs):
outputdir = GetOutputDir()
@ -969,6 +1003,7 @@ def MakeInstallerAndroid(version, **kwargs):
def MakeInstaller(version, **kwargs):
target = GetTarget()
if target == 'windows':
dir = kwargs.pop('installdir', None)
if dir is None:
@ -991,8 +1026,10 @@ def MakeInstaller(version, **kwargs):
if GetTargetArch() == 'x64':
fn += '-x64'
compressor = kwargs.get('compressor')
MakeInstallerNSIS(version, fn + '.exe', title, dir, **kwargs)
MakeDebugSymbolArchive(fn + '-pdb.zip', dir)
MakeDebugSymbolArchive(fn + '-pdb', compressor)
elif target == 'linux':
MakeInstallerLinux(version, **kwargs)
elif target == 'darwin':

View File

@ -93,7 +93,7 @@ PkgListSet(["PYTHON", "DIRECT", # Python support
"VRPN", "OPENSSL", # Transport
"FFTW", # Algorithm helpers
"ARTOOLKIT", "OPENCV", "DIRECTCAM", "VISION", # Augmented Reality
"GTK2", # GTK2 is used for PStats on Unix
"GTK3", # GTK3 is used for PStats on Unix
"MFC", "WX", "FLTK", # Used for web plug-in only
"COCOA", # macOS toolkits
"X11", # Unix platform support
@ -103,6 +103,7 @@ PkgListSet(["PYTHON", "DIRECT", # Python support
"PANDAPARTICLESYSTEM", # Built in particle system
"CONTRIB", # Experimental
"SSE2", "NEON", # Compiler features
"MIMALLOC", # Memory allocators
"NAMETAG", "MOVEMENT", "NAVIGATION", # libotp
"DNA", "SUIT", "PETS", # libtoontown
])
@ -638,13 +639,19 @@ if (COMPILER == "MSVC"):
if (PkgSkip("DIRECTCAM")==0): LibName("DIRECTCAM", "quartz.lib")
if (PkgSkip("DIRECTCAM")==0): LibName("DIRECTCAM", "odbc32.lib")
if (PkgSkip("DIRECTCAM")==0): LibName("DIRECTCAM", "odbccp32.lib")
if (PkgSkip("MIMALLOC")==0): LibName("MIMALLOC", GetThirdpartyDir() + "mimalloc/lib/mimalloc-static.lib")
if (PkgSkip("OPENSSL")==0):
if os.path.isfile(GetThirdpartyDir() + "openssl/lib/libpandassl.lib"):
LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libpandassl.lib")
LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libpandaeay.lib")
else:
elif os.path.isfile(GetThirdpartyDir() + "openssl/lib/ssleay32.lib"):
LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libeay32.lib")
LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/ssleay32.lib")
else:
LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libssl.lib")
LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libcrypto.lib")
LibName("OPENSSL", "crypt32.lib")
LibName("OPENSSL", "ws2_32.lib")
if (PkgSkip("PNG")==0):
if os.path.isfile(GetThirdpartyDir() + "png/lib/libpng16_static.lib"):
LibName("PNG", GetThirdpartyDir() + "png/lib/libpng16_static.lib")
@ -656,23 +663,39 @@ if (COMPILER == "MSVC"):
else:
LibName("TIFF", GetThirdpartyDir() + "tiff/lib/tiff.lib")
if (PkgSkip("OPENEXR")==0):
suffix = ""
if os.path.isfile(GetThirdpartyDir() + "openexr/lib/IlmImf-2_2.lib"):
suffix = "-2_2"
elif os.path.isfile(GetThirdpartyDir() + "openexr/lib/IlmImf-2_3.lib"):
suffix = "-2_3"
elif os.path.isfile(GetThirdpartyDir() + "openexr/lib/IlmImf-2_4.lib"):
suffix = "-2_4"
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Imath" + suffix + ".lib")
if os.path.isfile(GetThirdpartyDir() + "openexr/lib/IlmImf" + suffix + "_s.lib"):
suffix += "_s" # _s suffix observed for OpenEXR 2.3 only so far
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/IlmImf" + suffix + ".lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/IlmThread" + suffix + ".lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Iex" + suffix + ".lib")
if suffix == "-2_2":
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Half.lib")
if os.path.isfile(GetThirdpartyDir() + "openexr/lib/OpenEXRCore-3_1.lib"):
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/OpenEXR-3_1.lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/IlmThread-3_1.lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Imath-3_1.lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Iex-3_1.lib")
elif os.path.isfile(GetThirdpartyDir() + "openexr/lib/OpenEXR-3_0.lib"):
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/OpenEXR-3_0.lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/IlmThread-3_0.lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Imath-3_0.lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Iex-3_0.lib")
elif os.path.isfile(GetThirdpartyDir() + "openexr/lib/OpenEXR.lib"):
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/OpenEXR.lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/IlmThread.lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Imath.lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Iex.lib")
else:
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Half" + suffix + ".lib")
suffix = ""
if os.path.isfile(GetThirdpartyDir() + "openexr/lib/IlmImf-2_2.lib"):
suffix = "-2_2"
elif os.path.isfile(GetThirdpartyDir() + "openexr/lib/IlmImf-2_3.lib"):
suffix = "-2_3"
elif os.path.isfile(GetThirdpartyDir() + "openexr/lib/IlmImf-2_4.lib"):
suffix = "-2_4"
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Imath" + suffix + ".lib")
if os.path.isfile(GetThirdpartyDir() + "openexr/lib/IlmImf" + suffix + "_s.lib"):
suffix += "_s" # _s suffix observed for OpenEXR 2.3 only so far
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/IlmImf" + suffix + ".lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/IlmThread" + suffix + ".lib")
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Iex" + suffix + ".lib")
if suffix == "-2_2":
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Half.lib")
else:
LibName("OPENEXR", GetThirdpartyDir() + "openexr/lib/Half" + suffix + ".lib")
IncDirectory("OPENEXR", GetThirdpartyDir() + "openexr/include/OpenEXR")
IncDirectory("OPENEXR", GetThirdpartyDir() + "openexr/include/Imath")
if (PkgSkip("JPEG")==0): LibName("JPEG", GetThirdpartyDir() + "jpeg/lib/jpeg-static.lib")
@ -849,13 +872,13 @@ if (COMPILER=="GCC"):
SmartPkgEnable("OPENAL", "openal", ("openal"), "AL/al.h", framework = "OpenAL")
SmartPkgEnable("SQUISH", "", ("squish"), "squish.h")
SmartPkgEnable("TIFF", "libtiff-4", ("tiff"), "tiff.h")
SmartPkgEnable("OPENEXR", "OpenEXR", ("IlmImf", "Imath", "Half", "Iex", "IexMath", "IlmThread"), ("OpenEXR", "Imath", "OpenEXR/ImfOutputFile.h"))
SmartPkgEnable("VRPN", "", ("vrpn", "quat"), ("vrpn", "quat.h", "vrpn/vrpn_Types.h"))
SmartPkgEnable("BULLET", "bullet", ("BulletSoftBody", "BulletDynamics", "BulletCollision", "LinearMath"), ("bullet", "bullet/btBulletDynamicsCommon.h"))
SmartPkgEnable("VORBIS", "vorbisfile",("vorbisfile", "vorbis", "ogg"), ("ogg/ogg.h", "vorbis/vorbisfile.h"))
SmartPkgEnable("OPUS", "opusfile", ("opusfile", "opus", "ogg"), ("ogg/ogg.h", "opus/opusfile.h", "opus"))
SmartPkgEnable("JPEG", "", ("jpeg"), "jpeglib.h")
SmartPkgEnable("PNG", "libpng", ("png"), "png.h", tool = "libpng-config")
SmartPkgEnable("MIMALLOC", "", ("mimalloc"), "mimalloc.h")
# Copy freetype libraries to be specified after harfbuzz libraries as well,
# because there's a circular dependency between the two libraries.
@ -874,6 +897,23 @@ if (COMPILER=="GCC"):
for ffmpeg_lib in ffmpeg_libs:
LibName("FFMPEG", "-Wl,--exclude-libs,%s.a" % (ffmpeg_lib))
if not PkgSkip("OPENEXR"):
# OpenEXR libraries have different names depending on the version.
openexr_libdir = os.path.join(GetThirdpartyDir(), "openexr", "lib")
openexr_incs = ("OpenEXR", "Imath", "OpenEXR/ImfOutputFile.h")
if os.path.isfile(os.path.join(openexr_libdir, "libOpenEXR-3_1.a")):
SmartPkgEnable("OPENEXR", "", ("OpenEXR-3_1", "IlmThread-3_1", "Imath-3_1", "Iex-3_1"), openexr_incs)
if os.path.isfile(os.path.join(openexr_libdir, "libOpenEXR-3_0.a")):
SmartPkgEnable("OPENEXR", "", ("OpenEXR-3_0", "IlmThread-3_0", "Imath-3_0", "Iex-3_0"), openexr_incs)
elif os.path.isfile(os.path.join(openexr_libdir, "libOpenEXR.a")):
SmartPkgEnable("OPENEXR", "", ("OpenEXR", "IlmThread", "Imath", "Iex"), openexr_incs)
elif os.path.isfile(os.path.join(openexr_libdir, "libIlmImf.a")):
SmartPkgEnable("OPENEXR", "", ("IlmImf", "Imath", "Half", "Iex", "IexMath", "IlmThread"), openexr_incs)
else:
# Find it in the system, preferably using pkg-config, otherwise
# using the OpenEXR 3 naming scheme.
SmartPkgEnable("OPENEXR", "OpenEXR", ("OpenEXR", "IlmThread", "Imath", "Iex"), openexr_incs)
if GetTarget() != "darwin":
for fcollada_lib in fcollada_libs:
LibName("FCOLLADA", "-Wl,--exclude-libs,lib%s.a" % (fcollada_lib))
@ -905,6 +945,9 @@ if (COMPILER=="GCC"):
LibName("OPENEXR", "-Wl,--exclude-libs,libIlmImfUtil.a")
LibName("OPENEXR", "-Wl,--exclude-libs,libIlmThread.a")
LibName("OPENEXR", "-Wl,--exclude-libs,libImath.a")
LibName("OPENEXR", "-Wl,--exclude-libs,libOpenEXR.a")
LibName("OPENEXR", "-Wl,--exclude-libs,libOpenEXRCore.a")
LibName("OPENEXR", "-Wl,--exclude-libs,libOpenEXRUtil.a")
if not PkgSkip("VORBIS"):
LibName("VORBIS", "-Wl,--exclude-libs,libogg.a")
@ -925,6 +968,9 @@ if (COMPILER=="GCC"):
LibName("ARTOOLKIT", "-Wl,--exclude-libs,libAR.a")
LibName("ARTOOLKIT", "-Wl,--exclude-libs,libARMulti.a")
if not PkgSkip("MIMALLOC"):
LibName("MIMALLOC", "-Wl,--exclude-libs,libmimalloc.a")
if PkgSkip("FFMPEG") or GetTarget() == "darwin":
cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV")
if cv_lib == "opencv_core":
@ -965,7 +1011,7 @@ if (COMPILER=="GCC"):
SmartPkgEnable("OPENSSL", "openssl", ("ssl", "crypto"), ("openssl/ssl.h", "openssl/crypto.h"))
SmartPkgEnable("ZLIB", "zlib", ("z"), "zlib.h")
SmartPkgEnable("GTK2", "gtk+-2.0")
SmartPkgEnable("GTK3", "gtk+-3.0")
if not PkgSkip("OPENSSL") and GetTarget() != "darwin":
LibName("OPENSSL", "-Wl,--exclude-libs,libssl.a")
@ -983,11 +1029,6 @@ if (COMPILER=="GCC"):
if GetHost() != "darwin":
# Workaround for an issue where pkg-config does not include this path
if GetTargetArch() in ("x86_64", "amd64"):
if (os.path.isdir("/usr/lib64/glib-2.0/include")):
IncDirectory("GTK2", "/usr/lib64/glib-2.0/include")
if (os.path.isdir("/usr/lib64/gtk-2.0/include")):
IncDirectory("GTK2", "/usr/lib64/gtk-2.0/include")
if not PkgSkip("X11"):
if (os.path.isdir("/usr/X11R6/lib64")):
LibDirectory("ALWAYS", "/usr/X11R6/lib64")
@ -1033,8 +1074,6 @@ if (COMPILER=="GCC"):
LibName("FFMPEG", "-undefined dynamic_lookup")
if not PkgSkip("ASSIMP"):
LibName("ASSIMP", "-undefined dynamic_lookup")
if not PkgSkip("OPENEXR"):
LibName("OPENEXR", "-undefined dynamic_lookup")
if not PkgSkip("VRPN"):
LibName("VRPN", "-undefined dynamic_lookup")
@ -1175,7 +1214,7 @@ def CompileCxx(obj,src,opts):
cmd = "cl "
if GetTargetArch() == 'x64':
cmd += "/favor:blend "
cmd += "/wd4996 /wd4275 /wd4273 "
cmd += "/wd4996 "
# Set the minimum version to Windows Vista.
cmd += "/DWINVER=0x600 "
@ -1207,7 +1246,7 @@ def CompileCxx(obj,src,opts):
if (building):
cmd += " /DBUILDING_" + building
if ("BIGOBJ" in opts) or GetTargetArch() == 'x64':
if ("BIGOBJ" in opts) or GetTargetArch() == 'x64' or not PkgSkip("EIGEN"):
cmd += " /bigobj"
cmd += " /Zm300"
@ -1225,7 +1264,7 @@ def CompileCxx(obj,src,opts):
cmd = "icl "
if GetTargetArch() == 'x64':
cmd += "/favor:blend "
cmd += "/wd4996 /wd4275 /wd4267 /wd4101 /wd4273 "
cmd += "/wd4996 /wd4267 /wd4101 "
cmd += "/DWINVER=0x600 "
cmd += "/Fo" + obj + " /c"
for x in ipath: cmd += " /I" + x
@ -1336,6 +1375,10 @@ def CompileCxx(obj,src,opts):
if 'NOARCH:' + arch.upper() not in opts:
cmd += " -arch %s" % arch
elif 'clang' not in GetCXX().split('/')[-1]:
# Enable interprocedural optimizations in GCC.
cmd += " -fno-semantic-interposition"
if "SYSROOT" in SDK:
if GetTarget() != "android":
cmd += ' --sysroot=%s' % (SDK["SYSROOT"])
@ -1422,10 +1465,7 @@ def CompileCxx(obj,src,opts):
if (optlevel==4): cmd += " -O3 -DNDEBUG"
# Enable more warnings.
cmd += " -Wall -Wno-unused-function"
if not src.endswith(".c"):
cmd += " -Wno-reorder"
cmd += " -Wall -Wno-unused-function -Werror=return-type"
# Ignore unused variables in NDEBUG builds, often used in asserts.
if optlevel == 4:
@ -2298,6 +2338,7 @@ DTOOL_CONFIG=[
("REPORT_OPENSSL_ERRORS", '1', '1'),
("USE_PANDAFILESTREAM", '1', '1'),
("USE_DELETED_CHAIN", '1', '1'),
("HAVE_MIMALLOC", 'UNDEF', 'UNDEF'),
("HAVE_WGL", '1', 'UNDEF'),
("HAVE_DX9", 'UNDEF', 'UNDEF'),
("HAVE_THREADS", '1', '1'),
@ -2443,6 +2484,20 @@ def WriteConfigSettings():
dtool_config["HAVE_NET"] = '1'
if GetTarget() == 'windows':
if not PkgSkip("MIMALLOC"):
# This is faster than both DeletedBufferChain and malloc,
# especially in the multi-threaded case.
dtool_config["USE_MEMORY_MIMALLOC"] = '1'
dtool_config["USE_DELETED_CHAIN"] = 'UNDEF'
else:
# If we don't have mimalloc, use DeletedBufferChain as fallback,
# which is still more efficient than malloc.
dtool_config["USE_DELETED_CHAIN"] = '1'
else:
# On other systems, the default malloc seems to be fine.
dtool_config["USE_DELETED_CHAIN"] = 'UNDEF'
if (PkgSkip("NVIDIACG")==0):
dtool_config["HAVE_CG"] = '1'
dtool_config["HAVE_CGGL"] = '1'
@ -3374,7 +3429,7 @@ if GetTarget() == 'windows':
# DIRECTORY: dtool/src/dtoolbase/
#
OPTS=['DIR:dtool/src/dtoolbase', 'BUILDING:DTOOL']
OPTS=['DIR:dtool/src/dtoolbase', 'BUILDING:DTOOL', 'MIMALLOC']
TargetAdd('p3dtoolbase_composite1.obj', opts=OPTS, input='p3dtoolbase_composite1.cxx')
TargetAdd('p3dtoolbase_composite2.obj', opts=OPTS, input='p3dtoolbase_composite2.cxx')
TargetAdd('p3dtoolbase_lookup3.obj', opts=OPTS, input='lookup3.c')
@ -3405,7 +3460,7 @@ TargetAdd('libp3dtool.dll', input='p3dtoolbase_composite1.obj')
TargetAdd('libp3dtool.dll', input='p3dtoolbase_composite2.obj')
TargetAdd('libp3dtool.dll', input='p3dtoolbase_indent.obj')
TargetAdd('libp3dtool.dll', input='p3dtoolbase_lookup3.obj')
TargetAdd('libp3dtool.dll', opts=['ADVAPI','WINSHELL','WINKERNEL'])
TargetAdd('libp3dtool.dll', opts=['ADVAPI','WINSHELL','WINKERNEL','MIMALLOC'])
#
# DIRECTORY: dtool/src/cppparser/
@ -4997,8 +5052,10 @@ if GetTarget() == 'android' and not PkgSkip("EGL") and not PkgSkip("GLES2"):
# DIRECTORY: panda/src/tinydisplay/
#
if (GetTarget() in ('windows', 'darwin') or not PkgSkip("X11")) and not PkgSkip("TINYDISPLAY"):
if not PkgSkip("TINYDISPLAY"):
OPTS=['DIR:panda/src/tinydisplay', 'BUILDING:TINYDISPLAY', 'X11']
if not PkgSkip("X11"):
OPTS += ['X11']
TargetAdd('p3tinydisplay_composite1.obj', opts=OPTS, input='p3tinydisplay_composite1.cxx')
TargetAdd('p3tinydisplay_composite2.obj', opts=OPTS, input='p3tinydisplay_composite2.cxx')
TargetAdd('p3tinydisplay_ztriangle_1.obj', opts=OPTS, input='ztriangle_1.cxx')
@ -5009,7 +5066,7 @@ if (GetTarget() in ('windows', 'darwin') or not PkgSkip("X11")) and not PkgSkip(
if GetTarget() == 'windows':
TargetAdd('libp3tinydisplay.dll', input='libp3windisplay.dll')
TargetAdd('libp3tinydisplay.dll', opts=['WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM'])
elif GetTarget() != 'darwin':
elif GetTarget() != 'darwin' and not PkgSkip("X11"):
TargetAdd('libp3tinydisplay.dll', input='p3x11display_composite1.obj')
TargetAdd('libp3tinydisplay.dll', opts=['X11'])
TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_composite1.obj')
@ -6032,19 +6089,19 @@ if not PkgSkip("PANDATOOL"):
# DIRECTORY: pandatool/src/gtk-stats/
#
if not PkgSkip("PANDATOOL") and (GetTarget() == 'windows' or not PkgSkip("GTK2")):
if not PkgSkip("PANDATOOL") and (GetTarget() == 'windows' or not PkgSkip("GTK3")):
if GetTarget() == 'windows':
OPTS=['DIR:pandatool/src/win-stats']
TargetAdd('pstats_composite1.obj', opts=OPTS, input='winstats_composite1.cxx')
else:
OPTS=['DIR:pandatool/src/gtk-stats', 'GTK2']
OPTS=['DIR:pandatool/src/gtk-stats', 'GTK3']
TargetAdd('pstats_composite1.obj', opts=OPTS, input='gtkstats_composite1.cxx')
TargetAdd('pstats.exe', input='pstats_composite1.obj')
TargetAdd('pstats.exe', input='libp3pstatserver.lib')
TargetAdd('pstats.exe', input='libp3progbase.lib')
TargetAdd('pstats.exe', input='libp3pandatoolbase.lib')
TargetAdd('pstats.exe', input=COMMON_PANDA_LIBS)
TargetAdd('pstats.exe', opts=['SUBSYSTEM:WINDOWS', 'WINSOCK', 'WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM', 'GTK2'])
TargetAdd('pstats.exe', opts=['SUBSYSTEM:WINDOWS', 'WINCOMCTL', 'WINSOCK', 'WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM', 'GTK3'])
#
# DIRECTORY: pandatool/src/xfileprogs/
@ -6192,17 +6249,21 @@ for VER in MAYAVERSIONS:
TargetAdd('egg2maya'+VNUM+'.exe', opts=['ADVAPI']+ARCH_OPTS)
if MAYA_BUILT:
OPTS=['DIR:pandatool/src/mayaprogs', 'DIR:pandatool/src/maya', 'DIR:pandatool/src/mayaegg', 'BUILDING:MISC', 'NOARCH:ARM64']
TargetAdd('mayaprogs_mayaConversionClient.obj', opts=OPTS, input='mayaConversionClient.cxx')
TargetAdd('maya2egg_mayaToEggClient.obj', opts=OPTS, input='mayaToEggClient.cxx')
TargetAdd('maya2egg_client.exe', input='mayaprogs_mayaConversionClient.obj')
TargetAdd('maya2egg_client.exe', input='maya2egg_mayaToEggClient.obj')
TargetAdd('maya2egg_client.exe', input=COMMON_EGG2X_LIBS)
TargetAdd('maya2egg_client.exe', opts=['NOARCH:ARM64'])
TargetAdd('egg2maya_eggToMayaClient.obj', opts=OPTS, input='eggToMayaClient.cxx')
TargetAdd('egg2maya_client.exe', input='mayaprogs_mayaConversionClient.obj')
TargetAdd('egg2maya_client.exe', input='egg2maya_eggToMayaClient.obj')
TargetAdd('egg2maya_client.exe', input=COMMON_EGG2X_LIBS)
TargetAdd('egg2maya_client.exe', opts=['NOARCH:ARM64'])
#
# DIRECTORY: contrib/src/ai/
@ -6260,7 +6321,7 @@ if PkgSkip("PYTHON") == 0:
if GetTarget() == 'linux' or GetTarget() == 'freebsd':
# Setup rpath so libs can be found in the same directory as the deployed game
LibName('DEPLOYSTUB', "-Wl,-rpath,\\$ORIGIN")
LibName('DEPLOYSTUB', "-Wl,--disable-new-dtags,-rpath,\\$ORIGIN")
LibName('DEPLOYSTUB', "-Wl,-z,origin")
LibName('DEPLOYSTUB', "-rdynamic")
@ -6280,6 +6341,9 @@ if PkgSkip("PYTHON") == 0:
PyTargetAdd('deploy-stubw.exe', input='deploy-stubw.obj')
PyTargetAdd('deploy-stubw.exe', opts=['MACOS_APP_BUNDLE', 'DEPLOYSTUB', 'NOICON'])
elif GetTarget() == 'android':
TargetAdd('org/jnius/NativeInvocationHandler.class', opts=OPTS, input='NativeInvocationHandler.java')
TargetAdd('classes.dex', input='org/jnius/NativeInvocationHandler.class')
PyTargetAdd('deploy-stubw_android_main.obj', opts=OPTS, input='android_main.cxx')
PyTargetAdd('deploy-stubw_android_log.obj', opts=OPTS, input='android_log.c')
PyTargetAdd('libdeploy-stubw.dll', input='android_native_app_glue.obj')
@ -6408,6 +6472,8 @@ def ParallelMake(tasklist):
tasklist = extras
sys.stdout.flush()
if tasksqueued == 0:
if len(tasklist) > 0:
continue
break
donetask = donequeue.get()
if donetask == 0:

View File

@ -572,6 +572,26 @@ def GetFlexVersion():
Warn("Unable to detect flex version")
return (0, 0, 0)
SEVENZIP = None
def GetSevenZip():
global SEVENZIP
if SEVENZIP is not None:
return SEVENZIP
win_util = os.path.join(GetThirdpartyBase(), 'win-util')
if GetHost() == 'windows' and os.path.isdir(win_util):
SEVENZIP = GetThirdpartyBase() + "/win-util/7za.exe"
elif LocateBinary('7z'):
SEVENZIP = '7z'
else:
# We don't strictly need it, so don't give an error
return None
return SEVENZIP
def HasSevenZip():
return GetSevenZip() is not None
########################################################################
##
## LocateBinary
@ -635,6 +655,9 @@ def oscmd(cmd, ignoreError = False, cwd=None):
res = os.spawnl(os.P_WAIT, exe_path, cmd)
if res == -1073741510: # 0xc000013a
exit("keyboard interrupt")
if cwd is not None:
os.chdir(pwd)
else:
@ -717,7 +740,7 @@ def GetTimestamp(path):
if path in TIMESTAMPCACHE:
return TIMESTAMPCACHE[path]
try:
date = os.path.getmtime(path)
date = int(os.path.getmtime(path))
except:
date = 0
TIMESTAMPCACHE[path] = date
@ -854,8 +877,11 @@ def JavaGetImports(path):
imports = []
try:
for match in JavaImportRegex.finditer(source, 0):
impname = match.group(1)
imports.append(impname.strip())
impname = match.group(1).strip()
if not impname.startswith('java.') and \
not impname.startswith('dalvik.') and \
not impname.startswith('android.'):
imports.append(impname.strip())
except:
print("Failed to determine dependencies of \"" + path +"\".")
raise
@ -871,7 +897,7 @@ def JavaGetImports(path):
##
########################################################################
DCACHE_VERSION = 2
DCACHE_VERSION = 3
DCACHE_BACKED_UP = False
def SaveDependencyCache():
@ -3347,7 +3373,12 @@ def SetOrigExt(x, v):
ORIG_EXT[x] = v
def GetExtensionSuffix():
if CrossCompiling():
if GetTarget() == 'windows':
if GetTargetArch() == 'x64':
return '.cp%d%d-win_amd64.pyd' % (sys.version_info[:2])
else:
return '.cp%d%d-win32.pyd' % (sys.version_info[:2])
elif CrossCompiling():
return '.{0}.so'.format(GetPythonABI())
else:
import _imp

View File

@ -800,6 +800,21 @@ if __debug__:
whl.write_file(target_path, source_path)
# Include the special sysconfigdata module.
if os.name == 'posix':
import sysconfig
if hasattr(sysconfig, '_get_sysconfigdata_name'):
modname = sysconfig._get_sysconfigdata_name() + '.py'
else:
modname = '_sysconfigdata.py'
for entry in sys.path:
source_path = os.path.join(entry, modname)
if os.path.isfile(source_path):
whl.write_file('deploy_libs/' + modname, source_path)
break
# Add plug-ins.
for lib in PLUGIN_LIBS:
plugin_name = 'lib' + lib

View File

@ -16,8 +16,14 @@ package org.panda3d.android;
import org.panda3d.android.PandaActivity;
/**
* This is only declared as a separate class from PandaActivity so that we
* can have two separate activity definitions in ApplicationManifest.xml.
* Extends PandaActivity with some things that are useful in a Python
* application.
*/
public class PythonActivity extends PandaActivity {
// This is required by plyer.
public static PythonActivity mActivity;
public PythonActivity() {
mActivity = this;
}
}

View File

@ -59,7 +59,7 @@ get_positional() const {
*/
INLINE bool AudioLoadRequest::
is_ready() const {
return (FutureState)AtomicAdjust::get(_future_state) == FS_finished;
return (FutureState)_future_state.load(std::memory_order_relaxed) == FS_finished;
}
/**
@ -70,6 +70,5 @@ is_ready() const {
*/
INLINE AudioSound *AudioLoadRequest::
get_sound() const {
nassertr_always(done(), nullptr);
return (AudioSound *)_result;
return (AudioSound *)get_result();
}

View File

@ -60,6 +60,11 @@ if(HAVE_OPENAL)
set_target_properties(p3openal_audio PROPERTIES DEFINE_SYMBOL BUILDING_OPENAL_AUDIO)
target_link_libraries(p3openal_audio panda PKG::OPENAL)
if(CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang)$")
# When statically linking OpenAL, keep its symbols private to this module.
target_link_options(p3openal_audio PRIVATE "LINKER:--exclude-libs,libopenal.a")
endif()
install(TARGETS p3openal_audio
EXPORT OpenAL COMPONENT OpenAL
DESTINATION ${CMAKE_INSTALL_LIBDIR}

View File

@ -20,13 +20,14 @@
#include "bullet_utils.h"
#include "luse.h"
#include "memoryBase.h"
#include "pandaNode.h"
#include "collideMask.h"
/**
*
*/
struct EXPCL_PANDABULLET BulletRayHit {
struct EXPCL_PANDABULLET BulletRayHit : public MemoryBase {
PUBLISHED:
INLINE static BulletRayHit empty();
@ -61,7 +62,7 @@ private:
/**
*
*/
struct EXPCL_PANDABULLET BulletAllHitsRayResult : public btCollisionWorld::AllHitsRayResultCallback {
struct EXPCL_PANDABULLET BulletAllHitsRayResult : public btCollisionWorld::AllHitsRayResultCallback, public MemoryBase {
PUBLISHED:
INLINE static BulletAllHitsRayResult empty();

View File

@ -20,13 +20,14 @@
#include "bullet_utils.h"
#include "luse.h"
#include "memoryBase.h"
#include "pandaNode.h"
#include "collideMask.h"
/**
*
*/
struct EXPCL_PANDABULLET BulletClosestHitRayResult : public btCollisionWorld::ClosestRayResultCallback {
struct EXPCL_PANDABULLET BulletClosestHitRayResult : public btCollisionWorld::ClosestRayResultCallback, public MemoryBase {
PUBLISHED:
INLINE static BulletClosestHitRayResult empty();

View File

@ -20,13 +20,14 @@
#include "bullet_utils.h"
#include "luse.h"
#include "memoryBase.h"
#include "pandaNode.h"
#include "collideMask.h"
/**
*
*/
struct EXPCL_PANDABULLET BulletClosestHitSweepResult : public btCollisionWorld::ClosestConvexResultCallback {
struct EXPCL_PANDABULLET BulletClosestHitSweepResult : public btCollisionWorld::ClosestConvexResultCallback, public MemoryBase {
PUBLISHED:
INLINE static BulletClosestHitSweepResult empty();

View File

@ -194,7 +194,7 @@ make_from_bam(const FactoryParams &params) {
void BulletConvexHullShape::
fillin(DatagramIterator &scan, BamReader *manager) {
BulletShape::fillin(scan, manager);
nassertv(_shape == nullptr);
nassertv(_shape);
_shape->setMargin(scan.get_stdfloat());
unsigned int num_points = scan.get_uint32();

Some files were not shown because too many files have changed in this diff Show More