Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
c0887f457a
|
|
@ -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: |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
53
README.md
53
README.md
|
|
@ -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
|
||||
=============
|
||||
|
|
|
|||
|
|
@ -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>")
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ------------
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ CPPStructType(const CPPStructType ©) :
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(CPPPARSER)
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "mutexWin32Impl.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include "patomic.cxx"
|
||||
#include "mutexPosixImpl.cxx"
|
||||
#include "mutexWin32Impl.cxx"
|
||||
#include "mutexSpinlockImpl.cxx"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 ¶ms =
|
||||
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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public:
|
|||
INLINE bool parameter_has_name(int n) const;
|
||||
INLINE const std::string ¶meter_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;
|
||||
|
|
|
|||
|
|
@ -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 <<
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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':
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ make_from_bam(const FactoryParams ¶ms) {
|
|||
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
Loading…
Reference in New Issue