Browse Source

Merge branch 'master' into webgl-port

rdb 3 years ago
parent
commit
185e439ff6
100 changed files with 1475 additions and 1153 deletions
  1. 4 4
      .github/workflows/ci.yml
  2. 5 29
      CMakeLists.txt
  3. 19 22
      README.md
  4. 12 77
      cmake/macros/BuildMetalib.cmake
  5. 2 15
      cmake/macros/PackageConfig.cmake
  6. 53 33
      cmake/modules/FindLibSquish.cmake
  7. 0 88
      cmake/modules/FindOpenEXR.cmake
  8. 5 5
      contrib/src/rplight/shadowSource.h
  9. 89 66
      direct/src/dist/FreezeTool.py
  10. 5 0
      direct/src/dist/_android.py
  11. 27 18
      direct/src/dist/commands.py
  12. 13 0
      direct/src/distributed/PyDatagramIterator.py
  13. 4 5
      direct/src/distributed/cConnectionRepository.cxx
  14. 15 5
      direct/src/filter/CommonFilters.py
  15. 2 1
      direct/src/filter/filterBloomI.py
  16. 3 2
      direct/src/filter/filterBloomX.py
  17. 2 1
      direct/src/filter/filterBloomY.py
  18. 4 4
      direct/src/filter/filterBlurX.py
  19. 4 4
      direct/src/filter/filterBlurY.py
  20. 3 2
      direct/src/filter/filterCopy.py
  21. 3 2
      direct/src/filter/filterDown4.py
  22. 0 6
      direct/src/gui/DirectGuiBase.py
  23. 2 1
      direct/src/motiontrail/cMotionTrail.h
  24. 4 4
      direct/src/showbase/BufferViewer.py
  25. 5 1
      direct/src/showbase/ShowBase.py
  26. 7 7
      direct/src/stdpy/threading.py
  27. 9 5
      direct/src/task/Task.py
  28. 12 32
      dtool/CompilerFlags.cmake
  29. 33 17
      dtool/Package.cmake
  30. 0 4
      dtool/PandaVersion.cmake
  31. 139 139
      dtool/metalibs/dtoolconfig/pydtool.cxx
  32. 2 2
      dtool/src/cppparser/cppManifest.cxx
  33. 1 1
      dtool/src/cppparser/cppManifest.h
  34. 2 2
      dtool/src/cppparser/cppNamespace.cxx
  35. 2 2
      dtool/src/cppparser/cppStructType.cxx
  36. 7 0
      dtool/src/dtoolbase/CMakeLists.txt
  37. 1 0
      dtool/src/dtoolbase/p3dtoolbase_composite2.cxx
  38. 211 6
      dtool/src/dtoolbase/patomic.I
  39. 168 0
      dtool/src/dtoolbase/patomic.cxx
  40. 85 18
      dtool/src/dtoolbase/patomic.h
  41. 0 1
      dtool/src/dtoolbase/typeHandle_ext.cxx
  42. 39 6
      dtool/src/dtoolutil/executionEnvironment.cxx
  43. 15 1
      dtool/src/dtoolutil/filename.cxx
  44. 2 0
      dtool/src/dtoolutil/pandaSystem.cxx
  45. 10 2
      dtool/src/dtoolutil/panda_getopt_impl.cxx
  46. 3 4
      dtool/src/dtoolutil/pfstreamBuf.cxx
  47. 4 4
      dtool/src/interrogate/interfaceMaker.cxx
  48. 2 2
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  49. 2 2
      dtool/src/interrogate/interfaceMakerPythonObj.cxx
  50. 2 2
      dtool/src/interrogate/interfaceMakerPythonSimple.cxx
  51. 7 0
      dtool/src/interrogate/interrogate.cxx
  52. 6 0
      dtool/src/prc/CMakeLists.txt
  53. 1 0
      dtool/src/prc/configFlags.h
  54. 2 1
      dtool/src/prc/configVariableBase.h
  55. 2 1
      dtool/src/prc/configVariableCore.h
  56. 47 10
      makepanda/makepackage.py
  57. 37 10
      makepanda/makepanda.py
  58. 33 5
      makepanda/makepandacore.py
  59. 8 2
      panda/src/android/PythonActivity.java
  60. 2 3
      panda/src/audio/audioLoadRequest.I
  61. 5 0
      panda/src/audiotraits/CMakeLists.txt
  62. 3 2
      panda/src/bullet/bulletAllHitsRayResult.h
  63. 2 1
      panda/src/bullet/bulletClosestHitRayResult.h
  64. 2 1
      panda/src/bullet/bulletClosestHitSweepResult.h
  65. 2 2
      panda/src/bullet/bulletConvexPointCloudShape.I
  66. 2 2
      panda/src/bullet/bulletTriangleMeshShape.cxx
  67. 2 2
      panda/src/chan/animControl.cxx
  68. 7 7
      panda/src/char/character.cxx
  69. 4 36
      panda/src/collide/collisionBox.I
  70. 54 81
      panda/src/collide/collisionBox.cxx
  71. 7 10
      panda/src/collide/collisionBox.h
  72. 0 9
      panda/src/collide/collisionHandlerEvent.I
  73. 0 1
      panda/src/collide/collisionHandlerEvent.h
  74. 0 1
      panda/src/collide/collisionHandlerPhysical_ext.cxx
  75. 7 7
      panda/src/collide/collisionLevelStateBase.I
  76. 3 3
      panda/src/collide/collisionTraverser.cxx
  77. 0 1
      panda/src/collide/collisionTraverser_ext.cxx
  78. 4 4
      panda/src/device/evdevInputDevice.cxx
  79. 1 1
      panda/src/device/inputDeviceManager.h
  80. 1 1
      panda/src/device/trackerData.h
  81. 1 1
      panda/src/device/xInputDevice.cxx
  82. 4 4
      panda/src/display/displayRegion.cxx
  83. 86 70
      panda/src/display/graphicsEngine.cxx
  84. 1 5
      panda/src/display/graphicsEngine.h
  85. 2 2
      panda/src/display/graphicsOutput.cxx
  86. 39 173
      panda/src/display/graphicsStateGuardian.cxx
  87. 6 15
      panda/src/display/graphicsStateGuardian.h
  88. 21 0
      panda/src/display/graphicsWindow.cxx
  89. 4 0
      panda/src/display/graphicsWindow.h
  90. 0 1
      panda/src/display/pStatGPUTimer.h
  91. 3 3
      panda/src/display/standardMunger.cxx
  92. 7 0
      panda/src/downloadertools/multify.cxx
  93. 1 1
      panda/src/dxgsg9/dxShaderContext9.cxx
  94. 2 2
      panda/src/dxgsg9/wdxGraphicsBuffer9.cxx
  95. 1 1
      panda/src/dxgsg9/wdxGraphicsWindow9.cxx
  96. 0 12
      panda/src/egg/eggMesherEdge.I
  97. 0 1
      panda/src/egg/eggMesherEdge.h
  98. 2 1
      panda/src/egg/eggTransform.h
  99. 1 1
      panda/src/egg2pg/eggSaver.cxx
  100. 0 2
      panda/src/event/CMakeLists.txt

+ 4 - 4
.github/workflows/ci.yml

@@ -333,7 +333,7 @@ jobs:
     if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')"
     if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')"
     strategy:
     strategy:
       matrix:
       matrix:
-        os: [ubuntu-18.04, windows-2016, macOS-11]
+        os: [ubuntu-18.04, windows-2019, macOS-11]
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     steps:
     steps:
     - uses: actions/checkout@v1
     - uses: actions/checkout@v1
@@ -365,7 +365,7 @@ jobs:
     - name: Build Python 3.9
     - name: Build Python 3.9
       shell: bash
       shell: bash
       run: |
       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
     - name: Test Python 3.9
       shell: bash
       shell: bash
       run: |
       run: |
@@ -378,7 +378,7 @@ jobs:
     - name: Build Python 3.8
     - name: Build Python 3.8
       shell: bash
       shell: bash
       run: |
       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
     - name: Test Python 3.8
       shell: bash
       shell: bash
       run: |
       run: |
@@ -391,7 +391,7 @@ jobs:
     - name: Build Python 3.7
     - name: Build Python 3.7
       shell: bash
       shell: bash
       run: |
       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
     - name: Test Python 3.7
       shell: bash
       shell: bash
       run: |
       run: |

+ 5 - 29
CMakeLists.txt

@@ -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_SOURCE_CHANGES ON) # Must go before project() below
 set(CMAKE_DISABLE_IN_SOURCE_BUILD 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)
 if(POLICY CMP0091)
   # Needed for CMake to pass /MD flag properly with non-VC generators.
   # Needed for CMake to pass /MD flag properly with non-VC generators.
   cmake_policy(SET CMP0091 NEW)
   cmake_policy(SET CMP0091 NEW)
 endif()
 endif()
 
 
 # Determine whether we are using a multi-config generator.
 # 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().
 # Set the default CMAKE_BUILD_TYPE before calling project().
 if(IS_MULTICONFIG)
 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/modules/")
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros/")
 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 modules builtin to CMake
 include(GNUInstallDirs)     # Defines CMAKE_INSTALL_<dir> variables
 include(GNUInstallDirs)     # Defines CMAKE_INSTALL_<dir> variables

+ 19 - 22
README.md

@@ -177,35 +177,32 @@ directory which you can install using `pkg install`.
 Android
 Android
 -------
 -------
 
 
-Note: building on Android is very experimental and not guaranteed to work.
+Although it's possible to build Panda3D on an Android device itself 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
 
 
-```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
-```
+This does not include Python at the moment, which can be extracted from
+[this archive](https://rdb.name/thirdparty-android.tar.gz) instead.
 
 
-Then, you can build the .apk using this command:
+These commands show how to compile wheels for the supported Android ABIs:
 
 
 ```bash
 ```bash
-python makepanda/makepanda.py --everything --target android-21 --no-tiff --installer
+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
 ```
 ```
 
 
-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).
+It is now possible to use the generated wheels with `build_apps`, as explained
+on this page:
+
+https://discourse.panda3d.org/t/deployment-for-android/28226
 
 
 Running Tests
 Running Tests
 =============
 =============

+ 12 - 77
cmake/macros/BuildMetalib.cmake

@@ -5,83 +5,6 @@
 #   instead just an agglomeration of the various component libraries that get
 #   instead just an agglomeration of the various component libraries that get
 #   linked into them. A library of libraries - a "metalibrary."
 #   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]
 # Function: add_component_library(target [SYMBOL building_symbol]
 #                                 [SOURCES] [[NOINIT]/[INIT func [header]]])
 #                                 [SOURCES] [[NOINIT]/[INIT func [header]]])
@@ -305,6 +228,7 @@ function(add_metalib target_name)
   set(interface_defines)
   set(interface_defines)
   set(includes)
   set(includes)
   set(libs)
   set(libs)
+  set(link_options)
   set(component_init_funcs "")
   set(component_init_funcs "")
   foreach(component ${components})
   foreach(component ${components})
     if(NOT TARGET "${component}")
     if(NOT TARGET "${component}")
@@ -392,6 +316,16 @@ function(add_metalib target_name)
         endif()
         endif()
       endforeach(component_library)
       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
       # Consume this component's objects
       list(APPEND sources "$<TARGET_OBJECTS:${component}>")
       list(APPEND sources "$<TARGET_OBJECTS:${component}>")
 
 
@@ -419,6 +353,7 @@ function(add_metalib target_name)
     PRIVATE ${private_defines}
     PRIVATE ${private_defines}
     INTERFACE ${interface_defines})
     INTERFACE ${interface_defines})
   target_link_libraries("${target_name}" ${libs})
   target_link_libraries("${target_name}" ${libs})
+  target_link_options("${target_name}" PRIVATE ${link_options})
   target_include_directories("${target_name}"
   target_include_directories("${target_name}"
     PUBLIC ${includes}
     PUBLIC ${includes}
     INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}/panda3d>")
     INTERFACE "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}/panda3d>")

+ 2 - 15
cmake/macros/PackageConfig.cmake

@@ -176,18 +176,6 @@ function(package_option name)
   # Create the INTERFACE library used to depend on this package.
   # Create the INTERFACE library used to depend on this package.
   add_library(PKG::${name} INTERFACE IMPORTED GLOBAL)
   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 the option actually is enabled, populate the INTERFACE library created above
   if(HAVE_${name})
   if(HAVE_${name})
     set(use_variables ON)
     set(use_variables ON)
@@ -412,9 +400,8 @@ function(export_packages filename)
             endforeach(config)
             endforeach(config)
           endif()
           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)
           get_target_property(imported_libname "${head}" IMPORTED_LIBNAME)
           if(imported_libname)
           if(imported_libname)
             list(APPEND libraries ${imported_libname})
             list(APPEND libraries ${imported_libname})

+ 53 - 33
cmake/modules/FindLibSquish.cmake

@@ -14,42 +14,62 @@
 #   LIBSQUISH_DEBUG_LIBRARY   - the filepath of the libsquish debug library
 #   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_INCLUDE_DIR)
 mark_as_advanced(LIBSQUISH_RELEASE_LIBRARY)
 mark_as_advanced(LIBSQUISH_RELEASE_LIBRARY)

+ 0 - 88
cmake/modules/FindOpenEXR.cmake

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

+ 5 - 5
contrib/src/rplight/shadowSource.h

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

+ 89 - 66
direct/src/dist/FreezeTool.py

@@ -80,6 +80,7 @@ defaultHiddenImports = {
     ],
     ],
     'pandas.compat': ['lzma', 'cmath'],
     'pandas.compat': ['lzma', 'cmath'],
     'pandas._libs.tslibs.conversion': ['pandas._libs.tslibs.base'],
     'pandas._libs.tslibs.conversion': ['pandas._libs.tslibs.base'],
+    'plyer': ['plyer.platforms'],
 }
 }
 
 
 
 
@@ -791,10 +792,6 @@ class Freezer:
         # default object will be created when it is needed.
         # default object will be created when it is needed.
         self.cenv = None
         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
         # The filename extension to append to the source file before
         # compiling.
         # compiling.
         self.sourceExtension = '.c'
         self.sourceExtension = '.c'
@@ -843,32 +840,44 @@ class Freezer:
         # builds.  It can be explicitly included if desired.
         # builds.  It can be explicitly included if desired.
         self.modules['doctest'] = self.ModuleDef('doctest', exclude = True)
         self.modules['doctest'] = self.ModuleDef('doctest', exclude = True)
 
 
-        self.mf = None
-
         # Actually, make sure we know how to find all of the
         # Actually, make sure we know how to find all of the
         # already-imported modules.  (Some of them might do their own
         # already-imported modules.  (Some of them might do their own
         # special path mangling.)
         # special path mangling.)
         for moduleName, module in list(sys.modules.items()):
         for moduleName, module in list(sys.modules.items()):
             if module and getattr(module, '__path__', None) is not None:
             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
         # Module with non-obvious dependencies
         self.hiddenImports = defaultHiddenImports.copy()
         self.hiddenImports = defaultHiddenImports.copy()
         if hiddenImports is not None:
         if hiddenImports is not None:
             self.hiddenImports.update(hiddenImports)
             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
         # Suffix/extension for Python C extension modules
         if self.platform == PandaSystem.getPlatform():
         if self.platform == PandaSystem.getPlatform():
-            self.moduleSuffixes = imp.get_suffixes()
+            suffixes = imp.get_suffixes()
 
 
             # Set extension for Python files to binary mode
             # 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:
                 if suffix[2] == imp.PY_SOURCE:
-                    self.moduleSuffixes[i] = (suffix[0], 'rb', imp.PY_SOURCE)
+                    suffixes[i] = (suffix[0], 'rb', imp.PY_SOURCE)
         else:
         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_version = '{0}{1}'.format(*sys.version_info)
             abi_flags = ''
             abi_flags = ''
@@ -876,7 +885,7 @@ class Freezer:
                 abi_flags += 'm'
                 abi_flags += 'm'
 
 
             if 'linux' in self.platform:
             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}-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),
                     ('.cpython-{0}{1}-i686-linux-gnu.so'.format(abi_version, abi_flags), 'rb', 3),
                     ('.abi{0}.so'.format(sys.version_info[0]), 'rb', 3),
                     ('.abi{0}.so'.format(sys.version_info[0]), 'rb', 3),
@@ -884,24 +893,26 @@ class Freezer:
                 ]
                 ]
             elif 'win' in self.platform:
             elif 'win' in self.platform:
                 # ABI flags are not appended on Windows.
                 # ABI flags are not appended on Windows.
-                self.moduleSuffixes += [
+                suffixes += [
                     ('.cp{0}-win_amd64.pyd'.format(abi_version), 'rb', 3),
                     ('.cp{0}-win_amd64.pyd'.format(abi_version), 'rb', 3),
                     ('.cp{0}-win32.pyd'.format(abi_version), 'rb', 3),
                     ('.cp{0}-win32.pyd'.format(abi_version), 'rb', 3),
                     ('.pyd', 'rb', 3),
                     ('.pyd', 'rb', 3),
                 ]
                 ]
             elif 'mac' in self.platform:
             elif 'mac' in self.platform:
-                self.moduleSuffixes += [
+                suffixes += [
                     ('.cpython-{0}{1}-darwin.so'.format(abi_version, abi_flags), 'rb', 3),
                     ('.cpython-{0}{1}-darwin.so'.format(abi_version, abi_flags), 'rb', 3),
                     ('.abi{0}.so'.format(sys.version_info[0]), 'rb', 3),
                     ('.abi{0}.so'.format(sys.version_info[0]), 'rb', 3),
                     ('.so', 'rb', 3),
                     ('.so', 'rb', 3),
                 ]
                 ]
             else: # FreeBSD et al.
             else: # FreeBSD et al.
-                self.moduleSuffixes += [
+                suffixes += [
                     ('.cpython-{0}{1}.so'.format(abi_version, abi_flags), 'rb', 3),
                     ('.cpython-{0}{1}.so'.format(abi_version, abi_flags), 'rb', 3),
                     ('.abi{0}.so'.format(sys.version_info[0]), 'rb', 3),
                     ('.abi{0}.so'.format(sys.version_info[0]), 'rb', 3),
                     ('.so', 'rb', 3),
                     ('.so', 'rb', 3),
                 ]
                 ]
 
 
+        self.mf = PandaModuleFinder(excludes=['doctest'], suffixes=suffixes, path=path)
+
     def excludeFrom(self, freezer):
     def excludeFrom(self, freezer):
         """ Excludes all modules that have already been processed by
         """ Excludes all modules that have already been processed by
         the indicated FreezeTool.  This is equivalent to passing the
         the indicated FreezeTool.  This is equivalent to passing the
@@ -921,8 +932,6 @@ class Freezer:
         allowChildren is true, the children of the indicated module
         allowChildren is true, the children of the indicated module
         may still be included."""
         may still be included."""
 
 
-        assert self.mf is None
-
         self.modules[moduleName] = self.ModuleDef(
         self.modules[moduleName] = self.ModuleDef(
             moduleName, exclude = True,
             moduleName, exclude = True,
             forbid = forbid, allowChildren = allowChildren,
             forbid = forbid, allowChildren = allowChildren,
@@ -947,24 +956,6 @@ class Freezer:
         files can be found.  If the module is a .py file and not a
         files can be found.  If the module is a .py file and not a
         directory, returns None. """
         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
         path = None
         baseName = moduleName
         baseName = moduleName
         if '.' in baseName:
         if '.' in baseName:
@@ -974,34 +965,20 @@ class Freezer:
                 return None
                 return None
 
 
         try:
         try:
-            file, pathname, description = imp.find_module(baseName, path)
+            file, pathname, description = self.mf.find_module(baseName, path)
         except ImportError:
         except ImportError:
             return None
             return None
 
 
-        if not os.path.isdir(pathname):
+        if not self.mf._dir_exists(pathname):
             return None
             return None
+
         return [pathname]
         return [pathname]
 
 
     def getModuleStar(self, moduleName):
     def getModuleStar(self, moduleName):
         """ Looks for the indicated directory module and returns the
         """ Looks for the indicated directory module and returns the
         __all__ member: the list of symbols within the module. """
         __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
         path = None
         baseName = moduleName
         baseName = moduleName
         if '.' in baseName:
         if '.' in baseName:
@@ -1011,16 +988,16 @@ class Freezer:
                 return None
                 return None
 
 
         try:
         try:
-            file, pathname, description = imp.find_module(baseName, path)
+            file, pathname, description = self.mf.find_module(baseName, path)
         except ImportError:
         except ImportError:
             return None
             return None
 
 
-        if not os.path.isdir(pathname):
+        if not self.mf._dir_exists(pathname):
             return None
             return None
 
 
         # Scan the directory, looking for .py files.
         # Scan the directory, looking for .py files.
         modules = []
         modules = []
-        for basename in sorted(os.listdir(pathname)):
+        for basename in sorted(self.mf._listdir(pathname)):
             if basename.endswith('.py') and basename != '__init__.py':
             if basename.endswith('.py') and basename != '__init__.py':
                 modules.append(basename[:-3])
                 modules.append(basename[:-3])
 
 
@@ -1054,8 +1031,8 @@ class Freezer:
             modulePath = self.getModulePath(topName)
             modulePath = self.getModulePath(topName)
             if modulePath:
             if modulePath:
                 for dirname in 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)
                             parentName = '%s.%s' % (topName, basename)
                             newParentName = '%s.%s' % (newTopName, basename)
                             newParentName = '%s.%s' % (newTopName, basename)
                             if self.getModulePath(parentName):
                             if self.getModulePath(parentName):
@@ -1100,8 +1077,6 @@ class Freezer:
         directories within a particular directory.
         directories within a particular directory.
         """
         """
 
 
-        assert self.mf is None
-
         if not newName:
         if not newName:
             newName = moduleName
             newName = moduleName
 
 
@@ -1122,8 +1097,6 @@ class Freezer:
         to done(), you may not add any more modules until you call
         to done(), you may not add any more modules until you call
         reset(). """
         reset(). """
 
 
-        assert self.mf is None
-
         # If we are building an exe, we also need to implicitly
         # If we are building an exe, we also need to implicitly
         # bring in Python's startup modules.
         # bring in Python's startup modules.
         if addStartupModules:
         if addStartupModules:
@@ -1165,7 +1138,9 @@ class Freezer:
             else:
             else:
                 includes.append(mdef)
                 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.
         # Attempt to import the explicit modules into the modulefinder.
 
 
@@ -2428,6 +2403,17 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
 
 
         return None
         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):
     def _dir_exists(self, path):
         """Returns True if the given directory exists, either on disk or inside
         """Returns True if the given directory exists, either on disk or inside
         a wheel."""
         a wheel."""
@@ -2466,6 +2452,43 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
 
 
         return False
         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):
     def load_module(self, fqname, fp, pathname, file_info):
         """Copied from ModuleFinder.load_module with fixes to handle sending bytes
         """Copied from ModuleFinder.load_module with fixes to handle sending bytes
         to compile() for PY_SOURCE types. Sending bytes to compile allows it to
         to compile() for PY_SOURCE types. Sending bytes to compile allows it to
@@ -2712,7 +2735,7 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
         modules = {}
         modules = {}
         for dir in m.__path__:
         for dir in m.__path__:
             try:
             try:
-                names = os.listdir(dir)
+                names = self._listdir(dir)
             except OSError:
             except OSError:
                 self.msg(2, "can't list directory", dir)
                 self.msg(2, "can't list directory", dir)
                 continue
                 continue

+ 5 - 0
direct/src/dist/_android.py

@@ -169,9 +169,11 @@ ANDROID_ATTRIBUTES = {
     'alwaysRetainTaskState': bool_resource(0x1010203),
     'alwaysRetainTaskState': bool_resource(0x1010203),
     'clearTaskOnLaunch': bool_resource(0x1010015),
     'clearTaskOnLaunch': bool_resource(0x1010015),
     'debuggable': bool_resource(0x0101000f),
     '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),
     '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),
     'enabled': bool_resource(0x101000e),
     'excludeFromRecents': bool_resource(0x1010017),
     'excludeFromRecents': bool_resource(0x1010017),
+    'exported': bool_resource(0x1010010),
     'extractNativeLibs': bool_resource(0x10104ea),
     'extractNativeLibs': bool_resource(0x10104ea),
     'finishOnTaskLaunch': bool_resource(0x1010014),
     'finishOnTaskLaunch': bool_resource(0x1010014),
     'fullBackupContent': bool_resource(0x10104eb),
     'fullBackupContent': bool_resource(0x10104eb),
@@ -189,9 +191,12 @@ ANDROID_ATTRIBUTES = {
     'minSdkVersion': int_resource(0x101020c),
     'minSdkVersion': int_resource(0x101020c),
     'multiprocess': bool_resource(0x1010013),
     'multiprocess': bool_resource(0x1010013),
     'name': str_resource(0x1010003),
     'name': str_resource(0x1010003),
+    'noHistory': bool_resource(0x101022d),
     'pathPattern': str_resource(0x101002c),
     'pathPattern': str_resource(0x101002c),
+    'resizeableActivity': bool_resource(0x10104f6),
     'required': bool_resource(0x101028e),
     'required': bool_resource(0x101028e),
     'scheme': str_resource(0x1010027),
     '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),
     'stateNotNeeded': bool_resource(0x1010016),
     'supportsRtl': bool_resource(0x010103af),
     'supportsRtl': bool_resource(0x010103af),
     'supportsUploading': bool_resource(0x101029b),
     'supportsUploading': bool_resource(0x101029b),

+ 27 - 18
direct/src/dist/commands.py

@@ -116,7 +116,7 @@ from _frozen_importlib import _imp, FrozenImporter
 
 
 sys.frozen = True
 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.
     # Make sure the preferred encoding is something we actually support.
     import _bootlocale
     import _bootlocale
     enc = _bootlocale.getpreferredencoding().lower()
     enc = _bootlocale.getpreferredencoding().lower()
@@ -155,7 +155,9 @@ from android_log import write as android_log_write
 
 
 
 
 sys.frozen = True
 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.
 # 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:
         elif not self.android_abis:
             self.android_abis = ['arm64-v8a', 'armeabi-v7a', 'x86_64', 'x86']
             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 = {}
         self.icon_objects = {}
         for app, iconpaths in self.icons.items():
         for app, iconpaths in self.icons.items():
             if not isinstance(iconpaths, list) and not isinstance(iconpaths, tuple):
             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
                     else: # e.g. x86, x86_64, mips, mips64
                         suffix = '_' + abi.replace('-', '_')
                         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.
                 # Write out the icons to the res directory.
                 for appname, icon in self.icon_objects.items():
                 for appname, icon in self.icon_objects.items():
@@ -532,13 +542,13 @@ class build_apps(setuptools.Command):
                     if icon.getLargestSize() >= 192:
                     if icon.getLargestSize() >= 192:
                         icon.writeSize(192, os.path.join(res_dir, 'mipmap-xxxhdpi-v4', basename))
                         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
                 # Generate an AndroidManifest.xml
                 self.generate_android_manifest(os.path.join(build_dir, 'AndroidManifest.xml'))
                 self.generate_android_manifest(os.path.join(build_dir, 'AndroidManifest.xml'))
             else:
             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
             # Bundle into an .app on macOS
             if self.macos_main_app and 'macosx' in platform:
             if self.macos_main_app and 'macosx' in platform:
@@ -727,7 +737,7 @@ class build_apps(setuptools.Command):
 
 
         for appname in self.gui_apps:
         for appname in self.gui_apps:
             activity = ET.SubElement(application, 'activity')
             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:label', appname)
             activity.set('android:theme', '@android:style/Theme.NoTitleBar')
             activity.set('android:theme', '@android:style/Theme.NoTitleBar')
             activity.set('android:configChanges', 'orientation|keyboardHidden')
             activity.set('android:configChanges', 'orientation|keyboardHidden')
@@ -750,7 +760,7 @@ class build_apps(setuptools.Command):
         with open(path, 'wb') as fh:
         with open(path, 'wb') as fh:
             tree.write(fh, encoding='utf-8', xml_declaration=True)
             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. """
         """ Builds the binary data for the given platform. """
 
 
         use_wheels = True
         use_wheels = True
@@ -1015,7 +1025,7 @@ class build_apps(setuptools.Command):
 
 
             freezer_extras.update(freezer.extras)
             freezer_extras.update(freezer.extras)
             freezer_modules.update(freezer.getAllModuleNames())
             freezer_modules.update(freezer.getAllModuleNames())
-            for suffix in freezer.moduleSuffixes:
+            for suffix in freezer.mf.suffixes:
                 if suffix[2] == imp.C_EXTENSION:
                 if suffix[2] == imp.C_EXTENSION:
                     ext_suffixes.add(suffix[0])
                     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!")
             self.warn("Detected use of tkinter, but tkinter is not specified in requirements.txt!")
 
 
         # Copy extension modules
         # Copy extension modules
-        whl_modules = []
-        whl_modules_ext = ''
+        whl_modules = {}
         if use_wheels:
         if use_wheels:
             # Get the module libs
             # Get the module libs
-            whl_modules = []
-
             for i in p3dwhl.namelist():
             for i in p3dwhl.namelist():
                 if not i.startswith('deploy_libs/'):
                 if not i.startswith('deploy_libs/'):
                     continue
                     continue
@@ -1050,8 +1057,7 @@ class build_apps(setuptools.Command):
 
 
                 base = os.path.basename(i)
                 base = os.path.basename(i)
                 module, _, ext = base.partition('.')
                 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
         # Make sure to copy any builtins that have shared objects in the
         # deploy libs, assuming they are not already in freezer_extras.
         # deploy libs, assuming they are not already in freezer_extras.
@@ -1103,7 +1109,7 @@ class build_apps(setuptools.Command):
             else:
             else:
                 # Builtin module, but might not be builtin in wheel libs, so double check
                 # Builtin module, but might not be builtin in wheel libs, so double check
                 if module in whl_modules:
                 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)
                     basename = os.path.basename(source_path)
                     #XXX should we remove python version string here too?
                     #XXX should we remove python version string here too?
                 else:
                 else:
@@ -1125,6 +1131,9 @@ class build_apps(setuptools.Command):
                       os.path.join(binary_dir, '..', '..', 'classes.dex'))
                       os.path.join(binary_dir, '..', '..', 'classes.dex'))
 
 
         # Extract any other data files from dependency packages.
         # Extract any other data files from dependency packages.
+        if data_dir is None:
+            return
+
         for module, datadesc in self.package_data_dirs.items():
         for module, datadesc in self.package_data_dirs.items():
             if module not in freezer_modules:
             if module not in freezer_modules:
                 continue
                 continue
@@ -1165,11 +1174,11 @@ class build_apps(setuptools.Command):
                             else:
                             else:
                                 self.copy(source_path, target_path)
                                 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. """
         """ Builds the data files for the given platform. """
 
 
         # Copy Game Files
         # 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 = [
         ignore_copy_list = [
             '**/__pycache__/**',
             '**/__pycache__/**',
             '**/*.pyc',
             '**/*.pyc',

+ 13 - 0
direct/src/distributed/PyDatagramIterator.py

@@ -30,6 +30,19 @@ class PyDatagramIterator(DatagramIterator):
 
 
     getChannel = DatagramIterator.getUint64
     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):
     def getArg(self, subatomicType, divisor=1):
         # Import the type numbers
         # Import the type numbers
         if divisor == 1:
         if divisor == 1:

+ 4 - 5
direct/src/distributed/cConnectionRepository.cxx

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

+ 15 - 5
direct/src/filter/CommonFilters.py

@@ -20,6 +20,7 @@ from panda3d.core import LVecBase4, LPoint2
 from panda3d.core import AuxBitplaneAttrib
 from panda3d.core import AuxBitplaneAttrib
 from panda3d.core import Texture, Shader, ATSNone
 from panda3d.core import Texture, Shader, ATSNone
 from panda3d.core import FrameBufferProperties
 from panda3d.core import FrameBufferProperties
+from panda3d.core import getDefaultCoordinateSystem, CS_zup_right, CS_zup_left
 
 
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
 
 
@@ -52,6 +53,7 @@ o_color = lerp(o_color, k_cartooncolor, cartoon_thresh);
 SSAO_BODY = """//Cg
 SSAO_BODY = """//Cg
 
 
 void vshader(float4 vtx_position : POSITION,
 void vshader(float4 vtx_position : POSITION,
+             float2 vtx_texcoord : TEXCOORD0,
              out float4 l_position : POSITION,
              out float4 l_position : POSITION,
              out float2 l_texcoord : TEXCOORD0,
              out float2 l_texcoord : TEXCOORD0,
              out float2 l_texcoordD : TEXCOORD1,
              out float2 l_texcoordD : TEXCOORD1,
@@ -61,9 +63,9 @@ void vshader(float4 vtx_position : POSITION,
              uniform float4x4 mat_modelproj)
              uniform float4x4 mat_modelproj)
 {
 {
   l_position = mul(mat_modelproj, vtx_position);
   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));
 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 += "{\n"
             text += "  l_position = mul(mat_modelproj, vtx_position);\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():
             for texcoord, padTex in texcoordPadding.items():
                 if padTex is None:
                 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:
                 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:
                     if "HalfPixelShift" in configuration:
                         text += "  %s += texpix_tx%s.xy * 0.5;\n" % (texcoord, padTex)
                         text += "  %s += texpix_tx%s.xy * 0.5;\n" % (texcoord, padTex)

+ 2 - 1
direct/src/filter/filterBloomI.py

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

+ 3 - 2
direct/src/filter/filterBloomX.py

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

+ 2 - 1
direct/src/filter/filterBloomY.py

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

+ 4 - 4
direct/src/filter/filterBlurX.py

@@ -4,14 +4,14 @@ BLUR_X = """
 //Cg profile arbvp1 arbfp1
 //Cg profile arbvp1 arbfp1
 
 
 void vshader(float4 vtx_position : POSITION,
 void vshader(float4 vtx_position : POSITION,
-             float2 vtx_texcoord0 : TEXCOORD0,
+             float2 vtx_texcoord : TEXCOORD0,
              out float4 l_position : POSITION,
              out float4 l_position : POSITION,
-      	     out float2 l_texcoord0 : TEXCOORD0,
+             out float2 l_texcoord0 : TEXCOORD0,
              uniform float4 texpad_src,
              uniform float4 texpad_src,
              uniform float4x4 mat_modelproj)
              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 - 4
direct/src/filter/filterBlurY.py

@@ -4,14 +4,14 @@ BLUR_Y = """
 //Cg profile arbvp1 arbfp1
 //Cg profile arbvp1 arbfp1
 
 
 void vshader(float4 vtx_position : POSITION,
 void vshader(float4 vtx_position : POSITION,
-             float2 vtx_texcoord0 : TEXCOORD0,
+             float2 vtx_texcoord : TEXCOORD0,
              out float4 l_position : POSITION,
              out float4 l_position : POSITION,
-      	     out float2 l_texcoord0 : TEXCOORD0,
+             out float2 l_texcoord0 : TEXCOORD0,
              uniform float4 texpad_src,
              uniform float4 texpad_src,
              uniform float4x4 mat_modelproj)
              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 - 2
direct/src/filter/filterCopy.py

@@ -3,13 +3,14 @@ COPY = """
 
 
 
 
 void vshader(float4 vtx_position : POSITION,
 void vshader(float4 vtx_position : POSITION,
+             float2 vtx_texcoord : TEXCOORD0,
              out float4 l_position : POSITION,
              out float4 l_position : POSITION,
              out float2 l_texcoord : TEXCOORD0,
              out float2 l_texcoord : TEXCOORD0,
              uniform float4 texpad_src,
              uniform float4 texpad_src,
              uniform float4x4 mat_modelproj)
              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,
 void fshader(float2 l_texcoord : TEXCOORD0,

+ 3 - 2
direct/src/filter/filterDown4.py

@@ -2,6 +2,7 @@ DOWN_4 = """
 //Cg
 //Cg
 
 
 void vshader(float4 vtx_position : POSITION,
 void vshader(float4 vtx_position : POSITION,
+             float2 vtx_texcoord : TEXCOORD0,
              out float4 l_position : POSITION,
              out float4 l_position : POSITION,
              out float2 l_texcoordNW : TEXCOORD0,
              out float2 l_texcoordNW : TEXCOORD0,
              out float2 l_texcoordNE : TEXCOORD1,
              out float2 l_texcoordNE : TEXCOORD1,
@@ -11,8 +12,8 @@ void vshader(float4 vtx_position : POSITION,
              uniform float4 texpix_src,
              uniform float4 texpix_src,
              uniform float4x4 mat_modelproj)
              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_texcoordNW = c + float2( texpix_src.x, -texpix_src.y);
   l_texcoordNE = 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);
   l_texcoordSW = c + float2(-texpix_src.x, -texpix_src.y);

+ 0 - 6
direct/src/gui/DirectGuiBase.py

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

+ 2 - 1
direct/src/motiontrail/cMotionTrail.h

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

+ 4 - 4
direct/src/showbase/BufferViewer.py

@@ -240,10 +240,10 @@ class BufferViewer(DirectObject):
             offsetx = (ringoffset[ring]*2.0) / float(sizex)
             offsetx = (ringoffset[ring]*2.0) / float(sizex)
             offsety = (ringoffset[ring]*2.0) / float(sizey)
             offsety = (ringoffset[ring]*2.0) / float(sizey)
             bright = ringbright[ring]
             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(Vec3.rfu(-1 - offsetx, 0, -1 - offsety))
+            vwriter.addData3f(Vec3.rfu( 1 + offsetx, 0, -1 - offsety))
+            vwriter.addData3f(Vec3.rfu( 1 + offsetx, 0,  1 + offsety))
+            vwriter.addData3f(Vec3.rfu(-1 - offsetx, 0,  1 + offsety))
             cwriter.addData3f(bright, bright, bright)
             cwriter.addData3f(bright, bright, bright)
             cwriter.addData3f(bright, bright, bright)
             cwriter.addData3f(bright, bright, bright)
             cwriter.addData3f(bright, bright, bright)
             cwriter.addData3f(bright, bright, bright)

+ 5 - 1
direct/src/showbase/ShowBase.py

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

+ 7 - 7
direct/src/stdpy/threading.py

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

+ 9 - 5
direct/src/task/Task.py

@@ -16,11 +16,17 @@ from direct.showbase.MessengerGlobal import messenger
 import types
 import types
 import random
 import random
 import importlib
 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
     signal = None
+else:
+    try:
+        import _signal as signal
+    except ImportError:
+        signal = None
 
 
 from panda3d.core import *
 from panda3d.core import *
 from direct.extensions_native import HTTPChannel_extensions
 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
     Print the usual traceback information, followed by a listing of all the
     local variables in each frame.
     local variables in each frame.
     """
     """
-    import sys
     import traceback
     import traceback
 
 
     tb = sys.exc_info()[2]
     tb = sys.exc_info()[2]
@@ -1271,7 +1276,6 @@ class TaskManager:
 
 
 if __debug__:
 if __debug__:
     def checkLeak():
     def checkLeak():
-        import sys
         import gc
         import gc
         gc.enable()
         gc.enable()
         from direct.showbase.DirectObject import DirectObject
         from direct.showbase.DirectObject import DirectObject

+ 12 - 32
dtool/CompilerFlags.cmake

@@ -48,21 +48,9 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GCC")
 
 
 endif()
 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 certain CMake flags we expect
 set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
 set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
@@ -110,21 +98,6 @@ if(APPLE)
   set(CMAKE_SHARED_MODULE_SUFFIX ".dylib")
   set(CMAKE_SHARED_MODULE_SUFFIX ".dylib")
 endif()
 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
 # Set warning levels
 if(MSVC)
 if(MSVC)
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3")
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3")
@@ -138,7 +111,7 @@ endif()
 
 
 if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
 if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
   set(global_flags
   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")
   set(release_flags "-Wno-unused-variable")
 
 
   if(NOT MSVC)
   if(NOT MSVC)
@@ -154,7 +127,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
   endif()
   endif()
 
 
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${global_flags}")
   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_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${release_flags}")
   set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${release_flags}")
   set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${release_flags}")
   set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${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")
     add_compile_options("-fvisibility=hidden")
   endif()
   endif()
 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()

+ 33 - 17
dtool/Package.cmake

@@ -1,5 +1,5 @@
 set(_thirdparty_dir_default "${PROJECT_SOURCE_DIR}/thirdparty")
 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 "")
   set(_thirdparty_dir_default "")
 endif()
 endif()
 
 
@@ -47,6 +47,27 @@ if(THIRDPARTY_DIRECTORY)
     set(BISON_ROOT "${THIRDPARTY_DIRECTORY}/win-util")
     set(BISON_ROOT "${THIRDPARTY_DIRECTORY}/win-util")
     set(FLEX_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()
   else()
     message(FATAL_ERROR
     message(FATAL_ERROR
       "You can't use THIRDPARTY_DIRECTORY on this platform. Unset it to continue.")
       "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_INCLUDE_DIRS ${Python_INCLUDE_DIRS})
   set(PYTHON_LIBRARY_DIRS ${Python_LIBRARY_DIRS})
   set(PYTHON_LIBRARY_DIRS ${Python_LIBRARY_DIRS})
   set(PYTHON_VERSION_STRING ${Python_VERSION})
   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()
 endif()
 
 
 if(CMAKE_VERSION VERSION_LESS "3.15")
 if(CMAKE_VERSION VERSION_LESS "3.15")
@@ -369,14 +377,22 @@ package_option(TIFF "Enable support for loading .tif images.")
 package_status(TIFF "libtiff")
 package_status(TIFF "libtiff")
 
 
 # OpenEXR
 # 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")
 package_status(OpenEXR "OpenEXR")
 
 
 # libsquish
 # libsquish
-find_package(LibSquish QUIET)
+find_package(LibSquish QUIET MODULE)
 
 
 package_option(SQUISH
 package_option(SQUISH
   "Enables support for automatic compression of DXT textures."
   "Enables support for automatic compression of DXT textures."

+ 0 - 4
dtool/PandaVersion.cmake

@@ -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 SOURCE_DATE_EPOCH is set, it affects PandaSystem::get_build_date()
 if(DEFINED ENV{SOURCE_DATE_EPOCH})
 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)
   string(TIMESTAMP _build_date "%b %d %Y %H:%M:%S" UTC)
 
 
   # CMake doesn't support %e, replace leading zero in day with space
   # CMake doesn't support %e, replace leading zero in day with space

+ 139 - 139
dtool/metalibs/dtoolconfig/pydtool.cxx

@@ -2449,145 +2449,145 @@ _inP07ytw_15(PyObject *, PyObject *args) {
 
 
 
 
 static PyMethodDef python_simple_funcs[] = {
 static PyMethodDef python_simple_funcs[] = {
-  { "interrogate_add_search_directory", &_inP07yttbRf, METH_VARARGS },
-  { "interrogate_add_search_path", &_inP07ytda_g, METH_VARARGS },
-  { "interrogate_error_flag", &_inP07yt4RgX, METH_VARARGS },
-  { "interrogate_number_of_manifests", &_inP07yt3Gip, METH_VARARGS },
-  { "interrogate_get_manifest", &_inP07ytRKDz, METH_VARARGS },
-  { "interrogate_get_manifest_by_name", &_inP07ytgZ9N, METH_VARARGS },
-  { "interrogate_manifest_name", &_inP07ytFnRZ, METH_VARARGS },
-  { "interrogate_manifest_definition", &_inP07ytg0Qv, METH_VARARGS },
-  { "interrogate_manifest_has_type", &_inP07yttrqw, METH_VARARGS },
-  { "interrogate_manifest_get_type", &_inP07ytdmpW, METH_VARARGS },
-  { "interrogate_manifest_has_getter", &_inP07ytUYgQ, METH_VARARGS },
-  { "interrogate_manifest_getter", &_inP07yt0k7F, METH_VARARGS },
-  { "interrogate_manifest_has_int_value", &_inP07ytfIsr, METH_VARARGS },
-  { "interrogate_manifest_get_int_value", &_inP07ytvysR, METH_VARARGS },
-  { "interrogate_element_name", &_inP07ytYQ_2, METH_VARARGS },
-  { "interrogate_element_scoped_name", &_inP07yt3kdv, METH_VARARGS },
-  { "interrogate_element_has_comment", &_inP07ytew01, METH_VARARGS },
-  { "interrogate_element_comment", &_inP07ytQna7, METH_VARARGS },
-  { "interrogate_get_element_by_name", &_inP07ytkg95, METH_VARARGS },
-  { "interrogate_get_element_by_scoped_name", &_inP07ytluRc, METH_VARARGS },
-  { "interrogate_element_type", &_inP07yttHdM, METH_VARARGS },
-  { "interrogate_element_has_getter", &_inP07ytDId0, METH_VARARGS },
-  { "interrogate_element_getter", &_inP07ytHuAm, METH_VARARGS },
-  { "interrogate_element_has_setter", &_inP07yt_xr0, METH_VARARGS },
-  { "interrogate_element_setter", &_inP07ytH5qp, METH_VARARGS },
-  { "interrogate_element_is_sequence", &_inP07ytq45U, METH_VARARGS },
-  { "interrogate_element_is_mapping", &_inP07yt6IPa, METH_VARARGS },
-  { "interrogate_number_of_globals", &_inP07ytU2_B, METH_VARARGS },
-  { "interrogate_get_global", &_inP07ytHFO2, METH_VARARGS },
-  { "interrogate_number_of_global_functions", &_inP07ytcfjm, METH_VARARGS },
-  { "interrogate_get_global_function", &_inP07yt3Sjw, METH_VARARGS },
-  { "interrogate_number_of_functions", &_inP07ytgJcX, METH_VARARGS },
-  { "interrogate_get_function", &_inP07ytYlw6, METH_VARARGS },
-  { "interrogate_function_name", &_inP07ytsmnz, METH_VARARGS },
-  { "interrogate_function_scoped_name", &_inP07ytxQ10, METH_VARARGS },
-  { "interrogate_function_has_comment", &_inP07yt6gPB, METH_VARARGS },
-  { "interrogate_function_comment", &_inP07ytISgV, METH_VARARGS },
-  { "interrogate_function_prototype", &_inP07ytH3bx, METH_VARARGS },
-  { "interrogate_function_is_method", &_inP07ytzeUk, METH_VARARGS },
-  { "interrogate_function_class", &_inP07ytUeI5, METH_VARARGS },
-  { "interrogate_function_has_module_name", &_inP07ytuSvx, METH_VARARGS },
-  { "interrogate_function_module_name", &_inP07ytwpYd, METH_VARARGS },
-  { "interrogate_function_has_library_name", &_inP07ytOfNh, METH_VARARGS },
-  { "interrogate_function_library_name", &_inP07ytf5_U, METH_VARARGS },
-  { "interrogate_function_is_virtual", &_inP07ytL3ZB, METH_VARARGS },
-  { "interrogate_function_number_of_c_wrappers", &_inP07ytXw0I, METH_VARARGS },
-  { "interrogate_function_c_wrapper", &_inP07yt3zru, METH_VARARGS },
-  { "interrogate_function_number_of_python_wrappers", &_inP07ytRrg2, METH_VARARGS },
-  { "interrogate_function_python_wrapper", &_inP07ytEJCx, METH_VARARGS },
-  { "interrogate_wrapper_name", &_inP07ytWAZr, METH_VARARGS },
-  { "interrogate_wrapper_is_callable_by_name", &_inP07ytrD_M, METH_VARARGS },
-  { "interrogate_wrapper_has_comment", &_inP07ytjolz, METH_VARARGS },
-  { "interrogate_wrapper_comment", &_inP07ytt_JD, METH_VARARGS },
-  { "interrogate_wrapper_has_return_value", &_inP07ytwEts, METH_VARARGS },
-  { "interrogate_wrapper_return_type", &_inP07ytrJWs, METH_VARARGS },
-  { "interrogate_wrapper_caller_manages_return_value", &_inP07ytpmFD, METH_VARARGS },
-  { "interrogate_wrapper_return_value_destructor", &_inP07ytyYUX, METH_VARARGS },
-  { "interrogate_wrapper_number_of_parameters", &_inP07yt54dn, METH_VARARGS },
-  { "interrogate_wrapper_parameter_type", &_inP07ytGMpW, METH_VARARGS },
-  { "interrogate_wrapper_parameter_has_name", &_inP07ytNuBV, METH_VARARGS },
-  { "interrogate_wrapper_parameter_name", &_inP07yt9UwA, METH_VARARGS },
-  { "interrogate_wrapper_parameter_is_this", &_inP07yt3FDt, METH_VARARGS },
-  { "interrogate_wrapper_has_pointer", &_inP07ytf513, METH_VARARGS },
-  { "interrogate_wrapper_pointer", &_inP07ytsqGH, METH_VARARGS },
-  { "interrogate_wrapper_unique_name", &_inP07yt7shV, METH_VARARGS },
-  { "interrogate_get_wrapper_by_unique_name", &_inP07ytA1eF, METH_VARARGS },
-  { "interrogate_make_seq_seq_name", &_inP07yt776V, METH_VARARGS },
-  { "interrogate_make_seq_scoped_name", &_inP07ytryup, METH_VARARGS },
-  { "interrogate_make_seq_has_comment", &_inP07ytiytI, METH_VARARGS },
-  { "interrogate_make_seq_comment", &_inP07ytZc07, METH_VARARGS },
-  { "interrogate_make_seq_num_name", &_inP07ytfaH0, METH_VARARGS },
-  { "interrogate_make_seq_element_name", &_inP07ytGB9D, METH_VARARGS },
-  { "interrogate_number_of_global_types", &_inP07ytsxxs, METH_VARARGS },
-  { "interrogate_get_global_type", &_inP07ytMT0z, METH_VARARGS },
-  { "interrogate_number_of_types", &_inP07ytiW3v, METH_VARARGS },
-  { "interrogate_get_type", &_inP07yt4Px8, METH_VARARGS },
-  { "interrogate_get_type_by_name", &_inP07ytNHcs, METH_VARARGS },
-  { "interrogate_get_type_by_scoped_name", &_inP07ytqHrb, METH_VARARGS },
-  { "interrogate_get_type_by_true_name", &_inP07ytaOqq, METH_VARARGS },
-  { "interrogate_type_is_global", &_inP07ytpTBb, METH_VARARGS },
-  { "interrogate_type_name", &_inP07ytqWOw, METH_VARARGS },
-  { "interrogate_type_scoped_name", &_inP07ytHu7x, METH_VARARGS },
-  { "interrogate_type_true_name", &_inP07ytwGnA, METH_VARARGS },
-  { "interrogate_type_is_nested", &_inP07ytXGxx, METH_VARARGS },
-  { "interrogate_type_outer_class", &_inP07ytj04Z, METH_VARARGS },
-  { "interrogate_type_has_comment", &_inP07ytEOv4, METH_VARARGS },
-  { "interrogate_type_comment", &_inP07ytpCqJ, METH_VARARGS },
-  { "interrogate_type_has_module_name", &_inP07yt_Pz3, METH_VARARGS },
-  { "interrogate_type_module_name", &_inP07ytt_06, METH_VARARGS },
-  { "interrogate_type_has_library_name", &_inP07ytmuPs, METH_VARARGS },
-  { "interrogate_type_library_name", &_inP07ytvM8B, METH_VARARGS },
-  { "interrogate_type_is_atomic", &_inP07ytap97, METH_VARARGS },
-  { "interrogate_type_atomic_token", &_inP07yt0o8D, METH_VARARGS },
-  { "interrogate_type_is_unsigned", &_inP07ytOoQ2, METH_VARARGS },
-  { "interrogate_type_is_signed", &_inP07ytKuFh, METH_VARARGS },
-  { "interrogate_type_is_long", &_inP07yto5L6, METH_VARARGS },
-  { "interrogate_type_is_longlong", &_inP07ytzgKK, METH_VARARGS },
-  { "interrogate_type_is_short", &_inP07yt0FIF, METH_VARARGS },
-  { "interrogate_type_is_wrapped", &_inP07ytZqvD, METH_VARARGS },
-  { "interrogate_type_is_pointer", &_inP07ytDyRd, METH_VARARGS },
-  { "interrogate_type_is_const", &_inP07ytMnKa, METH_VARARGS },
-  { "interrogate_type_is_typedef", &_inP07ytRtji, METH_VARARGS },
-  { "interrogate_type_wrapped_type", &_inP07ytCnbQ, METH_VARARGS },
-  { "interrogate_type_is_enum", &_inP07ytdUVN, METH_VARARGS },
-  { "interrogate_type_number_of_enum_values", &_inP07ytihbt, METH_VARARGS },
-  { "interrogate_type_enum_value_name", &_inP07ytbyPY, METH_VARARGS },
-  { "interrogate_type_enum_value_scoped_name", &_inP07ytAaT6, METH_VARARGS },
-  { "interrogate_type_enum_value_comment", &_inP07ytgL9q, METH_VARARGS },
-  { "interrogate_type_enum_value", &_inP07ytWB97, METH_VARARGS },
-  { "interrogate_type_is_struct", &_inP07ytDUAl, METH_VARARGS },
-  { "interrogate_type_is_class", &_inP07yt1_Kf, METH_VARARGS },
-  { "interrogate_type_is_union", &_inP07yt98lD, METH_VARARGS },
-  { "interrogate_type_is_fully_defined", &_inP07yt9SHr, METH_VARARGS },
-  { "interrogate_type_is_unpublished", &_inP07ytdiZP, METH_VARARGS },
-  { "interrogate_type_number_of_constructors", &_inP07ytTdER, METH_VARARGS },
-  { "interrogate_type_get_constructor", &_inP07ytYO56, METH_VARARGS },
-  { "interrogate_type_has_destructor", &_inP07ytxtCG, METH_VARARGS },
-  { "interrogate_type_destructor_is_inherited", &_inP07yt_EB2, METH_VARARGS },
-  { "interrogate_type_get_destructor", &_inP07ytEG1l, METH_VARARGS },
-  { "interrogate_type_number_of_elements", &_inP07yt7tUq, METH_VARARGS },
-  { "interrogate_type_get_element", &_inP07ytyStU, METH_VARARGS },
-  { "interrogate_type_number_of_methods", &_inP07ytdM85, METH_VARARGS },
-  { "interrogate_type_get_method", &_inP07ytk_GN, METH_VARARGS },
-  { "interrogate_type_number_of_make_seqs", &_inP07yt8QjG, METH_VARARGS },
-  { "interrogate_type_get_make_seq", &_inP07ytyMtj, METH_VARARGS },
-  { "interrogate_type_number_of_casts", &_inP07ytHDtN, METH_VARARGS },
-  { "interrogate_type_get_cast", &_inP07ytHFjA, METH_VARARGS },
-  { "interrogate_type_number_of_derivations", &_inP07yt_NPR, METH_VARARGS },
-  { "interrogate_type_get_derivation", &_inP07ytcTOH, METH_VARARGS },
-  { "interrogate_type_derivation_has_upcast", &_inP07ythdU7, METH_VARARGS },
-  { "interrogate_type_get_upcast", &_inP07ytQPxU, METH_VARARGS },
-  { "interrogate_type_derivation_downcast_is_impossible", &_inP07ytO7Pz, METH_VARARGS },
-  { "interrogate_type_derivation_has_downcast", &_inP07ytvu_E, METH_VARARGS },
-  { "interrogate_type_get_downcast", &_inP07ytxGUt, METH_VARARGS },
-  { "interrogate_type_number_of_nested_types", &_inP07ytzM1P, METH_VARARGS },
-  { "interrogate_type_get_nested_type", &_inP07ytoY5L, METH_VARARGS },
-  { "interrogate_request_database", &_inP07yte_7S, METH_VARARGS },
-  { "interrogate_request_module", &_inP07ytw_15, METH_VARARGS },
-  { nullptr, nullptr }
+  { "interrogate_add_search_directory", &_inP07yttbRf, METH_VARARGS, nullptr },
+  { "interrogate_add_search_path", &_inP07ytda_g, METH_VARARGS, nullptr },
+  { "interrogate_error_flag", &_inP07yt4RgX, METH_VARARGS, nullptr },
+  { "interrogate_number_of_manifests", &_inP07yt3Gip, METH_VARARGS, nullptr },
+  { "interrogate_get_manifest", &_inP07ytRKDz, METH_VARARGS, nullptr },
+  { "interrogate_get_manifest_by_name", &_inP07ytgZ9N, METH_VARARGS, nullptr },
+  { "interrogate_manifest_name", &_inP07ytFnRZ, METH_VARARGS, nullptr },
+  { "interrogate_manifest_definition", &_inP07ytg0Qv, METH_VARARGS, nullptr },
+  { "interrogate_manifest_has_type", &_inP07yttrqw, METH_VARARGS, nullptr },
+  { "interrogate_manifest_get_type", &_inP07ytdmpW, METH_VARARGS, nullptr },
+  { "interrogate_manifest_has_getter", &_inP07ytUYgQ, METH_VARARGS, nullptr },
+  { "interrogate_manifest_getter", &_inP07yt0k7F, METH_VARARGS, nullptr },
+  { "interrogate_manifest_has_int_value", &_inP07ytfIsr, METH_VARARGS, nullptr },
+  { "interrogate_manifest_get_int_value", &_inP07ytvysR, METH_VARARGS, nullptr },
+  { "interrogate_element_name", &_inP07ytYQ_2, METH_VARARGS, nullptr },
+  { "interrogate_element_scoped_name", &_inP07yt3kdv, METH_VARARGS, nullptr },
+  { "interrogate_element_has_comment", &_inP07ytew01, METH_VARARGS, nullptr },
+  { "interrogate_element_comment", &_inP07ytQna7, METH_VARARGS, nullptr },
+  { "interrogate_get_element_by_name", &_inP07ytkg95, METH_VARARGS, nullptr },
+  { "interrogate_get_element_by_scoped_name", &_inP07ytluRc, METH_VARARGS, nullptr },
+  { "interrogate_element_type", &_inP07yttHdM, METH_VARARGS, nullptr },
+  { "interrogate_element_has_getter", &_inP07ytDId0, METH_VARARGS, nullptr },
+  { "interrogate_element_getter", &_inP07ytHuAm, METH_VARARGS, nullptr },
+  { "interrogate_element_has_setter", &_inP07yt_xr0, METH_VARARGS, nullptr },
+  { "interrogate_element_setter", &_inP07ytH5qp, METH_VARARGS, nullptr },
+  { "interrogate_element_is_sequence", &_inP07ytq45U, METH_VARARGS, nullptr },
+  { "interrogate_element_is_mapping", &_inP07yt6IPa, METH_VARARGS, nullptr },
+  { "interrogate_number_of_globals", &_inP07ytU2_B, METH_VARARGS, nullptr },
+  { "interrogate_get_global", &_inP07ytHFO2, METH_VARARGS, nullptr },
+  { "interrogate_number_of_global_functions", &_inP07ytcfjm, METH_VARARGS, nullptr },
+  { "interrogate_get_global_function", &_inP07yt3Sjw, METH_VARARGS, nullptr },
+  { "interrogate_number_of_functions", &_inP07ytgJcX, METH_VARARGS, nullptr },
+  { "interrogate_get_function", &_inP07ytYlw6, METH_VARARGS, nullptr },
+  { "interrogate_function_name", &_inP07ytsmnz, METH_VARARGS, nullptr },
+  { "interrogate_function_scoped_name", &_inP07ytxQ10, METH_VARARGS, nullptr },
+  { "interrogate_function_has_comment", &_inP07yt6gPB, METH_VARARGS, nullptr },
+  { "interrogate_function_comment", &_inP07ytISgV, METH_VARARGS, nullptr },
+  { "interrogate_function_prototype", &_inP07ytH3bx, METH_VARARGS, nullptr },
+  { "interrogate_function_is_method", &_inP07ytzeUk, METH_VARARGS, nullptr },
+  { "interrogate_function_class", &_inP07ytUeI5, METH_VARARGS, nullptr },
+  { "interrogate_function_has_module_name", &_inP07ytuSvx, METH_VARARGS, nullptr },
+  { "interrogate_function_module_name", &_inP07ytwpYd, METH_VARARGS, nullptr },
+  { "interrogate_function_has_library_name", &_inP07ytOfNh, METH_VARARGS, nullptr },
+  { "interrogate_function_library_name", &_inP07ytf5_U, METH_VARARGS, nullptr },
+  { "interrogate_function_is_virtual", &_inP07ytL3ZB, METH_VARARGS, nullptr },
+  { "interrogate_function_number_of_c_wrappers", &_inP07ytXw0I, METH_VARARGS, nullptr },
+  { "interrogate_function_c_wrapper", &_inP07yt3zru, METH_VARARGS, nullptr },
+  { "interrogate_function_number_of_python_wrappers", &_inP07ytRrg2, METH_VARARGS, nullptr },
+  { "interrogate_function_python_wrapper", &_inP07ytEJCx, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_name", &_inP07ytWAZr, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_is_callable_by_name", &_inP07ytrD_M, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_has_comment", &_inP07ytjolz, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_comment", &_inP07ytt_JD, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_has_return_value", &_inP07ytwEts, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_return_type", &_inP07ytrJWs, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_caller_manages_return_value", &_inP07ytpmFD, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_return_value_destructor", &_inP07ytyYUX, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_number_of_parameters", &_inP07yt54dn, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_parameter_type", &_inP07ytGMpW, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_parameter_has_name", &_inP07ytNuBV, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_parameter_name", &_inP07yt9UwA, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_parameter_is_this", &_inP07yt3FDt, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_has_pointer", &_inP07ytf513, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_pointer", &_inP07ytsqGH, METH_VARARGS, nullptr },
+  { "interrogate_wrapper_unique_name", &_inP07yt7shV, METH_VARARGS, nullptr },
+  { "interrogate_get_wrapper_by_unique_name", &_inP07ytA1eF, METH_VARARGS, nullptr },
+  { "interrogate_make_seq_seq_name", &_inP07yt776V, METH_VARARGS, nullptr },
+  { "interrogate_make_seq_scoped_name", &_inP07ytryup, METH_VARARGS, nullptr },
+  { "interrogate_make_seq_has_comment", &_inP07ytiytI, METH_VARARGS, nullptr },
+  { "interrogate_make_seq_comment", &_inP07ytZc07, METH_VARARGS, nullptr },
+  { "interrogate_make_seq_num_name", &_inP07ytfaH0, METH_VARARGS, nullptr },
+  { "interrogate_make_seq_element_name", &_inP07ytGB9D, METH_VARARGS, nullptr },
+  { "interrogate_number_of_global_types", &_inP07ytsxxs, METH_VARARGS, nullptr },
+  { "interrogate_get_global_type", &_inP07ytMT0z, METH_VARARGS, nullptr },
+  { "interrogate_number_of_types", &_inP07ytiW3v, METH_VARARGS, nullptr },
+  { "interrogate_get_type", &_inP07yt4Px8, METH_VARARGS, nullptr },
+  { "interrogate_get_type_by_name", &_inP07ytNHcs, METH_VARARGS, nullptr },
+  { "interrogate_get_type_by_scoped_name", &_inP07ytqHrb, METH_VARARGS, nullptr },
+  { "interrogate_get_type_by_true_name", &_inP07ytaOqq, METH_VARARGS, nullptr },
+  { "interrogate_type_is_global", &_inP07ytpTBb, METH_VARARGS, nullptr },
+  { "interrogate_type_name", &_inP07ytqWOw, METH_VARARGS, nullptr },
+  { "interrogate_type_scoped_name", &_inP07ytHu7x, METH_VARARGS, nullptr },
+  { "interrogate_type_true_name", &_inP07ytwGnA, METH_VARARGS, nullptr },
+  { "interrogate_type_is_nested", &_inP07ytXGxx, METH_VARARGS, nullptr },
+  { "interrogate_type_outer_class", &_inP07ytj04Z, METH_VARARGS, nullptr },
+  { "interrogate_type_has_comment", &_inP07ytEOv4, METH_VARARGS, nullptr },
+  { "interrogate_type_comment", &_inP07ytpCqJ, METH_VARARGS, nullptr },
+  { "interrogate_type_has_module_name", &_inP07yt_Pz3, METH_VARARGS, nullptr },
+  { "interrogate_type_module_name", &_inP07ytt_06, METH_VARARGS, nullptr },
+  { "interrogate_type_has_library_name", &_inP07ytmuPs, METH_VARARGS, nullptr },
+  { "interrogate_type_library_name", &_inP07ytvM8B, METH_VARARGS, nullptr },
+  { "interrogate_type_is_atomic", &_inP07ytap97, METH_VARARGS, nullptr },
+  { "interrogate_type_atomic_token", &_inP07yt0o8D, METH_VARARGS, nullptr },
+  { "interrogate_type_is_unsigned", &_inP07ytOoQ2, METH_VARARGS, nullptr },
+  { "interrogate_type_is_signed", &_inP07ytKuFh, METH_VARARGS, nullptr },
+  { "interrogate_type_is_long", &_inP07yto5L6, METH_VARARGS, nullptr },
+  { "interrogate_type_is_longlong", &_inP07ytzgKK, METH_VARARGS, nullptr },
+  { "interrogate_type_is_short", &_inP07yt0FIF, METH_VARARGS, nullptr },
+  { "interrogate_type_is_wrapped", &_inP07ytZqvD, METH_VARARGS, nullptr },
+  { "interrogate_type_is_pointer", &_inP07ytDyRd, METH_VARARGS, nullptr },
+  { "interrogate_type_is_const", &_inP07ytMnKa, METH_VARARGS, nullptr },
+  { "interrogate_type_is_typedef", &_inP07ytRtji, METH_VARARGS, nullptr },
+  { "interrogate_type_wrapped_type", &_inP07ytCnbQ, METH_VARARGS, nullptr },
+  { "interrogate_type_is_enum", &_inP07ytdUVN, METH_VARARGS, nullptr },
+  { "interrogate_type_number_of_enum_values", &_inP07ytihbt, METH_VARARGS, nullptr },
+  { "interrogate_type_enum_value_name", &_inP07ytbyPY, METH_VARARGS, nullptr },
+  { "interrogate_type_enum_value_scoped_name", &_inP07ytAaT6, METH_VARARGS, nullptr },
+  { "interrogate_type_enum_value_comment", &_inP07ytgL9q, METH_VARARGS, nullptr },
+  { "interrogate_type_enum_value", &_inP07ytWB97, METH_VARARGS, nullptr },
+  { "interrogate_type_is_struct", &_inP07ytDUAl, METH_VARARGS, nullptr },
+  { "interrogate_type_is_class", &_inP07yt1_Kf, METH_VARARGS, nullptr },
+  { "interrogate_type_is_union", &_inP07yt98lD, METH_VARARGS, nullptr },
+  { "interrogate_type_is_fully_defined", &_inP07yt9SHr, METH_VARARGS, nullptr },
+  { "interrogate_type_is_unpublished", &_inP07ytdiZP, METH_VARARGS, nullptr },
+  { "interrogate_type_number_of_constructors", &_inP07ytTdER, METH_VARARGS, nullptr },
+  { "interrogate_type_get_constructor", &_inP07ytYO56, METH_VARARGS, nullptr },
+  { "interrogate_type_has_destructor", &_inP07ytxtCG, METH_VARARGS, nullptr },
+  { "interrogate_type_destructor_is_inherited", &_inP07yt_EB2, METH_VARARGS, nullptr },
+  { "interrogate_type_get_destructor", &_inP07ytEG1l, METH_VARARGS, nullptr },
+  { "interrogate_type_number_of_elements", &_inP07yt7tUq, METH_VARARGS, nullptr },
+  { "interrogate_type_get_element", &_inP07ytyStU, METH_VARARGS, nullptr },
+  { "interrogate_type_number_of_methods", &_inP07ytdM85, METH_VARARGS, nullptr },
+  { "interrogate_type_get_method", &_inP07ytk_GN, METH_VARARGS, nullptr },
+  { "interrogate_type_number_of_make_seqs", &_inP07yt8QjG, METH_VARARGS, nullptr },
+  { "interrogate_type_get_make_seq", &_inP07ytyMtj, METH_VARARGS, nullptr },
+  { "interrogate_type_number_of_casts", &_inP07ytHDtN, METH_VARARGS, nullptr },
+  { "interrogate_type_get_cast", &_inP07ytHFjA, METH_VARARGS, nullptr },
+  { "interrogate_type_number_of_derivations", &_inP07yt_NPR, METH_VARARGS, nullptr },
+  { "interrogate_type_get_derivation", &_inP07ytcTOH, METH_VARARGS, nullptr },
+  { "interrogate_type_derivation_has_upcast", &_inP07ythdU7, METH_VARARGS, nullptr },
+  { "interrogate_type_get_upcast", &_inP07ytQPxU, METH_VARARGS, nullptr },
+  { "interrogate_type_derivation_downcast_is_impossible", &_inP07ytO7Pz, METH_VARARGS, nullptr },
+  { "interrogate_type_derivation_has_downcast", &_inP07ytvu_E, METH_VARARGS, nullptr },
+  { "interrogate_type_get_downcast", &_inP07ytxGUt, METH_VARARGS, nullptr },
+  { "interrogate_type_number_of_nested_types", &_inP07ytzM1P, METH_VARARGS, nullptr },
+  { "interrogate_type_get_nested_type", &_inP07ytoY5L, METH_VARARGS, nullptr },
+  { "interrogate_request_database", &_inP07yte_7S, METH_VARARGS, nullptr },
+  { "interrogate_request_module", &_inP07ytw_15, METH_VARARGS, nullptr },
+  { nullptr, nullptr, 0, nullptr }
 };
 };
 
 
 #if PY_MAJOR_VERSION >= 3
 #if PY_MAJOR_VERSION >= 3

+ 2 - 2
dtool/src/cppparser/cppManifest.cxx

@@ -226,8 +226,8 @@ output(std::ostream &out) const {
         out << "$1";
         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 << ", ...";
           out << ", ...";
         } else {
         } else {
           out << ", $" << i + 1;
           out << ", $" << i + 1;

+ 1 - 1
dtool/src/cppparser/cppManifest.h

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

+ 2 - 2
dtool/src/cppparser/cppNamespace.cxx

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

+ 2 - 2
dtool/src/cppparser/cppStructType.cxx

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

+ 7 - 0
dtool/src/dtoolbase/CMakeLists.txt

@@ -46,6 +46,7 @@ set(P3DTOOLBASE_HEADERS
   typeRegistryNode.I typeRegistryNode.h
   typeRegistryNode.I typeRegistryNode.h
   typedObject.I typedObject.h
   typedObject.I typedObject.h
   pallocator.T pallocator.h
   pallocator.T pallocator.h
+  patomic.h patomic.I
   pdeque.h plist.h pmap.h pset.h
   pdeque.h plist.h pmap.h pset.h
   pvector.h epvector.h
   pvector.h epvector.h
   lookup3.h
   lookup3.h
@@ -70,6 +71,7 @@ set(P3DTOOLBASE_SOURCES
   mutexWin32Impl.cxx
   mutexWin32Impl.cxx
   mutexSpinlockImpl.cxx
   mutexSpinlockImpl.cxx
   neverFreeMemory.cxx
   neverFreeMemory.cxx
+  patomic.cxx
   pdtoa.cxx
   pdtoa.cxx
   pstrtod.cxx
   pstrtod.cxx
   register_type.cxx
   register_type.cxx
@@ -95,6 +97,11 @@ target_include_directories(p3dtoolbase PUBLIC
 target_link_libraries(p3dtoolbase PKG::EIGEN PKG::THREADS PKG::MIMALLOC)
 target_link_libraries(p3dtoolbase PKG::EIGEN PKG::THREADS PKG::MIMALLOC)
 target_interrogate(p3dtoolbase ${P3DTOOLBASE_SOURCES} EXTENSIONS ${P3DTOOLBASE_IGATEEXT})
 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)
 if(NOT BUILD_METALIBS)
   install(TARGETS p3dtoolbase
   install(TARGETS p3dtoolbase
     EXPORT Core COMPONENT Core
     EXPORT Core COMPONENT Core

+ 1 - 0
dtool/src/dtoolbase/p3dtoolbase_composite2.cxx

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

+ 211 - 6
dtool/src/dtoolbase/patomic.I

@@ -11,6 +11,7 @@
  * @date 2022-01-28
  * @date 2022-01-28
  */
  */
 
 
+#if defined(THREAD_DUMMY_IMPL) || defined(THREAD_SIMPLE_IMPL)
 /**
 /**
  * Value initializer.
  * Value initializer.
  */
  */
@@ -247,21 +248,225 @@ operator ^=(T arg) noexcept {
   return _value ^= arg;
   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.
  * Sets the flag to true and returns the previous value.
  */
  */
 ALWAYS_INLINE bool patomic_flag::
 ALWAYS_INLINE bool patomic_flag::
 test_and_set(std::memory_order order) noexcept {
 test_and_set(std::memory_order order) noexcept {
-  bool value = __internal_flag;
-  __internal_flag = true;
-  return value;
+  return _value.exchange(1u, order) != 0u;
 }
 }
 
 
 /**
 /**
- * Sets the flag to false.
+ * 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::
 ALWAYS_INLINE void patomic_flag::
-clear(std::memory_order order) noexcept {
-  __internal_flag = false;
+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
 }
 }

+ 168 - 0
dtool/src/dtoolbase/patomic.cxx

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

+ 85 - 18
dtool/src/dtoolbase/patomic.h

@@ -19,6 +19,19 @@
 
 
 #include <atomic>
 #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)
 #if defined(THREAD_DUMMY_IMPL) || defined(THREAD_SIMPLE_IMPL)
 
 
 /**
 /**
@@ -73,36 +86,90 @@ private:
   T _value;
   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
+
 /**
 /**
- * Dummy implementation of std::atomic_flag that does not do any atomic
- * operations.
+ * Implementation of atomic_unsigned_lock_free with C++20 semantics.
  */
  */
-struct EXPCL_DTOOL_DTOOLBASE patomic_flag {
-  constexpr patomic_flag() noexcept = default;
+class EXPCL_DTOOL_DTOOLBASE patomic_unsigned_lock_free : public patomic<uint32_t> {
+public:
+  typedef uint32_t value_type;
 
 
-  patomic_flag(const patomic_flag &) = delete;
-  patomic_flag &operator=(const patomic_flag &) = delete;
-
-  ALWAYS_INLINE bool test_and_set(std::memory_order order = std::memory_order_seq_cst) noexcept;
-  ALWAYS_INLINE void clear(std::memory_order order = std::memory_order_seq_cst) noexcept;
+  constexpr patomic_unsigned_lock_free() noexcept;
+  constexpr patomic_unsigned_lock_free(uint32_t desired) noexcept;
 
 
-  bool __internal_flag = false;
+  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;
 };
 };
 
 
-#define patomic_thread_fence(order) (std::atomic_signal_fence((order)))
+/**
+ * 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;
 
 
-#include "patomic.I"
+  constexpr patomic_signed_lock_free() noexcept;
+  constexpr patomic_signed_lock_free(int32_t desired) noexcept;
 
 
-#else
+  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;
+};
 
 
-// We're using real threading, so use the real implementation.
-template<class T>
-using patomic = std::atomic<T>;
+/**
+ * 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;
 
 
-typedef std::atomic_flag patomic_flag;
+  patomic_flag(const patomic_flag &) = delete;
+  patomic_flag &operator=(const patomic_flag &) = delete;
 
 
-#define patomic_thread_fence(order) (std::atomic_thread_fence((order)))
+  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
 #endif
 
 
+#include "patomic.I"
+#endif  // CPPPARSER
+
 #endif
 #endif

+ 0 - 1
dtool/src/dtoolbase/typeHandle_ext.cxx

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

+ 39 - 6
dtool/src/dtoolutil/executionEnvironment.cxx

@@ -259,10 +259,14 @@ ns_has_environment_variable(const string &var) const {
     return true;
     return true;
   }
   }
 
 
-#ifndef PREREAD_ENVIRONMENT
-  return getenv(var.c_str()) != nullptr;
-#else
+#ifdef PREREAD_ENVIRONMENT
   return false;
   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
 #endif
 }
 }
 
 
@@ -301,11 +305,24 @@ ns_get_environment_variable(const string &var) const {
   }
   }
 
 
 #ifndef PREREAD_ENVIRONMENT
 #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());
   const char *def = getenv(var.c_str());
   if (def != nullptr) {
   if (def != nullptr) {
     return def;
     return def;
   }
   }
 #endif
 #endif
+#endif
 
 
 #ifdef _WIN32
 #ifdef _WIN32
   // On Windows only, we also simulate several standard folder names as
   // 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::
 void ExecutionEnvironment::
 ns_set_environment_variable(const string &var, const string &value) {
 ns_set_environment_variable(const string &var, const string &value) {
   _variables[var] = value;
   _variables[var] = value;
+
+#ifdef _MSC_VER
+  _putenv_s(var.c_str(), value.c_str());
+#else
   string putstr = var + "=" + value;
   string putstr = var + "=" + value;
 
 
   // putenv() requires us to malloc a new C-style string.
   // putenv() requires us to malloc a new C-style string.
   char *put = (char *)malloc(putstr.length() + 1);
   char *put = (char *)malloc(putstr.length() + 1);
   strcpy(put, putstr.c_str());
   strcpy(put, putstr.c_str());
-#ifdef _MSC_VER
-  _putenv(put);
-#else
   putenv(put);
   putenv(put);
 #endif
 #endif
 }
 }
@@ -447,12 +465,27 @@ ns_clear_shadow(const string &var) {
 
 
 #ifdef PREREAD_ENVIRONMENT
 #ifdef PREREAD_ENVIRONMENT
   // Now we have to replace the value in the table.
   // 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());
   const char *def = getenv(var.c_str());
   if (def != nullptr) {
   if (def != nullptr) {
     (*vi).second = def;
     (*vi).second = def;
   } else {
   } else {
     _variables.erase(vi);
     _variables.erase(vi);
   }
   }
+#endif
 #endif  // PREREAD_ENVIRONMENT
 #endif  // PREREAD_ENVIRONMENT
 }
 }
 
 

+ 15 - 1
dtool/src/dtoolutil/filename.cxx

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

+ 2 - 0
dtool/src/dtoolutil/pandaSystem.cxx

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

+ 10 - 2
dtool/src/dtoolutil/panda_getopt_impl.cxx

@@ -140,6 +140,10 @@ PandaGetopt(int argc, char *const argv[], const char *optstring,
   // _options[0] is used for invalid characters.
   // _options[0] is used for invalid characters.
   _options.push_back(Option('?', no_argument));
   _options.push_back(Option('?', no_argument));
 
 
+#ifdef _MSC_VER
+  size_t size;
+#endif
+
   if (optstring[0] == '-') {
   if (optstring[0] == '-') {
     // RETURN_IN_ORDER: Non-option arguments (operands) are handled as if they
     // RETURN_IN_ORDER: Non-option arguments (operands) are handled as if they
     // were the argument to an option with the value 1 ('\001').
     // 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 "--".
     // argument is reached, or when the element of argv is "--".
     ++optstring;
     ++optstring;
     _require_order = true;
     _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.
     _require_order = true;
     _require_order = true;
 
 

+ 3 - 4
dtool/src/dtoolutil/pfstreamBuf.cxx

@@ -333,8 +333,9 @@ open_pipe(const string &cmd) {
 
 
   // Both WinExec() and CreateProcess() want a non-const char pointer.  Maybe
   // Both WinExec() and CreateProcess() want a non-const char pointer.  Maybe
   // they change it, and maybe they don't.  I'm not taking chances.
   // 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
   // We should be using CreateProcess() instead of WinExec(), but that seems
   // to be likely to crash Win98.  WinExec() seems better behaved, and it's
   // to be likely to crash Win98.  WinExec() seems better behaved, and it's
@@ -347,8 +348,6 @@ open_pipe(const string &cmd) {
     // Don't return yet, since we still need to clean up.
     // Don't return yet, since we still need to clean up.
   }
   }
 
 
-  delete[] cmdline;
-
   // Now restore our own stdout, up here in the parent process.
   // Now restore our own stdout, up here in the parent process.
   if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) {
   if (!SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) {
 #ifndef NDEBUG
 #ifndef NDEBUG

+ 4 - 4
dtool/src/interrogate/interfaceMaker.cxx

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

+ 2 - 2
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -2510,11 +2510,11 @@ write_module_class(ostream &out, Object *obj) {
           out << "  if (arg2 != nullptr && arg2 != Py_None) {\n";
           out << "  if (arg2 != nullptr && arg2 != Py_None) {\n";
           out << "    PyObject *args = PyTuple_Pack(2, arg, arg2);\n";
           out << "    PyObject *args = PyTuple_Pack(2, arg, arg2);\n";
           write_function_forset(out, two_param_remaps, 2, 2, expected_params, 4,
           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 << "    Py_DECREF(args);\n";
           out << "  } else {\n";
           out << "  } else {\n";
           write_function_forset(out, one_param_remaps, 1, 1, expected_params, 4,
           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 << "  }\n\n";
 
 
           out << "  if (!_PyErr_OCCURRED()) {\n";
           out << "  if (!_PyErr_OCCURRED()) {\n";

+ 2 - 2
dtool/src/interrogate/interfaceMakerPythonObj.cxx

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

+ 2 - 2
dtool/src/interrogate/interfaceMakerPythonSimple.cxx

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

+ 7 - 0
dtool/src/interrogate/interrogate.cxx

@@ -547,8 +547,15 @@ main(int argc, char **argv) {
   // We allow overriding this value by setting SOURCE_DATE_EPOCH to support
   // We allow overriding this value by setting SOURCE_DATE_EPOCH to support
   // reproducible builds.
   // reproducible builds.
   int file_identifier;
   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");
   const char *source_date_epoch = getenv("SOURCE_DATE_EPOCH");
   if (source_date_epoch != nullptr && source_date_epoch[0] != 0) {
   if (source_date_epoch != nullptr && source_date_epoch[0] != 0) {
+#endif
     file_identifier = atoi(source_date_epoch);
     file_identifier = atoi(source_date_epoch);
   } else {
   } else {
     file_identifier = time(nullptr);
     file_identifier = time(nullptr);

+ 6 - 0
dtool/src/prc/CMakeLists.txt

@@ -99,6 +99,12 @@ if(ANDROID)
   target_link_libraries(p3prc log)
   target_link_libraries(p3prc log)
 endif()
 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
 install(TARGETS p3prc
   EXPORT Core COMPONENT Core
   EXPORT Core COMPONENT Core
   DESTINATION ${CMAKE_INSTALL_LIBDIR}
   DESTINATION ${CMAKE_INSTALL_LIBDIR}

+ 1 - 0
dtool/src/prc/configFlags.h

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

+ 2 - 1
dtool/src/prc/configVariableBase.h

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

+ 2 - 1
dtool/src/prc/configVariableCore.h

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

+ 47 - 10
makepanda/makepackage.py

@@ -189,31 +189,65 @@ def MakeInstallerNSIS(version, file, title, installdir, compressor="lzma", **kwa
     oscmd(cmd)
     oscmd(cmd)
 
 
 
 
-def MakeDebugSymbolArchive(zipname, dirname):
-    outputdir = GetOutputDir()
-
+def MakeDebugSymbolZipArchive(zipname):
     import zipfile
     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')):
     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')):
     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')):
     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')):
     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')):
     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()
     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,
 def MakeInstallerLinux(version, debversion=None, rpmversion=None, rpmrelease=1,
                        python_versions=[], **kwargs):
                        python_versions=[], **kwargs):
     outputdir = GetOutputDir()
     outputdir = GetOutputDir()
@@ -969,6 +1003,7 @@ def MakeInstallerAndroid(version, **kwargs):
 
 
 def MakeInstaller(version, **kwargs):
 def MakeInstaller(version, **kwargs):
     target = GetTarget()
     target = GetTarget()
+
     if target == 'windows':
     if target == 'windows':
         dir = kwargs.pop('installdir', None)
         dir = kwargs.pop('installdir', None)
         if dir is None:
         if dir is None:
@@ -991,8 +1026,10 @@ def MakeInstaller(version, **kwargs):
         if GetTargetArch() == 'x64':
         if GetTargetArch() == 'x64':
             fn += '-x64'
             fn += '-x64'
 
 
+        compressor = kwargs.get('compressor')
+
         MakeInstallerNSIS(version, fn + '.exe', title, dir, **kwargs)
         MakeInstallerNSIS(version, fn + '.exe', title, dir, **kwargs)
-        MakeDebugSymbolArchive(fn + '-pdb.zip', dir)
+        MakeDebugSymbolArchive(fn + '-pdb', compressor)
     elif target == 'linux':
     elif target == 'linux':
         MakeInstallerLinux(version, **kwargs)
         MakeInstallerLinux(version, **kwargs)
     elif target == 'darwin':
     elif target == 'darwin':

+ 37 - 10
makepanda/makepanda.py

@@ -860,7 +860,6 @@ if (COMPILER=="GCC"):
     SmartPkgEnable("OPENAL",    "openal",    ("openal"), "AL/al.h", framework = "OpenAL")
     SmartPkgEnable("OPENAL",    "openal",    ("openal"), "AL/al.h", framework = "OpenAL")
     SmartPkgEnable("SQUISH",    "",          ("squish"), "squish.h")
     SmartPkgEnable("SQUISH",    "",          ("squish"), "squish.h")
     SmartPkgEnable("TIFF",      "libtiff-4", ("tiff"), "tiff.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("VRPN",      "",          ("vrpn", "quat"), ("vrpn", "quat.h", "vrpn/vrpn_Types.h"))
     SmartPkgEnable("OPUS",      "opusfile",  ("opusfile", "opus", "ogg"), ("ogg/ogg.h", "opus/opusfile.h", "opus"))
     SmartPkgEnable("OPUS",      "opusfile",  ("opusfile", "opus", "ogg"), ("ogg/ogg.h", "opus/opusfile.h", "opus"))
     SmartPkgEnable("JPEG",      "",          ("jpeg"), "jpeglib.h")
     SmartPkgEnable("JPEG",      "",          ("jpeg"), "jpeglib.h")
@@ -914,6 +913,23 @@ if (COMPILER=="GCC"):
                 for ffmpeg_lib in ffmpeg_libs:
                 for ffmpeg_lib in ffmpeg_libs:
                     LibName("FFMPEG", "-Wl,--exclude-libs,%s.a" % (ffmpeg_lib))
                     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() not in ("darwin", "emscripten"):
     if GetTarget() not in ("darwin", "emscripten"):
         for fcollada_lib in fcollada_libs:
         for fcollada_lib in fcollada_libs:
             LibName("FCOLLADA", "-Wl,--exclude-libs,lib%s.a" % (fcollada_lib))
             LibName("FCOLLADA", "-Wl,--exclude-libs,lib%s.a" % (fcollada_lib))
@@ -945,6 +961,9 @@ if (COMPILER=="GCC"):
             LibName("OPENEXR", "-Wl,--exclude-libs,libIlmImfUtil.a")
             LibName("OPENEXR", "-Wl,--exclude-libs,libIlmImfUtil.a")
             LibName("OPENEXR", "-Wl,--exclude-libs,libIlmThread.a")
             LibName("OPENEXR", "-Wl,--exclude-libs,libIlmThread.a")
             LibName("OPENEXR", "-Wl,--exclude-libs,libImath.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"):
         if not PkgSkip("VORBIS"):
             LibName("VORBIS", "-Wl,--exclude-libs,libogg.a")
             LibName("VORBIS", "-Wl,--exclude-libs,libogg.a")
@@ -1072,8 +1091,6 @@ if (COMPILER=="GCC"):
             LibName("FFMPEG", "-undefined dynamic_lookup")
             LibName("FFMPEG", "-undefined dynamic_lookup")
         if not PkgSkip("ASSIMP"):
         if not PkgSkip("ASSIMP"):
             LibName("ASSIMP", "-undefined dynamic_lookup")
             LibName("ASSIMP", "-undefined dynamic_lookup")
-        if not PkgSkip("OPENEXR"):
-            LibName("OPENEXR", "-undefined dynamic_lookup")
         if not PkgSkip("VRPN"):
         if not PkgSkip("VRPN"):
             LibName("VRPN", "-undefined dynamic_lookup")
             LibName("VRPN", "-undefined dynamic_lookup")
 
 
@@ -1214,7 +1231,7 @@ def CompileCxx(obj,src,opts):
             cmd = "cl "
             cmd = "cl "
             if GetTargetArch() == 'x64':
             if GetTargetArch() == 'x64':
                 cmd += "/favor:blend "
                 cmd += "/favor:blend "
-            cmd += "/wd4996 /wd4275 /wd4273 "
+            cmd += "/wd4996 "
 
 
             # Set the minimum version to Windows Vista.
             # Set the minimum version to Windows Vista.
             cmd += "/DWINVER=0x600 "
             cmd += "/DWINVER=0x600 "
@@ -1246,7 +1263,7 @@ def CompileCxx(obj,src,opts):
             if (building):
             if (building):
                 cmd += " /DBUILDING_" + 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 += " /bigobj"
 
 
             cmd += " /Zm300"
             cmd += " /Zm300"
@@ -1264,7 +1281,7 @@ def CompileCxx(obj,src,opts):
             cmd = "icl "
             cmd = "icl "
             if GetTargetArch() == 'x64':
             if GetTargetArch() == 'x64':
                 cmd += "/favor:blend "
                 cmd += "/favor:blend "
-            cmd += "/wd4996 /wd4275 /wd4267 /wd4101 /wd4273 "
+            cmd += "/wd4996 /wd4267 /wd4101 "
             cmd += "/DWINVER=0x600 "
             cmd += "/DWINVER=0x600 "
             cmd += "/Fo" + obj + " /c"
             cmd += "/Fo" + obj + " /c"
             for x in ipath: cmd += " /I" + x
             for x in ipath: cmd += " /I" + x
@@ -1377,6 +1394,10 @@ def CompileCxx(obj,src,opts):
                 if 'NOARCH:' + arch.upper() not in opts:
                 if 'NOARCH:' + arch.upper() not in opts:
                     cmd += " -arch %s" % arch
                     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 "SYSROOT" in SDK:
             if GetTarget() != "android":
             if GetTarget() != "android":
                 cmd += ' --sysroot=%s' % (SDK["SYSROOT"])
                 cmd += ' --sysroot=%s' % (SDK["SYSROOT"])
@@ -1477,10 +1498,7 @@ def CompileCxx(obj,src,opts):
         if (optlevel==4): cmd += " -O3 -DNDEBUG"
         if (optlevel==4): cmd += " -O3 -DNDEBUG"
 
 
         # Enable more warnings.
         # 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.
         # Ignore unused variables in NDEBUG builds, often used in asserts.
         if optlevel == 4:
         if optlevel == 4:
@@ -6137,17 +6155,21 @@ for VER in MAYAVERSIONS:
     TargetAdd('egg2maya'+VNUM+'.exe', opts=['ADVAPI']+ARCH_OPTS)
     TargetAdd('egg2maya'+VNUM+'.exe', opts=['ADVAPI']+ARCH_OPTS)
 
 
 if MAYA_BUILT:
 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('mayaprogs_mayaConversionClient.obj', opts=OPTS, input='mayaConversionClient.cxx')
 
 
     TargetAdd('maya2egg_mayaToEggClient.obj', opts=OPTS, input='mayaToEggClient.cxx')
     TargetAdd('maya2egg_mayaToEggClient.obj', opts=OPTS, input='mayaToEggClient.cxx')
     TargetAdd('maya2egg_client.exe', input='mayaprogs_mayaConversionClient.obj')
     TargetAdd('maya2egg_client.exe', input='mayaprogs_mayaConversionClient.obj')
     TargetAdd('maya2egg_client.exe', input='maya2egg_mayaToEggClient.obj')
     TargetAdd('maya2egg_client.exe', input='maya2egg_mayaToEggClient.obj')
     TargetAdd('maya2egg_client.exe', input=COMMON_EGG2X_LIBS)
     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_eggToMayaClient.obj', opts=OPTS, input='eggToMayaClient.cxx')
     TargetAdd('egg2maya_client.exe', input='mayaprogs_mayaConversionClient.obj')
     TargetAdd('egg2maya_client.exe', input='mayaprogs_mayaConversionClient.obj')
     TargetAdd('egg2maya_client.exe', input='egg2maya_eggToMayaClient.obj')
     TargetAdd('egg2maya_client.exe', input='egg2maya_eggToMayaClient.obj')
     TargetAdd('egg2maya_client.exe', input=COMMON_EGG2X_LIBS)
     TargetAdd('egg2maya_client.exe', input=COMMON_EGG2X_LIBS)
+    TargetAdd('egg2maya_client.exe', opts=['NOARCH:ARM64'])
 
 
 #
 #
 # DIRECTORY: contrib/src/ai/
 # DIRECTORY: contrib/src/ai/
@@ -6228,6 +6250,9 @@ if PkgSkip("PYTHON") == 0:
         PyTargetAdd('deploy-stubw.exe', input='deploy-stubw.obj')
         PyTargetAdd('deploy-stubw.exe', input='deploy-stubw.obj')
         PyTargetAdd('deploy-stubw.exe', opts=['MACOS_APP_BUNDLE', 'DEPLOYSTUB', 'NOICON'])
         PyTargetAdd('deploy-stubw.exe', opts=['MACOS_APP_BUNDLE', 'DEPLOYSTUB', 'NOICON'])
     elif GetTarget() == 'android':
     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_main.obj', opts=OPTS, input='android_main.cxx')
         PyTargetAdd('deploy-stubw_android_log.obj', opts=OPTS, input='android_log.c')
         PyTargetAdd('deploy-stubw_android_log.obj', opts=OPTS, input='android_log.c')
         PyTargetAdd('libdeploy-stubw.dll', input='android_native_app_glue.obj')
         PyTargetAdd('libdeploy-stubw.dll', input='android_native_app_glue.obj')
@@ -6356,6 +6381,8 @@ def ParallelMake(tasklist):
             tasklist = extras
             tasklist = extras
         sys.stdout.flush()
         sys.stdout.flush()
         if tasksqueued == 0:
         if tasksqueued == 0:
+            if len(tasklist) > 0:
+                continue
             break
             break
         donetask = donequeue.get()
         donetask = donequeue.get()
         if donetask == 0:
         if donetask == 0:

+ 33 - 5
makepanda/makepandacore.py

@@ -588,6 +588,26 @@ def GetFlexVersion():
         Warn("Unable to detect flex version")
         Warn("Unable to detect flex version")
         return (0, 0, 0)
         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
 ## LocateBinary
@@ -873,8 +893,11 @@ def JavaGetImports(path):
     imports = []
     imports = []
     try:
     try:
         for match in JavaImportRegex.finditer(source, 0):
         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:
     except:
         print("Failed to determine dependencies of \"" + path  +"\".")
         print("Failed to determine dependencies of \"" + path  +"\".")
         raise
         raise
@@ -3375,10 +3398,15 @@ def SetOrigExt(x, v):
     ORIG_EXT[x] = v
     ORIG_EXT[x] = v
 
 
 def GetExtensionSuffix():
 def GetExtensionSuffix():
-    if GetTarget() == 'emscripten':
+    target = GetTarget()
+    if target == '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 target == 'emscripten':
         return '.so'
         return '.so'
-
-    if CrossCompiling():
+    elif CrossCompiling():
         return '.{0}.so'.format(GetPythonABI())
         return '.{0}.so'.format(GetPythonABI())
     else:
     else:
         import _imp
         import _imp

+ 8 - 2
panda/src/android/PythonActivity.java

@@ -16,8 +16,14 @@ package org.panda3d.android;
 import org.panda3d.android.PandaActivity;
 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 {
 public class PythonActivity extends PandaActivity {
+    // This is required by plyer.
+    public static PythonActivity mActivity;
+
+    public PythonActivity() {
+        mActivity = this;
+    }
 }
 }

+ 2 - 3
panda/src/audio/audioLoadRequest.I

@@ -59,7 +59,7 @@ get_positional() const {
  */
  */
 INLINE bool AudioLoadRequest::
 INLINE bool AudioLoadRequest::
 is_ready() const {
 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::
 INLINE AudioSound *AudioLoadRequest::
 get_sound() const {
 get_sound() const {
-  nassertr_always(done(), nullptr);
-  return (AudioSound *)_result;
+  return (AudioSound *)get_result();
 }
 }

+ 5 - 0
panda/src/audiotraits/CMakeLists.txt

@@ -60,6 +60,11 @@ if(HAVE_OPENAL)
   set_target_properties(p3openal_audio PROPERTIES DEFINE_SYMBOL BUILDING_OPENAL_AUDIO)
   set_target_properties(p3openal_audio PROPERTIES DEFINE_SYMBOL BUILDING_OPENAL_AUDIO)
   target_link_libraries(p3openal_audio panda PKG::OPENAL)
   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
   install(TARGETS p3openal_audio
     EXPORT OpenAL COMPONENT OpenAL
     EXPORT OpenAL COMPONENT OpenAL
     DESTINATION ${CMAKE_INSTALL_LIBDIR}
     DESTINATION ${CMAKE_INSTALL_LIBDIR}

+ 3 - 2
panda/src/bullet/bulletAllHitsRayResult.h

@@ -20,13 +20,14 @@
 #include "bullet_utils.h"
 #include "bullet_utils.h"
 
 
 #include "luse.h"
 #include "luse.h"
+#include "memoryBase.h"
 #include "pandaNode.h"
 #include "pandaNode.h"
 #include "collideMask.h"
 #include "collideMask.h"
 
 
 /**
 /**
  *
  *
  */
  */
-struct EXPCL_PANDABULLET BulletRayHit {
+struct EXPCL_PANDABULLET BulletRayHit : public MemoryBase {
 
 
 PUBLISHED:
 PUBLISHED:
   INLINE static BulletRayHit empty();
   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:
 PUBLISHED:
   INLINE static BulletAllHitsRayResult empty();
   INLINE static BulletAllHitsRayResult empty();

+ 2 - 1
panda/src/bullet/bulletClosestHitRayResult.h

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

+ 2 - 1
panda/src/bullet/bulletClosestHitSweepResult.h

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

+ 2 - 2
panda/src/bullet/bulletConvexPointCloudShape.I

@@ -16,8 +16,8 @@
  */
  */
 INLINE BulletConvexPointCloudShape::
 INLINE BulletConvexPointCloudShape::
 BulletConvexPointCloudShape() :
 BulletConvexPointCloudShape() :
-  _scale(1),
-  _shape(nullptr) {
+  _shape(nullptr),
+  _scale(1) {
 }
 }
 
 
 /**
 /**

+ 2 - 2
panda/src/bullet/bulletTriangleMeshShape.cxx

@@ -29,9 +29,9 @@ TypeHandle BulletTriangleMeshShape::_type_handle;
  */
  */
 BulletTriangleMeshShape::
 BulletTriangleMeshShape::
 BulletTriangleMeshShape() :
 BulletTriangleMeshShape() :
-  _mesh(nullptr),
-  _gimpact_shape(nullptr),
   _bvh_shape(nullptr),
   _bvh_shape(nullptr),
+  _gimpact_shape(nullptr),
+  _mesh(nullptr),
   _dynamic(false),
   _dynamic(false),
   _compress(false),
   _compress(false),
   _bvh(false) {
   _bvh(false) {

+ 2 - 2
panda/src/chan/animControl.cxx

@@ -32,8 +32,8 @@ AnimControl(const std::string &name, PartBundle *part,
   Namable(name),
   Namable(name),
   _pending_lock(name),
   _pending_lock(name),
   _pending_cvar(_pending_lock),
   _pending_cvar(_pending_lock),
-  _bound_joints(BitArray::all_on()),
-  _part(part)
+  _part(part),
+  _bound_joints(BitArray::all_on())
 {
 {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::update_type(this, get_class_type());
   MemoryUsage::update_type(this, get_class_type());

+ 7 - 7
panda/src/char/character.cxx

@@ -38,16 +38,16 @@ PStatCollector Character::_animation_pcollector("*:Animation");
 Character::
 Character::
 Character(const Character &copy, bool copy_bundles) :
 Character(const Character &copy, bool copy_bundles) :
   PartBundleNode(copy),
   PartBundleNode(copy),
+  _last_auto_update(-1.0),
+  _view_frame(-1),
+  _view_distance2(0.0f),
   _lod_center(copy._lod_center),
   _lod_center(copy._lod_center),
   _lod_far_distance(copy._lod_far_distance),
   _lod_far_distance(copy._lod_far_distance),
   _lod_near_distance(copy._lod_near_distance),
   _lod_near_distance(copy._lod_near_distance),
   _lod_delay_factor(copy._lod_delay_factor),
   _lod_delay_factor(copy._lod_delay_factor),
   _do_lod_animation(copy._do_lod_animation),
   _do_lod_animation(copy._do_lod_animation),
   _joints_pcollector(copy._joints_pcollector),
   _joints_pcollector(copy._joints_pcollector),
-  _skinning_pcollector(copy._skinning_pcollector),
-  _last_auto_update(-1.0),
-  _view_frame(-1),
-  _view_distance2(0.0f)
+  _skinning_pcollector(copy._skinning_pcollector)
 {
 {
   set_cull_callback();
   set_cull_callback();
 
 
@@ -75,11 +75,11 @@ Character(const Character &copy, bool copy_bundles) :
 Character::
 Character::
 Character(const std::string &name) :
 Character(const std::string &name) :
   PartBundleNode(name, new CharacterJointBundle(name)),
   PartBundleNode(name, new CharacterJointBundle(name)),
-  _joints_pcollector(PStatCollector(_animation_pcollector, name), "Joints"),
-  _skinning_pcollector(PStatCollector(_animation_pcollector, name), "Vertices"),
   _last_auto_update(-1.0),
   _last_auto_update(-1.0),
   _view_frame(-1),
   _view_frame(-1),
-  _view_distance2(0.0f)
+  _view_distance2(0.0f),
+  _joints_pcollector(PStatCollector(_animation_pcollector, name), "Joints"),
+  _skinning_pcollector(PStatCollector(_animation_pcollector, name), "Vertices")
 {
 {
   set_cull_callback();
   set_cull_callback();
   clear_lod_animation();
   clear_lod_animation();

+ 4 - 36
panda/src/collide/collisionBox.I

@@ -17,11 +17,10 @@
  */
  */
 INLINE CollisionBox::
 INLINE CollisionBox::
 CollisionBox(const LPoint3 &center, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) :
 CollisionBox(const LPoint3 &center, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) :
-  _center(center), _x(x), _y(y), _z(z)
+  _center(center)
 {
 {
-  _min = LPoint3(_center.get_x() - _x, _center.get_y() - _y, _center.get_z() - _z);
-  _max = LPoint3(_center.get_x() + _x, _center.get_y() + _y, _center.get_z() + _z);
-  _radius = sqrt(_x*_x + _y*_y + _z*_z);
+  _min = LPoint3(_center.get_x() - x, _center.get_y() - y, _center.get_z() - z);
+  _max = LPoint3(_center.get_x() + x, _center.get_y() + y, _center.get_z() + z);
   for(int v = 0; v < 8; v++)
   for(int v = 0; v < 8; v++)
     _vertex[v] = get_point_aabb(v);
     _vertex[v] = get_point_aabb(v);
   for(int p = 0; p < 6; p++)
   for(int p = 0; p < 6; p++)
@@ -37,10 +36,6 @@ CollisionBox(const LPoint3 &min, const LPoint3 &max) :
   _min(min), _max(max)
   _min(min), _max(max)
 {
 {
   _center = (_min + _max) / 2;
   _center = (_min + _max) / 2;
-  _x = _center.get_x() - _min.get_x();
-  _y = _center.get_y() - _min.get_y();
-  _z = _center.get_z() - _min.get_z();
-  _radius = sqrt(_x*_x + _y*_y + _z*_z);
   for(int v = 0; v < 8; v++)
   for(int v = 0; v < 8; v++)
     _vertex[v] = get_point_aabb(v);
     _vertex[v] = get_point_aabb(v);
   for(int p = 0; p < 6; p++)
   for(int p = 0; p < 6; p++)
@@ -63,11 +58,7 @@ CollisionBox(const CollisionBox &copy) :
   CollisionSolid(copy),
   CollisionSolid(copy),
   _center(copy._center),
   _center(copy._center),
   _min(copy._min),
   _min(copy._min),
-  _max(copy._max),
-  _x(copy._x ),
-  _y(copy._y ),
-  _z(copy._z ),
-  _radius(copy._radius )
+  _max(copy._max)
 {
 {
   for(int v = 0; v < 8; v++)
   for(int v = 0; v < 8; v++)
     _vertex[v] = copy._vertex[v];
     _vertex[v] = copy._vertex[v];
@@ -152,7 +143,6 @@ get_point(int n) const {
   return _vertex[n];
   return _vertex[n];
 }
 }
 
 
-
 /**
 /**
  * Returns the nth vertex of the Axis Aligned Bounding Box.
  * Returns the nth vertex of the Axis Aligned Bounding Box.
  */
  */
@@ -243,20 +233,6 @@ calc_to_3d_mat(LMatrix4 &to_3d_mat,int plane) const {
   to_3d_mat.set_row(3, get_plane(plane).get_point());
   to_3d_mat.set_row(3, get_plane(plane).get_point());
 }
 }
 
 
-/**
- * Fills the indicated matrix with the appropriate rotation transform to move
- * points from the 2-d plane into the 3-d (X, 0, Z) plane.
- *
- * This is essentially similar to calc_to_3d_mat, except that the matrix is
- * rederived from whatever is stored in _to_2d_mat, guaranteeing that it will
- * match whatever algorithm produced that one, even if it was produced on a
- * different machine with different numerical precision.
- */
-INLINE void CollisionBox::
-rederive_to_3d_mat(LMatrix4 &to_3d_mat, int plane) const {
-  to_3d_mat.invert_from(_to_2d_mat[plane]);
-}
-
 /**
 /**
  * Extrude the indicated point in the polygon's 2-d definition space back into
  * Extrude the indicated point in the polygon's 2-d definition space back into
  * 3-d coordinates.
  * 3-d coordinates.
@@ -295,11 +271,3 @@ operator = (const CollisionBox::PointDef &copy) {
   _p = copy._p;
   _p = copy._p;
   _v = copy._v;
   _v = copy._v;
 }
 }
-
-/**
- * returns the points that form the nth plane
- */
-INLINE CollisionBox::Points CollisionBox::
-get_plane_points(int n) {
-  return _points[n];
-}

+ 54 - 81
panda/src/collide/collisionBox.cxx

@@ -66,14 +66,11 @@ make_copy() {
  * Compute parameters for each of the box's sides
  * Compute parameters for each of the box's sides
  */
  */
 void CollisionBox::
 void CollisionBox::
-setup_box(){
-  for(int plane = 0; plane < 6; plane++) {
-    LPoint3 array[4];
-    array[0] = get_point(plane_def[plane][0]);
-    array[1] = get_point(plane_def[plane][1]);
-    array[2] = get_point(plane_def[plane][2]);
-    array[3] = get_point(plane_def[plane][3]);
-    setup_points(array, array+4, plane);
+setup_box() {
+  assert(sizeof(_points) / sizeof(_points[0]) == 6);
+  assert(sizeof(_points[0]) / sizeof(_points[0][0]) == 4);
+  for (int plane = 0; plane < 6; plane++) {
+    setup_points(plane);
   }
   }
 }
 }
 
 
@@ -81,11 +78,8 @@ setup_box(){
  * Computes the plane and 2d projection of points that make up this side.
  * Computes the plane and 2d projection of points that make up this side.
  */
  */
 void CollisionBox::
 void CollisionBox::
-setup_points(const LPoint3 *begin, const LPoint3 *end, int plane) {
-  int num_points = end - begin;
-  nassertv(num_points >= 3);
-
-  _points[plane].clear();
+setup_points(int plane) {
+  PointDef *points = _points[plane];
 
 
   // Construct a matrix that rotates the points from the (X,0,Z) plane into
   // Construct a matrix that rotates the points from the (X,0,Z) plane into
   // the 3-d plane.
   // the 3-d plane.
@@ -96,32 +90,15 @@ setup_points(const LPoint3 *begin, const LPoint3 *end, int plane) {
   _to_2d_mat[plane].invert_from(to_3d_mat);
   _to_2d_mat[plane].invert_from(to_3d_mat);
 
 
   // Now project all of the points onto the 2-d plane.
   // Now project all of the points onto the 2-d plane.
-
-  const LPoint3 *pi;
-  for (pi = begin; pi != end; ++pi) {
-    LPoint3 point = (*pi) * _to_2d_mat[plane];
-    _points[plane].push_back(PointDef(point[0], point[2]));
+  for (size_t i = 0; i < 4; ++i) {
+    LPoint3 point = get_point(plane_def[plane][i]) * _to_2d_mat[plane];
+    points[i] = PointDef(point[0], point[2]);
   }
   }
 
 
-  nassertv(_points[plane].size() >= 3);
-
-#ifndef NDEBUG
-  /*
-  // Now make sure the points define a convex polygon.
-  if (is_concave()) {
-  collide_cat.error() << "Invalid concave CollisionPolygon defined:\n";
-  const LPoint3 *pi;
-  for (pi = begin; pi != end; ++pi) {
-  collide_cat.error(false) << "  " << (*pi) << "\n";
-  }
-  collide_cat.error(false)
-  << "  normal " << normal << " with length " << normal.length() << "\n";
-  _points.clear();
-  }
-  */
-#endif
-
-  compute_vectors(_points[plane]);
+  for (size_t i = 0; i < 4; i++) {
+    points[i]._v = points[(i + 1) % 4]._p - points[i]._p;
+    points[i]._v.normalize();
+  }
 }
 }
 
 
 /**
 /**
@@ -146,10 +123,6 @@ xform(const LMatrix4 &mat) {
   for(int p = 0; p < 6 ; p++) {
   for(int p = 0; p < 6 ; p++) {
     _planes[p] = set_plane(p);
     _planes[p] = set_plane(p);
   }
   }
-  _x = _vertex[0].get_x() - _center.get_x();
-  _y = _vertex[0].get_y() - _center.get_y();
-  _z = _vertex[0].get_z() - _center.get_z();
-  _radius = sqrt(_x * _x + _y * _y + _z * _z);
   setup_box();
   setup_box();
   mark_viz_stale();
   mark_viz_stale();
   mark_internal_bounds_stale();
   mark_internal_bounds_stale();
@@ -196,7 +169,11 @@ output(std::ostream &out) const {
  */
  */
 PT(BoundingVolume) CollisionBox::
 PT(BoundingVolume) CollisionBox::
 compute_internal_bounds() const {
 compute_internal_bounds() const {
-  return new BoundingSphere(_center, _radius);
+  PN_stdfloat x = _vertex[0].get_x() - _center.get_x();
+  PN_stdfloat y = _vertex[0].get_y() - _center.get_y();
+  PN_stdfloat z = _vertex[0].get_z() - _center.get_z();
+  PN_stdfloat radius = sqrt(x * x + y * y + z * z);
+  return new BoundingSphere(_center, radius);
 }
 }
 
 
 /**
 /**
@@ -233,10 +210,8 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   LVector3 normal;
   LVector3 normal;
 
 
   for(ip = 0, intersect = false; ip < 6 && !intersect; ip++) {
   for(ip = 0, intersect = false; ip < 6 && !intersect; ip++) {
-    plane = get_plane( ip );
-    if (_points[ip].size() < 3) {
-      continue;
-    }
+    plane = get_plane(ip);
+
     if (wrt_prev_space != wrt_space) {
     if (wrt_prev_space != wrt_space) {
       // If we have a delta between the previous position and the current
       // If we have a delta between the previous position and the current
       // position, we use that to determine some more properties of the
       // position, we use that to determine some more properties of the
@@ -322,17 +297,17 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
       Points new_points;
       Points new_points;
       if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform(),ip)) {
       if (apply_clip_plane(new_points, cpa, entry.get_into_node_path().get_net_transform(),ip)) {
         // All points are behind the clip plane; just do the default test.
         // All points are behind the clip plane; just do the default test.
-        edge_dist = dist_to_polygon(p, _points[ip]);
+        edge_dist = dist_to_polygon(p, _points[ip], 4);
       } else if (new_points.empty()) {
       } else if (new_points.empty()) {
         // The polygon is completely clipped.
         // The polygon is completely clipped.
         continue;
         continue;
       } else {
       } else {
         // Test against the clipped polygon.
         // Test against the clipped polygon.
-        edge_dist = dist_to_polygon(p, new_points);
+        edge_dist = dist_to_polygon(p, new_points.data(), new_points.size());
       }
       }
     } else {
     } else {
       // No clip plane is in effect.  Do the default test.
       // No clip plane is in effect.  Do the default test.
-      edge_dist = dist_to_polygon(p, _points[ip]);
+      edge_dist = dist_to_polygon(p, _points[ip], 4);
     }
     }
 
 
     max_dist = from_radius;
     max_dist = from_radius;
@@ -506,7 +481,7 @@ test_intersection_from_parabola(const CollisionEntry &entry) const {
   LParabola local_p(parabola->get_parabola());
   LParabola local_p(parabola->get_parabola());
   local_p.xform(wrt_mat);
   local_p.xform(wrt_mat);
 
 
-  PN_stdfloat t = INT_MAX;
+  PN_stdfloat t = FLT_MAX;
   PN_stdfloat t1, t2;
   PN_stdfloat t1, t2;
   int intersecting_face = -1;
   int intersecting_face = -1;
   for (int i = 0; i < get_num_planes(); i++) {
   for (int i = 0; i < get_num_planes(); i++) {
@@ -1129,13 +1104,13 @@ apply_clip_plane(CollisionBox::Points &new_points,
       LPlane plane = plane_node->get_plane() * new_transform->get_mat();
       LPlane plane = plane_node->get_plane() * new_transform->get_mat();
       if (first_plane) {
       if (first_plane) {
         first_plane = false;
         first_plane = false;
-        if (!clip_polygon(new_points, _points[plane_no], plane, plane_no)) {
+        if (!clip_polygon(new_points, _points[plane_no], 4, plane, plane_no)) {
           all_in = false;
           all_in = false;
         }
         }
       } else {
       } else {
         Points last_points;
         Points last_points;
         last_points.swap(new_points);
         last_points.swap(new_points);
-        if (!clip_polygon(new_points, last_points, plane, plane_no)) {
+        if (!clip_polygon(new_points, last_points.data(), last_points.size(), plane, plane_no)) {
           all_in = false;
           all_in = false;
         }
         }
       }
       }
@@ -1158,10 +1133,10 @@ apply_clip_plane(CollisionBox::Points &new_points,
  */
  */
 bool CollisionBox::
 bool CollisionBox::
 clip_polygon(CollisionBox::Points &new_points,
 clip_polygon(CollisionBox::Points &new_points,
-             const CollisionBox::Points &source_points,
+             const PointDef *source_points, size_t num_source_points,
              const LPlane &plane, int plane_no) const {
              const LPlane &plane, int plane_no) const {
   new_points.clear();
   new_points.clear();
-  if (source_points.empty()) {
+  if (num_source_points == 0) {
     return true;
     return true;
   }
   }
 
 
@@ -1173,7 +1148,7 @@ clip_polygon(CollisionBox::Points &new_points,
     if (plane.dist_to_plane(get_plane(plane_no).get_point()) < 0.0) {
     if (plane.dist_to_plane(get_plane(plane_no).get_point()) < 0.0) {
       // A point within the polygon is behind the clipping plane: the polygon
       // A point within the polygon is behind the clipping plane: the polygon
       // is all in.
       // is all in.
-      new_points = source_points;
+      new_points.insert(new_points.end(), source_points, source_points + num_source_points);
       return true;
       return true;
     }
     }
     return false;
     return false;
@@ -1194,14 +1169,13 @@ clip_polygon(CollisionBox::Points &new_points,
   // We might increase the number of vertices by as many as 1, if the plane
   // We might increase the number of vertices by as many as 1, if the plane
   // clips off exactly one corner.  (We might also decrease the number of
   // clips off exactly one corner.  (We might also decrease the number of
   // vertices, or keep them the same number.)
   // vertices, or keep them the same number.)
-  new_points.reserve(source_points.size() + 1);
+  new_points.reserve(num_source_points + 1);
 
 
-  LPoint2 last_point = source_points.back()._p;
+  LPoint2 last_point = source_points[num_source_points - 1]._p;
   bool last_is_in = !is_right(last_point - from2d, delta2d);
   bool last_is_in = !is_right(last_point - from2d, delta2d);
   bool all_in = last_is_in;
   bool all_in = last_is_in;
-  Points::const_iterator pi;
-  for (pi = source_points.begin(); pi != source_points.end(); ++pi) {
-    const LPoint2 &this_point = (*pi)._p;
+  for (size_t pi = 0; pi < num_source_points; ++pi) {
+    const LPoint2 &this_point = source_points[pi]._p;
     bool this_is_in = !is_right(this_point - from2d, delta2d);
     bool this_is_in = !is_right(this_point - from2d, delta2d);
 
 
     // There appears to be a compiler bug in gcc 4.0: we need to extract this
     // There appears to be a compiler bug in gcc 4.0: we need to extract this
@@ -1234,15 +1208,13 @@ clip_polygon(CollisionBox::Points &new_points,
   return all_in;
   return all_in;
 }
 }
 
 
-
 /**
 /**
  * Returns the linear distance from the 2-d point to the nearest part of the
  * Returns the linear distance from the 2-d point to the nearest part of the
  * polygon defined by the points vector.  The result is negative if the point
  * polygon defined by the points vector.  The result is negative if the point
  * is within the polygon.
  * is within the polygon.
  */
  */
 PN_stdfloat CollisionBox::
 PN_stdfloat CollisionBox::
-dist_to_polygon(const LPoint2 &p, const CollisionBox::Points &points) const {
-
+dist_to_polygon(const LPoint2 &p, const PointDef *points, size_t num_points) const {
   // We know that that the polygon is convex and is defined with the points in
   // We know that that the polygon is convex and is defined with the points in
   // counterclockwise order.  Therefore, we simply compare the signed distance
   // counterclockwise order.  Therefore, we simply compare the signed distance
   // to each line segment; we ignore any negative values, and take the minimum
   // to each line segment; we ignore any negative values, and take the minimum
@@ -1254,10 +1226,9 @@ dist_to_polygon(const LPoint2 &p, const CollisionBox::Points &points) const {
   bool got_dist = false;
   bool got_dist = false;
   PN_stdfloat best_dist = -1.0f;
   PN_stdfloat best_dist = -1.0f;
 
 
-  size_t num_points = points.size();
   for (size_t i = 0; i < num_points - 1; ++i) {
   for (size_t i = 0; i < num_points - 1; ++i) {
     PN_stdfloat d = dist_to_line_segment(p, points[i]._p, points[i + 1]._p,
     PN_stdfloat d = dist_to_line_segment(p, points[i]._p, points[i + 1]._p,
-                                   points[i]._v);
+                                         points[i]._v);
     if (d >= 0.0f) {
     if (d >= 0.0f) {
       if (!got_dist || d < best_dist) {
       if (!got_dist || d < best_dist) {
         best_dist = d;
         best_dist = d;
@@ -1267,7 +1238,7 @@ dist_to_polygon(const LPoint2 &p, const CollisionBox::Points &points) const {
   }
   }
 
 
   PN_stdfloat d = dist_to_line_segment(p, points[num_points - 1]._p, points[0]._p,
   PN_stdfloat d = dist_to_line_segment(p, points[num_points - 1]._p, points[0]._p,
-                                 points[num_points - 1]._v);
+                                       points[num_points - 1]._v);
   if (d >= 0.0f) {
   if (d >= 0.0f) {
     if (!got_dist || d < best_dist) {
     if (!got_dist || d < best_dist) {
       best_dist = d;
       best_dist = d;
@@ -1450,10 +1421,14 @@ write_datagram(BamWriter *manager, Datagram &me) {
   for(int i=0; i < 8; i++) {
   for(int i=0; i < 8; i++) {
     _vertex[i].write_datagram(me);
     _vertex[i].write_datagram(me);
   }
   }
-  me.add_stdfloat(_radius);
-  me.add_stdfloat(_x);
-  me.add_stdfloat(_y);
-  me.add_stdfloat(_z);
+  PN_stdfloat x = _vertex[0].get_x() - _center.get_x();
+  PN_stdfloat y = _vertex[0].get_y() - _center.get_y();
+  PN_stdfloat z = _vertex[0].get_z() - _center.get_z();
+  PN_stdfloat radius = sqrt(x * x + y * y + z * z);
+  me.add_stdfloat(radius);
+  me.add_stdfloat(x);
+  me.add_stdfloat(y);
+  me.add_stdfloat(z);
   for(int i=0; i < 6; i++) {
   for(int i=0; i < 6; i++) {
     _planes[i].write_datagram(me);
     _planes[i].write_datagram(me);
   }
   }
@@ -1461,8 +1436,8 @@ write_datagram(BamWriter *manager, Datagram &me) {
     _to_2d_mat[i].write_datagram(me);
     _to_2d_mat[i].write_datagram(me);
   }
   }
   for(int i=0; i < 6; i++) {
   for(int i=0; i < 6; i++) {
-    me.add_uint16(_points[i].size());
-    for (size_t j = 0; j < _points[i].size(); j++) {
+    me.add_uint16(4);
+    for (size_t j = 0; j < 4; j++) {
       _points[i][j]._p.write_datagram(me);
       _points[i][j]._p.write_datagram(me);
       _points[i][j]._v.write_datagram(me);
       _points[i][j]._v.write_datagram(me);
     }
     }
@@ -1497,10 +1472,10 @@ fillin(DatagramIterator& scan, BamReader* manager) {
   for(int i=0; i < 8; i++) {
   for(int i=0; i < 8; i++) {
     _vertex[i].read_datagram(scan);
     _vertex[i].read_datagram(scan);
   }
   }
-  _radius = scan.get_stdfloat();
-  _x = scan.get_stdfloat();
-  _y = scan.get_stdfloat();
-  _z = scan.get_stdfloat();
+  scan.get_stdfloat();
+  scan.get_stdfloat();
+  scan.get_stdfloat();
+  scan.get_stdfloat();
   for(int i=0; i < 6; i++) {
   for(int i=0; i < 6; i++) {
     _planes[i].read_datagram(scan);
     _planes[i].read_datagram(scan);
   }
   }
@@ -1509,12 +1484,10 @@ fillin(DatagramIterator& scan, BamReader* manager) {
   }
   }
   for(int i=0; i < 6; i++) {
   for(int i=0; i < 6; i++) {
     size_t size = scan.get_uint16();
     size_t size = scan.get_uint16();
+    nassertv(size == 4);
     for (size_t j = 0; j < size; j++) {
     for (size_t j = 0; j < size; j++) {
-      LPoint2 p;
-      LVector2 v;
-      p.read_datagram(scan);
-      v.read_datagram(scan);
-      _points[i].push_back(PointDef(p, v));
+      _points[i][j]._p.read_datagram(scan);
+      _points[i][j]._v.read_datagram(scan);
     }
     }
   }
   }
 }
 }

+ 7 - 10
panda/src/collide/collisionBox.h

@@ -99,7 +99,6 @@ private:
   LPoint3 _center;
   LPoint3 _center;
   LPoint3 _min;
   LPoint3 _min;
   LPoint3 _max;
   LPoint3 _max;
-  PN_stdfloat _x, _y, _z, _radius;
   LPoint3 _vertex[8]; // Each of the Eight Vertices of the Box
   LPoint3 _vertex[8]; // Each of the Eight Vertices of the Box
   LPlane _planes[6]; //Points to each of the six sides of the Box
   LPlane _planes[6]; //Points to each of the six sides of the Box
 
 
@@ -119,6 +118,7 @@ private:
 public:
 public:
   class PointDef {
   class PointDef {
   public:
   public:
+    PointDef() = default;
     INLINE PointDef(const LPoint2 &p, const LVector2 &v);
     INLINE PointDef(const LPoint2 &p, const LVector2 &v);
     INLINE PointDef(PN_stdfloat x, PN_stdfloat y);
     INLINE PointDef(PN_stdfloat x, PN_stdfloat y);
     INLINE PointDef(const PointDef &copy);
     INLINE PointDef(const PointDef &copy);
@@ -134,25 +134,22 @@ public:
                     const Points &points) const;
                     const Points &points) const;
 
 
   bool point_is_inside(const LPoint2 &p, const Points &points) const;
   bool point_is_inside(const LPoint2 &p, const Points &points) const;
-  PN_stdfloat dist_to_polygon(const LPoint2 &p, const Points &points) const;
+  PN_stdfloat dist_to_polygon(const LPoint2 &p, const PointDef *points, size_t num_points) const;
 
 
-  void setup_points(const LPoint3 *begin, const LPoint3 *end, int plane);
+  void setup_points(int plane);
   INLINE LPoint2 to_2d(const LVecBase3 &point3d, int plane) const;
   INLINE LPoint2 to_2d(const LVecBase3 &point3d, int plane) const;
   INLINE void calc_to_3d_mat(LMatrix4 &to_3d_mat, int plane) const;
   INLINE void calc_to_3d_mat(LMatrix4 &to_3d_mat, int plane) const;
-  INLINE void rederive_to_3d_mat(LMatrix4 &to_3d_mat, int plane) const;
   INLINE static LPoint3 to_3d(const LVecBase2 &point2d, const LMatrix4 &to_3d_mat);
   INLINE static LPoint3 to_3d(const LVecBase2 &point2d, const LMatrix4 &to_3d_mat);
-  bool clip_polygon(Points &new_points, const Points &source_points,
-                    const LPlane &plane,int plane_no) const;
+  bool clip_polygon(Points &new_points, const PointDef *source_points,
+                    size_t num_source_points, const LPlane &plane,
+                    int plane_no) const;
   bool apply_clip_plane(Points &new_points, const ClipPlaneAttrib *cpa,
   bool apply_clip_plane(Points &new_points, const ClipPlaneAttrib *cpa,
                         const TransformState *net_transform, int plane_no) const;
                         const TransformState *net_transform, int plane_no) const;
 
 
 private:
 private:
-  Points _points[6]; // one set of points for each of the six planes that make up the box
+  PointDef _points[6][4]; // one set of points for each of the six planes that make up the box
   LMatrix4 _to_2d_mat[6];
   LMatrix4 _to_2d_mat[6];
 
 
-public:
-  INLINE Points get_plane_points( int n );
-
 public:
 public:
   static void register_with_read_factory();
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &me);
   virtual void write_datagram(BamWriter *manager, Datagram &me);

+ 0 - 9
panda/src/collide/collisionHandlerEvent.I

@@ -25,15 +25,6 @@ operator () (const PT(CollisionEntry) &a,
   return a->get_into_node_path() < b->get_into_node_path();
   return a->get_into_node_path() < b->get_into_node_path();
 }
 }
 
 
-/**
- * The assignment operator does absolutely nothing, since this is just a
- * function object class that stores no data.  We define it just to quiet up
- * g++ in -Wall mode.
- */
-INLINE void CollisionHandlerEvent::SortEntries::
-operator = (const CollisionHandlerEvent::SortEntries &) {
-}
-
 /**
 /**
  * Removes all of the previously-added in patterns.  See add_in_pattern.
  * Removes all of the previously-added in patterns.  See add_in_pattern.
  */
  */

+ 0 - 1
panda/src/collide/collisionHandlerEvent.h

@@ -90,7 +90,6 @@ protected:
     INLINE bool
     INLINE bool
     operator () (const PT(CollisionEntry) &a,
     operator () (const PT(CollisionEntry) &a,
                  const PT(CollisionEntry) &b) const;
                  const PT(CollisionEntry) &b) const;
-    INLINE void operator = (const SortEntries &other);
   };
   };
 
 
   typedef pset<PT(CollisionEntry), SortEntries> Colliding;
   typedef pset<PT(CollisionEntry), SortEntries> Colliding;

+ 0 - 1
panda/src/collide/collisionHandlerPhysical_ext.cxx

@@ -21,7 +21,6 @@
  */
  */
 PyObject *Extension<CollisionHandlerPhysical>::
 PyObject *Extension<CollisionHandlerPhysical>::
 __reduce__(PyObject *self) const {
 __reduce__(PyObject *self) const {
-  extern struct Dtool_PyTypedObject Dtool_Datagram;
   extern struct Dtool_PyTypedObject Dtool_NodePath;
   extern struct Dtool_PyTypedObject Dtool_NodePath;
 
 
   // Create a tuple with all the NodePath pointers.
   // Create a tuple with all the NodePath pointers.

+ 7 - 7
panda/src/collide/collisionLevelStateBase.I

@@ -31,8 +31,8 @@ CollisionLevelStateBase(const CollisionLevelStateBase &parent, PandaNode *child)
   _node_path(parent._node_path, child),
   _node_path(parent._node_path, child),
   _colliders(parent._colliders),
   _colliders(parent._colliders),
   _include_mask(parent._include_mask),
   _include_mask(parent._include_mask),
-  _local_bounds(parent._local_bounds),
-  _node_gbv(child->get_bounds()->as_geometric_bounding_volume())
+  _node_gbv(child->get_bounds()->as_geometric_bounding_volume()),
+  _local_bounds(parent._local_bounds)
 {
 {
 }
 }
 
 
@@ -44,8 +44,8 @@ CollisionLevelStateBase(const CollisionLevelStateBase &parent, const PandaNode::
   _node_path(parent._node_path, child.get_child()),
   _node_path(parent._node_path, child.get_child()),
   _colliders(parent._colliders),
   _colliders(parent._colliders),
   _include_mask(parent._include_mask),
   _include_mask(parent._include_mask),
-  _local_bounds(parent._local_bounds),
-  _node_gbv(child.get_bounds())
+  _node_gbv(child.get_bounds()),
+  _local_bounds(parent._local_bounds)
 {
 {
 }
 }
 
 
@@ -57,9 +57,9 @@ CollisionLevelStateBase(const CollisionLevelStateBase &copy) :
   _node_path(copy._node_path),
   _node_path(copy._node_path),
   _colliders(copy._colliders),
   _colliders(copy._colliders),
   _include_mask(copy._include_mask),
   _include_mask(copy._include_mask),
+  _node_gbv(copy._node_gbv),
   _local_bounds(copy._local_bounds),
   _local_bounds(copy._local_bounds),
-  _parent_bounds(copy._parent_bounds),
-  _node_gbv(copy._node_gbv)
+  _parent_bounds(copy._parent_bounds)
 {
 {
 }
 }
 
 
@@ -71,9 +71,9 @@ operator = (const CollisionLevelStateBase &copy) {
   _node_path = copy._node_path;
   _node_path = copy._node_path;
   _colliders = copy._colliders;
   _colliders = copy._colliders;
   _include_mask = copy._include_mask;
   _include_mask = copy._include_mask;
+  _node_gbv = copy._node_gbv;
   _local_bounds = copy._local_bounds;
   _local_bounds = copy._local_bounds;
   _parent_bounds = copy._parent_bounds;
   _parent_bounds = copy._parent_bounds;
-  _node_gbv = copy._node_gbv;
 }
 }
 
 
 /**
 /**

+ 3 - 3
panda/src/collide/collisionTraverser.cxx

@@ -647,7 +647,7 @@ r_traverse_single(CollisionLevelStateSingle &level_state, size_t pass) {
     // child.
     // child.
     int index = node->get_visible_child();
     int index = node->get_visible_child();
     PandaNode::Children children = node->get_children();
     PandaNode::Children children = node->get_children();
-    if (index >= 0 && index < children.get_num_children()) {
+    if (index >= 0 && (size_t)index < children.get_num_children()) {
       const PandaNode::DownConnection &child = children.get_child_connection(index);
       const PandaNode::DownConnection &child = children.get_child_connection(index);
       CollisionLevelStateSingle::CurrentMask mask = level_state.get_child_mask(child);
       CollisionLevelStateSingle::CurrentMask mask = level_state.get_child_mask(child);
       if (!mask.is_zero()) {
       if (!mask.is_zero()) {
@@ -856,7 +856,7 @@ r_traverse_double(CollisionLevelStateDouble &level_state, size_t pass) {
     // child.
     // child.
     int index = node->get_visible_child();
     int index = node->get_visible_child();
     PandaNode::Children children = node->get_children();
     PandaNode::Children children = node->get_children();
-    if (index >= 0 && index < children.get_num_children()) {
+    if (index >= 0 && (size_t)index < children.get_num_children()) {
       const PandaNode::DownConnection &child = children.get_child_connection(index);
       const PandaNode::DownConnection &child = children.get_child_connection(index);
       CollisionLevelStateDouble::CurrentMask mask = level_state.get_child_mask(child);
       CollisionLevelStateDouble::CurrentMask mask = level_state.get_child_mask(child);
       if (!mask.is_zero()) {
       if (!mask.is_zero()) {
@@ -1065,7 +1065,7 @@ r_traverse_quad(CollisionLevelStateQuad &level_state, size_t pass) {
     // child.
     // child.
     int index = node->get_visible_child();
     int index = node->get_visible_child();
     PandaNode::Children children = node->get_children();
     PandaNode::Children children = node->get_children();
-    if (index >= 0 && index < children.get_num_children()) {
+    if (index >= 0 && (size_t)index < children.get_num_children()) {
       const PandaNode::DownConnection &child = children.get_child_connection(index);
       const PandaNode::DownConnection &child = children.get_child_connection(index);
       CollisionLevelStateQuad::CurrentMask mask = level_state.get_child_mask(child);
       CollisionLevelStateQuad::CurrentMask mask = level_state.get_child_mask(child);
       if (!mask.is_zero()) {
       if (!mask.is_zero()) {

+ 0 - 1
panda/src/collide/collisionTraverser_ext.cxx

@@ -21,7 +21,6 @@
 PyObject *Extension<CollisionTraverser>::
 PyObject *Extension<CollisionTraverser>::
 __getstate__() const {
 __getstate__() const {
   extern struct Dtool_PyTypedObject Dtool_CollisionHandler;
   extern struct Dtool_PyTypedObject Dtool_CollisionHandler;
-  extern struct Dtool_PyTypedObject Dtool_CollisionTraverser;
   extern struct Dtool_PyTypedObject Dtool_NodePath;
   extern struct Dtool_PyTypedObject Dtool_NodePath;
 
 
   const std::string &name = _this->get_name();
   const std::string &name = _this->get_name();

+ 4 - 4
panda/src/device/evdevInputDevice.cxx

@@ -126,8 +126,9 @@ TypeHandle EvdevInputDevice::_type_handle;
 EvdevInputDevice::
 EvdevInputDevice::
 EvdevInputDevice(LinuxInputDeviceManager *manager, size_t index) :
 EvdevInputDevice(LinuxInputDeviceManager *manager, size_t index) :
   _manager(manager),
   _manager(manager),
-  _index(index),
   _fd(-1),
   _fd(-1),
+  _quirks(0),
+  _index(index),
   _can_write(false),
   _can_write(false),
   _ff_id(-1),
   _ff_id(-1),
   _ff_playing(false),
   _ff_playing(false),
@@ -138,9 +139,8 @@ EvdevInputDevice(LinuxInputDeviceManager *manager, size_t index) :
   _dpad_left_button(-1),
   _dpad_left_button(-1),
   _dpad_up_button(-1),
   _dpad_up_button(-1),
   _ltrigger_code(-1),
   _ltrigger_code(-1),
-  _rtrigger_code(-1),
-  _quirks(0) {
-
+  _rtrigger_code(-1)
+{
   char path[64];
   char path[64];
   sprintf(path, "/dev/input/event%zd", index);
   sprintf(path, "/dev/input/event%zd", index);
 
 

+ 1 - 1
panda/src/device/inputDeviceManager.h

@@ -30,7 +30,7 @@ class WinRawInputDevice;
  *
  *
  * @since 1.10.0
  * @since 1.10.0
  */
  */
-class EXPCL_PANDA_DEVICE InputDeviceManager {
+class EXPCL_PANDA_DEVICE InputDeviceManager : public MemoryBase {
 protected:
 protected:
   InputDeviceManager();
   InputDeviceManager();
   ~InputDeviceManager() = default;
   ~InputDeviceManager() = default;

+ 1 - 1
panda/src/device/trackerData.h

@@ -20,7 +20,7 @@
 /**
 /**
  * Stores the kinds of data that a tracker might output.
  * Stores the kinds of data that a tracker might output.
  */
  */
-class EXPCL_PANDA_DEVICE TrackerData {
+class EXPCL_PANDA_DEVICE TrackerData : public MemoryBase {
 public:
 public:
   INLINE TrackerData();
   INLINE TrackerData();
   INLINE TrackerData(const TrackerData &copy);
   INLINE TrackerData(const TrackerData &copy);

+ 1 - 1
panda/src/device/xInputDevice.cxx

@@ -70,7 +70,7 @@
 
 
 // With MingW32 this raises the error:
 // With MingW32 this raises the error:
 // Redefinition of '_XINPUT_BATTERY_INFORMATION'
 // Redefinition of '_XINPUT_BATTERY_INFORMATION'
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && _WIN32_WINNT < 0x0602
 typedef struct _XINPUT_BATTERY_INFORMATION {
 typedef struct _XINPUT_BATTERY_INFORMATION {
   BYTE BatteryType;
   BYTE BatteryType;
   BYTE BatteryLevel;
   BYTE BatteryLevel;

+ 4 - 4
panda/src/display/displayRegion.cxx

@@ -731,6 +731,7 @@ do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
  */
  */
 DisplayRegion::CData::
 DisplayRegion::CData::
 CData() :
 CData() :
+  _depth_range(0, 1),
   _lens_index(0),
   _lens_index(0),
   _camera_node(nullptr),
   _camera_node(nullptr),
   _active(true),
   _active(true),
@@ -738,8 +739,7 @@ CData() :
   _stereo_channel(Lens::SC_mono),
   _stereo_channel(Lens::SC_mono),
   _tex_view_offset(0),
   _tex_view_offset(0),
   _target_tex_page(-1),
   _target_tex_page(-1),
-  _scissor_enabled(true),
-  _depth_range(0, 1)
+  _scissor_enabled(true)
 {
 {
   _regions.push_back(Region());
   _regions.push_back(Region());
 }
 }
@@ -750,6 +750,7 @@ CData() :
 DisplayRegion::CData::
 DisplayRegion::CData::
 CData(const DisplayRegion::CData &copy) :
 CData(const DisplayRegion::CData &copy) :
   _regions(copy._regions),
   _regions(copy._regions),
+  _depth_range(copy._depth_range),
   _lens_index(copy._lens_index),
   _lens_index(copy._lens_index),
   _camera(copy._camera),
   _camera(copy._camera),
   _camera_node(copy._camera_node),
   _camera_node(copy._camera_node),
@@ -758,8 +759,7 @@ CData(const DisplayRegion::CData &copy) :
   _stereo_channel(copy._stereo_channel),
   _stereo_channel(copy._stereo_channel),
   _tex_view_offset(copy._tex_view_offset),
   _tex_view_offset(copy._tex_view_offset),
   _target_tex_page(copy._target_tex_page),
   _target_tex_page(copy._target_tex_page),
-  _scissor_enabled(copy._scissor_enabled),
-  _depth_range(copy._depth_range)
+  _scissor_enabled(copy._scissor_enabled)
 {
 {
 }
 }
 
 

+ 86 - 70
panda/src/display/graphicsEngine.cxx

@@ -69,9 +69,8 @@ PT(GraphicsEngine) GraphicsEngine::_global_ptr;
 
 
 PStatCollector GraphicsEngine::_wait_pcollector("Wait:Thread sync");
 PStatCollector GraphicsEngine::_wait_pcollector("Wait:Thread sync");
 PStatCollector GraphicsEngine::_cycle_pcollector("App:Cycle");
 PStatCollector GraphicsEngine::_cycle_pcollector("App:Cycle");
-PStatCollector GraphicsEngine::_app_pcollector("App:Show code:General");
+//PStatCollector GraphicsEngine::_app_pcollector("App:Show code:General");
 PStatCollector GraphicsEngine::_render_frame_pcollector("App:render_frame");
 PStatCollector GraphicsEngine::_render_frame_pcollector("App:render_frame");
-PStatCollector GraphicsEngine::_do_frame_pcollector("*:do_frame");
 PStatCollector GraphicsEngine::_yield_pcollector("App:Yield");
 PStatCollector GraphicsEngine::_yield_pcollector("App:Yield");
 PStatCollector GraphicsEngine::_cull_pcollector("Cull");
 PStatCollector GraphicsEngine::_cull_pcollector("Cull");
 PStatCollector GraphicsEngine::_cull_setup_pcollector("Cull:Setup");
 PStatCollector GraphicsEngine::_cull_setup_pcollector("Cull:Setup");
@@ -79,15 +78,12 @@ PStatCollector GraphicsEngine::_cull_sort_pcollector("Cull:Sort");
 PStatCollector GraphicsEngine::_draw_pcollector("Draw");
 PStatCollector GraphicsEngine::_draw_pcollector("Draw");
 PStatCollector GraphicsEngine::_sync_pcollector("Draw:Sync");
 PStatCollector GraphicsEngine::_sync_pcollector("Draw:Sync");
 PStatCollector GraphicsEngine::_flip_pcollector("Wait:Flip");
 PStatCollector GraphicsEngine::_flip_pcollector("Wait:Flip");
-PStatCollector GraphicsEngine::_flip_begin_pcollector("Wait:Flip:Begin");
-PStatCollector GraphicsEngine::_flip_end_pcollector("Wait:Flip:End");
 PStatCollector GraphicsEngine::_transform_states_pcollector("TransformStates");
 PStatCollector GraphicsEngine::_transform_states_pcollector("TransformStates");
 PStatCollector GraphicsEngine::_transform_states_unused_pcollector("TransformStates:Unused");
 PStatCollector GraphicsEngine::_transform_states_unused_pcollector("TransformStates:Unused");
 PStatCollector GraphicsEngine::_render_states_pcollector("RenderStates");
 PStatCollector GraphicsEngine::_render_states_pcollector("RenderStates");
 PStatCollector GraphicsEngine::_render_states_unused_pcollector("RenderStates:Unused");
 PStatCollector GraphicsEngine::_render_states_unused_pcollector("RenderStates:Unused");
 PStatCollector GraphicsEngine::_cyclers_pcollector("PipelineCyclers");
 PStatCollector GraphicsEngine::_cyclers_pcollector("PipelineCyclers");
-PStatCollector GraphicsEngine::_dirty_cyclers_pcollector("Dirty PipelineCyclers");
-PStatCollector GraphicsEngine::_delete_pcollector("App:Delete");
+PStatCollector GraphicsEngine::_dirty_cyclers_pcollector("PipelineCyclers:Dirty");
 
 
 
 
 PStatCollector GraphicsEngine::_sw_sprites_pcollector("SW Sprites");
 PStatCollector GraphicsEngine::_sw_sprites_pcollector("SW Sprites");
@@ -182,9 +178,9 @@ GraphicsEngine(Pipeline *pipeline) :
 GraphicsEngine::
 GraphicsEngine::
 ~GraphicsEngine() {
 ~GraphicsEngine() {
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
-  if (_app_pcollector.is_started()) {
-    _app_pcollector.stop();
-  }
+  //if (_app_pcollector.is_started()) {
+  //  _app_pcollector.stop();
+  //}
 #endif
 #endif
 
 
   remove_all_windows();
   remove_all_windows();
@@ -714,9 +710,9 @@ render_frame() {
   // to be App.
   // to be App.
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
   _render_frame_pcollector.start();
   _render_frame_pcollector.start();
-  if (_app_pcollector.is_started()) {
-    _app_pcollector.stop();
-  }
+  //if (_app_pcollector.is_started()) {
+  //  _app_pcollector.stop();
+  //}
 #endif
 #endif
 
 
   // Make sure our buffers and windows are fully realized before we render a
   // Make sure our buffers and windows are fully realized before we render a
@@ -854,6 +850,7 @@ render_frame() {
     // Reset our pcollectors that track data across the frame.
     // Reset our pcollectors that track data across the frame.
     CullTraverser::_nodes_pcollector.clear_level();
     CullTraverser::_nodes_pcollector.clear_level();
     CullTraverser::_geom_nodes_pcollector.clear_level();
     CullTraverser::_geom_nodes_pcollector.clear_level();
+    CullTraverser::_pgui_nodes_pcollector.clear_level();
     CullTraverser::_geoms_pcollector.clear_level();
     CullTraverser::_geoms_pcollector.clear_level();
     GeomCacheManager::_geom_cache_active_pcollector.clear_level();
     GeomCacheManager::_geom_cache_active_pcollector.clear_level();
     GeomCacheManager::_geom_cache_record_pcollector.clear_level();
     GeomCacheManager::_geom_cache_record_pcollector.clear_level();
@@ -925,10 +922,14 @@ render_frame() {
     for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
     for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
       RenderThread *thread = (*ti).second;
       RenderThread *thread = (*ti).second;
       if (thread->_thread_state == TS_wait) {
       if (thread->_thread_state == TS_wait) {
+        // Release before notifying, otherwise the other thread will wake up
+        // and get blocked on the mutex straight away.
         thread->_thread_state = TS_do_frame;
         thread->_thread_state = TS_do_frame;
+        thread->_cv_mutex.release();
         thread->_cv_start.notify();
         thread->_cv_start.notify();
+      } else {
+        thread->_cv_mutex.release();
       }
       }
-      thread->_cv_mutex.release();
     }
     }
 
 
     // Some threads may still be drawing, so indicate that we have to wait for
     // Some threads may still be drawing, so indicate that we have to wait for
@@ -950,7 +951,7 @@ render_frame() {
 
 
   // Anything that happens outside of GraphicsEngine::render_frame() is deemed
   // Anything that happens outside of GraphicsEngine::render_frame() is deemed
   // to be App.
   // to be App.
-  _app_pcollector.start();
+  //_app_pcollector.start();
   _render_frame_pcollector.stop();
   _render_frame_pcollector.stop();
 }
 }
 
 
@@ -1036,8 +1037,8 @@ open_windows() {
       }
       }
 
 
       thread->_thread_state = TS_do_windows;
       thread->_thread_state = TS_do_windows;
-      thread->_cv_start.notify();
       thread->_cv_mutex.release();
       thread->_cv_mutex.release();
+      thread->_cv_start.notify();
     }
     }
   }
   }
 
 
@@ -1154,11 +1155,11 @@ extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg) {
     thread->_gsg = gsg;
     thread->_gsg = gsg;
     thread->_texture = tex;
     thread->_texture = tex;
     thread->_thread_state = TS_do_extract;
     thread->_thread_state = TS_do_extract;
-    thread->_cv_start.notify();
     thread->_cv_mutex.release();
     thread->_cv_mutex.release();
+    thread->_cv_start.notify();
     thread->_cv_mutex.acquire();
     thread->_cv_mutex.acquire();
 
 
-    //XXX is this necessary, or is acquiring the mutex enough?
+    // Wait for it to finish the extraction.
     while (thread->_thread_state != TS_wait) {
     while (thread->_thread_state != TS_wait) {
       thread->_cv_done.wait();
       thread->_cv_done.wait();
     }
     }
@@ -1222,11 +1223,11 @@ dispatch_compute(const LVecBase3i &work_groups, const ShaderAttrib *sattr, Graph
     thread->_state = state.p();
     thread->_state = state.p();
     thread->_work_groups = work_groups;
     thread->_work_groups = work_groups;
     thread->_thread_state = TS_do_compute;
     thread->_thread_state = TS_do_compute;
-    thread->_cv_start.notify();
     thread->_cv_mutex.release();
     thread->_cv_mutex.release();
+    thread->_cv_start.notify();
     thread->_cv_mutex.acquire();
     thread->_cv_mutex.acquire();
 
 
-    //XXX is this necessary, or is acquiring the mutex enough?
+    // Wait for it to finish the compute task.
     while (thread->_thread_state != TS_wait) {
     while (thread->_thread_state != TS_wait) {
       thread->_cv_done.wait();
       thread->_cv_done.wait();
     }
     }
@@ -1292,11 +1293,11 @@ do_get_screenshot(DisplayRegion *region, GraphicsStateGuardian *gsg) {
   // Now that the draw thread is idle, signal it to do the extraction task.
   // Now that the draw thread is idle, signal it to do the extraction task.
   thread->_region = region;
   thread->_region = region;
   thread->_thread_state = TS_do_screenshot;
   thread->_thread_state = TS_do_screenshot;
-  thread->_cv_start.notify();
   thread->_cv_mutex.release();
   thread->_cv_mutex.release();
+  thread->_cv_start.notify();
   thread->_cv_mutex.acquire();
   thread->_cv_mutex.acquire();
 
 
-  //XXX is this necessary, or is acquiring the mutex enough?
+  // Wait for it to finish the extraction.
   while (thread->_thread_state != TS_wait) {
   while (thread->_thread_state != TS_wait) {
     thread->_cv_done.wait();
     thread->_cv_done.wait();
   }
   }
@@ -1408,14 +1409,13 @@ cull_and_draw_together(GraphicsEngine::Windows wlist,
     GraphicsOutput *win = wlist[wi];
     GraphicsOutput *win = wlist[wi];
     if (win->is_active() && win->get_gsg()->is_active()) {
     if (win->is_active() && win->get_gsg()->is_active()) {
       if (win->flip_ready()) {
       if (win->flip_ready()) {
-        {
-          PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
-          win->begin_flip();
-        }
-        {
-          PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
-          win->end_flip();
+        if (display_cat.is_spam()) {
+          display_cat.spam()
+            << "Flipping window " << win->get_name() << "\n";
         }
         }
+        PStatTimer timer(_flip_pcollector, current_thread);
+        win->begin_flip();
+        win->end_flip();
       }
       }
 
 
       if (win->begin_frame(GraphicsOutput::FM_render, current_thread)) {
       if (win->begin_frame(GraphicsOutput::FM_render, current_thread)) {
@@ -1427,6 +1427,11 @@ cull_and_draw_together(GraphicsEngine::Windows wlist,
           gsg->pop_group_marker();
           gsg->pop_group_marker();
         }
         }
 
 
+        if (display_cat.is_spam()) {
+          display_cat.spam()
+            << "Culling and drawing window " << win->get_name() << "\n";
+        }
+
         int num_display_regions = win->get_num_active_display_regions();
         int num_display_regions = win->get_num_active_display_regions();
         for (int i = 0; i < num_display_regions; i++) {
         for (int i = 0; i < num_display_regions; i++) {
           PT(DisplayRegion) dr = win->get_active_display_region(i);
           PT(DisplayRegion) dr = win->get_active_display_region(i);
@@ -1438,14 +1443,13 @@ cull_and_draw_together(GraphicsEngine::Windows wlist,
 
 
         if (_auto_flip) {
         if (_auto_flip) {
           if (win->flip_ready()) {
           if (win->flip_ready()) {
-            {
-              PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
-              win->begin_flip();
-            }
-            {
-              PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
-              win->end_flip();
+            if (display_cat.is_spam()) {
+              display_cat.spam()
+                << "Flipping window " << win->get_name() << "\n";
             }
             }
+            PStatTimer timer(_flip_pcollector, current_thread);
+            win->begin_flip();
+            win->end_flip();
           }
           }
         }
         }
       }
       }
@@ -1539,6 +1543,11 @@ cull_to_bins(GraphicsEngine::Windows wlist, Thread *current_thread) {
   for (size_t wi = 0; wi < wlist_size; ++wi) {
   for (size_t wi = 0; wi < wlist_size; ++wi) {
     GraphicsOutput *win = wlist[wi];
     GraphicsOutput *win = wlist[wi];
     if (win->is_active() && win->get_gsg()->is_active()) {
     if (win->is_active() && win->get_gsg()->is_active()) {
+      if (display_cat.is_spam()) {
+        display_cat.spam()
+          << "Culling window " << win->get_name() << "\n";
+      }
+
       GraphicsStateGuardian *gsg = win->get_gsg();
       GraphicsStateGuardian *gsg = win->get_gsg();
       PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
       PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
       int num_display_regions = win->get_num_active_display_regions();
       int num_display_regions = win->get_num_active_display_regions();
@@ -1683,6 +1692,8 @@ cull_to_bins(GraphicsOutput *win, GraphicsStateGuardian *gsg,
  */
  */
 void GraphicsEngine::
 void GraphicsEngine::
 draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
 draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
+  PStatTimer timer(_draw_pcollector, current_thread);
+
   nassertv(wlist.verify_list());
   nassertv(wlist.verify_list());
 
 
   size_t wlist_size = wlist.size();
   size_t wlist_size = wlist.size();
@@ -1694,16 +1705,14 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
 
 
       GraphicsOutput *host = win->get_host();
       GraphicsOutput *host = win->get_host();
       if (host->flip_ready()) {
       if (host->flip_ready()) {
-        {
-          // We can't use a PStatGPUTimer before begin_frame, so when using
-          // GPU timing, it is advisable to set auto-flip to #t.
-          PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
-          host->begin_flip();
-        }
-        {
-          PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
-          host->end_flip();
+        if (display_cat.is_spam()) {
+          display_cat.spam()
+            << "Flipping window " << host->get_name()
+            << " before drawing window " << win->get_name() << "\n";
         }
         }
+        PStatTimer timer(_flip_pcollector, current_thread);
+        host->begin_flip();
+        host->end_flip();
       }
       }
 
 
       if (win->begin_frame(GraphicsOutput::FM_render, current_thread)) {
       if (win->begin_frame(GraphicsOutput::FM_render, current_thread)) {
@@ -1733,24 +1742,14 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
         win->end_frame(GraphicsOutput::FM_render, current_thread);
         win->end_frame(GraphicsOutput::FM_render, current_thread);
 
 
         if (_auto_flip) {
         if (_auto_flip) {
-#ifdef DO_PSTATS
-          // This is a good time to perform a latency query.
-          if (gsg->get_timer_queries_active()) {
-            gsg->issue_timer_query(GraphicsStateGuardian::_command_latency_pcollector.get_index());
-          }
-#endif
-
           if (win->flip_ready()) {
           if (win->flip_ready()) {
-            {
-              // begin_flip doesn't do anything interesting, let's not waste
-              // two timer queries on that.
-              PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
-              win->begin_flip();
-            }
-            {
-              PStatGPUTimer timer(gsg, GraphicsEngine::_flip_end_pcollector, current_thread);
-              win->end_flip();
+            if (display_cat.is_spam()) {
+              display_cat.spam()
+                << "Flipping window " << win->get_name() << "\n";
             }
             }
+            PStatGPUTimer timer(gsg, _flip_pcollector, current_thread);
+            win->begin_flip();
+            win->end_flip();
           }
           }
         }
         }
 
 
@@ -1812,22 +1811,27 @@ flip_windows(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   size_t warray_count = 0;
   size_t warray_count = 0;
   GraphicsOutput **warray = (GraphicsOutput **)alloca(warray_size);
   GraphicsOutput **warray = (GraphicsOutput **)alloca(warray_size);
 
 
+  PStatTimer timer(_flip_pcollector, current_thread);
+
   size_t i;
   size_t i;
   for (i = 0; i < num_windows; ++i) {
   for (i = 0; i < num_windows; ++i) {
     GraphicsOutput *win = wlist[i];
     GraphicsOutput *win = wlist[i];
     if (win->flip_ready()) {
     if (win->flip_ready()) {
+      if (display_cat.is_spam()) {
+        display_cat.spam()
+          << "Flipping window " << win->get_name() << "\n";
+      }
+
       nassertv(warray_count < num_windows);
       nassertv(warray_count < num_windows);
       warray[warray_count] = win;
       warray[warray_count] = win;
       ++warray_count;
       ++warray_count;
 
 
-      PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
       win->begin_flip();
       win->begin_flip();
     }
     }
   }
   }
 
 
   for (i = 0; i < warray_count; ++i) {
   for (i = 0; i < warray_count; ++i) {
     GraphicsOutput *win = warray[i];
     GraphicsOutput *win = warray[i];
-    PStatTimer timer(GraphicsEngine::_flip_end_pcollector, current_thread);
     win->end_flip();
     win->end_flip();
   }
   }
 }
 }
@@ -1843,7 +1847,7 @@ ready_flip_windows(const GraphicsEngine::Windows &wlist, Thread *current_thread)
   for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
   for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
     GraphicsOutput *win = (*wi);
     GraphicsOutput *win = (*wi);
     if (win->flip_ready()) {
     if (win->flip_ready()) {
-      PStatTimer timer(GraphicsEngine::_flip_begin_pcollector, current_thread);
+      PStatTimer timer(_flip_pcollector, current_thread);
       win->ready_flip();
       win->ready_flip();
     }
     }
   }
   }
@@ -1937,8 +1941,8 @@ do_flip_frame(Thread *current_thread) {
       RenderThread *thread = (*ti).second;
       RenderThread *thread = (*ti).second;
       nassertv(thread->_thread_state == TS_wait);
       nassertv(thread->_thread_state == TS_wait);
       thread->_thread_state = TS_do_flip;
       thread->_thread_state = TS_do_flip;
-      thread->_cv_start.notify();
       thread->_cv_mutex.release();
       thread->_cv_mutex.release();
+      thread->_cv_start.notify();
     }
     }
   }
   }
 
 
@@ -2245,6 +2249,11 @@ void GraphicsEngine::
 do_resort_windows() {
 do_resort_windows() {
   _windows_sorted = true;
   _windows_sorted = true;
 
 
+  if (display_cat.is_spam()) {
+    display_cat.spam()
+      << "Re-sorting window list.\n";
+  }
+
   _app.resort_windows();
   _app.resort_windows();
   Threads::const_iterator ti;
   Threads::const_iterator ti;
   for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
   for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
@@ -2365,8 +2374,8 @@ terminate_threads(Thread *current_thread) {
   for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
   for (ti = _threads.begin(); ti != _threads.end(); ++ti) {
     RenderThread *thread = (*ti).second;
     RenderThread *thread = (*ti).second;
     thread->_thread_state = TS_terminate;
     thread->_thread_state = TS_terminate;
-    thread->_cv_start.notify();
     thread->_cv_mutex.release();
     thread->_cv_mutex.release();
+    thread->_cv_start.notify();
   }
   }
 
 
   // Finally, wait for them all to finish cleaning up.
   // Finally, wait for them all to finish cleaning up.
@@ -2569,13 +2578,20 @@ resort_windows() {
  */
  */
 void GraphicsEngine::WindowRenderer::
 void GraphicsEngine::WindowRenderer::
 do_frame(GraphicsEngine *engine, Thread *current_thread) {
 do_frame(GraphicsEngine *engine, Thread *current_thread) {
-  PStatTimer timer(engine->_do_frame_pcollector, current_thread);
   LightReMutexHolder holder(_wl_lock);
   LightReMutexHolder holder(_wl_lock);
 
 
-  engine->cull_to_bins(_cull, current_thread);
-  engine->cull_and_draw_together(_cdraw, current_thread);
-  engine->draw_bins(_draw, current_thread);
-  engine->process_events(_window, current_thread);
+  if (!_cull.empty()) {
+    engine->cull_to_bins(_cull, current_thread);
+  }
+  if (!_cdraw.empty()) {
+    engine->cull_and_draw_together(_cdraw, current_thread);
+  }
+  if (!_draw.empty()) {
+    engine->draw_bins(_draw, current_thread);
+  }
+  if (!_window.empty()) {
+    engine->process_events(_window, current_thread);
+  }
 
 
   // If any GSG's on the list have no more outstanding pointers, clean them
   // If any GSG's on the list have no more outstanding pointers, clean them
   // up.  (We are in the draw thread for all of these GSG's.)
   // up.  (We are in the draw thread for all of these GSG's.)

+ 1 - 5
panda/src/display/graphicsEngine.h

@@ -358,9 +358,8 @@ private:
 
 
   static PStatCollector _wait_pcollector;
   static PStatCollector _wait_pcollector;
   static PStatCollector _cycle_pcollector;
   static PStatCollector _cycle_pcollector;
-  static PStatCollector _app_pcollector;
+  //static PStatCollector _app_pcollector;
   static PStatCollector _render_frame_pcollector;
   static PStatCollector _render_frame_pcollector;
-  static PStatCollector _do_frame_pcollector;
   static PStatCollector _yield_pcollector;
   static PStatCollector _yield_pcollector;
   static PStatCollector _cull_pcollector;
   static PStatCollector _cull_pcollector;
   static PStatCollector _cull_setup_pcollector;
   static PStatCollector _cull_setup_pcollector;
@@ -368,15 +367,12 @@ private:
   static PStatCollector _draw_pcollector;
   static PStatCollector _draw_pcollector;
   static PStatCollector _sync_pcollector;
   static PStatCollector _sync_pcollector;
   static PStatCollector _flip_pcollector;
   static PStatCollector _flip_pcollector;
-  static PStatCollector _flip_begin_pcollector;
-  static PStatCollector _flip_end_pcollector;
   static PStatCollector _transform_states_pcollector;
   static PStatCollector _transform_states_pcollector;
   static PStatCollector _transform_states_unused_pcollector;
   static PStatCollector _transform_states_unused_pcollector;
   static PStatCollector _render_states_pcollector;
   static PStatCollector _render_states_pcollector;
   static PStatCollector _render_states_unused_pcollector;
   static PStatCollector _render_states_unused_pcollector;
   static PStatCollector _cyclers_pcollector;
   static PStatCollector _cyclers_pcollector;
   static PStatCollector _dirty_cyclers_pcollector;
   static PStatCollector _dirty_cyclers_pcollector;
-  static PStatCollector _delete_pcollector;
 
 
   static PStatCollector _sw_sprites_pcollector;
   static PStatCollector _sw_sprites_pcollector;
   static PStatCollector _vertex_data_small_pcollector;
   static PStatCollector _vertex_data_small_pcollector;

+ 2 - 2
panda/src/display/graphicsOutput.cxx

@@ -75,10 +75,10 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
                GraphicsOutput *host,
                GraphicsOutput *host,
                bool default_stereo_flags) :
                bool default_stereo_flags) :
   _lock("GraphicsOutput"),
   _lock("GraphicsOutput"),
+  _size(0, 0),
   _cull_window_pcollector(_cull_pcollector, name),
   _cull_window_pcollector(_cull_pcollector, name),
   _draw_window_pcollector(_draw_pcollector, name),
   _draw_window_pcollector(_draw_pcollector, name),
-  _clear_window_pcollector(_draw_window_pcollector, "Clear"),
-  _size(0, 0)
+  _clear_window_pcollector(_draw_window_pcollector, "Clear")
 {
 {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::update_type(this, this);
   MemoryUsage::update_type(this, this);

+ 39 - 173
panda/src/display/graphicsStateGuardian.cxx

@@ -63,9 +63,9 @@
 
 
 using std::string;
 using std::string;
 
 
-PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Buffer switch:Vertex");
-PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Buffer switch:Index");
-PStatCollector GraphicsStateGuardian::_shader_buffer_switch_pcollector("Buffer switch:Shader");
+//PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Buffer switch:Vertex");
+//PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Buffer switch:Index");
+//PStatCollector GraphicsStateGuardian::_shader_buffer_switch_pcollector("Buffer switch:Shader");
 PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer");
 PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer");
 PStatCollector GraphicsStateGuardian::_load_index_buffer_pcollector("Draw:Transfer data:Index buffer");
 PStatCollector GraphicsStateGuardian::_load_index_buffer_pcollector("Draw:Transfer data:Index buffer");
 PStatCollector GraphicsStateGuardian::_load_shader_buffer_pcollector("Draw:Transfer data:Shader buffer");
 PStatCollector GraphicsStateGuardian::_load_shader_buffer_pcollector("Draw:Transfer data:Shader buffer");
@@ -98,7 +98,6 @@ PStatCollector GraphicsStateGuardian::_compute_dispatch_pcollector("Draw:Compute
 PStatCollector GraphicsStateGuardian::_wait_occlusion_pcollector("Wait:Occlusion");
 PStatCollector GraphicsStateGuardian::_wait_occlusion_pcollector("Wait:Occlusion");
 PStatCollector GraphicsStateGuardian::_wait_timer_pcollector("Wait:Timer Queries");
 PStatCollector GraphicsStateGuardian::_wait_timer_pcollector("Wait:Timer Queries");
 PStatCollector GraphicsStateGuardian::_timer_queries_pcollector("Timer queries");
 PStatCollector GraphicsStateGuardian::_timer_queries_pcollector("Timer queries");
-PStatCollector GraphicsStateGuardian::_command_latency_pcollector("Command latency");
 
 
 PStatCollector GraphicsStateGuardian::_prepare_pcollector("Draw:Prepare");
 PStatCollector GraphicsStateGuardian::_prepare_pcollector("Draw:Prepare");
 PStatCollector GraphicsStateGuardian::_prepare_texture_pcollector("Draw:Prepare:Texture");
 PStatCollector GraphicsStateGuardian::_prepare_texture_pcollector("Draw:Prepare:Texture");
@@ -222,10 +221,6 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
 
 
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
   _timer_queries_active = false;
   _timer_queries_active = false;
-  _last_query_frame = 0;
-  _last_num_queried = 0;
-  // _timer_delta = 0.0;
-
   _pstats_gpu_thread = -1;
   _pstats_gpu_thread = -1;
 #endif
 #endif
 
 
@@ -778,9 +773,17 @@ end_occlusion_query() {
  * Adds a timer query to the command stream, associated with the given PStats
  * Adds a timer query to the command stream, associated with the given PStats
  * collector index.
  * collector index.
  */
  */
-PT(TimerQueryContext) GraphicsStateGuardian::
+void GraphicsStateGuardian::
 issue_timer_query(int pstats_index) {
 issue_timer_query(int pstats_index) {
-  return nullptr;
+}
+
+/**
+ * A latency query is a special type of timer query that measures the
+ * difference between CPU time and GPU time, ie. how far the GPU is behind in
+ * processing the commands being generated by the CPU right now.
+ */
+void GraphicsStateGuardian::
+issue_latency_query(int pstats_index) {
 }
 }
 
 
 /**
 /**
@@ -2032,7 +2035,7 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
     {
     {
       const TextureAttrib *texattrib;
       const TextureAttrib *texattrib;
       if (_target_rs->get_attrib(texattrib)) {
       if (_target_rs->get_attrib(texattrib)) {
-        size_t si = 0;
+        int si = 0;
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage::Mode mode = stage->get_mode();
           TextureStage::Mode mode = stage->get_mode();
@@ -2055,7 +2058,7 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
     {
     {
       const TextureAttrib *texattrib;
       const TextureAttrib *texattrib;
       if (_target_rs->get_attrib(texattrib)) {
       if (_target_rs->get_attrib(texattrib)) {
-        size_t si = 0;
+        int si = 0;
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage::Mode mode = stage->get_mode();
           TextureStage::Mode mode = stage->get_mode();
@@ -2084,7 +2087,7 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
     {
     {
       const TextureAttrib *texattrib;
       const TextureAttrib *texattrib;
       if (_target_rs->get_attrib(texattrib)) {
       if (_target_rs->get_attrib(texattrib)) {
-        size_t si = 0;
+        int si = 0;
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage::Mode mode = stage->get_mode();
           TextureStage::Mode mode = stage->get_mode();
@@ -2114,7 +2117,7 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
     {
     {
       const TextureAttrib *texattrib;
       const TextureAttrib *texattrib;
       if (_target_rs->get_attrib(texattrib)) {
       if (_target_rs->get_attrib(texattrib)) {
-        size_t si = 0;
+        int si = 0;
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage::Mode mode = stage->get_mode();
           TextureStage::Mode mode = stage->get_mode();
@@ -2137,7 +2140,7 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
     {
     {
       const TextureAttrib *texattrib;
       const TextureAttrib *texattrib;
       if (_target_rs->get_attrib(texattrib)) {
       if (_target_rs->get_attrib(texattrib)) {
-        size_t si = 0;
+        int si = 0;
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage::Mode mode = stage->get_mode();
           TextureStage::Mode mode = stage->get_mode();
@@ -2167,7 +2170,7 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
     {
     {
       const TextureAttrib *texattrib;
       const TextureAttrib *texattrib;
       if (_target_rs->get_attrib(texattrib)) {
       if (_target_rs->get_attrib(texattrib)) {
-        size_t si = 0;
+        int si = 0;
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage::Mode mode = stage->get_mode();
           TextureStage::Mode mode = stage->get_mode();
@@ -2188,7 +2191,7 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
     {
     {
       const TextureAttrib *texattrib;
       const TextureAttrib *texattrib;
       if (_target_rs->get_attrib(texattrib)) {
       if (_target_rs->get_attrib(texattrib)) {
-        size_t si = 0;
+        int si = 0;
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
         for (int i = 0; i < texattrib->get_num_on_stages(); ++i) {
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage *stage = texattrib->get_on_stage(i);
           TextureStage::Mode mode = stage->get_mode();
           TextureStage::Mode mode = stage->get_mode();
@@ -2360,7 +2363,10 @@ calc_projection_mat(const Lens *lens) {
  */
  */
 bool GraphicsStateGuardian::
 bool GraphicsStateGuardian::
 begin_frame(Thread *current_thread) {
 begin_frame(Thread *current_thread) {
-  _prepared_objects->begin_frame(this, current_thread);
+  {
+    PStatTimer timer(_prepare_pcollector);
+    _prepared_objects->begin_frame(this, current_thread);
+  }
 
 
   // We should reset the state to the default at the beginning of every frame.
   // We should reset the state to the default at the beginning of every frame.
   // Although this will incur additional overhead, particularly in a simple
   // Although this will incur additional overhead, particularly in a simple
@@ -2370,28 +2376,6 @@ begin_frame(Thread *current_thread) {
   _state_rs = RenderState::make_empty();
   _state_rs = RenderState::make_empty();
   _state_mask.clear();
   _state_mask.clear();
 
 
-#ifdef DO_PSTATS
-  // We have to do this here instead of in GraphicsEngine because we need a
-  // current context to issue timer queries.
-  int frame = ClockObject::get_global_clock()->get_frame_count();
-  if (_last_query_frame < frame) {
-    _last_query_frame = frame;
-    _timer_queries_pcollector.clear_level();
-
-    // Now is a good time to flush previous frame's queries.  We may not
-    // actually have all of the previous frame's results in yet, but that's
-    // okay; the GPU data is allowed to lag a few frames behind.
-    flush_timer_queries();
-
-    if (_timer_queries_active) {
-      // Issue a stop and start event for collector 0, marking the beginning
-      // of the new frame.
-      issue_timer_query(0x8000);
-      issue_timer_query(0x0000);
-    }
-  }
-#endif
-
   return !_needs_reset;
   return !_needs_reset;
 }
 }
 
 
@@ -2477,133 +2461,6 @@ end_frame(Thread *current_thread) {
   _prepared_objects->_graphics_memory_lru.begin_epoch();
   _prepared_objects->_graphics_memory_lru.begin_epoch();
 }
 }
 
 
-/**
- * Called by the graphics engine on the draw thread to check the status of the
- * running timer queries and submit their results to the PStats server.
- */
-void GraphicsStateGuardian::
-flush_timer_queries() {
-#ifdef DO_PSTATS
-  // This uses the lower-level PStats interfaces for now because of all the
-  // unnecessary overhead that would otherwise be incurred when adding such a
-  // large amount of data at once.
-
-  PStatClient *client = PStatClient::get_global_pstats();
-
-  if (!client->client_is_connected()) {
-    _timer_queries_active = false;
-    return;
-  }
-
-  if (!_timer_queries_active) {
-    if (pstats_gpu_timing && _supports_timer_query) {
-      // Check if timer queries should be enabled.
-      _timer_queries_active = true;
-    } else {
-      return;
-    }
-  }
-
-  // Currently, we use one thread per GSG, for convenience.  In the future, we
-  // may want to try and use one thread per graphics card.
-  if (_pstats_gpu_thread == -1) {
-    _pstats_gpu_thread = client->make_gpu_thread(get_driver_renderer()).get_index();
-  }
-  PStatThread gpu_thread(client, _pstats_gpu_thread);
-
-  // Get the results of all the timer queries.
-  int first = 0;
-  if (!_pending_timer_queries.empty()) {
-    int count = _pending_timer_queries.size();
-    if (count == 0) {
-      return;
-    }
-
-    PStatGPUTimer timer(this, _wait_timer_pcollector);
-
-    if (_last_num_queried > 0) {
-      // We know how many queries were available last frame, and this usually
-      // stays fairly constant, so use this as a starting point.
-      int i = std::min(_last_num_queried, count) - 1;
-
-      if (_pending_timer_queries[i]->is_answer_ready()) {
-        first = count;
-        while (i < count - 1) {
-          if (!_pending_timer_queries[++i]->is_answer_ready()) {
-            first = i;
-            break;
-          }
-        }
-      } else {
-        first = 0;
-        while (i > 0) {
-          if (_pending_timer_queries[--i]->is_answer_ready()) {
-            first = i + 1;
-            break;
-          }
-        }
-      }
-    } else {
-      // We figure out which tasks the GPU has already finished by doing a
-      // binary search for the first query that does not have an answer ready.
-      // We know then that everything before that must be ready.
-      while (count > 0) {
-        int step = count / 2;
-        int i = first + step;
-        if (_pending_timer_queries[i]->is_answer_ready()) {
-          first += step + 1;
-          count -= step + 1;
-        } else {
-          count = step;
-        }
-      }
-    }
-
-    if (first <= 0) {
-      return;
-    }
-
-    _last_num_queried = first;
-
-    for (int i = 0; i < first; ++i) {
-      CPT(TimerQueryContext) query = _pending_timer_queries[i];
-
-      double time_data = query->get_timestamp(); //  + _timer_delta;
-
-      if (query->_pstats_index == _command_latency_pcollector.get_index()) {
-        // Special case for the latency pcollector.
-        PStatCollectorDef *cdef;
-        cdef = client->get_collector_ptr(query->_pstats_index)->get_def(client, query->_pstats_index);
-        _pstats_gpu_data.add_level(query->_pstats_index, time_data * cdef->_factor);
-
-      } else if (query->_pstats_index & 0x8000) {
-        _pstats_gpu_data.add_stop(query->_pstats_index & 0x7fff, time_data);
-
-      } else {
-        _pstats_gpu_data.add_start(query->_pstats_index & 0x7fff, time_data);
-      }
-
-      // We found an end-frame marker (a stop event for collector 0). This
-      // means that the GPU actually caught up with that frame, and we can
-      // flush the GPU thread's frame data to the pstats server.
-      if (query->_pstats_index == 0x8000) {
-        gpu_thread.add_frame(_pstats_gpu_data);
-        _pstats_gpu_data.clear();
-      }
-    }
-  }
-
-  if (first > 0) {
-    // Do this out of the scope of _wait_timer_pcollector.
-    _pending_timer_queries.erase(
-      _pending_timer_queries.begin(),
-      _pending_timer_queries.begin() + first
-    );
-    _timer_queries_pcollector.add_level_now(first);
-  }
-#endif
-}
-
 /**
 /**
  * Returns true if this GSG can implement decals using a DepthOffsetAttrib, or
  * Returns true if this GSG can implement decals using a DepthOffsetAttrib, or
  * false if that is unreliable and the three-step rendering process should be
  * false if that is unreliable and the three-step rendering process should be
@@ -3223,8 +3080,9 @@ void GraphicsStateGuardian::
 init_frame_pstats() {
 init_frame_pstats() {
   if (PStatClient::is_connected()) {
   if (PStatClient::is_connected()) {
     _data_transferred_pcollector.clear_level();
     _data_transferred_pcollector.clear_level();
-    _vertex_buffer_switch_pcollector.clear_level();
-    _index_buffer_switch_pcollector.clear_level();
+    //_vertex_buffer_switch_pcollector.clear_level();
+    //_index_buffer_switch_pcollector.clear_level();
+    //_shader_buffer_switch_pcollector.clear_level();
 
 
     _primitive_batches_pcollector.clear_level();
     _primitive_batches_pcollector.clear_level();
     _primitive_batches_tristrip_pcollector.clear_level();
     _primitive_batches_tristrip_pcollector.clear_level();
@@ -3243,8 +3101,19 @@ init_frame_pstats() {
     _texture_state_pcollector.clear_level();
     _texture_state_pcollector.clear_level();
   }
   }
 }
 }
-#endif  // DO_PSTATS
 
 
+/**
+ * Returns a PStatThread used to represent this GL context.
+ */
+PStatThread GraphicsStateGuardian::
+get_pstats_thread() {
+  PStatClient *client = PStatClient::get_global_pstats();
+  if (_pstats_gpu_thread == -1) {
+    _pstats_gpu_thread = client->make_gpu_thread("GPU").get_index();
+  }
+  return PStatThread(client, _pstats_gpu_thread);
+}
+#endif  // DO_PSTATS
 
 
 /**
 /**
  * Create a gamma table.
  * Create a gamma table.
@@ -3464,9 +3333,6 @@ close_gsg() {
 
 
   // Make sure that all the contexts belonging to the GSG are deleted.
   // Make sure that all the contexts belonging to the GSG are deleted.
   _prepared_objects.clear();
   _prepared_objects.clear();
-#ifdef DO_PSTATS
-  _pending_timer_queries.clear();
-#endif
 
 
   free_pointers();
   free_pointers();
 }
 }

+ 6 - 15
panda/src/display/graphicsStateGuardian.h

@@ -44,7 +44,6 @@
 #include "bitMask.h"
 #include "bitMask.h"
 #include "texture.h"
 #include "texture.h"
 #include "occlusionQueryContext.h"
 #include "occlusionQueryContext.h"
-#include "timerQueryContext.h"
 #include "loader.h"
 #include "loader.h"
 #include "shaderAttrib.h"
 #include "shaderAttrib.h"
 #include "texGenAttrib.h"
 #include "texGenAttrib.h"
@@ -320,7 +319,8 @@ public:
   virtual void begin_occlusion_query();
   virtual void begin_occlusion_query();
   virtual PT(OcclusionQueryContext) end_occlusion_query();
   virtual PT(OcclusionQueryContext) end_occlusion_query();
 
 
-  virtual PT(TimerQueryContext) issue_timer_query(int pstats_index);
+  virtual void issue_timer_query(int pstats_index);
+  virtual void issue_latency_query(int pstats_index);
 
 
   virtual void dispatch_compute(int size_x, int size_y, int size_z);
   virtual void dispatch_compute(int size_x, int size_y, int size_z);
 
 
@@ -363,8 +363,6 @@ PUBLISHED:
 public:
 public:
   virtual void end_frame(Thread *current_thread);
   virtual void end_frame(Thread *current_thread);
 
 
-  void flush_timer_queries();
-
   void set_current_properties(const FrameBufferProperties *properties);
   void set_current_properties(const FrameBufferProperties *properties);
 
 
   virtual bool depth_offset_decals();
   virtual bool depth_offset_decals();
@@ -445,6 +443,7 @@ public:
 
 
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
   static void init_frame_pstats();
   static void init_frame_pstats();
+  PStatThread get_pstats_thread();
 #endif
 #endif
 
 
 protected:
 protected:
@@ -602,13 +601,6 @@ protected:
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
   int _pstats_gpu_thread;
   int _pstats_gpu_thread;
   bool _timer_queries_active;
   bool _timer_queries_active;
-  PStatFrameData _pstats_gpu_data;
-
-  int _last_query_frame;
-  int _last_num_queried;
-  // double _timer_delta;
-  typedef pdeque<PT(TimerQueryContext)> TimerQueryQueue;
-  TimerQueryQueue _pending_timer_queries;
 #endif
 #endif
 
 
   bool _copy_texture_inverted;
   bool _copy_texture_inverted;
@@ -664,9 +656,9 @@ protected:
 
 
 public:
 public:
   // Statistics
   // Statistics
-  static PStatCollector _vertex_buffer_switch_pcollector;
-  static PStatCollector _index_buffer_switch_pcollector;
-  static PStatCollector _shader_buffer_switch_pcollector;
+  //static PStatCollector _vertex_buffer_switch_pcollector;
+  //static PStatCollector _index_buffer_switch_pcollector;
+  //static PStatCollector _shader_buffer_switch_pcollector;
   static PStatCollector _load_vertex_buffer_pcollector;
   static PStatCollector _load_vertex_buffer_pcollector;
   static PStatCollector _load_index_buffer_pcollector;
   static PStatCollector _load_index_buffer_pcollector;
   static PStatCollector _load_shader_buffer_pcollector;
   static PStatCollector _load_shader_buffer_pcollector;
@@ -699,7 +691,6 @@ public:
   static PStatCollector _wait_occlusion_pcollector;
   static PStatCollector _wait_occlusion_pcollector;
   static PStatCollector _wait_timer_pcollector;
   static PStatCollector _wait_timer_pcollector;
   static PStatCollector _timer_queries_pcollector;
   static PStatCollector _timer_queries_pcollector;
-  static PStatCollector _command_latency_pcollector;
 
 
   static PStatCollector _prepare_pcollector;
   static PStatCollector _prepare_pcollector;
   static PStatCollector _prepare_texture_pcollector;
   static PStatCollector _prepare_texture_pcollector;

+ 21 - 0
panda/src/display/graphicsWindow.cxx

@@ -39,6 +39,7 @@ GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
                GraphicsOutput *host) :
                GraphicsOutput *host) :
   GraphicsOutput(engine, pipe, name, fb_prop, win_prop, flags, gsg, host, true),
   GraphicsOutput(engine, pipe, name, fb_prop, win_prop, flags, gsg, host, true),
   _input_lock("GraphicsWindow::_input_lock"),
   _input_lock("GraphicsWindow::_input_lock"),
+  _latency_pcollector(name + " latency"),
   _properties_lock("GraphicsWindow::_properties_lock")
   _properties_lock("GraphicsWindow::_properties_lock")
 {
 {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
@@ -610,6 +611,26 @@ close_window() {
   _is_valid = false;
   _is_valid = false;
 }
 }
 
 
+/**
+ * This function will be called within the draw thread after end_frame() has
+ * been called on all windows, to initiate the exchange of the front and back
+ * buffers.
+ *
+ * This should instruct the window to prepare for the flip at the next video
+ * sync, but it should not wait.
+ *
+ * We have the two separate functions, begin_flip() and end_flip(), to make it
+ * easier to flip all of the windows at the same time.
+ */
+void GraphicsWindow::
+begin_flip() {
+#ifdef DO_PSTATS
+  if (_gsg->get_timer_queries_active()) {
+    _gsg->issue_latency_query(_latency_pcollector.get_index());
+  }
+#endif
+}
+
 /**
 /**
  * Opens the window right now.  Called from the window thread.  Returns true
  * Opens the window right now.  Called from the window thread.  Returns true
  * if the window is successfully opened, or false if there was a problem.
  * if the window is successfully opened, or false if there was a problem.

+ 4 - 0
panda/src/display/graphicsWindow.h

@@ -126,6 +126,8 @@ public:
   virtual void process_events();
   virtual void process_events();
   virtual void set_properties_now(WindowProperties &properties);
   virtual void set_properties_now(WindowProperties &properties);
 
 
+  virtual void begin_flip();
+
 protected:
 protected:
   virtual void close_window();
   virtual void close_window();
   virtual bool open_window();
   virtual bool open_window();
@@ -152,6 +154,8 @@ protected:
 
 
   bool _got_expose_event;
   bool _got_expose_event;
 
 
+  PStatCollector _latency_pcollector;
+
 private:
 private:
   LightReMutex _properties_lock;
   LightReMutex _properties_lock;
   // protects _requested_properties, _rejected_properties, and _window_event.
   // protects _requested_properties, _rejected_properties, and _window_event.

+ 0 - 1
panda/src/display/pStatGPUTimer.h

@@ -18,7 +18,6 @@
 #include "pStatTimer.h"
 #include "pStatTimer.h"
 #include "pStatCollector.h"
 #include "pStatCollector.h"
 #include "config_pstatclient.h"
 #include "config_pstatclient.h"
-#include "timerQueryContext.h"
 
 
 class Thread;
 class Thread;
 class GraphicsStateGuardian;
 class GraphicsStateGuardian;

+ 3 - 3
panda/src/display/standardMunger.cxx

@@ -37,11 +37,11 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
   _num_components(num_components),
   _num_components(num_components),
   _numeric_type(numeric_type),
   _numeric_type(numeric_type),
   _contents(contents),
   _contents(contents),
-  _munge_color(false),
-  _munge_color_scale(false),
   _auto_shader(false),
   _auto_shader(false),
   _shader_skinning(false),
   _shader_skinning(false),
-  _remove_material(false)
+  _remove_material(false),
+  _munge_color(false),
+  _munge_color_scale(false)
 {
 {
   const ShaderAttrib *shader_attrib;
   const ShaderAttrib *shader_attrib;
   state->get_attrib_def(shader_attrib);
   state->get_attrib_def(shader_attrib);

+ 7 - 0
panda/src/downloadertools/multify.cxx

@@ -792,8 +792,15 @@ main(int argc, char **argv) {
     }
     }
   }
   }
 
 
+#ifdef _MSC_VER
+  char source_date_epoch_str[64];
+  size_t source_date_epoch_size = 0;
+  if (getenv_s(&source_date_epoch_size, source_date_epoch_str,
+               sizeof(source_date_epoch_str), "SOURCE_DATE_EPOCH"), source_date_epoch_size > 1) {
+#else
   const char *source_date_epoch_str = getenv("SOURCE_DATE_EPOCH");
   const char *source_date_epoch_str = getenv("SOURCE_DATE_EPOCH");
   if (source_date_epoch_str != nullptr && source_date_epoch_str[0] != 0) {
   if (source_date_epoch_str != nullptr && source_date_epoch_str[0] != 0) {
+#endif
     source_date_epoch = (time_t)strtoll(source_date_epoch_str, nullptr, 10);
     source_date_epoch = (time_t)strtoll(source_date_epoch_str, nullptr, 10);
   }
   }
 
 

+ 1 - 1
panda/src/dxgsg9/dxShaderContext9.cxx

@@ -693,7 +693,7 @@ update_shader_texture_bindings(DXShaderContext9 *prev, GSG *gsg) {
         continue;
         continue;
       }
       }
 
 
-      if (spec._suffix != 0) {
+      if (spec._suffix != nullptr) {
         // The suffix feature is inefficient.  It is a temporary hack.
         // The suffix feature is inefficient.  It is a temporary hack.
         tex = tex->load_related(spec._suffix);
         tex = tex->load_related(spec._suffix);
       }
       }

+ 2 - 2
panda/src/dxgsg9/wdxGraphicsBuffer9.cxx

@@ -266,7 +266,7 @@ rebuild_bitplanes() {
 
 
   // Decide how big the bitplanes should be.
   // Decide how big the bitplanes should be.
 
 
-  if ((_host != 0)&&(_creation_flags & GraphicsPipe::BF_size_track_host)) {
+  if (_host != nullptr && (_creation_flags & GraphicsPipe::BF_size_track_host) != 0) {
     if (_host->get_size() != _size) {
     if (_host->get_size() != _size) {
       set_size_and_recalc(_host->get_x_size(),
       set_size_and_recalc(_host->get_x_size(),
                           _host->get_y_size());
                           _host->get_y_size());
@@ -739,7 +739,7 @@ bool wdxGraphicsBuffer9::
 open_buffer() {
 open_buffer() {
 
 
   // GSG creationinitialization.
   // GSG creationinitialization.
-  if (_gsg == 0) {
+  if (_gsg == nullptr) {
     // The code below doesn't support creating a GSG on the fly.  Just error
     // The code below doesn't support creating a GSG on the fly.  Just error
     // out for now.  _dxgsg = new DXGraphicsStateGuardian9(_engine, _pipe);
     // out for now.  _dxgsg = new DXGraphicsStateGuardian9(_engine, _pipe);
     // _gsg = _dxgsg;
     // _gsg = _dxgsg;

+ 1 - 1
panda/src/dxgsg9/wdxGraphicsWindow9.cxx

@@ -261,7 +261,7 @@ open_window() {
   static ConfigVariableBool always_discard_device("always-discard-device", true);
   static ConfigVariableBool always_discard_device("always-discard-device", true);
   bool discard_device = always_discard_device;
   bool discard_device = always_discard_device;
 
 
-  if (_gsg == 0) {
+  if (_gsg == nullptr) {
     _dxgsg = new DXGraphicsStateGuardian9(_engine, _pipe);
     _dxgsg = new DXGraphicsStateGuardian9(_engine, _pipe);
     _gsg = _dxgsg;
     _gsg = _dxgsg;
   } else {
   } else {

+ 0 - 12
panda/src/egg/eggMesherEdge.I

@@ -20,18 +20,6 @@ EggMesherEdge(int vi_a, int vi_b) : _vi_a(vi_a), _vi_b(vi_b) {
   _opposite = nullptr;
   _opposite = nullptr;
 }
 }
 
 
-/**
- *
- */
-INLINE EggMesherEdge::
-EggMesherEdge(const EggMesherEdge &copy) :
-  _vi_a(copy._vi_a),
-  _vi_b(copy._vi_b),
-  _strips(copy._strips),
-  _opposite(copy._opposite)
-{
-}
-
 /**
 /**
  * Returns true if the edge contains the indicated vertex index, false
  * Returns true if the edge contains the indicated vertex index, false
  * otherwise.
  * otherwise.

+ 0 - 1
panda/src/egg/eggMesherEdge.h

@@ -29,7 +29,6 @@ class EggMesherStrip;
 class EXPCL_PANDA_EGG EggMesherEdge {
 class EXPCL_PANDA_EGG EggMesherEdge {
 public:
 public:
   INLINE EggMesherEdge(int vi_a, int vi_b);
   INLINE EggMesherEdge(int vi_a, int vi_b);
-  INLINE EggMesherEdge(const EggMesherEdge &copy);
 
 
   void remove(EggMesherStrip *strip);
   void remove(EggMesherStrip *strip);
   void change_strip(EggMesherStrip *from, EggMesherStrip *to);
   void change_strip(EggMesherStrip *from, EggMesherStrip *to);

+ 2 - 1
panda/src/egg/eggTransform.h

@@ -16,6 +16,7 @@
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 #include "luse.h"
 #include "luse.h"
+#include "memoryBase.h"
 #include "eggObject.h"
 #include "eggObject.h"
 
 
 /**
 /**
@@ -26,7 +27,7 @@
  * This may be either a 3-d transform, and therefore described by a 4x4
  * This may be either a 3-d transform, and therefore described by a 4x4
  * matrix, or a 2-d transform, described by a 3x3 matrix.
  * matrix, or a 2-d transform, described by a 3x3 matrix.
  */
  */
-class EXPCL_PANDA_EGG EggTransform {
+class EXPCL_PANDA_EGG EggTransform : public MemoryBase {
 PUBLISHED:
 PUBLISHED:
   EggTransform();
   EggTransform();
   EggTransform(const EggTransform &copy);
   EggTransform(const EggTransform &copy);

+ 1 - 1
panda/src/egg2pg/eggSaver.cxx

@@ -803,7 +803,7 @@ convert_primitive(const GeomVertexData *vertex_data,
     const TexMatrixAttrib *tma = nullptr;
     const TexMatrixAttrib *tma = nullptr;
     net_state->get_attrib(tma);
     net_state->get_attrib(tma);
 
 
-    for (size_t i = 0; i < ta->get_num_on_stages(); ++i) {
+    for (size_t i = 0; i < (size_t)ta->get_num_on_stages(); ++i) {
       TextureStage *tex_stage = ta->get_on_stage(i);
       TextureStage *tex_stage = ta->get_on_stage(i);
 
 
       EggTexture *egg_tex = get_egg_texture(ta->get_on_texture(tex_stage));
       EggTexture *egg_tex = get_egg_texture(ta->get_on_texture(tex_stage));

+ 0 - 2
panda/src/event/CMakeLists.txt

@@ -9,7 +9,6 @@ set(P3EVENT_HEADERS
   config_event.h
   config_event.h
   buttonEvent.I buttonEvent.h
   buttonEvent.I buttonEvent.h
   buttonEventList.I buttonEventList.h
   buttonEventList.I buttonEventList.h
-  functionAsyncTask.h functionAsyncTask.I
   genericAsyncTask.h genericAsyncTask.I
   genericAsyncTask.h genericAsyncTask.I
   pointerEvent.I pointerEvent.h
   pointerEvent.I pointerEvent.h
   pointerEventList.I pointerEventList.h
   pointerEventList.I pointerEventList.h
@@ -29,7 +28,6 @@ set(P3EVENT_SOURCES
   asyncTaskSequence.cxx
   asyncTaskSequence.cxx
   buttonEvent.cxx
   buttonEvent.cxx
   buttonEventList.cxx
   buttonEventList.cxx
-  functionAsyncTask.cxx
   genericAsyncTask.cxx
   genericAsyncTask.cxx
   pointerEvent.cxx
   pointerEvent.cxx
   pointerEventList.cxx
   pointerEventList.cxx

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