Browse Source

Merge branch 'master' into deploy-ng

Mitchell Stokes 8 years ago
parent
commit
3cb24fba91
96 changed files with 3024 additions and 2235 deletions
  1. 7 7
      README.md
  2. 1 1
      direct/src/directtools/DirectCameraControl.py
  3. 3 3
      direct/src/directtools/DirectManipulation.py
  4. 1 1
      direct/src/directtools/DirectSession.py
  5. 2 2
      direct/src/tkpanels/DirectSessionPanel.py
  6. 1 1
      direct/src/tkwidgets/MemoryExplorer.py
  7. 483 469
      dtool/src/cppparser/cppBison.cxx.prebuilt
  8. 198 194
      dtool/src/cppparser/cppBison.h.prebuilt
  9. 183 38
      dtool/src/cppparser/cppBison.yxx
  10. 4 0
      dtool/src/cppparser/cppBisonDefs.h
  11. 196 0
      dtool/src/cppparser/cppClosureType.cxx
  12. 65 0
      dtool/src/cppparser/cppClosureType.h
  13. 8 0
      dtool/src/cppparser/cppDeclaration.cxx
  14. 6 0
      dtool/src/cppparser/cppDeclaration.h
  15. 97 3
      dtool/src/cppparser/cppExpression.cxx
  16. 6 0
      dtool/src/cppparser/cppExpression.h
  17. 53 8
      dtool/src/cppparser/cppFunctionType.cxx
  18. 2 0
      dtool/src/cppparser/cppFunctionType.h
  19. 70 5
      dtool/src/cppparser/cppPreprocessor.cxx
  20. 2 0
      dtool/src/cppparser/cppPreprocessor.h
  21. 8 0
      dtool/src/cppparser/cppToken.cxx
  22. 1 0
      dtool/src/cppparser/p3cppParser_composite1.cxx
  23. 4 4
      dtool/src/dtoolbase/deletedBufferChain.cxx
  24. 60 85
      dtool/src/dtoolbase/deletedChain.T
  25. 2 2
      dtool/src/dtoolbase/deletedChain.h
  26. 45 0
      dtool/src/dtoolbase/dtoolbase.h
  27. 3 3
      dtool/src/dtoolbase/dtoolbase_cc.h
  28. 2 2
      dtool/src/dtoolbase/memoryBase.h
  29. 21 107
      dtool/src/dtoolbase/memoryHook.I
  30. 134 22
      dtool/src/dtoolbase/memoryHook.cxx
  31. 2 6
      dtool/src/dtoolbase/memoryHook.h
  32. 19 40
      dtool/src/dtoolbase/pallocator.T
  33. 4 2
      dtool/src/dtoolbase/pallocator.h
  34. 79 5
      dtool/src/dtoolbase/typeHandle.cxx
  35. 47 25
      dtool/src/dtoolbase/typeHandle.h
  36. 4 4
      dtool/src/dtoolutil/executionEnvironment.cxx
  37. 52 11
      dtool/src/dtoolutil/globPattern.cxx
  38. 13 0
      dtool/src/dtoolutil/pandaSystem.cxx
  39. 2 0
      dtool/src/dtoolutil/pandaSystem.h
  40. 10 1
      dtool/src/interrogate/functionRemap.cxx
  41. 1 0
      dtool/src/interrogate/functionRemap.h
  42. 32 11
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  43. 1 2
      dtool/src/parser-inc/openssl/evp.h
  44. 8 7
      dtool/src/parser-inc/openssl/ssl.h
  45. 1 3
      dtool/src/parser-inc/openssl/x509.h
  46. 1 0
      dtool/src/prc/encryptStreamBuf.cxx
  47. 1 1
      dtool/src/prc/encryptStreamBuf.h
  48. 4 0
      dtool/src/prc/prcKeyRegistry.cxx
  49. 1 3
      dtool/src/prc/prcKeyRegistry.h
  50. 14 0
      dtool/src/pystub/pystub.cxx
  51. 0 2
      makepanda/makepanda.py
  52. 21 73
      panda/src/display/displayInformation.cxx
  53. 5 13
      panda/src/display/displayInformation.h
  54. 6 0
      panda/src/display/displayRegion.cxx
  55. 67 95
      panda/src/display/graphicsEngine.cxx
  56. 5 4
      panda/src/display/graphicsEngine.h
  57. 154 16
      panda/src/display/graphicsPipe.cxx
  58. 2 2
      panda/src/display/graphicsPipe.h
  59. 8 0
      panda/src/display/graphicsStateGuardian.I
  60. 3 0
      panda/src/display/graphicsStateGuardian.cxx
  61. 3 0
      panda/src/display/graphicsStateGuardian.h
  62. 0 8
      panda/src/downloader/bioPtr.I
  63. 12 1
      panda/src/downloader/bioPtr.cxx
  64. 3 7
      panda/src/downloader/bioPtr.h
  65. 0 6
      panda/src/downloader/bioStreamBuf.h
  66. 0 6
      panda/src/downloader/bioStreamPtr.h
  67. 10 0
      panda/src/downloader/httpChannel.cxx
  68. 2 6
      panda/src/downloader/httpChannel.h
  69. 64 62
      panda/src/downloader/httpClient.cxx
  70. 5 7
      panda/src/downloader/httpClient.h
  71. 8 4
      panda/src/egg2pg/eggSaver.cxx
  72. 2 37
      panda/src/express/multifile.cxx
  73. 5 2
      panda/src/express/multifile.h
  74. 12 7
      panda/src/glstuff/glCgShaderContext_src.cxx
  75. 7 2
      panda/src/glstuff/glGraphicsBuffer_src.cxx
  76. 28 1
      panda/src/glstuff/glGraphicsStateGuardian_src.I
  77. 309 215
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  78. 6 0
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  79. 2 2
      panda/src/gobj/geomVertexArrayData.h
  80. 18 10
      panda/src/gobj/vertexDataBuffer.I
  81. 11 20
      panda/src/gobj/vertexDataBuffer.cxx
  82. 2 2
      panda/src/gobj/vertexDataBuffer.h
  83. 33 28
      panda/src/grutil/meshDrawer.cxx
  84. 1 1
      panda/src/linmath/lsimpleMatrix.h
  85. 3 1
      panda/src/parametrics/hermiteCurve.h
  86. 2 2
      panda/src/parametrics/parametricCurveCollection.h
  87. 2 0
      panda/src/pgraph/nodePath.h
  88. 216 0
      panda/src/pgraph/nodePath_ext.cxx
  89. 2 0
      panda/src/pgraph/nodePath_ext.h
  90. 2 4
      panda/src/pgraph/pandaNode.h
  91. 3 0
      panda/src/pgraph/shaderAttrib.h
  92. 4 4
      panda/src/pgraphnodes/shaderGenerator.h
  93. 2 4
      panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx
  94. 2 4
      panda/src/tinydisplay/tinyTextureContext.cxx
  95. 2 493
      panda/src/windisplay/winGraphicsPipe.cxx
  96. 6 6
      samples/chessboard/main.py

+ 7 - 7
README.md

@@ -31,8 +31,8 @@ are included as part of the Windows 7.1 SDK.
 You will also need to have the third-party dependency libraries available for
 You will also need to have the third-party dependency libraries available for
 the build scripts to use.  These are available from one of these two URLs,
 the build scripts to use.  These are available from one of these two URLs,
 depending on whether you are on a 32-bit or 64-bit system:
 depending on whether you are on a 32-bit or 64-bit system:
-https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-win32.zip
-https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-win64.zip
+https://www.panda3d.org/download/panda3d-1.9.3/panda3d-1.9.3-tools-win32.zip
+https://www.panda3d.org/download/panda3d-1.9.3/panda3d-1.9.3-tools-win64.zip
 
 
 After acquiring these dependencies, you may simply build Panda3D from the
 After acquiring these dependencies, you may simply build Panda3D from the
 command prompt using the following command:
 command prompt using the following command:
@@ -93,11 +93,11 @@ may have to use the installpanda.py script instead, which will directly copy the
 files into the appropriate locations on your computer.  You may have to run the
 files into the appropriate locations on your computer.  You may have to run the
 `ldconfig` tool in order to update your library cache after installing Panda3D.
 `ldconfig` tool in order to update your library cache after installing Panda3D.
 
 
-Mac OS X
---------
+macOS
+-----
 
 
-On Mac OS X, you will need to download a set of precompiled thirdparty packages in order to
-compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.9.2/panda3d-1.9.2-tools-mac.tar.gz).
+On macOS, you will need to download a set of precompiled thirdparty packages in order to
+compile Panda3D, which can be acquired from [here](https://www.panda3d.org/download/panda3d-1.9.3/panda3d-1.9.3-tools-mac.tar.gz).
 
 
 After placing the thirdparty directory inside the panda3d source directory,
 After placing the thirdparty directory inside the panda3d source directory,
 you may build Panda3D using a command like the following:
 you may build Panda3D using a command like the following:
@@ -107,7 +107,7 @@ python makepanda/makepanda.py --everything --installer
 ```
 ```
 
 
 In order to make a universal build, pass the --universal flag.  You may also
 In order to make a universal build, pass the --universal flag.  You may also
-target a specific minimum Mac OS X version using the --osxtarget flag followed
+target a specific minimum macOS version using the --osxtarget flag followed
 by the release number, eg. 10.6 or 10.7.
 by the release number, eg. 10.6 or 10.7.
 
 
 If the build was successful, makepanda will have generated a .dmg file in
 If the build was successful, makepanda will have generated a .dmg file in

+ 1 - 1
direct/src/directtools/DirectCameraControl.py

@@ -413,7 +413,7 @@ class DirectCameraControl(DirectObject):
                 np = NodePath('temp')
                 np = NodePath('temp')
                 np.setPos(base.direct.camera, hitPt)
                 np.setPos(base.direct.camera, hitPt)
                 self.coaMarkerPos = np.getPos()
                 self.coaMarkerPos = np.getPos()
-                np.remove()
+                np.removeNode()
                 self.coaMarker.setPos(self.coaMarkerPos)
                 self.coaMarker.setPos(self.coaMarkerPos)
 
 
             iRay.collisionNodePath.removeNode()
             iRay.collisionNodePath.removeNode()

+ 3 - 3
direct/src/directtools/DirectManipulation.py

@@ -186,7 +186,7 @@ class DirectManipulationControl(DirectObject):
 
 
     def drawMarquee(self, startX, startY):
     def drawMarquee(self, startX, startY):
         if self.marquee:
         if self.marquee:
-            self.marquee.remove()
+            self.marquee.removeNode()
             self.marquee = None
             self.marquee = None
 
 
         if base.direct.cameraControl.useMayaCamControls and base.direct.fAlt:
         if base.direct.cameraControl.useMayaCamControls and base.direct.fAlt:
@@ -228,7 +228,7 @@ class DirectManipulationControl(DirectObject):
             skipFlags |= SKIP_CAMERA * (1 - base.getControl())
             skipFlags |= SKIP_CAMERA * (1 - base.getControl())
 
 
             if self.marquee:
             if self.marquee:
-                self.marquee.remove()
+                self.marquee.removeNode()
                 self.marquee = None
                 self.marquee = None
                 base.direct.deselectAll()
                 base.direct.deselectAll()
 
 
@@ -1691,7 +1691,7 @@ class ObjectHandles(NodePath, DirectObject):
         np.setPos(base.direct.camera, hitPt)
         np.setPos(base.direct.camera, hitPt)
         resultPt = Point3(0)
         resultPt = Point3(0)
         resultPt.assign(np.getPos())
         resultPt.assign(np.getPos())
-        np.remove()
+        np.removeNode()
         del iRay
         del iRay
         return resultPt
         return resultPt
 
 

+ 1 - 1
direct/src/directtools/DirectSession.py

@@ -900,7 +900,7 @@ class DirectSession(DirectObject):
             # If nothing specified, try selected node path
             # If nothing specified, try selected node path
             nodePath = self.selected.last
             nodePath = self.selected.last
         if nodePath:
         if nodePath:
-            nodePath.remove()
+            nodePath.removeNode()
 
 
     def removeAllSelected(self):
     def removeAllSelected(self):
         self.selected.removeAll()
         self.selected.removeAll()

+ 2 - 2
direct/src/tkpanels/DirectSessionPanel.py

@@ -177,8 +177,8 @@ class DirectSessionPanel(AppShell):
             sgeFrame, nodePath = render,
             sgeFrame, nodePath = render,
             scrolledCanvas_hull_width = 250,
             scrolledCanvas_hull_width = 250,
             scrolledCanvas_hull_height = 300)
             scrolledCanvas_hull_height = 300)
-        self.SGE.pack(fill = BOTH, expand = 0)
-        sgeFrame.pack(side = LEFT, fill = 'both', expand = 0)
+        self.SGE.pack(fill = BOTH, expand = 1)
+        sgeFrame.pack(side = LEFT, fill = 'both', expand = 1)
 
 
         # Create the notebook pages
         # Create the notebook pages
         notebook = Pmw.NoteBook(notebookFrame)
         notebook = Pmw.NoteBook(notebookFrame)

+ 1 - 1
direct/src/tkwidgets/MemoryExplorer.py

@@ -284,7 +284,7 @@ class MemoryExplorerItem:
     def getNumChildren(self):
     def getNumChildren(self):
         return len(self.children)
         return len(self.children)
 
 
-    def getChildrenAsList(self):
+    def getChildren(self):
         return self.children
         return self.children
 
 
     def getName(self):
     def getName(self):

File diff suppressed because it is too large
+ 483 - 469
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 198 - 194
dtool/src/cppparser/cppBison.h.prebuilt

@@ -89,103 +89,105 @@ extern int cppyydebug;
     XOREQUAL = 299,
     XOREQUAL = 299,
     LSHIFTEQUAL = 300,
     LSHIFTEQUAL = 300,
     RSHIFTEQUAL = 301,
     RSHIFTEQUAL = 301,
-    KW_ALIGNAS = 302,
-    KW_ALIGNOF = 303,
-    KW_AUTO = 304,
-    KW_BEGIN_PUBLISH = 305,
-    KW_BLOCKING = 306,
-    KW_BOOL = 307,
-    KW_CATCH = 308,
-    KW_CHAR = 309,
-    KW_CHAR16_T = 310,
-    KW_CHAR32_T = 311,
-    KW_CLASS = 312,
-    KW_CONST = 313,
-    KW_CONSTEXPR = 314,
-    KW_CONST_CAST = 315,
-    KW_DECLTYPE = 316,
-    KW_DEFAULT = 317,
-    KW_DELETE = 318,
-    KW_DOUBLE = 319,
-    KW_DYNAMIC_CAST = 320,
-    KW_ELSE = 321,
-    KW_END_PUBLISH = 322,
-    KW_ENUM = 323,
-    KW_EXTENSION = 324,
-    KW_EXTERN = 325,
-    KW_EXPLICIT = 326,
-    KW_PUBLISHED = 327,
-    KW_FALSE = 328,
-    KW_FINAL = 329,
-    KW_FLOAT = 330,
-    KW_FRIEND = 331,
-    KW_FOR = 332,
-    KW_GOTO = 333,
-    KW_HAS_VIRTUAL_DESTRUCTOR = 334,
-    KW_IF = 335,
-    KW_INLINE = 336,
-    KW_INT = 337,
-    KW_IS_ABSTRACT = 338,
-    KW_IS_BASE_OF = 339,
-    KW_IS_CLASS = 340,
-    KW_IS_CONSTRUCTIBLE = 341,
-    KW_IS_CONVERTIBLE_TO = 342,
-    KW_IS_DESTRUCTIBLE = 343,
-    KW_IS_EMPTY = 344,
-    KW_IS_ENUM = 345,
-    KW_IS_FINAL = 346,
-    KW_IS_FUNDAMENTAL = 347,
-    KW_IS_POD = 348,
-    KW_IS_POLYMORPHIC = 349,
-    KW_IS_STANDARD_LAYOUT = 350,
-    KW_IS_TRIVIAL = 351,
-    KW_IS_UNION = 352,
-    KW_LONG = 353,
-    KW_MAKE_MAP_PROPERTY = 354,
-    KW_MAKE_PROPERTY = 355,
-    KW_MAKE_PROPERTY2 = 356,
-    KW_MAKE_SEQ = 357,
-    KW_MAKE_SEQ_PROPERTY = 358,
-    KW_MUTABLE = 359,
-    KW_NAMESPACE = 360,
-    KW_NEW = 361,
-    KW_NOEXCEPT = 362,
-    KW_NULLPTR = 363,
-    KW_OPERATOR = 364,
-    KW_OVERRIDE = 365,
-    KW_PRIVATE = 366,
-    KW_PROTECTED = 367,
-    KW_PUBLIC = 368,
-    KW_REGISTER = 369,
-    KW_REINTERPRET_CAST = 370,
-    KW_RETURN = 371,
-    KW_SHORT = 372,
-    KW_SIGNED = 373,
-    KW_SIZEOF = 374,
-    KW_STATIC = 375,
-    KW_STATIC_ASSERT = 376,
-    KW_STATIC_CAST = 377,
-    KW_STRUCT = 378,
-    KW_TEMPLATE = 379,
-    KW_THREAD_LOCAL = 380,
-    KW_THROW = 381,
-    KW_TRUE = 382,
-    KW_TRY = 383,
-    KW_TYPEDEF = 384,
-    KW_TYPEID = 385,
-    KW_TYPENAME = 386,
-    KW_UNDERLYING_TYPE = 387,
-    KW_UNION = 388,
-    KW_UNSIGNED = 389,
-    KW_USING = 390,
-    KW_VIRTUAL = 391,
-    KW_VOID = 392,
-    KW_VOLATILE = 393,
-    KW_WCHAR_T = 394,
-    KW_WHILE = 395,
-    START_CPP = 396,
-    START_CONST_EXPR = 397,
-    START_TYPE = 398
+    ATTR_LEFT = 302,
+    ATTR_RIGHT = 303,
+    KW_ALIGNAS = 304,
+    KW_ALIGNOF = 305,
+    KW_AUTO = 306,
+    KW_BEGIN_PUBLISH = 307,
+    KW_BLOCKING = 308,
+    KW_BOOL = 309,
+    KW_CATCH = 310,
+    KW_CHAR = 311,
+    KW_CHAR16_T = 312,
+    KW_CHAR32_T = 313,
+    KW_CLASS = 314,
+    KW_CONST = 315,
+    KW_CONSTEXPR = 316,
+    KW_CONST_CAST = 317,
+    KW_DECLTYPE = 318,
+    KW_DEFAULT = 319,
+    KW_DELETE = 320,
+    KW_DOUBLE = 321,
+    KW_DYNAMIC_CAST = 322,
+    KW_ELSE = 323,
+    KW_END_PUBLISH = 324,
+    KW_ENUM = 325,
+    KW_EXTENSION = 326,
+    KW_EXTERN = 327,
+    KW_EXPLICIT = 328,
+    KW_PUBLISHED = 329,
+    KW_FALSE = 330,
+    KW_FINAL = 331,
+    KW_FLOAT = 332,
+    KW_FRIEND = 333,
+    KW_FOR = 334,
+    KW_GOTO = 335,
+    KW_HAS_VIRTUAL_DESTRUCTOR = 336,
+    KW_IF = 337,
+    KW_INLINE = 338,
+    KW_INT = 339,
+    KW_IS_ABSTRACT = 340,
+    KW_IS_BASE_OF = 341,
+    KW_IS_CLASS = 342,
+    KW_IS_CONSTRUCTIBLE = 343,
+    KW_IS_CONVERTIBLE_TO = 344,
+    KW_IS_DESTRUCTIBLE = 345,
+    KW_IS_EMPTY = 346,
+    KW_IS_ENUM = 347,
+    KW_IS_FINAL = 348,
+    KW_IS_FUNDAMENTAL = 349,
+    KW_IS_POD = 350,
+    KW_IS_POLYMORPHIC = 351,
+    KW_IS_STANDARD_LAYOUT = 352,
+    KW_IS_TRIVIAL = 353,
+    KW_IS_UNION = 354,
+    KW_LONG = 355,
+    KW_MAKE_MAP_PROPERTY = 356,
+    KW_MAKE_PROPERTY = 357,
+    KW_MAKE_PROPERTY2 = 358,
+    KW_MAKE_SEQ = 359,
+    KW_MAKE_SEQ_PROPERTY = 360,
+    KW_MUTABLE = 361,
+    KW_NAMESPACE = 362,
+    KW_NEW = 363,
+    KW_NOEXCEPT = 364,
+    KW_NULLPTR = 365,
+    KW_OPERATOR = 366,
+    KW_OVERRIDE = 367,
+    KW_PRIVATE = 368,
+    KW_PROTECTED = 369,
+    KW_PUBLIC = 370,
+    KW_REGISTER = 371,
+    KW_REINTERPRET_CAST = 372,
+    KW_RETURN = 373,
+    KW_SHORT = 374,
+    KW_SIGNED = 375,
+    KW_SIZEOF = 376,
+    KW_STATIC = 377,
+    KW_STATIC_ASSERT = 378,
+    KW_STATIC_CAST = 379,
+    KW_STRUCT = 380,
+    KW_TEMPLATE = 381,
+    KW_THREAD_LOCAL = 382,
+    KW_THROW = 383,
+    KW_TRUE = 384,
+    KW_TRY = 385,
+    KW_TYPEDEF = 386,
+    KW_TYPEID = 387,
+    KW_TYPENAME = 388,
+    KW_UNDERLYING_TYPE = 389,
+    KW_UNION = 390,
+    KW_UNSIGNED = 391,
+    KW_USING = 392,
+    KW_VIRTUAL = 393,
+    KW_VOID = 394,
+    KW_VOLATILE = 395,
+    KW_WCHAR_T = 396,
+    KW_WHILE = 397,
+    START_CPP = 398,
+    START_CONST_EXPR = 399,
+    START_TYPE = 400
   };
   };
 #endif
 #endif
 /* Tokens.  */
 /* Tokens.  */
@@ -233,103 +235,105 @@ extern int cppyydebug;
 #define XOREQUAL 299
 #define XOREQUAL 299
 #define LSHIFTEQUAL 300
 #define LSHIFTEQUAL 300
 #define RSHIFTEQUAL 301
 #define RSHIFTEQUAL 301
-#define KW_ALIGNAS 302
-#define KW_ALIGNOF 303
-#define KW_AUTO 304
-#define KW_BEGIN_PUBLISH 305
-#define KW_BLOCKING 306
-#define KW_BOOL 307
-#define KW_CATCH 308
-#define KW_CHAR 309
-#define KW_CHAR16_T 310
-#define KW_CHAR32_T 311
-#define KW_CLASS 312
-#define KW_CONST 313
-#define KW_CONSTEXPR 314
-#define KW_CONST_CAST 315
-#define KW_DECLTYPE 316
-#define KW_DEFAULT 317
-#define KW_DELETE 318
-#define KW_DOUBLE 319
-#define KW_DYNAMIC_CAST 320
-#define KW_ELSE 321
-#define KW_END_PUBLISH 322
-#define KW_ENUM 323
-#define KW_EXTENSION 324
-#define KW_EXTERN 325
-#define KW_EXPLICIT 326
-#define KW_PUBLISHED 327
-#define KW_FALSE 328
-#define KW_FINAL 329
-#define KW_FLOAT 330
-#define KW_FRIEND 331
-#define KW_FOR 332
-#define KW_GOTO 333
-#define KW_HAS_VIRTUAL_DESTRUCTOR 334
-#define KW_IF 335
-#define KW_INLINE 336
-#define KW_INT 337
-#define KW_IS_ABSTRACT 338
-#define KW_IS_BASE_OF 339
-#define KW_IS_CLASS 340
-#define KW_IS_CONSTRUCTIBLE 341
-#define KW_IS_CONVERTIBLE_TO 342
-#define KW_IS_DESTRUCTIBLE 343
-#define KW_IS_EMPTY 344
-#define KW_IS_ENUM 345
-#define KW_IS_FINAL 346
-#define KW_IS_FUNDAMENTAL 347
-#define KW_IS_POD 348
-#define KW_IS_POLYMORPHIC 349
-#define KW_IS_STANDARD_LAYOUT 350
-#define KW_IS_TRIVIAL 351
-#define KW_IS_UNION 352
-#define KW_LONG 353
-#define KW_MAKE_MAP_PROPERTY 354
-#define KW_MAKE_PROPERTY 355
-#define KW_MAKE_PROPERTY2 356
-#define KW_MAKE_SEQ 357
-#define KW_MAKE_SEQ_PROPERTY 358
-#define KW_MUTABLE 359
-#define KW_NAMESPACE 360
-#define KW_NEW 361
-#define KW_NOEXCEPT 362
-#define KW_NULLPTR 363
-#define KW_OPERATOR 364
-#define KW_OVERRIDE 365
-#define KW_PRIVATE 366
-#define KW_PROTECTED 367
-#define KW_PUBLIC 368
-#define KW_REGISTER 369
-#define KW_REINTERPRET_CAST 370
-#define KW_RETURN 371
-#define KW_SHORT 372
-#define KW_SIGNED 373
-#define KW_SIZEOF 374
-#define KW_STATIC 375
-#define KW_STATIC_ASSERT 376
-#define KW_STATIC_CAST 377
-#define KW_STRUCT 378
-#define KW_TEMPLATE 379
-#define KW_THREAD_LOCAL 380
-#define KW_THROW 381
-#define KW_TRUE 382
-#define KW_TRY 383
-#define KW_TYPEDEF 384
-#define KW_TYPEID 385
-#define KW_TYPENAME 386
-#define KW_UNDERLYING_TYPE 387
-#define KW_UNION 388
-#define KW_UNSIGNED 389
-#define KW_USING 390
-#define KW_VIRTUAL 391
-#define KW_VOID 392
-#define KW_VOLATILE 393
-#define KW_WCHAR_T 394
-#define KW_WHILE 395
-#define START_CPP 396
-#define START_CONST_EXPR 397
-#define START_TYPE 398
+#define ATTR_LEFT 302
+#define ATTR_RIGHT 303
+#define KW_ALIGNAS 304
+#define KW_ALIGNOF 305
+#define KW_AUTO 306
+#define KW_BEGIN_PUBLISH 307
+#define KW_BLOCKING 308
+#define KW_BOOL 309
+#define KW_CATCH 310
+#define KW_CHAR 311
+#define KW_CHAR16_T 312
+#define KW_CHAR32_T 313
+#define KW_CLASS 314
+#define KW_CONST 315
+#define KW_CONSTEXPR 316
+#define KW_CONST_CAST 317
+#define KW_DECLTYPE 318
+#define KW_DEFAULT 319
+#define KW_DELETE 320
+#define KW_DOUBLE 321
+#define KW_DYNAMIC_CAST 322
+#define KW_ELSE 323
+#define KW_END_PUBLISH 324
+#define KW_ENUM 325
+#define KW_EXTENSION 326
+#define KW_EXTERN 327
+#define KW_EXPLICIT 328
+#define KW_PUBLISHED 329
+#define KW_FALSE 330
+#define KW_FINAL 331
+#define KW_FLOAT 332
+#define KW_FRIEND 333
+#define KW_FOR 334
+#define KW_GOTO 335
+#define KW_HAS_VIRTUAL_DESTRUCTOR 336
+#define KW_IF 337
+#define KW_INLINE 338
+#define KW_INT 339
+#define KW_IS_ABSTRACT 340
+#define KW_IS_BASE_OF 341
+#define KW_IS_CLASS 342
+#define KW_IS_CONSTRUCTIBLE 343
+#define KW_IS_CONVERTIBLE_TO 344
+#define KW_IS_DESTRUCTIBLE 345
+#define KW_IS_EMPTY 346
+#define KW_IS_ENUM 347
+#define KW_IS_FINAL 348
+#define KW_IS_FUNDAMENTAL 349
+#define KW_IS_POD 350
+#define KW_IS_POLYMORPHIC 351
+#define KW_IS_STANDARD_LAYOUT 352
+#define KW_IS_TRIVIAL 353
+#define KW_IS_UNION 354
+#define KW_LONG 355
+#define KW_MAKE_MAP_PROPERTY 356
+#define KW_MAKE_PROPERTY 357
+#define KW_MAKE_PROPERTY2 358
+#define KW_MAKE_SEQ 359
+#define KW_MAKE_SEQ_PROPERTY 360
+#define KW_MUTABLE 361
+#define KW_NAMESPACE 362
+#define KW_NEW 363
+#define KW_NOEXCEPT 364
+#define KW_NULLPTR 365
+#define KW_OPERATOR 366
+#define KW_OVERRIDE 367
+#define KW_PRIVATE 368
+#define KW_PROTECTED 369
+#define KW_PUBLIC 370
+#define KW_REGISTER 371
+#define KW_REINTERPRET_CAST 372
+#define KW_RETURN 373
+#define KW_SHORT 374
+#define KW_SIGNED 375
+#define KW_SIZEOF 376
+#define KW_STATIC 377
+#define KW_STATIC_ASSERT 378
+#define KW_STATIC_CAST 379
+#define KW_STRUCT 380
+#define KW_TEMPLATE 381
+#define KW_THREAD_LOCAL 382
+#define KW_THROW 383
+#define KW_TRUE 384
+#define KW_TRY 385
+#define KW_TYPEDEF 386
+#define KW_TYPEID 387
+#define KW_TYPENAME 388
+#define KW_UNDERLYING_TYPE 389
+#define KW_UNION 390
+#define KW_UNSIGNED 391
+#define KW_USING 392
+#define KW_VIRTUAL 393
+#define KW_VOID 394
+#define KW_VOLATILE 395
+#define KW_WCHAR_T 396
+#define KW_WHILE 397
+#define START_CPP 398
+#define START_CONST_EXPR 399
+#define START_TYPE 400
 
 
 /* Value type.  */
 /* Value type.  */
 
 

+ 183 - 38
dtool/src/cppparser/cppBison.yxx

@@ -8,6 +8,7 @@
 
 
 #include "cppBisonDefs.h"
 #include "cppBisonDefs.h"
 #include "cppParser.h"
 #include "cppParser.h"
+#include "cppClosureType.h"
 #include "cppExpression.h"
 #include "cppExpression.h"
 #include "cppSimpleType.h"
 #include "cppSimpleType.h"
 #include "cppExtensionType.h"
 #include "cppExtensionType.h"
@@ -44,6 +45,7 @@ static CPPEnumType *current_enum = NULL;
 static int current_storage_class = 0;
 static int current_storage_class = 0;
 static CPPType *current_type = NULL;
 static CPPType *current_type = NULL;
 static CPPExpression *current_expr = NULL;
 static CPPExpression *current_expr = NULL;
+static CPPClosureType *current_closure = NULL;
 static int publish_nest_level = 0;
 static int publish_nest_level = 0;
 static CPPVisibility publish_previous;
 static CPPVisibility publish_previous;
 static YYLTYPE publish_loc;
 static YYLTYPE publish_loc;
@@ -247,6 +249,8 @@ pop_struct() {
 %token XOREQUAL
 %token XOREQUAL
 %token LSHIFTEQUAL
 %token LSHIFTEQUAL
 %token RSHIFTEQUAL
 %token RSHIFTEQUAL
+%token ATTR_LEFT
+%token ATTR_RIGHT
 
 
 %token KW_ALIGNAS
 %token KW_ALIGNAS
 %token KW_ALIGNOF
 %token KW_ALIGNOF
@@ -363,6 +367,8 @@ pop_struct() {
 %type <u.param_list> function_parameters
 %type <u.param_list> function_parameters
 %type <u.param_list> formal_parameter_list
 %type <u.param_list> formal_parameter_list
 %type <u.param_list> formal_parameters
 %type <u.param_list> formal_parameters
+%type <u.closure_type> capture_list
+%type <u.capture> capture
 %type <u.expr> template_parameter_maybe_initialize
 %type <u.expr> template_parameter_maybe_initialize
 %type <u.expr> maybe_initialize
 %type <u.expr> maybe_initialize
 %type <u.expr> maybe_initialize_or_constructor_body
 %type <u.expr> maybe_initialize_or_constructor_body
@@ -870,10 +876,18 @@ storage_class:
 {
 {
   $$ = $2 | (int)CPPInstance::SC_thread_local;
   $$ = $2 | (int)CPPInstance::SC_thread_local;
 }
 }
-        | '[' '[' attribute_specifiers ']' ']' storage_class
+        | ATTR_LEFT attribute_specifiers ATTR_RIGHT storage_class
 {
 {
   // Ignore attribute specifiers for now.
   // Ignore attribute specifiers for now.
-  $$ = $6;
+  $$ = $4;
+}
+        | KW_ALIGNAS '(' const_expr ')' storage_class
+{
+  $$ = $5;
+}
+        | KW_ALIGNAS '(' type_decl ')' storage_class
+{
+  $$ = $5;
 }
 }
         ;
         ;
 
 
@@ -885,6 +899,7 @@ attribute_specifiers:
 attribute_specifier:
 attribute_specifier:
         name
         name
         | name '(' formal_parameter_list ')'
         | name '(' formal_parameter_list ')'
+        | KW_USING name ':' attribute_specifier
         ;
         ;
 
 
 type_like_declaration:
 type_like_declaration:
@@ -1221,6 +1236,15 @@ function_post:
 {
 {
   $$ = $1 | (int)CPPFunctionType::F_noexcept;
   $$ = $1 | (int)CPPFunctionType::F_noexcept;
 }
 }
+/*        | function_post KW_NOEXCEPT '(' const_expr ')'
+{
+  CPPExpression::Result result = $4->evaluate();
+  if (result._type == CPPExpression::RT_error) {
+    yywarning("noexcept requires a constant expression", @4);
+  } else if (result.as_boolean()) {
+    $$ = $1 | (int)CPPFunctionType::F_noexcept;
+  }
+}*/
         | function_post KW_FINAL
         | function_post KW_FINAL
 {
 {
   $$ = $1 | (int)CPPFunctionType::F_final;
   $$ = $1 | (int)CPPFunctionType::F_final;
@@ -1241,6 +1265,11 @@ function_post:
 {
 {
   // Used for lambdas, currently ignored.
   // Used for lambdas, currently ignored.
   $$ = $1;
   $$ = $1;
+}
+        | function_post KW_CONSTEXPR
+{
+  // Used for lambdas in C++17, currently ignored.
+  $$ = $1;
 }
 }
         | function_post KW_THROW '(' ')'
         | function_post KW_THROW '(' ')'
 {
 {
@@ -1254,10 +1283,10 @@ function_post:
 {
 {
   $$ = $1;
   $$ = $1;
 }
 }
-/*        | function_post '[' '[' attribute_specifiers ']' ']'
+        | function_post ATTR_LEFT attribute_specifiers ATTR_RIGHT
 {
 {
   $$ = $1;
   $$ = $1;
-}*/
+}
         ;
         ;
 
 
 function_operator:
 function_operator:
@@ -1422,10 +1451,12 @@ function_operator:
 more_template_declaration:
 more_template_declaration:
         type_like_declaration
         type_like_declaration
         | template_declaration
         | template_declaration
+        | friend_declaration
         ;
         ;
 
 
 template_declaration:
 template_declaration:
-        KW_TEMPLATE
+        KW_EXTERN template_declaration
+        | KW_TEMPLATE
 {
 {
   push_scope(new CPPTemplateScope(current_scope));
   push_scope(new CPPTemplateScope(current_scope));
 }
 }
@@ -1433,7 +1464,8 @@ template_declaration:
 {
 {
   pop_scope();
   pop_scope();
 }
 }
-	| KW_TEMPLATE type_like_declaration
+        | KW_TEMPLATE type_like_declaration
+        | KW_TEMPLATE friend_declaration
         ;
         ;
 
 
 template_formal_parameters:
 template_formal_parameters:
@@ -1885,6 +1917,10 @@ function_parameter:
         | KW_REGISTER function_parameter
         | KW_REGISTER function_parameter
 {
 {
   $$ = $2;
   $$ = $2;
+}
+        | ATTR_LEFT attribute_specifiers ATTR_RIGHT function_parameter
+{
+  $$ = $4;
 }
 }
         ;
         ;
 
 
@@ -2228,16 +2264,16 @@ type:
 {
 {
   $$ = CPPType::new_type($1);
   $$ = CPPType::new_type($1);
 }
 }
-        | struct_keyword name
+        | struct_keyword struct_attributes name
 {
 {
-  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer);
   if (type != NULL) {
   if (type != NULL) {
     $$ = type;
     $$ = type;
   } else {
   } else {
     CPPExtensionType *et =
     CPPExtensionType *et =
-      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file))
       ->as_extension_type();
       ->as_extension_type();
-    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    CPPScope *scope = $3->get_scope(current_scope, global_scope);
     if (scope != NULL) {
     if (scope != NULL) {
       scope->define_extension_type(et);
       scope->define_extension_type(et);
     }
     }
@@ -2268,6 +2304,10 @@ type:
     str << *$3;
     str << *$3;
     yyerror("could not determine type of " + str.str(), @3);
     yyerror("could not determine type of " + str.str(), @3);
   }
   }
+}
+        | KW_DECLTYPE '(' KW_AUTO ')'
+{
+  $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto));
 }
 }
         | KW_UNDERLYING_TYPE '(' full_type ')'
         | KW_UNDERLYING_TYPE '(' full_type ')'
 {
 {
@@ -2325,16 +2365,16 @@ type_decl:
 {
 {
   $$ = new CPPTypeDeclaration(CPPType::new_type($1));
   $$ = new CPPTypeDeclaration(CPPType::new_type($1));
 }
 }
-        | struct_keyword name
+        | struct_keyword struct_attributes name
 {
 {
-  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer);
   if (type != NULL) {
   if (type != NULL) {
     $$ = type;
     $$ = type;
   } else {
   } else {
     CPPExtensionType *et =
     CPPExtensionType *et =
-      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file))
       ->as_extension_type();
       ->as_extension_type();
-    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    CPPScope *scope = $3->get_scope(current_scope, global_scope);
     if (scope != NULL) {
     if (scope != NULL) {
       scope->define_extension_type(et);
       scope->define_extension_type(et);
     }
     }
@@ -2383,6 +2423,10 @@ type_decl:
     str << *$3;
     str << *$3;
     yyerror("could not determine type of " + str.str(), @3);
     yyerror("could not determine type of " + str.str(), @3);
   }
   }
+}
+        | KW_DECLTYPE '(' KW_AUTO ')'
+{
+  $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_auto));
 }
 }
         | KW_UNDERLYING_TYPE '(' full_type ')'
         | KW_UNDERLYING_TYPE '(' full_type ')'
 {
 {
@@ -2417,16 +2461,16 @@ predefined_type:
 {
 {
   $$ = CPPType::new_type(new CPPTBDType($2));
   $$ = CPPType::new_type(new CPPTBDType($2));
 }
 }
-        | struct_keyword name
+        | struct_keyword struct_attributes name
 {
 {
-  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  CPPType *type = $3->find_type(current_scope, global_scope, false, current_lexer);
   if (type != NULL) {
   if (type != NULL) {
     $$ = type;
     $$ = type;
   } else {
   } else {
     CPPExtensionType *et =
     CPPExtensionType *et =
-      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      CPPType::new_type(new CPPExtensionType($1, $3, current_scope, @1.file))
       ->as_extension_type();
       ->as_extension_type();
-    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    CPPScope *scope = $3->get_scope(current_scope, global_scope);
     if (scope != NULL) {
     if (scope != NULL) {
       scope->define_extension_type(et);
       scope->define_extension_type(et);
     }
     }
@@ -2507,8 +2551,15 @@ full_type:
 }
 }
         ;
         ;
 
 
+struct_attributes:
+        empty
+        | struct_attributes ATTR_LEFT attribute_specifiers ATTR_RIGHT
+        | struct_attributes KW_ALIGNAS '(' const_expr ')'
+        | struct_attributes KW_ALIGNAS '(' type_decl ')'
+        ;
+
 anonymous_struct:
 anonymous_struct:
-        struct_keyword '{'
+        struct_keyword struct_attributes '{'
 {
 {
   CPPVisibility starting_vis =
   CPPVisibility starting_vis =
   ($1 == CPPExtensionType::T_class) ? V_private : V_public;
   ($1 == CPPExtensionType::T_class) ? V_private : V_public;
@@ -2532,19 +2583,19 @@ anonymous_struct:
         ;
         ;
 
 
 named_struct:
 named_struct:
-        struct_keyword name_no_final
+        struct_keyword struct_attributes name_no_final
 {
 {
   CPPVisibility starting_vis =
   CPPVisibility starting_vis =
   ($1 == CPPExtensionType::T_class) ? V_private : V_public;
   ($1 == CPPExtensionType::T_class) ? V_private : V_public;
 
 
-  CPPScope *scope = $2->get_scope(current_scope, global_scope, current_lexer);
+  CPPScope *scope = $3->get_scope(current_scope, global_scope, current_lexer);
   if (scope == NULL) {
   if (scope == NULL) {
     scope = current_scope;
     scope = current_scope;
   }
   }
-  CPPScope *new_scope = new CPPScope(scope, $2->_names.back(),
+  CPPScope *new_scope = new CPPScope(scope, $3->_names.back(),
                                      starting_vis);
                                      starting_vis);
 
 
-  CPPStructType *st = new CPPStructType($1, $2, current_scope,
+  CPPStructType *st = new CPPStructType($1, $3, current_scope,
                                         new_scope, @1.file);
                                         new_scope, @1.file);
   new_scope->set_struct_type(st);
   new_scope->set_struct_type(st);
   current_scope->define_extension_type(st);
   current_scope->define_extension_type(st);
@@ -2927,6 +2978,7 @@ element:
         | SCOPE | PLUSPLUS | MINUSMINUS
         | SCOPE | PLUSPLUS | MINUSMINUS
         | TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL
         | TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL
         | OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL
         | OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL
+        | ATTR_LEFT | ATTR_RIGHT
         | KW_ALIGNAS | KW_ALIGNOF | KW_AUTO | KW_BOOL | KW_CATCH
         | KW_ALIGNAS | KW_ALIGNOF | KW_AUTO | KW_BOOL | KW_CATCH
         | KW_CHAR | KW_CHAR16_T | KW_CHAR32_T | KW_CLASS | KW_CONST
         | KW_CHAR | KW_CHAR16_T | KW_CHAR32_T | KW_CLASS | KW_CONST
         | KW_CONSTEXPR | KW_CONST_CAST | KW_DECLTYPE | KW_DEFAULT
         | KW_CONSTEXPR | KW_CONST_CAST | KW_DECLTYPE | KW_DEFAULT
@@ -3010,6 +3062,18 @@ no_angle_bracket_const_expr:
         | KW_SIZEOF '(' full_type ')' %prec UNARY
         | KW_SIZEOF '(' full_type ')' %prec UNARY
 {
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+{
+  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
+  if (arg == (CPPDeclaration *)NULL) {
+    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
+  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
+    CPPInstance *inst = arg->as_instance();
+    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
+  } else {
+    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
+  }
 }
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
 {
@@ -3172,6 +3236,16 @@ const_expr:
   }
   }
   assert(type != NULL);
   assert(type != NULL);
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
   $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+        | TYPENAME_IDENTIFIER '{' optional_const_expr_comma '}'
+{
+  // Aggregate initialization.
+  CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
+  if (type == NULL) {
+    yyerror(string("internal error resolving type ") + $1->get_fully_scoped_name(), @1);
+  }
+  assert(type != NULL);
+  $$ = new CPPExpression(CPPExpression::aggregate_init_op(type, $3));
 }
 }
         | KW_INT '(' optional_const_expr_comma ')'
         | KW_INT '(' optional_const_expr_comma ')'
 {
 {
@@ -3252,6 +3326,18 @@ const_expr:
         | KW_SIZEOF '(' full_type ')' %prec UNARY
         | KW_SIZEOF '(' full_type ')' %prec UNARY
 {
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+{
+  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
+  if (arg == (CPPDeclaration *)NULL) {
+    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
+  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
+    CPPInstance *inst = arg->as_instance();
+    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
+  } else {
+    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
+  }
 }
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
 {
@@ -3468,11 +3554,16 @@ const_operand:
 }
 }
         | '[' capture_list ']' function_post maybe_trailing_return_type '{' code '}'
         | '[' capture_list ']' function_post maybe_trailing_return_type '{' code '}'
 {
 {
-  $$ = NULL;
+  $2->_flags = $4;
+  $2->_return_type = $5;
+  $$ = new CPPExpression(CPPExpression::lambda($2));
 }
 }
         | '[' capture_list ']' '(' function_parameter_list ')' function_post maybe_trailing_return_type '{' code '}'
         | '[' capture_list ']' '(' function_parameter_list ')' function_post maybe_trailing_return_type '{' code '}'
 {
 {
-  $$ = NULL;
+  $2->_parameters = $5;
+  $2->_flags = $7;
+  $2->_return_type = $8;
+  $$ = new CPPExpression(CPPExpression::lambda($2));
 }
 }
         | KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')'
         | KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')'
 {
 {
@@ -3579,6 +3670,18 @@ formal_const_expr:
         | KW_SIZEOF '(' full_type ')' %prec UNARY
         | KW_SIZEOF '(' full_type ')' %prec UNARY
 {
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+{
+  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
+  if (arg == (CPPDeclaration *)NULL) {
+    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
+  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
+    CPPInstance *inst = arg->as_instance();
+    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
+  } else {
+    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
+  }
 }
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
 {
@@ -3794,15 +3897,65 @@ formal_const_operand:
 /* The contents of the [] list preceding a lambda expression. */
 /* The contents of the [] list preceding a lambda expression. */
 capture_list:
 capture_list:
         empty
         empty
-        | capture
-        | capture ',' capture_list
+{
+  $$ = new CPPClosureType();
+}
+        | '='
+{
+  $$ = new CPPClosureType(CPPClosureType::CT_by_value);
+}
+        | '&'
+{
+  $$ = new CPPClosureType(CPPClosureType::CT_by_reference);
+}
+        | capture maybe_initialize
+{
+  $$ = new CPPClosureType();
+  $1->_initializer = $2;
+  $$->_captures.push_back(*$1);
+  delete $1;
+}
+        | capture_list ',' capture maybe_initialize
+{
+  $$ = $1;
+  $3->_initializer = $4;
+  $$->_captures.push_back(*$3);
+  delete $3;
+}
         ;
         ;
 
 
 capture:
 capture:
-        '&'
-        | '='
-        | '&' name
+        '&' name
+{
+  $$ = new CPPClosureType::Capture;
+  $$->_name = $2->get_simple_name();
+  $$->_type = CPPClosureType::CT_by_reference;
+}
+        | '&' name ELLIPSIS
+{
+  $$ = new CPPClosureType::Capture;
+  $$->_name = $2->get_simple_name();
+  $$->_type = CPPClosureType::CT_by_reference;
+}
         | name
         | name
+{
+  $$ = new CPPClosureType::Capture;
+  $$->_name = $1->get_simple_name();
+  if ($$->_name == "this") {
+    $$->_type = CPPClosureType::CT_by_reference;
+  } else {
+    $$->_type = CPPClosureType::CT_by_value;
+  }
+}
+        | '*' name
+{
+  $$ = new CPPClosureType::Capture;
+  $$->_name = $2->get_simple_name();
+  $$->_type = CPPClosureType::CT_by_value;
+  if ($$->_name != "this") {
+    yywarning("only capture name 'this' may be preceded by an asterisk", @2);
+  }
+}
         ;
         ;
 
 
 class_derivation_name:
 class_derivation_name:
@@ -3813,14 +3966,6 @@ class_derivation_name:
     type = CPPType::new_type(new CPPTBDType($1));
     type = CPPType::new_type(new CPPTBDType($1));
   }
   }
   $$ = type;
   $$ = type;
-}
-        | struct_keyword name
-{
-  CPPType *type = $2->find_type(current_scope, global_scope, true, current_lexer);
-  if (type == NULL) {
-    type = CPPType::new_type(new CPPTBDType($2));
-  }
-  $$ = type;
 }
 }
         | KW_TYPENAME name
         | KW_TYPENAME name
 {
 {

+ 4 - 0
dtool/src/cppparser/cppBisonDefs.h

@@ -23,6 +23,7 @@
 
 
 #include <string>
 #include <string>
 
 
+#include "cppClosureType.h"
 #include "cppExtensionType.h"
 #include "cppExtensionType.h"
 #include "cppFile.h"
 #include "cppFile.h"
 
 
@@ -42,6 +43,7 @@ class CPPParameterList;
 class CPPTemplateParameterList;
 class CPPTemplateParameterList;
 class CPPScope;
 class CPPScope;
 class CPPIdentifier;
 class CPPIdentifier;
+class CPPCaptureType;
 
 
 void parse_cpp(CPPParser *cp);
 void parse_cpp(CPPParser *cp);
 CPPExpression *parse_const_expr(CPPPreprocessor *pp,
 CPPExpression *parse_const_expr(CPPPreprocessor *pp,
@@ -81,6 +83,8 @@ public:
     CPPExtensionType::Type extension_enum;
     CPPExtensionType::Type extension_enum;
     CPPExpression *expr;
     CPPExpression *expr;
     CPPIdentifier *identifier;
     CPPIdentifier *identifier;
+    CPPClosureType *closure_type;
+    CPPClosureType::Capture *capture;
   } u;
   } u;
 };
 };
 #define YYSTYPE cppyystype
 #define YYSTYPE cppyystype

+ 196 - 0
dtool/src/cppparser/cppClosureType.cxx

@@ -0,0 +1,196 @@
+/**
+ * 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 cppClosureType.cxx
+ * @author rdb
+ * @date 2017-01-14
+ */
+
+#include "cppClosureType.h"
+#include "cppParameterList.h"
+#include "cppExpression.h"
+
+/**
+ *
+ */
+CPPClosureType::
+CPPClosureType(CaptureType default_capture) :
+  CPPFunctionType(NULL, NULL, 0),
+  _default_capture(default_capture) {
+}
+
+/**
+ *
+ */
+CPPClosureType::
+CPPClosureType(const CPPClosureType &copy) :
+  CPPFunctionType(copy),
+  _captures(copy._captures),
+  _default_capture(copy._default_capture)
+{
+}
+
+/**
+ *
+ */
+void CPPClosureType::
+operator = (const CPPClosureType &copy) {
+  CPPFunctionType::operator = (copy);
+  _captures = copy._captures;
+  _default_capture = copy._default_capture;
+}
+
+/**
+ * Adds a new capture to the beginning of the capture list.
+ */
+void CPPClosureType::
+add_capture(string name, CaptureType type, CPPExpression *initializer) {
+  if (type == CT_none) {
+    if (name == "this") {
+      type = CT_by_reference;
+    } else {
+      type = CT_by_value;
+    }
+  }
+
+  Capture capture = {move(name), type, initializer};
+  _captures.insert(_captures.begin(), move(capture));
+}
+
+/**
+ * Returns true if this declaration is an actual, factual declaration, or
+ * false if some part of the declaration depends on a template parameter which
+ * has not yet been instantiated.
+ */
+bool CPPClosureType::
+is_fully_specified() const {
+  return CPPFunctionType::is_fully_specified();
+}
+
+/**
+ * Returns true if the type is default-constructible.
+ */
+bool CPPClosureType::
+is_default_constructible() const {
+  return false;
+}
+
+/**
+ * Returns true if the type is copy-constructible.
+ */
+bool CPPClosureType::
+is_copy_constructible() const {
+  return true;
+}
+
+/**
+ * Returns true if the type is destructible.
+ */
+bool CPPClosureType::
+is_destructible() const {
+  return true;
+}
+
+/**
+ *
+ */
+void CPPClosureType::
+output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
+  out.put('[');
+
+  bool have_capture = false;
+  switch (_default_capture) {
+  case CT_none:
+    break;
+  case CT_by_reference:
+    out.put('&');
+    have_capture = true;
+    break;
+  case CT_by_value:
+    out.put('=');
+    have_capture = true;
+    break;
+  }
+
+  Captures::const_iterator it;
+  for (it = _captures.begin(); it != _captures.end(); ++it) {
+    const Capture &capture = *it;
+    if (have_capture) {
+      out << ", ";
+    }
+    if (capture._name == "this") {
+      if (capture._type == CT_by_value) {
+        out.put('*');
+      }
+    } else {
+      if (capture._type == CT_by_reference) {
+        out.put('&');
+      }
+    }
+    out << capture._name;
+
+    if (capture._initializer != NULL) {
+      out << " = " << *capture._initializer;
+    }
+
+    have_capture = true;
+  }
+  out.put(']');
+
+  if (_parameters != NULL) {
+    out.put('(');
+    _parameters->output(out, scope, true, -1);
+    out.put(')');
+  }
+
+  if (_flags & F_noexcept) {
+    out << " noexcept";
+  }
+
+  if (_return_type != NULL) {
+    out << " -> ";
+    _return_type->output(out, indent_level, scope, false);
+  }
+
+  out << " {}";
+}
+
+/**
+ *
+ */
+CPPDeclaration::SubType CPPClosureType::
+get_subtype() const {
+  return ST_closure;
+}
+
+/**
+ *
+ */
+CPPClosureType *CPPClosureType::
+as_closure_type() {
+  return this;
+}
+
+/**
+ * Called by CPPDeclaration() to determine whether this type is equivalent to
+ * another type of the same type.
+ */
+bool CPPClosureType::
+is_equal(const CPPDeclaration *other) const {
+  return (this == other);
+}
+
+
+/**
+ * Called by CPPDeclaration() to determine whether this type should be ordered
+ * before another type of the same type, in an arbitrary but fixed ordering.
+ */
+bool CPPClosureType::
+is_less(const CPPDeclaration *other) const {
+  return (this < other);
+}

+ 65 - 0
dtool/src/cppparser/cppClosureType.h

@@ -0,0 +1,65 @@
+/**
+ * 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 cppClosureType.h
+ * @author rdb
+ * @date 2017-01-14
+ */
+
+#ifndef CPPCLOSURETYPE_H
+#define CPPCLOSURETYPE_H
+
+#include "dtoolbase.h"
+
+#include "cppFunctionType.h"
+
+/**
+ * The type of a lambda expression.  This is like a function, but with
+ * additional captures defined.
+ */
+class CPPClosureType : public CPPFunctionType {
+public:
+  enum CaptureType {
+    CT_none,
+    CT_by_reference,
+    CT_by_value,
+  };
+
+  CPPClosureType(CaptureType default_capture = CT_none);
+  CPPClosureType(const CPPClosureType &copy);
+  void operator = (const CPPClosureType &copy);
+
+  struct Capture {
+    string _name;
+    CaptureType _type;
+    CPPExpression *_initializer;
+  };
+  typedef vector<Capture> Captures;
+  Captures _captures;
+
+  CaptureType _default_capture;
+
+  void add_capture(string name, CaptureType type, CPPExpression *initializer = NULL);
+
+  virtual bool is_fully_specified() const;
+
+  virtual bool is_default_constructible() const;
+  virtual bool is_copy_constructible() const;
+  virtual bool is_destructible() const;
+
+  virtual void output(ostream &out, int indent_level, CPPScope *scope,
+                      bool complete) const;
+  virtual SubType get_subtype() const;
+  virtual CPPClosureType *as_closure_type();
+
+protected:
+  virtual bool is_equal(const CPPDeclaration *other) const;
+  virtual bool is_less(const CPPDeclaration *other) const;
+};
+
+#endif

+ 8 - 0
dtool/src/cppparser/cppDeclaration.cxx

@@ -311,6 +311,14 @@ as_make_seq() {
   return (CPPMakeSeq *)NULL;
   return (CPPMakeSeq *)NULL;
 }
 }
 
 
+/**
+ *
+ */
+CPPClosureType *CPPDeclaration::
+as_closure_type() {
+  return (CPPClosureType *)NULL;
+}
+
 /**
 /**
  * Called by CPPDeclaration to determine whether this type is equivalent to
  * Called by CPPDeclaration to determine whether this type is equivalent to
  * another type of the same type.
  * another type of the same type.

+ 6 - 0
dtool/src/cppparser/cppDeclaration.h

@@ -48,6 +48,7 @@ class CPPEnumType;
 class CPPTypeProxy;
 class CPPTypeProxy;
 class CPPMakeProperty;
 class CPPMakeProperty;
 class CPPMakeSeq;
 class CPPMakeSeq;
+class CPPClosureType;
 class CPPClassTemplateParameter;
 class CPPClassTemplateParameter;
 class CPPTBDType;
 class CPPTBDType;
 class CPPScope;
 class CPPScope;
@@ -85,6 +86,7 @@ public:
     ST_tbd,
     ST_tbd,
     ST_type_proxy,
     ST_type_proxy,
     ST_typedef,
     ST_typedef,
+    ST_closure,
   };
   };
 
 
   CPPDeclaration(const CPPFile &file);
   CPPDeclaration(const CPPFile &file);
@@ -140,6 +142,7 @@ public:
   virtual CPPTypeProxy *as_type_proxy();
   virtual CPPTypeProxy *as_type_proxy();
   virtual CPPMakeProperty *as_make_property();
   virtual CPPMakeProperty *as_make_property();
   virtual CPPMakeSeq *as_make_seq();
   virtual CPPMakeSeq *as_make_seq();
+  virtual CPPClosureType *as_closure_type();
 
 
   inline const CPPInstance *as_instance() const {
   inline const CPPInstance *as_instance() const {
     return ((CPPDeclaration *)this)->as_instance();
     return ((CPPDeclaration *)this)->as_instance();
@@ -207,6 +210,9 @@ public:
   inline const CPPMakeSeq *as_make_seq() const {
   inline const CPPMakeSeq *as_make_seq() const {
     return ((CPPDeclaration *)this)->as_make_seq();
     return ((CPPDeclaration *)this)->as_make_seq();
   }
   }
+  inline const CPPClosureType *as_closure_type() const {
+    return ((CPPDeclaration *)this)->as_closure_type();
+  }
 
 
   CPPVisibility _vis;
   CPPVisibility _vis;
   CPPTemplateScope *_template_scope;
   CPPTemplateScope *_template_scope;

+ 97 - 3
dtool/src/cppparser/cppExpression.cxx

@@ -24,6 +24,7 @@
 #include "cppInstance.h"
 #include "cppInstance.h"
 #include "cppFunctionGroup.h"
 #include "cppFunctionGroup.h"
 #include "cppFunctionType.h"
 #include "cppFunctionType.h"
+#include "cppClosureType.h"
 #include "cppStructType.h"
 #include "cppStructType.h"
 #include "cppBison.h"
 #include "cppBison.h"
 #include "pdtoa.h"
 #include "pdtoa.h"
@@ -256,13 +257,12 @@ CPPExpression(CPPIdentifier *ident, CPPScope *current_scope,
       _u._variable = inst;
       _u._variable = inst;
       return;
       return;
     }
     }
-    // Actually, we can't scope function groups.
-    /*CPPFunctionGroup *fgroup = decl->as_function_group();
+    CPPFunctionGroup *fgroup = decl->as_function_group();
     if (fgroup != NULL) {
     if (fgroup != NULL) {
       _type = T_function;
       _type = T_function;
       _u._fgroup = fgroup;
       _u._fgroup = fgroup;
       return;
       return;
-    }*/
+    }
   }
   }
 
 
   _type = T_unknown_ident;
   _type = T_unknown_ident;
@@ -346,6 +346,22 @@ construct_op(CPPType *type, CPPExpression *op1) {
   return expr;
   return expr;
 }
 }
 
 
+/**
+ * Creates an expression that represents an aggregate initialization.
+ */
+CPPExpression CPPExpression::
+aggregate_init_op(CPPType *type, CPPExpression *op1) {
+  CPPExpression expr(0);
+  if (op1 == NULL) {
+    expr._type = T_empty_aggregate_init;
+  } else {
+    expr._type = T_aggregate_init;
+  }
+  expr._u._typecast._to = type;
+  expr._u._typecast._op1 = op1;
+  return expr;
+}
+
 /**
 /**
  * Creates an expression that represents a use of the new operator.
  * Creates an expression that represents a use of the new operator.
  */
  */
@@ -438,6 +454,17 @@ alignof_func(CPPType *type) {
   return expr;
   return expr;
 }
 }
 
 
+/**
+ *
+ */
+CPPExpression CPPExpression::
+lambda(CPPClosureType *type) {
+  CPPExpression expr(0);
+  expr._type = T_lambda;
+  expr._u._closure_type = type;
+  return expr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -594,6 +621,8 @@ evaluate() const {
 
 
   case T_construct:
   case T_construct:
   case T_default_construct:
   case T_default_construct:
+  case T_aggregate_init:
+  case T_empty_aggregate_init:
   case T_new:
   case T_new:
   case T_default_new:
   case T_default_new:
   case T_sizeof:
   case T_sizeof:
@@ -1017,6 +1046,8 @@ determine_type() const {
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
   case T_default_construct:
   case T_default_construct:
+  case T_aggregate_init:
+  case T_empty_aggregate_init:
     return _u._typecast._to;
     return _u._typecast._to;
 
 
   case T_new:
   case T_new:
@@ -1135,10 +1166,28 @@ determine_type() const {
 
 
     case 'f': // Function evaluation
     case 'f': // Function evaluation
       if (t1 != NULL) {
       if (t1 != NULL) {
+        // Easy case, function with only a single overload.
         CPPFunctionType *ftype = t1->as_function_type();
         CPPFunctionType *ftype = t1->as_function_type();
         if (ftype != (CPPFunctionType *)NULL) {
         if (ftype != (CPPFunctionType *)NULL) {
           return ftype->_return_type;
           return ftype->_return_type;
         }
         }
+      } else if (_u._op._op1->_type == T_function) {
+        CPPFunctionGroup *fgroup = _u._op._op1->_u._fgroup;
+        if (_u._op._op2 == NULL) {
+          // If we are passing no args, look for an overload that has takes no
+          // args.
+          for (auto it = fgroup->_instances.begin(); it != fgroup->_instances.end(); ++it) {
+            CPPInstance *inst = *it;
+            if (inst != NULL && inst->_type != NULL) {
+              CPPFunctionType *type = inst->_type->as_function_type();
+              if (type != NULL && type->accepts_num_parameters(0)) {
+                return type->_return_type;
+              }
+            }
+          }
+        } else {
+          //TODO
+        }
       }
       }
       return NULL;
       return NULL;
 
 
@@ -1169,6 +1218,9 @@ determine_type() const {
   case T_type_trait:
   case T_type_trait:
     return bool_type;
     return bool_type;
 
 
+  case T_lambda:
+    return _u._closure_type;
+
   default:
   default:
     cerr << "**invalid operand**\n";
     cerr << "**invalid operand**\n";
     abort();
     abort();
@@ -1215,11 +1267,13 @@ is_fully_specified() const {
   case T_const_cast:
   case T_const_cast:
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
   case T_new:
     return (_u._typecast._to->is_fully_specified() &&
     return (_u._typecast._to->is_fully_specified() &&
             _u._typecast._op1->is_fully_specified());
             _u._typecast._op1->is_fully_specified());
 
 
   case T_default_construct:
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
   case T_sizeof:
   case T_sizeof:
   case T_alignof:
   case T_alignof:
@@ -1259,6 +1313,9 @@ is_fully_specified() const {
   case T_type_trait:
   case T_type_trait:
     return _u._type_trait._type->is_fully_specified();
     return _u._type_trait._type->is_fully_specified();
 
 
+  case T_lambda:
+    return _u._closure_type->is_fully_specified();
+
   default:
   default:
     return true;
     return true;
   }
   }
@@ -1342,6 +1399,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
   case T_const_cast:
   case T_const_cast:
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
   case T_new:
     rep->_u._typecast._op1 =
     rep->_u._typecast._op1 =
       _u._typecast._op1->substitute_decl(subst, current_scope, global_scope)
       _u._typecast._op1->substitute_decl(subst, current_scope, global_scope)
@@ -1350,6 +1408,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
     // fall through
     // fall through
 
 
   case T_default_construct:
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
   case T_sizeof:
   case T_sizeof:
   case T_alignof:
   case T_alignof:
@@ -1444,6 +1503,8 @@ is_tbd() const {
   case T_const_cast:
   case T_const_cast:
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
+  case T_aggregate_init:
+  case T_empty_aggregate_init:
   case T_new:
   case T_new:
   case T_default_construct:
   case T_default_construct:
   case T_default_new:
   case T_default_new:
@@ -1478,6 +1539,9 @@ is_tbd() const {
   case T_type_trait:
   case T_type_trait:
     return _u._type_trait._type->is_tbd();
     return _u._type_trait._type->is_tbd();
 
 
+  case T_lambda:
+    return _u._closure_type->is_tbd();
+
   default:
   default:
     return false;
     return false;
   }
   }
@@ -1558,6 +1622,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
           out << "\\\"";
           out << "\\\"";
           break;
           break;
 
 
+        case '\\':
+          out << "\\\\";
+          break;
+
         default:
         default:
           if (isprint(*si)) {
           if (isprint(*si)) {
             out << *si;
             out << *si;
@@ -1649,6 +1717,18 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << "()";
     out << "()";
     break;
     break;
 
 
+  case T_aggregate_init:
+    _u._typecast._to->output(out, indent_level, scope, false);
+    out << "{";
+    _u._typecast._op1->output(out, indent_level, scope, false);
+    out << "}";
+    break;
+
+  case T_empty_aggregate_init:
+    _u._typecast._to->output(out, indent_level, scope, false);
+    out << "{}";
+    break;
+
   case T_new:
   case T_new:
     out << "(new ";
     out << "(new ";
     _u._typecast._to->output(out, indent_level, scope, false);
     _u._typecast._to->output(out, indent_level, scope, false);
@@ -1946,6 +2026,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << ')';
     out << ')';
     break;
     break;
 
 
+  case T_lambda:
+    _u._closure_type->output(out, indent_level, scope, false);
+    break;
+
   default:
   default:
     out << "(** invalid operand type " << (int)_type << " **)";
     out << "(** invalid operand type " << (int)_type << " **)";
   }
   }
@@ -2066,11 +2150,13 @@ is_equal(const CPPDeclaration *other) const {
   case T_const_cast:
   case T_const_cast:
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
   case T_new:
     return _u._typecast._to == ot->_u._typecast._to &&
     return _u._typecast._to == ot->_u._typecast._to &&
       *_u._typecast._op1 == *ot->_u._typecast._op1;
       *_u._typecast._op1 == *ot->_u._typecast._op1;
 
 
   case T_default_construct:
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
   case T_sizeof:
   case T_sizeof:
   case T_alignof:
   case T_alignof:
@@ -2105,6 +2191,9 @@ is_equal(const CPPDeclaration *other) const {
     return _u._type_trait._trait == ot->_u._type_trait._trait &&
     return _u._type_trait._trait == ot->_u._type_trait._trait &&
            _u._type_trait._type == ot->_u._type_trait._type;
            _u._type_trait._type == ot->_u._type_trait._type;
 
 
+  case T_lambda:
+    return _u._closure_type == ot->_u._closure_type;
+
   default:
   default:
     cerr << "(** invalid operand type " << (int)_type << " **)";
     cerr << "(** invalid operand type " << (int)_type << " **)";
   }
   }
@@ -2161,6 +2250,7 @@ is_less(const CPPDeclaration *other) const {
   case T_const_cast:
   case T_const_cast:
   case T_reinterpret_cast:
   case T_reinterpret_cast:
   case T_construct:
   case T_construct:
+  case T_aggregate_init:
   case T_new:
   case T_new:
     if (_u._typecast._to != ot->_u._typecast._to) {
     if (_u._typecast._to != ot->_u._typecast._to) {
       return _u._typecast._to < ot->_u._typecast._to;
       return _u._typecast._to < ot->_u._typecast._to;
@@ -2168,6 +2258,7 @@ is_less(const CPPDeclaration *other) const {
     return *_u._typecast._op1 < *ot->_u._typecast._op1;
     return *_u._typecast._op1 < *ot->_u._typecast._op1;
 
 
   case T_default_construct:
   case T_default_construct:
+  case T_empty_aggregate_init:
   case T_default_new:
   case T_default_new:
   case T_sizeof:
   case T_sizeof:
   case T_alignof:
   case T_alignof:
@@ -2212,6 +2303,9 @@ is_less(const CPPDeclaration *other) const {
     }
     }
     return *_u._type_trait._type < *ot->_u._type_trait._type;
     return *_u._type_trait._type < *ot->_u._type_trait._type;
 
 
+  case T_lambda:
+    return _u._closure_type < ot->_u._closure_type;
+
   default:
   default:
     cerr << "(** invalid operand type " << (int)_type << " **)";
     cerr << "(** invalid operand type " << (int)_type << " **)";
   }
   }

+ 6 - 0
dtool/src/cppparser/cppExpression.h

@@ -48,6 +48,8 @@ public:
     T_reinterpret_cast,
     T_reinterpret_cast,
     T_construct,
     T_construct,
     T_default_construct,
     T_default_construct,
+    T_aggregate_init,
+    T_empty_aggregate_init,
     T_new,
     T_new,
     T_default_new,
     T_default_new,
     T_sizeof,
     T_sizeof,
@@ -61,6 +63,7 @@ public:
     T_typeid_type,
     T_typeid_type,
     T_typeid_expr,
     T_typeid_expr,
     T_type_trait,
     T_type_trait,
+    T_lambda,
 
 
     // These are used when parsing =default and =delete methods.
     // These are used when parsing =default and =delete methods.
     T_default,
     T_default,
@@ -80,6 +83,7 @@ public:
 
 
   static CPPExpression typecast_op(CPPType *type, CPPExpression *op1, Type cast_type = T_typecast);
   static CPPExpression typecast_op(CPPType *type, CPPExpression *op1, Type cast_type = T_typecast);
   static CPPExpression construct_op(CPPType *type, CPPExpression *op1);
   static CPPExpression construct_op(CPPType *type, CPPExpression *op1);
+  static CPPExpression aggregate_init_op(CPPType *type, CPPExpression *op1);
   static CPPExpression new_op(CPPType *type, CPPExpression *op1 = NULL);
   static CPPExpression new_op(CPPType *type, CPPExpression *op1 = NULL);
   static CPPExpression typeid_op(CPPType *type, CPPType *std_type_info);
   static CPPExpression typeid_op(CPPType *type, CPPType *std_type_info);
   static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info);
   static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info);
@@ -87,6 +91,7 @@ public:
   static CPPExpression sizeof_func(CPPType *type);
   static CPPExpression sizeof_func(CPPType *type);
   static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
   static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
   static CPPExpression alignof_func(CPPType *type);
   static CPPExpression alignof_func(CPPType *type);
+  static CPPExpression lambda(CPPClosureType *type);
 
 
   static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
   static CPPExpression literal(unsigned long long value, CPPInstance *lit_op);
   static CPPExpression literal(long double value, CPPInstance *lit_op);
   static CPPExpression literal(long double value, CPPInstance *lit_op);
@@ -150,6 +155,7 @@ public:
     CPPInstance *_variable;
     CPPInstance *_variable;
     CPPFunctionGroup *_fgroup;
     CPPFunctionGroup *_fgroup;
     CPPIdentifier *_ident;
     CPPIdentifier *_ident;
+    CPPClosureType *_closure_type;
     struct {
     struct {
       union {
       union {
         CPPType *_type;
         CPPType *_type;

+ 53 - 8
dtool/src/cppparser/cppFunctionType.cxx

@@ -31,7 +31,8 @@ CPPFunctionType(CPPType *return_type, CPPParameterList *parameters,
 
 
   // If the parameter list contains just the token "void", it means no
   // If the parameter list contains just the token "void", it means no
   // parameters.
   // parameters.
-  if (_parameters->_parameters.size() == 1 &&
+  if (_parameters != NULL &&
+      _parameters->_parameters.size() == 1 &&
       _parameters->_parameters.front()->_type->as_simple_type() != NULL &&
       _parameters->_parameters.front()->_type->as_simple_type() != NULL &&
       _parameters->_parameters.front()->_type->as_simple_type()->_type ==
       _parameters->_parameters.front()->_type->as_simple_type()->_type ==
       CPPSimpleType::T_void &&
       CPPSimpleType::T_void &&
@@ -65,6 +66,31 @@ operator = (const CPPFunctionType &copy) {
   _class_owner = copy._class_owner;
   _class_owner = copy._class_owner;
 }
 }
 
 
+/**
+ * Returns true if the function accepts the given number of parameters.
+ */
+bool CPPFunctionType::
+accepts_num_parameters(int num_parameters) {
+  if (_parameters == NULL) {
+    return (num_parameters == 0);
+  }
+  size_t actual_num_parameters = _parameters->_parameters.size();
+  // If we passed too many parameters, it must have an ellipsis.
+  if (num_parameters > actual_num_parameters) {
+    return _parameters->_includes_ellipsis;
+  }
+
+  // Make sure all superfluous parameters have a default value.
+  for (size_t i = num_parameters; i < actual_num_parameters; ++i) {
+    CPPInstance *param = _parameters->_parameters[i];
+    if (param->_initializer == NULL) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 /**
 /**
  * Returns true if this declaration is an actual, factual declaration, or
  * Returns true if this declaration is an actual, factual declaration, or
  * false if some part of the declaration depends on a template parameter which
  * false if some part of the declaration depends on a template parameter which
@@ -95,8 +121,10 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
       ->as_type();
       ->as_type();
   }
   }
 
 
-  rep->_parameters =
-    _parameters->substitute_decl(subst, current_scope, global_scope);
+  if (_parameters != NULL) {
+    rep->_parameters =
+      _parameters->substitute_decl(subst, current_scope, global_scope);
+  }
 
 
   if (rep->_return_type == _return_type &&
   if (rep->_return_type == _return_type &&
       rep->_parameters == _parameters) {
       rep->_parameters == _parameters) {
@@ -117,8 +145,12 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
 CPPType *CPPFunctionType::
 CPPType *CPPFunctionType::
 resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
 resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
   CPPType *rtype = _return_type->resolve_type(current_scope, global_scope);
   CPPType *rtype = _return_type->resolve_type(current_scope, global_scope);
-  CPPParameterList *params =
-    _parameters->resolve_type(current_scope, global_scope);
+  CPPParameterList *params;
+  if (_parameters == NULL) {
+    params = NULL;
+  } else {
+    params = _parameters->resolve_type(current_scope, global_scope);
+  }
 
 
   if (rtype != _return_type || params != _parameters) {
   if (rtype != _return_type || params != _parameters) {
     CPPFunctionType *rep = new CPPFunctionType(*this);
     CPPFunctionType *rep = new CPPFunctionType(*this);
@@ -139,7 +171,7 @@ is_tbd() const {
   if (_return_type->is_tbd()) {
   if (_return_type->is_tbd()) {
     return true;
     return true;
   }
   }
-  return _parameters->is_tbd();
+  return _parameters == NULL || _parameters->is_tbd();
 }
 }
 
 
 /**
 /**
@@ -294,6 +326,10 @@ get_num_default_parameters() const {
   // The trick is just to count, beginning from the end and working towards
   // The trick is just to count, beginning from the end and working towards
   // the front, the number of parameters that have some initializer.
   // the front, the number of parameters that have some initializer.
 
 
+  if (_parameters == NULL) {
+    return 0;
+  }
+
   const CPPParameterList::Parameters &params = _parameters->_parameters;
   const CPPParameterList::Parameters &params = _parameters->_parameters;
   CPPParameterList::Parameters::const_reverse_iterator pi;
   CPPParameterList::Parameters::const_reverse_iterator pi;
   int count = 0;
   int count = 0;
@@ -362,7 +398,11 @@ is_equal(const CPPDeclaration *other) const {
   if (_flags != ot->_flags) {
   if (_flags != ot->_flags) {
     return false;
     return false;
   }
   }
-  if (*_parameters != *ot->_parameters) {
+  if (_parameters == ot->_parameters) {
+    return true;
+  }
+  if (_parameters == NULL || ot->_parameters == NULL ||
+      *_parameters != *ot->_parameters) {
     return false;
     return false;
   }
   }
   return true;
   return true;
@@ -384,6 +424,11 @@ is_less(const CPPDeclaration *other) const {
   if (_flags != ot->_flags) {
   if (_flags != ot->_flags) {
     return _flags < ot->_flags;
     return _flags < ot->_flags;
   }
   }
-
+  if (_parameters == ot->_parameters) {
+    return 0;
+  }
+  if (_parameters == NULL || ot->_parameters == NULL) {
+    return _parameters < ot->_parameters;
+  }
   return *_parameters < *ot->_parameters;
   return *_parameters < *ot->_parameters;
 }
 }

+ 2 - 0
dtool/src/cppparser/cppFunctionType.h

@@ -50,6 +50,8 @@ public:
   CPPFunctionType(const CPPFunctionType &copy);
   CPPFunctionType(const CPPFunctionType &copy);
   void operator = (const CPPFunctionType &copy);
   void operator = (const CPPFunctionType &copy);
 
 
+  bool accepts_num_parameters(int num_parameters);
+
   CPPType *_return_type;
   CPPType *_return_type;
   CPPParameterList *_parameters;
   CPPParameterList *_parameters;
   int _flags;
   int _flags;

+ 70 - 5
dtool/src/cppparser/cppPreprocessor.cxx

@@ -209,6 +209,7 @@ CPPPreprocessor() {
   _state = S_eof;
   _state = S_eof;
   _paren_nesting = 0;
   _paren_nesting = 0;
   _parsing_template_params = false;
   _parsing_template_params = false;
+  _parsing_attribute = false;
   _unget = '\0';
   _unget = '\0';
   _last_c = '\0';
   _last_c = '\0';
   _start_of_line = true;
   _start_of_line = true;
@@ -986,6 +987,13 @@ internal_get_next_token() {
         return CPPToken(0, loc);
         return CPPToken(0, loc);
       }
       }
     }
     }
+  } else if (_parsing_attribute) {
+    // If we're parsing an attribute, also keep track of the paren nesting.
+    if (c == '[' || c == '(') {
+      ++_paren_nesting;
+    } else if (c == ']' || c == ')') {
+      --_paren_nesting;
+    }
   }
   }
 
 
   // Look for an end-of-line comment, and parse it before we finish this
   // Look for an end-of-line comment, and parse it before we finish this
@@ -1090,6 +1098,20 @@ check_digraph(int c) {
     if (next_c == '=') return MODEQUAL;
     if (next_c == '=') return MODEQUAL;
     if (next_c == '>') return '}';
     if (next_c == '>') return '}';
     break;
     break;
+
+  case '[':
+    if (next_c == '[' && !_parsing_attribute) {
+      _parsing_attribute = true;
+      return ATTR_LEFT;
+    }
+    break;
+
+  case ']':
+    if (next_c == ']' && _parsing_attribute && _paren_nesting == 0) {
+      _parsing_attribute = false;
+      return ATTR_RIGHT;
+    }
+    break;
   }
   }
 
 
   return 0;
   return 0;
@@ -1870,11 +1892,19 @@ get_identifier(int c) {
   loc.last_column = get_col_number();
   loc.last_column = get_col_number();
 
 
   if ((c == '\'' || c == '"') &&
   if ((c == '\'' || c == '"') &&
-      (name == "L" || name == "u8" ||
-       name == "u" || name == "U")) {
+      (name == "L" || name == "u8" || name == "u" || name == "U" ||
+       name == "R" || name == "LR" || name == "u8R" || name == "uR" || name == "UR")) {
     // This is actually a wide-character or wide-string literal or some such.
     // This is actually a wide-character or wide-string literal or some such.
-    // Figure out the correct character type to use.
+    get();
+    string str;
+    if (name[name.size() - 1] == 'R') {
+      name.resize(name.size() - 1);
+      str = scan_raw(c);
+    } else {
+      str = scan_quoted(c);
+    }
 
 
+    // Figure out the correct character type to use.
     CPPExpression::Type type;
     CPPExpression::Type type;
     if (name == "L") {
     if (name == "L") {
       type = CPPExpression::T_wstring;
       type = CPPExpression::T_wstring;
@@ -1887,8 +1917,6 @@ get_identifier(int c) {
     } else {
     } else {
       type = CPPExpression::T_string;
       type = CPPExpression::T_string;
     }
     }
-    get();
-    string str = scan_quoted(c);
 
 
     loc.last_line = get_line_number();
     loc.last_line = get_line_number();
     loc.last_column = get_col_number();
     loc.last_column = get_col_number();
@@ -2772,6 +2800,43 @@ scan_quoted(int c) {
   return str;
   return str;
 }
 }
 
 
+/**
+ * Parses a C++11 raw string.
+ */
+string CPPPreprocessor::
+scan_raw(int c) {
+  int quote_mark = c;
+
+  string delimiter = ")";
+
+  string str;
+  c = get();
+  while (c != EOF && c != '(') {
+    delimiter += c;
+    c = get();
+  }
+
+  // OK, now start parsing the string, until we see the delimiter again.
+  c = get();
+  while (c != EOF) {
+    if (c == quote_mark) {
+      // We encountered a quote mark - did the last part of the string end
+      // with the given delimiter?  If so, we've reached the end.
+      if (str.compare(str.size() - delimiter.size(), delimiter.size(), delimiter) == 0) {
+        str.resize(str.size() - delimiter.size());
+        break;
+      }
+    }
+    str += c;
+    c = get();
+  }
+
+  if (c != quote_mark) {
+    warning("Unclosed string");
+  }
+  return str;
+}
+
 /**
 /**
  * Returns true if the manifest is one that is being ignored right now
  * Returns true if the manifest is one that is being ignored right now
  * (presumably because we are presently expanding it).
  * (presumably because we are presently expanding it).

+ 2 - 0
dtool/src/cppparser/cppPreprocessor.h

@@ -166,6 +166,7 @@ private:
   static int check_keyword(const string &name);
   static int check_keyword(const string &name);
   int scan_escape_sequence(int c);
   int scan_escape_sequence(int c);
   string scan_quoted(int c);
   string scan_quoted(int c);
+  string scan_raw(int c);
 
 
   bool should_ignore_manifest(const CPPManifest *manifest) const;
   bool should_ignore_manifest(const CPPManifest *manifest) const;
   bool should_ignore_preprocessor() const;
   bool should_ignore_preprocessor() const;
@@ -212,6 +213,7 @@ private:
   State _state;
   State _state;
   int _paren_nesting;
   int _paren_nesting;
   bool _parsing_template_params;
   bool _parsing_template_params;
+  bool _parsing_attribute;
 
 
   bool _start_of_line;
   bool _start_of_line;
   int _unget;
   int _unget;

+ 8 - 0
dtool/src/cppparser/cppToken.cxx

@@ -252,6 +252,14 @@ output(ostream &out) const {
     out << "RSHIFTEQUAL";
     out << "RSHIFTEQUAL";
     break;
     break;
 
 
+  case ATTR_LEFT:
+    out << "ATTR_LEFT";
+    break;
+
+  case ATTR_RIGHT:
+    out << "ATTR_RIGHT";
+    break;
+
   case KW_BOOL:
   case KW_BOOL:
     out << "KW_BOOL";
     out << "KW_BOOL";
     break;
     break;

+ 1 - 0
dtool/src/cppparser/p3cppParser_composite1.cxx

@@ -2,6 +2,7 @@
 #include "cppFunctionType.cxx"
 #include "cppFunctionType.cxx"
 #include "cppGlobals.cxx"
 #include "cppGlobals.cxx"
 #include "cppCommentBlock.cxx"
 #include "cppCommentBlock.cxx"
+#include "cppClosureType.cxx"
 #include "cppConstType.cxx"
 #include "cppConstType.cxx"
 #include "cppDeclaration.cxx"
 #include "cppDeclaration.cxx"
 #include "cppMakeProperty.cxx"
 #include "cppMakeProperty.cxx"

+ 4 - 4
dtool/src/dtoolbase/deletedBufferChain.cxx

@@ -39,7 +39,7 @@ allocate(size_t size, TypeHandle type_handle) {
   assert(size <= _buffer_size);
   assert(size <= _buffer_size);
 
 
   // Determine how much space to allocate.
   // Determine how much space to allocate.
-  const size_t alloc_size = _buffer_size + flag_reserved_bytes + MemoryHook::get_memory_alignment() - 1;
+  const size_t alloc_size = _buffer_size + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1;
 
 
   ObjectNode *obj;
   ObjectNode *obj;
 
 
@@ -71,8 +71,8 @@ allocate(size_t size, TypeHandle type_handle) {
 
 
   // Allocate memory, and make sure the object starts at the proper alignment.
   // Allocate memory, and make sure the object starts at the proper alignment.
   void *mem = NeverFreeMemory::alloc(alloc_size);
   void *mem = NeverFreeMemory::alloc(alloc_size);
-  intptr_t pad = (-(intptr_t)flag_reserved_bytes - (intptr_t)mem) % MemoryHook::get_memory_alignment();
-  obj = (ObjectNode *)((uintptr_t)mem + pad);
+  uintptr_t aligned = ((uintptr_t)mem + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1);
+  obj = (ObjectNode *)(aligned - flag_reserved_bytes);
 
 
 #ifdef USE_DELETEDCHAINFLAG
 #ifdef USE_DELETEDCHAINFLAG
   obj->_flag = DCF_alive;
   obj->_flag = DCF_alive;
@@ -81,7 +81,7 @@ allocate(size_t size, TypeHandle type_handle) {
   void *ptr = node_to_buffer(obj);
   void *ptr = node_to_buffer(obj);
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
-  assert(((uintptr_t)ptr % MemoryHook::get_memory_alignment()) == 0);
+  assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
 #endif
 #endif
 
 
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE

+ 60 - 85
dtool/src/dtoolbase/deletedChain.T

@@ -1,25 +1,22 @@
-// Filename: deletedChain.T
-// Created by:  drose (01Apr06)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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."
-//
-////////////////////////////////////////////////////////////////////
+/**
+ * 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 deletedChain.T
+ * @author drose
+ * @date 2006-04-01
+ */
 
 
 template<class Type>
 template<class Type>
 DeletedChain<Type> StaticDeletedChain<Type>::_chain;
 DeletedChain<Type> StaticDeletedChain<Type>::_chain;
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::allocate
-//       Access: Public
-//  Description: Allocates the memory for a new object of Type.
-////////////////////////////////////////////////////////////////////
+/**
+ * Allocates the memory for a new object of Type.
+ */
 template<class Type>
 template<class Type>
 INLINE Type *DeletedChain<Type>::
 INLINE Type *DeletedChain<Type>::
 allocate(size_t size, TypeHandle type_handle) {
 allocate(size_t size, TypeHandle type_handle) {
@@ -31,14 +28,12 @@ allocate(size_t size, TypeHandle type_handle) {
   memory_hook->mark_pointer(ptr, _chain->get_buffer_size(), make_ref_ptr(ptr));
   memory_hook->mark_pointer(ptr, _chain->get_buffer_size(), make_ref_ptr(ptr));
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
 
 
-  return (Type *)ptr;
+  return (Type *)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT);
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::deallocate
-//       Access: Public
-//  Description: Frees the memory for an object of Type.
-////////////////////////////////////////////////////////////////////
+/**
+ * Frees the memory for an object of Type.
+ */
 template<class Type>
 template<class Type>
 INLINE void DeletedChain<Type>::
 INLINE void DeletedChain<Type>::
 deallocate(Type *ptr, TypeHandle type_handle) {
 deallocate(Type *ptr, TypeHandle type_handle) {
@@ -57,16 +52,13 @@ deallocate(Type *ptr, TypeHandle type_handle) {
   _chain->deallocate(ptr, type_handle);
   _chain->deallocate(ptr, type_handle);
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::validate
-//       Access: Public
-//  Description: Returns true if the pointer is valid, false if it has
-//               been deleted or if it was never a valid pointer.
-//
-//               This is only meaningful in debug mode, where
-//               USE_DELETEDCHAINFLAG is defined.  If not, this
-//               trivially returns true.
-////////////////////////////////////////////////////////////////////
+/**
+ * Returns true if the pointer is valid, false if it has been deleted or if it
+ * was never a valid pointer.
+ *
+ * This is only meaningful in debug mode, where USE_DELETEDCHAINFLAG is
+ * defined.  If not, this trivially returns true.
+ */
 template<class Type>
 template<class Type>
 INLINE bool DeletedChain<Type>::
 INLINE bool DeletedChain<Type>::
 validate(const Type *ptr) {
 validate(const Type *ptr) {
@@ -80,48 +72,37 @@ validate(const Type *ptr) {
 #endif  // USE_DELETEDCHAINFLAG
 #endif  // USE_DELETEDCHAINFLAG
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::make_ref_ptr
-//       Access: Public, Static
-//  Description: This method has two overloads: one that accepts a
-//               void *, and one that accepts a ReferenceCount *.  We
-//               rely on the C++ compiler to select the most
-//               appropriate one for a given type to return the
-//               ReferenceCount pointer that corresponds to a
-//               particular type, or NULL if the type does not inherit
-//               from ReferenceCount.
-////////////////////////////////////////////////////////////////////
+/**
+ * This method has two overloads: one that accepts a void *, and one that
+ * accepts a ReferenceCount *.  We rely on the C++ compiler to select the most
+ * appropriate one for a given type to return the ReferenceCount pointer that
+ * corresponds to a particular type, or NULL if the type does not inherit from
+ * ReferenceCount.
+ */
 template<class Type>
 template<class Type>
 INLINE ReferenceCount *DeletedChain<Type>::
 INLINE ReferenceCount *DeletedChain<Type>::
 make_ref_ptr(void *) {
 make_ref_ptr(void *) {
   return NULL;
   return NULL;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::make_ref_ptr
-//       Access: Public, Static
-//  Description: This method has two overloads: one that accepts a
-//               void *, and one that accepts a ReferenceCount *.  We
-//               rely on the C++ compiler to select the most
-//               appropriate one for a given type to return the
-//               ReferenceCount pointer that corresponds to a
-//               particular type, or NULL if the type does not inherit
-//               from ReferenceCount.
-////////////////////////////////////////////////////////////////////
+/**
+ * This method has two overloads: one that accepts a void *, and one that
+ * accepts a ReferenceCount *.  We rely on the C++ compiler to select the most
+ * appropriate one for a given type to return the ReferenceCount pointer that
+ * corresponds to a particular type, or NULL if the type does not inherit from
+ * ReferenceCount.
+ */
 template<class Type>
 template<class Type>
 INLINE ReferenceCount *DeletedChain<Type>::
 INLINE ReferenceCount *DeletedChain<Type>::
 make_ref_ptr(ReferenceCount *ptr) {
 make_ref_ptr(ReferenceCount *ptr) {
   return ptr;
   return ptr;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedChain::init_deleted_chain
-//       Access: Private
-//  Description: Assigns the _chain pointer if it is not already
-//               assigned.  This can't be done by a constructor, since
-//               often the DeletedChain instance is used before its
-//               static construct has had a chance to be called.
-////////////////////////////////////////////////////////////////////
+/**
+ * Assigns the _chain pointer if it is not already assigned.  This can't be
+ * done by a constructor, since often the DeletedChain instance is used before
+ * its static construct has had a chance to be called.
+ */
 template<class Type>
 template<class Type>
 void DeletedChain<Type>::
 void DeletedChain<Type>::
 init_deleted_chain() {
 init_deleted_chain() {
@@ -131,38 +112,32 @@ init_deleted_chain() {
   }
   }
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: StaticDeletedChain::allocate
-//       Access: Public, Static
-//  Description: Allocates the memory for a new object of Type.
-////////////////////////////////////////////////////////////////////
+/**
+ * Allocates the memory for a new object of Type.
+ */
 template<class Type>
 template<class Type>
 INLINE Type *StaticDeletedChain<Type>::
 INLINE Type *StaticDeletedChain<Type>::
 allocate(size_t size, TypeHandle type_handle) {
 allocate(size_t size, TypeHandle type_handle) {
-  return _chain.allocate(size, type_handle);
+  Type *ptr = _chain.allocate(size, type_handle);
+  return (Type *)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT);
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: StaticDeletedChain::deallocate
-//       Access: Public
-//  Description: Frees the memory for an object of Type.
-////////////////////////////////////////////////////////////////////
+/**
+ * Frees the memory for an object of Type.
+ */
 template<class Type>
 template<class Type>
 INLINE void StaticDeletedChain<Type>::
 INLINE void StaticDeletedChain<Type>::
 deallocate(Type *ptr, TypeHandle type_handle) {
 deallocate(Type *ptr, TypeHandle type_handle) {
   _chain.deallocate(ptr, type_handle);
   _chain.deallocate(ptr, type_handle);
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: StaticDeletedChain::validate
-//       Access: Public
-//  Description: Returns true if the pointer is valid, false if it has
-//               been deleted or if it was never a valid pointer.
-//
-//               This is only meaningful in debug mode, where
-//               USE_DELETEDCHAINFLAG is defined.  If not, this
-//               trivially returns true.
-////////////////////////////////////////////////////////////////////
+/**
+ * Returns true if the pointer is valid, false if it has been deleted or if it
+ * was never a valid pointer.
+ *
+ * This is only meaningful in debug mode, where USE_DELETEDCHAINFLAG is
+ * defined.  If not, this trivially returns true.
+ */
 template<class Type>
 template<class Type>
 INLINE bool StaticDeletedChain<Type>::
 INLINE bool StaticDeletedChain<Type>::
 validate(const Type *ptr) {
 validate(const Type *ptr) {

+ 2 - 2
dtool/src/dtoolbase/deletedChain.h

@@ -77,7 +77,7 @@ public:
 // Place this macro within a class definition to define appropriate operator
 // Place this macro within a class definition to define appropriate operator
 // new and delete methods that take advantage of DeletedChain.
 // new and delete methods that take advantage of DeletedChain.
 #define ALLOC_DELETED_CHAIN(Type)                            \
 #define ALLOC_DELETED_CHAIN(Type)                            \
-  inline void *operator new(size_t size) {                   \
+  inline void *operator new(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT) { \
     return (void *)StaticDeletedChain< Type >::allocate(size, get_type_handle(Type)); \
     return (void *)StaticDeletedChain< Type >::allocate(size, get_type_handle(Type)); \
   }                                                          \
   }                                                          \
   inline void *operator new(size_t size, void *ptr) {        \
   inline void *operator new(size_t size, void *ptr) {        \
@@ -96,7 +96,7 @@ public:
 // Use this variant of the above macro in cases in which the compiler fails to
 // Use this variant of the above macro in cases in which the compiler fails to
 // unify the static template pointers properly, to prevent leaks.
 // unify the static template pointers properly, to prevent leaks.
 #define ALLOC_DELETED_CHAIN_DECL(Type)                       \
 #define ALLOC_DELETED_CHAIN_DECL(Type)                       \
-  inline void *operator new(size_t size) {                   \
+  inline void *operator new(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT) { \
     return (void *)_deleted_chain.allocate(size, get_type_handle(Type)); \
     return (void *)_deleted_chain.allocate(size, get_type_handle(Type)); \
   }                                                          \
   }                                                          \
   inline void *operator new(size_t size, void *ptr) {        \
   inline void *operator new(size_t size, void *ptr) {        \

+ 45 - 0
dtool/src/dtoolbase/dtoolbase.h

@@ -76,6 +76,10 @@
 #define __has_builtin(x) 0
 #define __has_builtin(x) 0
 #endif
 #endif
 
 
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
 // Use NODEFAULT to optimize a switch() stmt to tell MSVC to automatically go
 // Use NODEFAULT to optimize a switch() stmt to tell MSVC to automatically go
 // to the final untested case after it has failed all the other cases (i.e.
 // to the final untested case after it has failed all the other cases (i.e.
 // 'assume at least one of the cases is always true')
 // 'assume at least one of the cases is always true')
@@ -89,6 +93,18 @@
 #define NODEFAULT
 #define NODEFAULT
 #endif
 #endif
 
 
+// Use this to hint the compiler that a memory address is aligned.
+#if __has_builtin(__builtin_assume_aligned) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
+#define ASSUME_ALIGNED(x, y) (__builtin_assume_aligned(x, y))
+#else
+#define ASSUME_ALIGNED(x, y) (x)
+#endif
+
+#if __has_attribute(assume_aligned) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
+#define RETURNS_ALIGNED(x) __attribute__((assume_aligned(x)))
+#else
+#define RETURNS_ALIGNED(x)
+#endif
 
 
 /*
 /*
   include win32 defns for everything up to WinServer2003, and assume
   include win32 defns for everything up to WinServer2003, and assume
@@ -394,6 +410,35 @@ typedef struct _object PyObject;
 
 
 #endif
 #endif
 
 
+#ifdef LINMATH_ALIGN
+/* We require 16-byte alignment of certain structures, to support SSE2.  We
+   don't strictly have to align everything, but it's just easier to do so. */
+#if defined(HAVE_EIGEN) && defined(__AVX__) && defined(STDFLOAT_DOUBLE)
+/* Eigen uses AVX instructions, but let's only enable this when compiling with
+   double precision, so that we can keep our ABI a bit more stable. */
+#define MEMORY_HOOK_ALIGNMENT 32
+#else
+#define MEMORY_HOOK_ALIGNMENT 16
+#endif
+/* Otherwise, align to two words.  This seems to be pretty standard to the
+   point where some code may rely on this being the case. */
+#elif defined(IS_OSX) || NATIVE_WORDSIZE >= 64
+#define MEMORY_HOOK_ALIGNMENT 16
+#else
+#define MEMORY_HOOK_ALIGNMENT 8
+#endif
+
+#ifdef HAVE_EIGEN
+/* Make sure that Eigen doesn't assume alignment guarantees we don't offer. */
+#define EIGEN_MAX_ALIGN_BYTES MEMORY_HOOK_ALIGNMENT
+#ifndef EIGEN_MPL2_ONLY
+#define EIGEN_MPL2_ONLY 1
+#endif
+#if !defined(_DEBUG) && !defined(EIGEN_NO_DEBUG)
+#define EIGEN_NO_DEBUG 1
+#endif
+#endif
+
 /* Determine our memory-allocation requirements. */
 /* Determine our memory-allocation requirements. */
 #if defined(USE_MEMORY_PTMALLOC2) || defined(USE_MEMORY_DLMALLOC) || defined(DO_MEMORY_USAGE) || defined(MEMORY_HOOK_DO_ALIGN)
 #if defined(USE_MEMORY_PTMALLOC2) || defined(USE_MEMORY_DLMALLOC) || defined(DO_MEMORY_USAGE) || defined(MEMORY_HOOK_DO_ALIGN)
 /* In this case we have some custom memory management requirements. */
 /* In this case we have some custom memory management requirements. */

+ 3 - 3
dtool/src/dtoolbase/dtoolbase_cc.h

@@ -290,10 +290,10 @@ EXPCL_DTOOL void init_memory_hook();
 
 
 // Now redefine some handy macros to hook into the above MemoryHook object.
 // Now redefine some handy macros to hook into the above MemoryHook object.
 #ifndef USE_MEMORY_NOWRAPPERS
 #ifndef USE_MEMORY_NOWRAPPERS
-#define PANDA_MALLOC_SINGLE(size) (memory_hook->heap_alloc_single(size))
+#define PANDA_MALLOC_SINGLE(size) (ASSUME_ALIGNED(memory_hook->heap_alloc_single(size), MEMORY_HOOK_ALIGNMENT))
 #define PANDA_FREE_SINGLE(ptr) memory_hook->heap_free_single(ptr)
 #define PANDA_FREE_SINGLE(ptr) memory_hook->heap_free_single(ptr)
-#define PANDA_MALLOC_ARRAY(size) (memory_hook->heap_alloc_array(size))
-#define PANDA_REALLOC_ARRAY(ptr, size) (memory_hook->heap_realloc_array(ptr, size))
+#define PANDA_MALLOC_ARRAY(size) (ASSUME_ALIGNED(memory_hook->heap_alloc_array(size), MEMORY_HOOK_ALIGNMENT))
+#define PANDA_REALLOC_ARRAY(ptr, size) (ASSUME_ALIGNED(memory_hook->heap_realloc_array(ptr, size), MEMORY_HOOK_ALIGNMENT))
 #define PANDA_FREE_ARRAY(ptr) memory_hook->heap_free_array(ptr)
 #define PANDA_FREE_ARRAY(ptr) memory_hook->heap_free_array(ptr)
 #else
 #else
 #define PANDA_MALLOC_SINGLE(size) ::malloc(size)
 #define PANDA_MALLOC_SINGLE(size) ::malloc(size)

+ 2 - 2
dtool/src/dtoolbase/memoryBase.h

@@ -26,7 +26,7 @@
 #ifndef USE_MEMORY_NOWRAPPERS
 #ifndef USE_MEMORY_NOWRAPPERS
 
 
 #define ALLOC_MEMORY_BASE                                    \
 #define ALLOC_MEMORY_BASE                                    \
-  inline void *operator new(size_t size) {                   \
+  inline void *operator new(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT) { \
     return PANDA_MALLOC_SINGLE(size);                        \
     return PANDA_MALLOC_SINGLE(size);                        \
   }                                                          \
   }                                                          \
   inline void *operator new(size_t size, void *ptr) {        \
   inline void *operator new(size_t size, void *ptr) {        \
@@ -38,7 +38,7 @@
   }                                                          \
   }                                                          \
   inline void operator delete(void *, void *) {              \
   inline void operator delete(void *, void *) {              \
   }                                                          \
   }                                                          \
-  inline void *operator new[](size_t size) {                 \
+  inline void *operator new[](size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT) { \
     return PANDA_MALLOC_ARRAY(size);                         \
     return PANDA_MALLOC_ARRAY(size);                         \
   }                                                          \
   }                                                          \
   inline void *operator new[](size_t size, void *ptr) {      \
   inline void *operator new[](size_t size, void *ptr) {      \

+ 21 - 107
dtool/src/dtoolbase/memoryHook.I

@@ -38,57 +38,9 @@ dec_heap(size_t size) {
  * Returns the global memory alignment.  This is the number of bytes at which
  * Returns the global memory alignment.  This is the number of bytes at which
  * each allocated memory pointer will be aligned.
  * each allocated memory pointer will be aligned.
  */
  */
-INLINE size_t MemoryHook::
+CONSTEXPR size_t MemoryHook::
 get_memory_alignment() {
 get_memory_alignment() {
-#ifdef LINMATH_ALIGN
-  // We require 16-byte alignment of certain structures, to support SSE2.  We
-  // don't strictly have to align *everything*, but it's just easier to do so.
-#ifdef __AVX__
-  // Eigen requires 32-byte alignment when using AVX instructions.
-  const size_t alignment_size = 32;
-#else
-  const size_t alignment_size = 16;
-#endif
-#else
-  // Otherwise, align to two words.  This seems to be pretty standard to the
-  // point where some code may rely on this being the case.
-  const size_t alignment_size = sizeof(void *) * 2;
-#endif
-  return alignment_size;
-}
-
-/**
- * Returns the number of additional bytes that are reserved at the beginning
- * of every allocated block to store a size_t.
- */
-INLINE size_t MemoryHook::
-get_header_reserved_bytes() {
-  // We need to figure out the minimum amount of additional space we need in
-  // order to place a single word at the start of each allocated block, to
-  // store the size of the block.
-
-#ifdef LINMATH_ALIGN
-  // If we're doing SSE2 alignment, we must reserve a full 16-byte block,
-  // since anything less than that will spoil the alignment.
-#ifdef __AVX__
-  // Eigen requires 32-byte alignment when using AVX instructions.
-  static const size_t header_reserved_bytes = 32;
-#else
-  static const size_t header_reserved_bytes = 16;
-#endif
-
-#elif defined(MEMORY_HOOK_DO_ALIGN)
-  // If we're just aligning to words, we reserve a block as big as two words,
-  // to allow us wiggle room to align the word precisely within that block.
-  static const size_t header_reserved_bytes = sizeof(size_t) + sizeof(size_t);
-
-#else
-  // Virtually all allocators align to two words, so we make sure we preserve
-  // that alignment for the benefit of anyone who relies upon that.
-  static const size_t header_reserved_bytes = sizeof(void *) * 2;
-#endif
-
-  return header_reserved_bytes;
+  return MEMORY_HOOK_ALIGNMENT;
 }
 }
 
 
 /**
 /**
@@ -110,67 +62,29 @@ round_up_to_page_size(size_t size) const {
 }
 }
 
 
 /**
 /**
- * Increments the amount of requested size as necessary to accommodate the
- * extra data we might piggyback on each allocated block.
+ * Given a pointer that was returned by a MemoryHook allocation, returns the
+ * number of bytes that were allocated for it.  This may be slightly larger
+ * than the number of bytes requested.
+ * The behavior of this function is undefined if the given pointer was not
+ * returned by the MemoryHook allocator or was already freed.
+ * May return 0 if not compiling with DO_MEMORY_USAGE.
+ *
+ * This is only defined publicly so TypeHandle can get at it; it really
+ * shouldn't be used outside of dtoolbase.
  */
  */
 INLINE size_t MemoryHook::
 INLINE size_t MemoryHook::
-inflate_size(size_t size) {
-#if defined(MEMORY_HOOK_DO_ALIGN)
-  // If we're aligning, we need to request the header size, plus extra bytes
-  // to give us wiggle room to adjust the pointer.
-  return size + get_header_reserved_bytes() + get_memory_alignment() - 1;
-#elif defined(DO_MEMORY_USAGE)
-  // If we're not aligning, but we're tracking memory allocations, we just
-  // need the header size extra (this gives us a place to store the size of
-  // the allocated block).
-  return size + get_header_reserved_bytes();
-#else
-  // If we're not doing any of that, we can just allocate the precise
-  // requested amount.
-  return size;
-#endif  // DO_MEMORY_USAGE
-}
-
-/**
- * Converts an allocated pointer to a pointer returnable to the application.
- * Stuffs size in the first n bytes of the allocated space.
- */
-INLINE void *MemoryHook::
-alloc_to_ptr(void *alloc, size_t size) {
-#if defined(MEMORY_HOOK_DO_ALIGN)
-  size_t alignment = get_memory_alignment();
-  // Move the allocated pointer up to the next even alignment.
-  size_t *root = (size_t *)((((size_t)alloc + alignment - 1) / alignment) * alignment);
-  assert(alloc <= root && (size_t)((char *)root - (char *)alloc) < alignment);
-  root[0] = size;
-  root[1] = (size_t)alloc;  // Save the pointer we originally allocated.
-  return (void *)((char *)root + get_header_reserved_bytes());
-#elif defined(DO_MEMORY_USAGE)
-  size_t *root = (size_t *)alloc;
-  root[0] = size;
-  return (void *)((char *)root + get_header_reserved_bytes());
-#else
-  return alloc;
-#endif  // DO_MEMORY_USAGE
-}
-
-/**
- * Converts an application pointer back to the original allocated pointer.
- * Extracts size from the first n bytes of the allocated space.
- */
-INLINE void *MemoryHook::
-ptr_to_alloc(void *ptr, size_t &size) {
+get_ptr_size(void *ptr) {
 #if defined(MEMORY_HOOK_DO_ALIGN)
 #if defined(MEMORY_HOOK_DO_ALIGN)
-  size_t *root = (size_t *)((char *)ptr - get_header_reserved_bytes());
-  size = root[0];
-  void *alloc = (void *)root[1]; // Get the pointer we originally allocated.
-  assert(alloc <= root && (size_t)((char *)root - (char *)alloc) < get_memory_alignment());
-  return alloc;
+  uintptr_t *root = (uintptr_t *)ptr;
+  return (size_t)root[-2];
+#elif defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
+  // If we are using dlmalloc, we know how it stores the size.
+  size_t *root = (size_t *)ptr;
+  return (root[-1] & ~0x7) - sizeof(size_t);
 #elif defined(DO_MEMORY_USAGE)
 #elif defined(DO_MEMORY_USAGE)
-  size_t *root = (size_t *)((char *)ptr - get_header_reserved_bytes());
-  size = root[0];
-  return (void *)root;
+  size_t *root = (size_t *)((char *)ptr - MEMORY_HOOK_ALIGNMENT);
+  return *root;
 #else
 #else
-  return ptr;
+  return 0;
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
 }
 }

+ 134 - 22
dtool/src/dtoolbase/memoryHook.cxx

@@ -14,6 +14,7 @@
 #include "memoryHook.h"
 #include "memoryHook.h"
 #include "deletedBufferChain.h"
 #include "deletedBufferChain.h"
 #include <stdlib.h>
 #include <stdlib.h>
+#include "typeRegistry.h"
 
 
 #ifdef WIN32
 #ifdef WIN32
 
 
@@ -36,6 +37,15 @@
 
 
 #endif  // WIN32
 #endif  // WIN32
 
 
+// Ensure we made the right decisions about the alignment size.
+static_assert(MEMORY_HOOK_ALIGNMENT >= sizeof(size_t),
+              "MEMORY_HOOK_ALIGNMENT should at least be sizeof(size_t)");
+static_assert(MEMORY_HOOK_ALIGNMENT >= sizeof(void *),
+              "MEMORY_HOOK_ALIGNMENT should at least be sizeof(void *)");
+static_assert(MEMORY_HOOK_ALIGNMENT * 8 >= NATIVE_WORDSIZE,
+              "MEMORY_HOOK_ALIGNMENT * 8 should at least be NATIVE_WORDSIZE");
+static_assert((MEMORY_HOOK_ALIGNMENT & (MEMORY_HOOK_ALIGNMENT - 1)) == 0,
+              "MEMORY_HOOK_ALIGNMENT should be a power of two");
 
 
 #if defined(USE_MEMORY_DLMALLOC)
 #if defined(USE_MEMORY_DLMALLOC)
 
 
@@ -49,17 +59,8 @@
 #ifdef _DEBUG
 #ifdef _DEBUG
   #define DEBUG 1
   #define DEBUG 1
 #endif
 #endif
-#ifdef LINMATH_ALIGN
-// drose: We require 16-byte alignment of certain structures, to
-// support SSE2.  We don't strictly have to align *everything*, but
-// it's just easier to do so.
-#ifdef __AVX__
-// Eigen requires 32-byte alignment when using AVX instructions.
-#define MALLOC_ALIGNMENT ((size_t)32U)
-#else
-#define MALLOC_ALIGNMENT ((size_t)16U)
-#endif
-#endif
+// dlmalloc can do the alignment we ask for.
+#define MALLOC_ALIGNMENT MEMORY_HOOK_ALIGNMENT
 
 
 #include "dlmalloc_src.cxx"
 #include "dlmalloc_src.cxx"
 
 
@@ -104,6 +105,83 @@
 
 
 #endif  // USE_MEMORY_*
 #endif  // USE_MEMORY_*
 
 
+/**
+ * Increments the amount of requested size as necessary to accommodate the
+ * extra data we might piggyback on each allocated block.
+ */
+INLINE static size_t
+inflate_size(size_t size) {
+#if defined(MEMORY_HOOK_DO_ALIGN)
+  // If we're aligning, we need to request the header size, plus extra bytes
+  // to give us wiggle room to adjust the pointer.
+  return size + sizeof(uintptr_t) * 2 + MEMORY_HOOK_ALIGNMENT - 1;
+#elif defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
+  // If we are can access the allocator's bookkeeping to figure out how many
+  // bytes were allocated, we don't need to add our own information.
+  return size;
+#elif defined(DO_MEMORY_USAGE)
+  // If we're not aligning, but we're tracking memory allocations, we just
+  // need the header size extra (this gives us a place to store the size of
+  // the allocated block).  However, we do need to make sure that any
+  // alignment guarantee is kept.
+  return size + MEMORY_HOOK_ALIGNMENT;
+#else
+  // If we're not doing any of that, we can just allocate the precise
+  // requested amount.
+  return size;
+#endif  // DO_MEMORY_USAGE
+}
+
+/**
+ * Converts an allocated pointer to a pointer returnable to the application.
+ * Stuffs size in the first n bytes of the allocated space.
+ */
+INLINE static void *
+alloc_to_ptr(void *alloc, size_t size) {
+#if defined(MEMORY_HOOK_DO_ALIGN)
+  // Add room for two uintptr_t values.
+  uintptr_t *root = (uintptr_t *)((char *)alloc + sizeof(uintptr_t) * 2);
+  // Align this to the requested boundary.
+  root = (uintptr_t *)(((uintptr_t)root + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1));
+  root[-2] = size;
+  root[-1] = (uintptr_t)alloc;  // Save the pointer we originally allocated.
+  return (void *)root;
+#elif defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
+  return alloc;
+#elif defined(DO_MEMORY_USAGE)
+  size_t *root = (size_t *)alloc;
+  root[0] = size;
+  return (void *)((char *)root + MEMORY_HOOK_ALIGNMENT);
+#else
+  return alloc;
+#endif  // DO_MEMORY_USAGE
+}
+
+/**
+ * Converts an application pointer back to the original allocated pointer.
+ * Extracts size from the first n bytes of the allocated space, but only if
+ * DO_MEMORY_USAGE is defined.
+ */
+INLINE static void *
+ptr_to_alloc(void *ptr, size_t &size) {
+#if defined(MEMORY_HOOK_DO_ALIGN)
+  uintptr_t *root = (uintptr_t *)ptr;
+  size = root[-2];
+  return (void *)root[-1]; // Get the pointer we originally allocated.
+#elif defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
+#ifdef DO_MEMORY_USAGE
+  size = MemoryHook::get_ptr_size(ptr);
+#endif
+  return ptr;
+#elif defined(DO_MEMORY_USAGE)
+  size_t *root = (size_t *)((char *)ptr - MEMORY_HOOK_ALIGNMENT);
+  size = root[0];
+  return (void *)root;
+#else
+  return ptr;
+#endif  // DO_MEMORY_USAGE
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -195,6 +273,11 @@ heap_alloc_single(size_t size) {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   // In the DO_MEMORY_USAGE case, we want to track the total size of allocated
   // In the DO_MEMORY_USAGE case, we want to track the total size of allocated
   // bytes on the heap.
   // bytes on the heap.
+#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
+  // dlmalloc may slightly overallocate, however.
+  size = get_ptr_size(alloc);
+  inflated_size = size;
+#endif
   AtomicAdjust::add(_total_heap_single_size, (AtomicAdjust::Integer)size);
   AtomicAdjust::add(_total_heap_single_size, (AtomicAdjust::Integer)size);
   if ((size_t)AtomicAdjust::get(_total_heap_single_size) +
   if ((size_t)AtomicAdjust::get(_total_heap_single_size) +
       (size_t)AtomicAdjust::get(_total_heap_array_size) >
       (size_t)AtomicAdjust::get(_total_heap_array_size) >
@@ -204,7 +287,10 @@ heap_alloc_single(size_t size) {
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
 
 
   void *ptr = alloc_to_ptr(alloc, size);
   void *ptr = alloc_to_ptr(alloc, size);
+#ifdef _DEBUG
+  assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
   assert(ptr >= alloc && (char *)ptr + size <= (char *)alloc + inflated_size);
   assert(ptr >= alloc && (char *)ptr + size <= (char *)alloc + inflated_size);
+#endif
   return ptr;
   return ptr;
 }
 }
 
 
@@ -264,6 +350,11 @@ heap_alloc_array(size_t size) {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   // In the DO_MEMORY_USAGE case, we want to track the total size of allocated
   // In the DO_MEMORY_USAGE case, we want to track the total size of allocated
   // bytes on the heap.
   // bytes on the heap.
+#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
+  // dlmalloc may slightly overallocate, however.
+  size = get_ptr_size(alloc);
+  inflated_size = size;
+#endif
   AtomicAdjust::add(_total_heap_array_size, (AtomicAdjust::Integer)size);
   AtomicAdjust::add(_total_heap_array_size, (AtomicAdjust::Integer)size);
   if ((size_t)AtomicAdjust::get(_total_heap_single_size) +
   if ((size_t)AtomicAdjust::get(_total_heap_single_size) +
       (size_t)AtomicAdjust::get(_total_heap_array_size) >
       (size_t)AtomicAdjust::get(_total_heap_array_size) >
@@ -273,7 +364,10 @@ heap_alloc_array(size_t size) {
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
 
 
   void *ptr = alloc_to_ptr(alloc, size);
   void *ptr = alloc_to_ptr(alloc, size);
+#ifdef _DEBUG
+  assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
   assert(ptr >= alloc && (char *)ptr + size <= (char *)alloc + inflated_size);
   assert(ptr >= alloc && (char *)ptr + size <= (char *)alloc + inflated_size);
+#endif
   return ptr;
   return ptr;
 }
 }
 
 
@@ -285,11 +379,6 @@ heap_realloc_array(void *ptr, size_t size) {
   size_t orig_size;
   size_t orig_size;
   void *alloc = ptr_to_alloc(ptr, orig_size);
   void *alloc = ptr_to_alloc(ptr, orig_size);
 
 
-#ifdef DO_MEMORY_USAGE
-  assert((AtomicAdjust::Integer)orig_size <= _total_heap_array_size);
-  AtomicAdjust::add(_total_heap_array_size, (AtomicAdjust::Integer)size-(AtomicAdjust::Integer)orig_size);
-#endif  // DO_MEMORY_USAGE
-
   size_t inflated_size = inflate_size(size);
   size_t inflated_size = inflate_size(size);
 
 
   void *alloc1 = alloc;
   void *alloc1 = alloc;
@@ -316,17 +405,40 @@ heap_realloc_array(void *ptr, size_t size) {
 #endif
 #endif
   }
   }
 
 
-  void *ptr1 = alloc_to_ptr(alloc1, size);
-  assert(ptr1 >= alloc1 && (char *)ptr1 + size <= (char *)alloc1 + inflated_size);
-#if defined(MEMORY_HOOK_DO_ALIGN)
-  // We might have to shift the memory to account for the new offset due to
-  // the alignment.
+#ifdef DO_MEMORY_USAGE
+#if defined(USE_MEMORY_DLMALLOC) || defined(USE_MEMORY_PTMALLOC2)
+  // dlmalloc may slightly overallocate, however.
+  size = get_ptr_size(alloc1);
+  inflated_size = size;
+#endif
+  assert((AtomicAdjust::Integer)orig_size <= _total_heap_array_size);
+  AtomicAdjust::add(_total_heap_array_size, (AtomicAdjust::Integer)size-(AtomicAdjust::Integer)orig_size);
+#endif  // DO_MEMORY_USAGE
+
+  // Align this to the requested boundary.
+#ifdef MEMORY_HOOK_DO_ALIGN
+  // This copies the code from alloc_to_ptr, since we can't write the size and
+  // pointer until after we have done the memmove.
+  uintptr_t *root = (uintptr_t *)((char *)alloc1 + sizeof(uintptr_t) * 2);
+  root = (uintptr_t *)(((uintptr_t)root + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1));
+  void *ptr1 = (void *)root;
+
   size_t orig_delta = (char *)ptr - (char *)alloc;
   size_t orig_delta = (char *)ptr - (char *)alloc;
   size_t new_delta = (char *)ptr1 - (char *)alloc1;
   size_t new_delta = (char *)ptr1 - (char *)alloc1;
   if (orig_delta != new_delta) {
   if (orig_delta != new_delta) {
     memmove((char *)alloc1 + new_delta, (char *)alloc1 + orig_delta, min(size, orig_size));
     memmove((char *)alloc1 + new_delta, (char *)alloc1 + orig_delta, min(size, orig_size));
   }
   }
-#endif  // MEMORY_HOOK_DO_ALIGN
+
+  root[-2] = size;
+  root[-1] = (uintptr_t)alloc1;  // Save the pointer we originally allocated.
+#else
+  void *ptr1 = alloc_to_ptr(alloc1, size);
+#endif
+
+#ifdef _DEBUG
+  assert(ptr1 >= alloc1 && (char *)ptr1 + size <= (char *)alloc1 + inflated_size);
+  assert(((uintptr_t)ptr1 % MEMORY_HOOK_ALIGNMENT) == 0);
+#endif
   return ptr1;
   return ptr1;
 }
 }
 
 

+ 2 - 6
dtool/src/dtoolbase/memoryHook.h

@@ -52,8 +52,7 @@ public:
 
 
   bool heap_trim(size_t pad);
   bool heap_trim(size_t pad);
 
 
-  INLINE static size_t get_memory_alignment();
-  INLINE static size_t get_header_reserved_bytes();
+  CONSTEXPR static size_t get_memory_alignment();
 
 
   virtual void *mmap_alloc(size_t size, bool allow_exec);
   virtual void *mmap_alloc(size_t size, bool allow_exec);
   virtual void mmap_free(void *ptr, size_t size);
   virtual void mmap_free(void *ptr, size_t size);
@@ -66,10 +65,7 @@ public:
 
 
   virtual void alloc_fail(size_t attempted_size);
   virtual void alloc_fail(size_t attempted_size);
 
 
-private:
-  INLINE static size_t inflate_size(size_t size);
-  INLINE static void *alloc_to_ptr(void *alloc, size_t size);
-  INLINE static void *ptr_to_alloc(void *ptr, size_t &size);
+  INLINE static size_t get_ptr_size(void *ptr);
 
 
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
 protected:
 protected:

+ 19 - 40
dtool/src/dtoolbase/pallocator.T

@@ -1,16 +1,15 @@
-// Filename: pallocator.T
-// Created by:  drose (05Jun01)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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."
-//
-////////////////////////////////////////////////////////////////////
+/**
+ * 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 pallocator.T
+ * @author drose
+ * @date 2001-06-05
+ */
 
 
 template<class Type>
 template<class Type>
 INLINE pallocator_single<Type>::
 INLINE pallocator_single<Type>::
@@ -20,12 +19,13 @@ pallocator_single(TypeHandle type_handle) NOEXCEPT :
 }
 }
 
 
 template<class Type>
 template<class Type>
-INLINE TYPENAME pallocator_single<Type>::pointer pallocator_single<Type>::
+INLINE Type *pallocator_single<Type>::
 allocate(TYPENAME pallocator_single<Type>::size_type n, TYPENAME allocator<void>::const_pointer) {
 allocate(TYPENAME pallocator_single<Type>::size_type n, TYPENAME allocator<void>::const_pointer) {
   TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER);
   TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER);
   // This doesn't support allocating arrays.
   // This doesn't support allocating arrays.
   assert(n == 1);
   assert(n == 1);
-  return StaticDeletedChain<Type>::allocate(sizeof(Type), _type_handle);
+  return (Type *)ASSUME_ALIGNED(StaticDeletedChain<Type>::allocate(sizeof(Type), _type_handle),
+                                MEMORY_HOOK_ALIGNMENT);
 }
 }
 
 
 template<class Type>
 template<class Type>
@@ -43,35 +43,14 @@ pallocator_array(TypeHandle type_handle) NOEXCEPT :
 }
 }
 
 
 template<class Type>
 template<class Type>
-INLINE TYPENAME pallocator_array<Type>::pointer pallocator_array<Type>::
+INLINE Type *pallocator_array<Type>::
 allocate(TYPENAME pallocator_array<Type>::size_type n, TYPENAME allocator<void>::const_pointer) {
 allocate(TYPENAME pallocator_array<Type>::size_type n, TYPENAME allocator<void>::const_pointer) {
-  TAU_PROFILE("pallocator_array:allocate()", " ", TAU_USER);
-#ifdef DO_MEMORY_USAGE
-  const size_t header_reserved_bytes = MemoryHook::get_header_reserved_bytes();
-  size_t alloc_size = n * sizeof(Type);
-  // We also need to store the total number of bytes we allocated.
-  alloc_size += header_reserved_bytes;
-  _type_handle.inc_memory_usage(TypeHandle::MC_array, alloc_size);
-  void *ptr = (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(alloc_size);
-  *((size_t *)ptr) = alloc_size;
-  return (TYPENAME pallocator_array<Type>::pointer)(((char *)ptr) + header_reserved_bytes);
-#else
-  return (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(n * sizeof(Type));
-#endif  // DO_MEMORY_USAGE
+  return (TYPENAME pallocator_array<Type>::pointer)
+    ASSUME_ALIGNED(_type_handle.allocate_array(n * sizeof(Type)), MEMORY_HOOK_ALIGNMENT);
 }
 }
 
 
 template<class Type>
 template<class Type>
 INLINE void pallocator_array<Type>::
 INLINE void pallocator_array<Type>::
 deallocate(TYPENAME pallocator_array<Type>::pointer p, TYPENAME pallocator_array<Type>::size_type) {
 deallocate(TYPENAME pallocator_array<Type>::pointer p, TYPENAME pallocator_array<Type>::size_type) {
-  TAU_PROFILE("pallocator_array:deallocate()", " ", TAU_USER);
-#ifdef DO_MEMORY_USAGE
-  // Now we need to recover the total number of bytes.
-  const size_t header_reserved_bytes = MemoryHook::get_header_reserved_bytes();
-  void *ptr = (void *)((char *)p - header_reserved_bytes);
-  size_t alloc_size = *((size_t *)ptr);
-  _type_handle.dec_memory_usage(TypeHandle::MC_array, alloc_size);
-  PANDA_FREE_ARRAY(ptr);
-#else
-  PANDA_FREE_ARRAY(p);
-#endif  // DO_MEMORY_USAGE
+  _type_handle.deallocate_array((void *)p);
 }
 }

+ 4 - 2
dtool/src/dtoolbase/pallocator.h

@@ -59,7 +59,8 @@ public:
   INLINE pallocator_single(const pallocator_single<U> &copy) NOEXCEPT :
   INLINE pallocator_single(const pallocator_single<U> &copy) NOEXCEPT :
     _type_handle(copy._type_handle) { }
     _type_handle(copy._type_handle) { }
 
 
-  INLINE pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);
+  INLINE Type *allocate(size_type n, allocator<void>::const_pointer hint = 0)
+    RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
   INLINE void deallocate(pointer p, size_type n);
   INLINE void deallocate(pointer p, size_type n);
 
 
   template<class U> struct rebind {
   template<class U> struct rebind {
@@ -87,7 +88,8 @@ public:
   INLINE pallocator_array(const pallocator_array<U> &copy) NOEXCEPT :
   INLINE pallocator_array(const pallocator_array<U> &copy) NOEXCEPT :
     _type_handle(copy._type_handle) { }
     _type_handle(copy._type_handle) { }
 
 
-  INLINE pointer allocate(size_type n, allocator<void>::const_pointer hint = 0);
+  INLINE Type *allocate(size_type n, allocator<void>::const_pointer hint = 0)
+    RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
   INLINE void deallocate(pointer p, size_type n);
   INLINE void deallocate(pointer p, size_type n);
 
 
   template<class U> struct rebind {
   template<class U> struct rebind {

+ 79 - 5
dtool/src/dtoolbase/typeHandle.cxx

@@ -18,7 +18,6 @@
 // This is initialized to zero by static initialization.
 // This is initialized to zero by static initialization.
 TypeHandle TypeHandle::_none;
 TypeHandle TypeHandle::_none;
 
 
-#ifdef DO_MEMORY_USAGE
 /**
 /**
  * Returns the total allocated memory used by objects of this type, for the
  * Returns the total allocated memory used by objects of this type, for the
  * indicated memory class.  This is only updated if track-memory-usage is set
  * indicated memory class.  This is only updated if track-memory-usage is set
@@ -26,6 +25,7 @@ TypeHandle TypeHandle::_none;
  */
  */
 size_t TypeHandle::
 size_t TypeHandle::
 get_memory_usage(MemoryClass memory_class) const {
 get_memory_usage(MemoryClass memory_class) const {
+#ifdef DO_MEMORY_USAGE
   assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
   assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
   if ((*this) == TypeHandle::none()) {
   if ((*this) == TypeHandle::none()) {
     return 0;
     return 0;
@@ -34,16 +34,17 @@ get_memory_usage(MemoryClass memory_class) const {
     assert(rnode != (TypeRegistryNode *)NULL);
     assert(rnode != (TypeRegistryNode *)NULL);
     return (size_t)AtomicAdjust::get(rnode->_memory_usage[memory_class]);
     return (size_t)AtomicAdjust::get(rnode->_memory_usage[memory_class]);
   }
   }
-}
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
+  return 0;
+}
 
 
-#ifdef DO_MEMORY_USAGE
 /**
 /**
  * Adds the indicated amount to the record for the total allocated memory for
  * Adds the indicated amount to the record for the total allocated memory for
  * objects of this type.
  * objects of this type.
  */
  */
 void TypeHandle::
 void TypeHandle::
 inc_memory_usage(MemoryClass memory_class, size_t size) {
 inc_memory_usage(MemoryClass memory_class, size_t size) {
+#ifdef DO_MEMORY_USAGE
   assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
   assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
   if ((*this) != TypeHandle::none()) {
   if ((*this) != TypeHandle::none()) {
     TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
     TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
@@ -56,16 +57,16 @@ inc_memory_usage(MemoryClass memory_class, size_t size) {
       abort();
       abort();
     }
     }
   }
   }
-}
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
+}
 
 
-#ifdef DO_MEMORY_USAGE
 /**
 /**
  * Subtracts the indicated amount from the record for the total allocated
  * Subtracts the indicated amount from the record for the total allocated
  * memory for objects of this type.
  * memory for objects of this type.
  */
  */
 void TypeHandle::
 void TypeHandle::
 dec_memory_usage(MemoryClass memory_class, size_t size) {
 dec_memory_usage(MemoryClass memory_class, size_t size) {
+#ifdef DO_MEMORY_USAGE
   assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
   assert((int)memory_class >= 0 && (int)memory_class < (int)MC_limit);
   if ((*this) != TypeHandle::none()) {
   if ((*this) != TypeHandle::none()) {
     TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
     TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
@@ -75,8 +76,81 @@ dec_memory_usage(MemoryClass memory_class, size_t size) {
     // rnode->_memory_usage[memory_class] << "\n";
     // rnode->_memory_usage[memory_class] << "\n";
     assert(rnode->_memory_usage[memory_class] >= 0);
     assert(rnode->_memory_usage[memory_class] >= 0);
   }
   }
+#endif  // DO_MEMORY_USAGE
+}
+
+/**
+ * Allocates memory, adding it to the total amount of memory allocated for
+ * this type.
+ */
+void *TypeHandle::
+allocate_array(size_t size) {
+  TAU_PROFILE("TypeHandle:allocate_array()", " ", TAU_USER);
+
+  void *ptr = PANDA_MALLOC_ARRAY(size);
+#ifdef DO_MEMORY_USAGE
+  if ((*this) != TypeHandle::none()) {
+    size_t alloc_size = MemoryHook::get_ptr_size(ptr);
+#ifdef _DEBUG
+    assert(size <= alloc_size);
+#endif
+    TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
+    assert(rnode != (TypeRegistryNode *)NULL);
+    AtomicAdjust::add(rnode->_memory_usage[MC_array], (AtomicAdjust::Integer)alloc_size);
+    if (rnode->_memory_usage[MC_array] < 0) {
+      cerr << "Memory usage overflow for type " << *this << ".\n";
+      abort();
+    }
+  }
+#endif  // DO_MEMORY_USAGE
+  return ptr;
+}
+
+/**
+ * Reallocates memory, adjusting the total amount of memory allocated for this
+ * type.
+ */
+void *TypeHandle::
+reallocate_array(void *old_ptr, size_t size) {
+  TAU_PROFILE("TypeHandle:reallocate_array()", " ", TAU_USER);
+
+#ifdef DO_MEMORY_USAGE
+  size_t old_size = MemoryHook::get_ptr_size(old_ptr);
+  void *new_ptr = PANDA_REALLOC_ARRAY(old_ptr, size);
+
+  if ((*this) != TypeHandle::none()) {
+    size_t new_size = MemoryHook::get_ptr_size(new_ptr);
+
+    TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
+    assert(rnode != (TypeRegistryNode *)NULL);
+    AtomicAdjust::add(rnode->_memory_usage[MC_array], (AtomicAdjust::Integer)new_size - (AtomicAdjust::Integer)old_size);
+    assert(rnode->_memory_usage[MC_array] >= 0);
+  }
+#else
+  void *new_ptr = PANDA_REALLOC_ARRAY(old_ptr, size);
+#endif
+  return new_ptr;
 }
 }
+
+/**
+ * Deallocates memory, subtracting it from the total amount of memory
+ * allocated for this type.
+ */
+void TypeHandle::
+deallocate_array(void *ptr) {
+  TAU_PROFILE("TypeHandle:deallocate_array()", " ", TAU_USER);
+
+#ifdef DO_MEMORY_USAGE
+  size_t alloc_size = MemoryHook::get_ptr_size(ptr);
+  if ((*this) != TypeHandle::none()) {
+    TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, NULL);
+    assert(rnode != (TypeRegistryNode *)NULL);
+    AtomicAdjust::add(rnode->_memory_usage[MC_array], -(AtomicAdjust::Integer)alloc_size);
+    assert(rnode->_memory_usage[MC_array] >= 0);
+  }
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
+  PANDA_FREE_ARRAY(ptr);
+}
 
 
 /**
 /**
  * Return the Index of the BEst fit Classs from a set
  * Return the Index of the BEst fit Classs from a set

+ 47 - 25
dtool/src/dtoolbase/typeHandle.h

@@ -18,25 +18,49 @@
 
 
 #include <set>
 #include <set>
 
 
-// The following illustrates the convention for declaring a type that uses
-// TypeHandle.  In this example, ThisThingie inherits from TypedObject, which
-// automatically supplies some type-differentiation functions at the cost of
-// one virtual function, get_type(); however, this inheritance is optional,
-// and may be omitted to avoid the virtual function pointer overhead.  (If you
-// do use TypedObject, be sure to consider whether your destructor should also
-// be virtual.)
-
-/*
- * class ThatThingie : public SimpleTypedObject { public: static TypeHandle
- * get_class_type() { return _type_handle; } static void init_type() {
- * register_type(_type_handle, "ThatThingie"); } private: static TypeHandle
- * _type_handle; }; class ThisThingie : public ThatThingie, publid TypedObject
- * { public: static TypeHandle get_class_type() { return _type_handle; }
- * static void init_type() { ThatThingie::init_type();
- * TypedObject::init_type(); register_type(_type_handle, "ThisThingie",
- * ThatThingie::get_class_type(), TypedObject::get_class_type()); } virtual
- * TypeHandle get_type() const { return get_class_type(); } private: static
- * TypeHandle _type_handle; };
+/**
+ * The following illustrates the convention for declaring a type that uses
+ * TypeHandle.  In this example, ThisThingie inherits from TypedObject, which
+ * automatically supplies some type-differentiation functions at the cost of
+ * one virtual function, get_type(); however, this inheritance is optional,
+ * and may be omitted to avoid the virtual function pointer overhead.  (If you
+ * do use TypedObject, be sure to consider whether your destructor should also
+ * be virtual.)
+ *
+ * @code
+ * class ThatThingie : public SimpleTypedObject {
+ * public:
+ *   static TypeHandle get_class_type() {
+ *     return _type_handle;
+ *   }
+ *   static void init_type() {
+ *     register_type(_type_handle, "ThatThingie");
+ *   }
+ *
+ * private:
+ *   static TypeHandle _type_handle;
+ * };
+ *
+ * class ThisThingie : public ThatThingie, publid TypedObject {
+ * public:
+ *   static TypeHandle get_class_type() {
+ *     return _type_handle;
+ *   }
+ *   static void init_type() {
+ *     ThatThingie::init_type();
+ *     TypedObject::init_type();
+ *     register_type(_type_handle, "ThisThingie",
+ *                  ThatThingie::get_class_type(),
+ *                  TypedObject::get_class_type());
+ *   }
+ *   virtual TypeHandle get_type() const {
+ *     return get_class_type();
+ *   }
+ *
+ * private:
+ *   static TypeHandle _type_handle;
+ * };
+ * @endcode
  */
  */
 
 
 class TypedObject;
 class TypedObject;
@@ -97,15 +121,9 @@ PUBLISHED:
 
 
   int get_best_parent_from_Set(const std::set< int > &legal_vals) const;
   int get_best_parent_from_Set(const std::set< int > &legal_vals) const;
 
 
-#ifdef DO_MEMORY_USAGE
   size_t get_memory_usage(MemoryClass memory_class) const;
   size_t get_memory_usage(MemoryClass memory_class) const;
   void inc_memory_usage(MemoryClass memory_class, size_t size);
   void inc_memory_usage(MemoryClass memory_class, size_t size);
   void dec_memory_usage(MemoryClass memory_class, size_t size);
   void dec_memory_usage(MemoryClass memory_class, size_t size);
-#else
-  static CONSTEXPR size_t get_memory_usage(MemoryClass) { return 0; }
-  INLINE void inc_memory_usage(MemoryClass, size_t) { }
-  INLINE void dec_memory_usage(MemoryClass, size_t) { }
-#endif  // DO_MEMORY_USAGE
 
 
   INLINE int get_index() const;
   INLINE int get_index() const;
   INLINE void output(ostream &out) const;
   INLINE void output(ostream &out) const;
@@ -118,6 +136,10 @@ PUBLISHED:
   MAKE_SEQ_PROPERTY(child_classes, get_num_child_classes, get_child_class);
   MAKE_SEQ_PROPERTY(child_classes, get_num_child_classes, get_child_class);
 
 
 public:
 public:
+  void *allocate_array(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
+  void *reallocate_array(void *ptr, size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
+  void deallocate_array(void *ptr);
+
   INLINE static TypeHandle from_index(int index);
   INLINE static TypeHandle from_index(int index);
 
 
 private:
 private:

+ 4 - 4
dtool/src/dtoolutil/executionEnvironment.cxx

@@ -591,8 +591,8 @@ read_args() {
     dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
     dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
 
 
     while (map != NULL) {
     while (map != NULL) {
-      char *tail = strrchr(map->l_name, '/');
-      char *head = strchr(map->l_name, '/');
+      const char *tail = strrchr(map->l_name, '/');
+      const char *head = strchr(map->l_name, '/');
       if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
       if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
                         || strcmp(tail, "/libp3dtool.so") == 0)) {
                         || strcmp(tail, "/libp3dtool.so") == 0)) {
         _dtool_name = head;
         _dtool_name = head;
@@ -615,8 +615,8 @@ read_args() {
       char buffer[PATH_MAX];
       char buffer[PATH_MAX];
       buffer[0] = 0;
       buffer[0] = 0;
       maps.getline(buffer, PATH_MAX);
       maps.getline(buffer, PATH_MAX);
-      char *tail = strrchr(buffer, '/');
-      char *head = strchr(buffer, '/');
+      const char *tail = strrchr(buffer, '/');
+      const char *head = strchr(buffer, '/');
       if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
       if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
                         || strcmp(tail, "/libp3dtool.so") == 0)) {
                         || strcmp(tail, "/libp3dtool.so") == 0)) {
         _dtool_name = head;
         _dtool_name = head;

+ 52 - 11
dtool/src/dtoolutil/globPattern.cxx

@@ -99,7 +99,7 @@ match_files(vector_string &results, const Filename &cwd) const {
     pattern = source;
     pattern = source;
   } else {
   } else {
     pattern = source.substr(0, slash);
     pattern = source.substr(0, slash);
-    suffix = source.substr(slash + 1);
+    suffix = source.substr(slash);
   }
   }
 
 
   GlobPattern glob(pattern);
   GlobPattern glob(pattern);
@@ -118,11 +118,21 @@ r_match_files(const Filename &prefix, const string &suffix,
   size_t slash = suffix.find('/');
   size_t slash = suffix.find('/');
   if (slash == string::npos) {
   if (slash == string::npos) {
     next_pattern = suffix;
     next_pattern = suffix;
+  } else if (slash + 1 == suffix.size()) {
+    // If the slash is at the end, we need to keep it, since it indicates that
+    // we only want to match directories.
+    next_pattern = suffix.substr(0, slash);
+    next_suffix = "/";
   } else {
   } else {
     next_pattern = suffix.substr(0, slash);
     next_pattern = suffix.substr(0, slash);
     next_suffix = suffix.substr(slash + 1);
     next_suffix = suffix.substr(slash + 1);
   }
   }
 
 
+  if (_pattern == "**" && next_pattern == "**") {
+    // Collapse consecutive globstar patterns.
+    return r_match_files(prefix, next_suffix, results, cwd);
+  }
+
   Filename parent_dir;
   Filename parent_dir;
   if (prefix.is_local() && !cwd.empty()) {
   if (prefix.is_local() && !cwd.empty()) {
     parent_dir = Filename(cwd, prefix);
     parent_dir = Filename(cwd, prefix);
@@ -136,19 +146,24 @@ r_match_files(const Filename &prefix, const string &suffix,
   if (!has_glob_characters()) {
   if (!has_glob_characters()) {
     // If there are no special characters in the pattern, it's a literal
     // If there are no special characters in the pattern, it's a literal
     // match.
     // match.
+    Filename fn(parent_dir, _pattern);
     if (suffix.empty()) {
     if (suffix.empty()) {
       // Time to stop.
       // Time to stop.
-      Filename single_filename(parent_dir, _pattern);
-      if (single_filename.exists()) {
+      if (fn.exists()) {
         results.push_back(Filename(prefix, _pattern));
         results.push_back(Filename(prefix, _pattern));
         return 1;
         return 1;
       }
       }
       return 0;
       return 0;
+    } else if (fn.is_directory()) {
+      // If the pattern ends with a slash, match a directory only.
+      if (suffix == "/") {
+        results.push_back(Filename(prefix, _pattern + "/"));
+        return 1;
+      } else {
+        return next_glob.r_match_files(Filename(prefix, _pattern),
+                                       next_suffix, results, cwd);
+      }
     }
     }
-
-    return next_glob.r_match_files(Filename(prefix, _pattern),
-                                   next_suffix, results, cwd);
-
   }
   }
 
 
   // If there *are* special glob characters, we must attempt to match the
   // If there *are* special glob characters, we must attempt to match the
@@ -164,18 +179,44 @@ r_match_files(const Filename &prefix, const string &suffix,
   // the pattern.
   // the pattern.
   int num_matched = 0;
   int num_matched = 0;
 
 
+  // A globstar pattern matches zero or more directories.
+  if (_pattern == "**") {
+    // Try to match this directory (as if the globstar wasn't there)
+    if (suffix.empty()) {
+      // This is a directory.  Add it.
+      results.push_back(Filename(prefix));
+      num_matched++;
+    } else if (suffix == "/") {
+      // Keep the trailing slash, but be sure not to duplicate it.
+      results.push_back(Filename(prefix, ""));
+      num_matched++;
+    } else {
+      num_matched += next_glob.r_match_files(prefix, next_suffix, results, cwd);
+    }
+    next_suffix = suffix;
+    next_glob = *this;
+  }
+
   vector_string::const_iterator fi;
   vector_string::const_iterator fi;
   for (fi = dir_files.begin(); fi != dir_files.end(); ++fi) {
   for (fi = dir_files.begin(); fi != dir_files.end(); ++fi) {
     const string &local_file = (*fi);
     const string &local_file = (*fi);
     if (_pattern[0] == '.' || (local_file.empty() || local_file[0] != '.')) {
     if (_pattern[0] == '.' || (local_file.empty() || local_file[0] != '.')) {
       if (matches(local_file)) {
       if (matches(local_file)) {
         // We have a match; continue.
         // We have a match; continue.
-        if (suffix.empty()) {
+        if (Filename(parent_dir, local_file).is_directory()) {
+          if (suffix.empty() && _pattern != "**") {
+            results.push_back(Filename(prefix, local_file));
+            num_matched++;
+          } else if (suffix == "/" && _pattern != "**") {
+            results.push_back(Filename(prefix, local_file + "/"));
+            num_matched++;
+          } else {
+            num_matched += next_glob.r_match_files(Filename(prefix, local_file),
+                                                   next_suffix, results, cwd);
+          }
+        } else if (suffix.empty()) {
           results.push_back(Filename(prefix, local_file));
           results.push_back(Filename(prefix, local_file));
           num_matched++;
           num_matched++;
-        } else {
-          num_matched += next_glob.r_match_files(Filename(prefix, local_file),
-                                                 next_suffix, results, cwd);
         }
         }
       }
       }
     }
     }

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

@@ -45,6 +45,11 @@ PandaSystem() :
 #else
 #else
   set_system_tag("eigen", "vectorize", "0");
   set_system_tag("eigen", "vectorize", "0");
 #endif
 #endif
+#ifdef __AVX__
+  set_system_tag("eigen", "avx", "1");
+#else
+  set_system_tag("eigen", "avx", "0");
+#endif
 #endif  // HAVE_EIGEN
 #endif  // HAVE_EIGEN
 
 
 #ifdef USE_MEMORY_DLMALLOC
 #ifdef USE_MEMORY_DLMALLOC
@@ -189,6 +194,14 @@ is_official_version() {
 #endif
 #endif
 }
 }
 
 
+/**
+ * Returns the memory alignment that Panda's allocators are using.
+ */
+int PandaSystem::
+get_memory_alignment() {
+  return MEMORY_HOOK_ALIGNMENT;
+}
+
 /**
 /**
  * Returns the string defined by the distributor of this version of Panda, or
  * Returns the string defined by the distributor of this version of Panda, or
  * "homebuilt" if this version was built directly from the sources by the end-
  * "homebuilt" if this version was built directly from the sources by the end-

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

@@ -39,6 +39,8 @@ PUBLISHED:
   static int get_sequence_version();
   static int get_sequence_version();
   static bool is_official_version();
   static bool is_official_version();
 
 
+  static int get_memory_alignment();
+
   static string get_distributor();
   static string get_distributor();
   static string get_compiler();
   static string get_compiler();
   static string get_build_date();
   static string get_build_date();

+ 10 - 1
dtool/src/interrogate/functionRemap.cxx

@@ -791,6 +791,15 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
     _args_type = InterfaceMaker::AT_single_arg;
     _args_type = InterfaceMaker::AT_single_arg;
   } else {
   } else {
     _args_type = InterfaceMaker::AT_varargs;
     _args_type = InterfaceMaker::AT_varargs;
+
+    // If the arguments are named "args" and "kwargs", we will be directly
+    // passing the argument tuples to the function.
+    if (_parameters.size() == first_param + 2 &&
+        _parameters[first_param]._name == "args" &&
+        (_parameters[first_param + 1]._name == "kwargs" ||
+          _parameters[first_param + 1]._name == "kwds")) {
+      _flags |= F_explicit_args;
+    }
   }
   }
 
 
   switch (_type) {
   switch (_type) {
@@ -890,7 +899,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
       if (_args_type == InterfaceMaker::AT_varargs) {
       if (_args_type == InterfaceMaker::AT_varargs) {
         // Every other method can take keyword arguments, if they take more
         // Every other method can take keyword arguments, if they take more
         // than one argument.
         // than one argument.
-        _args_type = InterfaceMaker::AT_keyword_args;
+        _args_type |= InterfaceMaker::AT_keyword_args;
       }
       }
     }
     }
     break;
     break;

+ 1 - 0
dtool/src/interrogate/functionRemap.h

@@ -100,6 +100,7 @@ public:
     F_coerce_constructor = 0x1000,
     F_coerce_constructor = 0x1000,
     F_divide_float       = 0x2000,
     F_divide_float       = 0x2000,
     F_hash               = 0x4000,
     F_hash               = 0x4000,
+    F_explicit_args      = 0x8000,
   };
   };
 
 
   typedef vector<Parameter> Parameters;
   typedef vector<Parameter> Parameters;

+ 32 - 11
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -3453,7 +3453,13 @@ write_function_for_name(ostream &out, Object *obj,
     max_required_args = collapse_default_remaps(map_sets, max_required_args);
     max_required_args = collapse_default_remaps(map_sets, max_required_args);
   }
   }
 
 
-  if (map_sets.size() > 1 && (args_type == AT_varargs || args_type == AT_keyword_args)) {
+  if (remap->_flags & FunctionRemap::F_explicit_args) {
+    // We have a remap that wants to handle the wrapper itself.
+    string expected_params;
+    write_function_instance(out, remap, 0, 0, expected_params, 2, true, true,
+                            args_type, return_flags);
+
+  } else if (map_sets.size() > 1 && (args_type == AT_varargs || args_type == AT_keyword_args)) {
     switch (args_type) {
     switch (args_type) {
     case AT_keyword_args:
     case AT_keyword_args:
       indent(out, 2) << "int parameter_count = (int)PyTuple_Size(args);\n";
       indent(out, 2) << "int parameter_count = (int)PyTuple_Size(args);\n";
@@ -4536,19 +4542,23 @@ write_function_instance(ostream &out, FunctionRemap *remap,
   expected_params += methodNameFromCppName(remap, "", false);
   expected_params += methodNameFromCppName(remap, "", false);
   expected_params += "(";
   expected_params += "(";
 
 
-  int num_params = max_num_args;
-  if (remap->_has_this) {
-    num_params += 1;
-  }
-  if (num_params > (int)remap->_parameters.size()) {
-    // Limit to how many parameters this remap actually has.
-    num_params = (int)remap->_parameters.size();
-    max_num_args = num_params;
+  int num_params = 0;
+
+  if ((remap->_flags & FunctionRemap::F_explicit_args) == 0) {
+    num_params = max_num_args;
     if (remap->_has_this) {
     if (remap->_has_this) {
-      --max_num_args;
+      num_params += 1;
     }
     }
+    if (num_params > (int)remap->_parameters.size()) {
+      // Limit to how many parameters this remap actually has.
+      num_params = (int)remap->_parameters.size();
+      max_num_args = num_params;
+      if (remap->_has_this) {
+        --max_num_args;
+      }
+    }
+    nassertv(num_params <= (int)remap->_parameters.size());
   }
   }
-  nassertv(num_params <= (int)remap->_parameters.size());
 
 
   bool only_pyobjects = true;
   bool only_pyobjects = true;
 
 
@@ -4584,6 +4594,17 @@ write_function_instance(ostream &out, FunctionRemap *remap,
     }
     }
   }
   }
 
 
+  if (remap->_flags & FunctionRemap::F_explicit_args) {
+    // The function handles the arguments by itself.
+    expected_params += "*args";
+    pexprs.push_back("args");
+    if (args_type == AT_keyword_args) {
+      expected_params += ", **kwargs";
+      pexprs.push_back("kwds");
+    }
+    num_params = 0;
+  }
+
   // Now convert (the rest of the) actual arguments, one by one.
   // Now convert (the rest of the) actual arguments, one by one.
   for (; pn < num_params; ++pn) {
   for (; pn < num_params; ++pn) {
     ParameterRemap *param = remap->_parameters[pn]._remap;
     ParameterRemap *param = remap->_parameters[pn]._remap;

+ 1 - 2
dtool/src/parser-inc/openssl/evp.h

@@ -2,7 +2,6 @@
 #ifndef EVP_H
 #ifndef EVP_H
 #define EVP_H
 #define EVP_H
 
 
-struct EVP_CIPHER_CTX;
-struct EVP_PKEY;
+#include <openssl/ssl.h>
 
 
 #endif
 #endif

+ 8 - 7
dtool/src/parser-inc/openssl/ssl.h

@@ -2,13 +2,14 @@
 #ifndef SSL_H
 #ifndef SSL_H
 #define SSL_H
 #define SSL_H
 
 
-struct BIO;
-struct SSL_CTX;
-struct EVP_CIPHER_CTX;
-struct EVP_PKEY;
-struct X509;
-struct X509_STORE;
-struct X509_NAME;
+typedef struct bio_st BIO;
+typedef struct ssl_ctx_st SSL_CTX;
+typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
+typedef struct evp_pkey_st EVP_PKEY;
+typedef struct x509_st X509;
+typedef struct x509_store_st X509_STORE;
+typedef struct X509_name_st X509_NAME;
+typedef struct ssl_cipher_st SSL_CIPHER;
 struct SSL;
 struct SSL;
 #define STACK_OF(type) struct stack_st_##type
 #define STACK_OF(type) struct stack_st_##type
 
 

+ 1 - 3
dtool/src/parser-inc/openssl/x509.h

@@ -2,9 +2,7 @@
 #ifndef X509_H
 #ifndef X509_H
 #define X509_H
 #define X509_H
 
 
-struct X509;
-struct X509_STORE;
-struct X509_NAME;
+#include <openssl/ssl.h>
 
 
 #endif
 #endif
 
 

+ 1 - 0
dtool/src/prc/encryptStreamBuf.cxx

@@ -21,6 +21,7 @@
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
 #include "openssl/rand.h"
 #include "openssl/rand.h"
+#include "openssl/evp.h"
 
 
 #ifndef HAVE_STREAMSIZE
 #ifndef HAVE_STREAMSIZE
 // Some compilers (notably SGI) don't define this for us
 // Some compilers (notably SGI) don't define this for us

+ 1 - 1
dtool/src/prc/encryptStreamBuf.h

@@ -19,7 +19,7 @@
 // This module is not compiled if OpenSSL is not available.
 // This module is not compiled if OpenSSL is not available.
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
-#include "openssl/evp.h"
+typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
 
 
 /**
 /**
  * The streambuf object that implements IDecompressStream and OCompressStream.
  * The streambuf object that implements IDecompressStream and OCompressStream.

+ 4 - 0
dtool/src/prc/prcKeyRegistry.cxx

@@ -19,8 +19,12 @@
 
 
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
+#include "openssl/evp.h"
 #include "openssl/pem.h"
 #include "openssl/pem.h"
 
 
+// Some versions of OpenSSL appear to define this as a macro.  Yucky.
+#undef set_key
+
 PrcKeyRegistry *PrcKeyRegistry::_global_ptr = NULL;
 PrcKeyRegistry *PrcKeyRegistry::_global_ptr = NULL;
 
 
 /**
 /**

+ 1 - 3
dtool/src/prc/prcKeyRegistry.h

@@ -22,10 +22,8 @@
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
 #include <vector>
 #include <vector>
-#include "openssl/evp.h"
 
 
-// Some versions of OpenSSL appear to define this as a macro.  Yucky.
-#undef set_key
+typedef struct evp_pkey_st EVP_PKEY;
 
 
 /**
 /**
  * This class records the set of public keys used to verify the signature on a
  * This class records the set of public keys used to verify the signature on a

+ 14 - 0
dtool/src/pystub/pystub.cxx

@@ -90,6 +90,7 @@ extern "C" {
   EXPCL_PYSTUB int PyModule_AddObject(...);
   EXPCL_PYSTUB int PyModule_AddObject(...);
   EXPCL_PYSTUB int PyModule_AddStringConstant(...);
   EXPCL_PYSTUB int PyModule_AddStringConstant(...);
   EXPCL_PYSTUB int PyModule_Create2(...);
   EXPCL_PYSTUB int PyModule_Create2(...);
+  EXPCL_PYSTUB int PyModule_Create2TraceRefs(...);
   EXPCL_PYSTUB int PyNumber_Check(...);
   EXPCL_PYSTUB int PyNumber_Check(...);
   EXPCL_PYSTUB int PyNumber_Float(...);
   EXPCL_PYSTUB int PyNumber_Float(...);
   EXPCL_PYSTUB int PyNumber_Int(...);
   EXPCL_PYSTUB int PyNumber_Int(...);
@@ -175,6 +176,7 @@ extern "C" {
   EXPCL_PYSTUB int Py_InitModule4(...);
   EXPCL_PYSTUB int Py_InitModule4(...);
   EXPCL_PYSTUB int Py_InitModule4_64(...);
   EXPCL_PYSTUB int Py_InitModule4_64(...);
   EXPCL_PYSTUB int Py_InitModule4TraceRefs(...);
   EXPCL_PYSTUB int Py_InitModule4TraceRefs(...);
+  EXPCL_PYSTUB int Py_InitModule4TraceRefs_64(...);
   EXPCL_PYSTUB int _PyArg_ParseTuple_SizeT(...);
   EXPCL_PYSTUB int _PyArg_ParseTuple_SizeT(...);
   EXPCL_PYSTUB int _PyArg_ParseTupleAndKeywords_SizeT(...);
   EXPCL_PYSTUB int _PyArg_ParseTupleAndKeywords_SizeT(...);
   EXPCL_PYSTUB int _PyArg_Parse_SizeT(...);
   EXPCL_PYSTUB int _PyArg_Parse_SizeT(...);
@@ -184,9 +186,14 @@ extern "C" {
   EXPCL_PYSTUB int _PyObject_Del(...);
   EXPCL_PYSTUB int _PyObject_Del(...);
   EXPCL_PYSTUB int _PyUnicode_AsString(...);
   EXPCL_PYSTUB int _PyUnicode_AsString(...);
   EXPCL_PYSTUB int _PyUnicode_AsStringAndSize(...);
   EXPCL_PYSTUB int _PyUnicode_AsStringAndSize(...);
+  EXPCL_PYSTUB int _Py_AddToAllObjects(...);
   EXPCL_PYSTUB int _Py_BuildValue_SizeT(...);
   EXPCL_PYSTUB int _Py_BuildValue_SizeT(...);
   EXPCL_PYSTUB int _Py_Dealloc(...);
   EXPCL_PYSTUB int _Py_Dealloc(...);
+  EXPCL_PYSTUB int _Py_ForgetReference(...);
   EXPCL_PYSTUB int _Py_NegativeRefcount(...);
   EXPCL_PYSTUB int _Py_NegativeRefcount(...);
+  EXPCL_PYSTUB int _Py_NewReference(...);
+  EXPCL_PYSTUB int _Py_PrintReferenceAddresses(...);
+  EXPCL_PYSTUB int _Py_PrintReferences(...);
   EXPCL_PYSTUB int _Py_RefTotal(...);
   EXPCL_PYSTUB int _Py_RefTotal(...);
 
 
   EXPCL_PYSTUB void Py_Initialize();
   EXPCL_PYSTUB void Py_Initialize();
@@ -292,6 +299,7 @@ int PyModule_AddIntConstant(...) { return 0; };
 int PyModule_AddObject(...) { return 0; };
 int PyModule_AddObject(...) { return 0; };
 int PyModule_AddStringConstant(...) { return 0; };
 int PyModule_AddStringConstant(...) { return 0; };
 int PyModule_Create2(...) { return 0; };
 int PyModule_Create2(...) { return 0; };
+int PyModule_Create2TraceRefs(...) { return 0; };
 int PyNumber_Check(...) { return 0; }
 int PyNumber_Check(...) { return 0; }
 int PyNumber_Float(...) { return 0; }
 int PyNumber_Float(...) { return 0; }
 int PyNumber_Int(...) { return 0; }
 int PyNumber_Int(...) { return 0; }
@@ -377,6 +385,7 @@ int Py_BuildValue(...) { return 0; }
 int Py_InitModule4(...) { return 0; }
 int Py_InitModule4(...) { return 0; }
 int Py_InitModule4_64(...) { return 0; }
 int Py_InitModule4_64(...) { return 0; }
 int Py_InitModule4TraceRefs(...) { return 0; };
 int Py_InitModule4TraceRefs(...) { return 0; };
+int Py_InitModule4TraceRefs_64(...) { return 0; };
 int _PyArg_ParseTuple_SizeT(...) { return 0; };
 int _PyArg_ParseTuple_SizeT(...) { return 0; };
 int _PyArg_ParseTupleAndKeywords_SizeT(...) { return 0; };
 int _PyArg_ParseTupleAndKeywords_SizeT(...) { return 0; };
 int _PyArg_Parse_SizeT(...) { return 0; };
 int _PyArg_Parse_SizeT(...) { return 0; };
@@ -386,9 +395,14 @@ int _PyObject_DebugFree(...) { return 0; };
 int _PyObject_Del(...) { return 0; };
 int _PyObject_Del(...) { return 0; };
 int _PyUnicode_AsString(...) { return 0; };
 int _PyUnicode_AsString(...) { return 0; };
 int _PyUnicode_AsStringAndSize(...) { return 0; };
 int _PyUnicode_AsStringAndSize(...) { return 0; };
+int _Py_AddToAllObjects(...) { return 0; };
 int _Py_BuildValue_SizeT(...) { return 0; };
 int _Py_BuildValue_SizeT(...) { return 0; };
 int _Py_Dealloc(...) { return 0; };
 int _Py_Dealloc(...) { return 0; };
+int _Py_ForgetReference(...) { return 0; };
 int _Py_NegativeRefcount(...) { return 0; };
 int _Py_NegativeRefcount(...) { return 0; };
+int _Py_NewReference(...) { return 0; };
+int _Py_PrintReferenceAddresses(...) { return 0; };
+int _Py_PrintReferences(...) { return 0; };
 int _Py_RefTotal(...) { return 0; };
 int _Py_RefTotal(...) { return 0; };
 
 
 // We actually might call this one.
 // We actually might call this one.

+ 0 - 2
makepanda/makepanda.py

@@ -974,9 +974,7 @@ if GetTarget() == 'android':
     DefSymbol("ALWAYS", "ANDROID")
     DefSymbol("ALWAYS", "ANDROID")
 
 
 if not PkgSkip("EIGEN"):
 if not PkgSkip("EIGEN"):
-    DefSymbol("ALWAYS", "EIGEN_MPL2_ONLY")
     if GetOptimize() >= 3:
     if GetOptimize() >= 3:
-        DefSymbol("ALWAYS", "EIGEN_NO_DEBUG")
         if COMPILER == "MSVC":
         if COMPILER == "MSVC":
             # Squeeze out a bit more performance on MSVC builds...
             # Squeeze out a bit more performance on MSVC builds...
             # Only do this if EIGEN_NO_DEBUG is also set, otherwise it
             # Only do this if EIGEN_NO_DEBUG is also set, otherwise it

+ 21 - 73
panda/src/display/displayInformation.cxx

@@ -14,6 +14,13 @@
 #include "graphicsStateGuardian.h"
 #include "graphicsStateGuardian.h"
 #include "displayInformation.h"
 #include "displayInformation.h"
 
 
+// For __rdtsc
+#ifdef _MSC_VER
+#include <intrin.h>
+#elif defined(__GNUC__) && !defined(__clang__)
+#include <x86intrin.h>
+#endif
+
 /**
 /**
  * Returns true if these two DisplayModes are identical.
  * Returns true if these two DisplayModes are identical.
  */
  */
@@ -58,12 +65,6 @@ DisplayInformation::
   if (_display_mode_array != NULL) {
   if (_display_mode_array != NULL) {
     delete[] _display_mode_array;
     delete[] _display_mode_array;
   }
   }
-  if (_cpu_id_data != NULL) {
-    delete _cpu_id_data;
-  }
-  if (_cpu_brand_string != NULL) {
-    delete _cpu_brand_string;
-  }
 }
 }
 
 
 /**
 /**
@@ -134,12 +135,6 @@ DisplayInformation() {
   _driver_date_day = 0;
   _driver_date_day = 0;
   _driver_date_year = 0;
   _driver_date_year = 0;
 
 
-  _cpu_id_version = 1;
-  _cpu_id_size = 0;
-  _cpu_id_data = 0;
-
-  _cpu_vendor_string = 0;
-  _cpu_brand_string = 0;
   _cpu_version_information = 0;
   _cpu_version_information = 0;
   _cpu_brand_index = 0;
   _cpu_brand_index = 0;
 
 
@@ -152,7 +147,6 @@ DisplayInformation() {
   _num_logical_cpus = 0;
   _num_logical_cpus = 0;
 
 
   _get_memory_information_function = 0;
   _get_memory_information_function = 0;
-  _cpu_time_function = 0;
   _update_cpu_frequency_function = 0;
   _update_cpu_frequency_function = 0;
 
 
   _os_version_major = -1;
   _os_version_major = -1;
@@ -493,62 +487,17 @@ get_driver_date_year() {
 /**
 /**
  *
  *
  */
  */
-int DisplayInformation::
-get_cpu_id_version() {
-  return _cpu_id_version;
-}
-
-/**
- * Returns the number of 32-bit values for cpu id binary data.
- */
-int DisplayInformation::
-get_cpu_id_size() {
-  return _cpu_id_size;
-}
-
-/**
- * Returns part of cpu id binary data based on the index.
- */
-unsigned int DisplayInformation::
-get_cpu_id_data(int index) {
-  unsigned int data;
-
-  data = 0;
-  if (index >= 0 && index < _cpu_id_size) {
-    data = _cpu_id_data [index];
-  }
-
-  return data;
+const string &DisplayInformation::
+get_cpu_vendor_string() const {
+  return _cpu_vendor_string;
 }
 }
 
 
 /**
 /**
  *
  *
  */
  */
-const char *DisplayInformation::
-get_cpu_vendor_string() {
-  const char *string;
-
-  string = _cpu_vendor_string;
-  if (string == 0) {
-    string = "";
-  }
-
-  return string;
-}
-
-/**
- *
- */
-const char *DisplayInformation::
-get_cpu_brand_string() {
-  const char *string;
-
-  string = _cpu_brand_string;
-  if (string == 0) {
-    string = "";
-  }
-
-  return string;
+const string &DisplayInformation::
+get_cpu_brand_string() const {
+  return _cpu_brand_string;
 }
 }
 
 
 /**
 /**
@@ -576,18 +525,17 @@ get_cpu_frequency() {
 }
 }
 
 
 /**
 /**
- *
+ * Equivalent to the rdtsc processor instruction.
  */
  */
 uint64_t DisplayInformation::
 uint64_t DisplayInformation::
 get_cpu_time() {
 get_cpu_time() {
-  uint64_t cpu_time;
-
-  cpu_time = 0;
-  if (_cpu_time_function) {
-    cpu_time = _cpu_time_function();
-  }
-
-  return cpu_time;
+#if defined(_MSC_VER) || (defined(__GNUC__) && !defined(__clang__))
+  return __rdtsc();
+#else
+  unsigned int lo, hi = 0;
+  __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+  return ((uint64_t)hi << 32) | lo;
+#endif
 }
 }
 
 
 /**
 /**

+ 5 - 13
panda/src/display/displayInformation.h

@@ -94,17 +94,13 @@ PUBLISHED:
   int get_driver_date_day();
   int get_driver_date_day();
   int get_driver_date_year();
   int get_driver_date_year();
 
 
-  int get_cpu_id_version();
-  int get_cpu_id_size();
-  unsigned int get_cpu_id_data(int index);
-
-  const char *get_cpu_vendor_string();
-  const char *get_cpu_brand_string();
+  const string &get_cpu_vendor_string() const;
+  const string &get_cpu_brand_string() const;
   unsigned int get_cpu_version_information();
   unsigned int get_cpu_version_information();
   unsigned int get_cpu_brand_index();
   unsigned int get_cpu_brand_index();
 
 
   uint64_t get_cpu_frequency();
   uint64_t get_cpu_frequency();
-  uint64_t get_cpu_time();
+  static uint64_t get_cpu_time();
 
 
   uint64_t get_maximum_cpu_frequency();
   uint64_t get_maximum_cpu_frequency();
   uint64_t get_current_cpu_frequency();
   uint64_t get_current_cpu_frequency();
@@ -158,12 +154,9 @@ public:
   int _driver_date_day;
   int _driver_date_day;
   int _driver_date_year;
   int _driver_date_year;
 
 
-  int _cpu_id_version;
-  int _cpu_id_size;
-  unsigned int *_cpu_id_data;
 
 
-  char *_cpu_vendor_string;
-  char *_cpu_brand_string;
+  string _cpu_vendor_string;
+  string _cpu_brand_string;
   unsigned int _cpu_version_information;
   unsigned int _cpu_version_information;
   unsigned int _cpu_brand_index;
   unsigned int _cpu_brand_index;
 
 
@@ -176,7 +169,6 @@ public:
   int _num_logical_cpus;
   int _num_logical_cpus;
 
 
   void (*_get_memory_information_function) (DisplayInformation *display_information);
   void (*_get_memory_information_function) (DisplayInformation *display_information);
-  uint64_t (*_cpu_time_function) (void);
   int (*_update_cpu_frequency_function) (int processor_number, DisplayInformation *display_information);
   int (*_update_cpu_frequency_function) (int processor_number, DisplayInformation *display_information);
 
 
   int _os_version_major;
   int _os_version_major;

+ 6 - 0
panda/src/display/displayRegion.cxx

@@ -491,6 +491,12 @@ get_screenshot() {
     return NULL;
     return NULL;
   }
   }
 
 
+  {
+    // Make sure that the correct viewport is active.
+    DisplayRegionPipelineReader dr_reader(this, current_thread);
+    gsg->prepare_display_region(&dr_reader);
+  }
+
   PT(Texture) tex = new Texture;
   PT(Texture) tex = new Texture;
 
 
   RenderBuffer buffer = gsg->get_render_buffer(get_screenshot_buffer_type(),
   RenderBuffer buffer = gsg->get_render_buffer(get_screenshot_buffer_type(),

+ 67 - 95
panda/src/display/graphicsEngine.cxx

@@ -1328,21 +1328,24 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
   GraphicsStateGuardian *gsg = win->get_gsg();
   GraphicsStateGuardian *gsg = win->get_gsg();
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
   nassertv(gsg != (GraphicsStateGuardian *)NULL);
 
 
-  DisplayRegionPipelineReader *dr_reader =
-    new DisplayRegionPipelineReader(dr, current_thread);
+  PT(SceneSetup) scene_setup;
+
+  {
+    DisplayRegionPipelineReader dr_reader(dr, current_thread);
+    win->change_scenes(&dr_reader);
+    gsg->prepare_display_region(&dr_reader);
 
 
-  win->change_scenes(dr_reader);
-  gsg->prepare_display_region(dr_reader);
+    if (dr_reader.is_any_clear_active()) {
+      gsg->clear(dr);
+    }
 
 
-  if (dr_reader->is_any_clear_active()) {
-    gsg->clear(dr);
+    scene_setup = setup_scene(gsg, &dr_reader);
   }
   }
 
 
-  PT(SceneSetup) scene_setup = setup_scene(gsg, dr_reader);
   if (scene_setup == (SceneSetup *)NULL) {
   if (scene_setup == (SceneSetup *)NULL) {
     // Never mind.
     // Never mind.
 
 
-  } else if (dr_reader->get_object()->is_stereo()) {
+  } else if (dr->is_stereo()) {
     // Don't draw stereo DisplayRegions directly.
     // Don't draw stereo DisplayRegions directly.
 
 
   } else if (!gsg->set_scene(scene_setup)) {
   } else if (!gsg->set_scene(scene_setup)) {
@@ -1353,9 +1356,6 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
   } else {
   } else {
     DrawCullHandler cull_handler(gsg);
     DrawCullHandler cull_handler(gsg);
     if (gsg->begin_scene()) {
     if (gsg->begin_scene()) {
-      delete dr_reader;
-      dr_reader = NULL;
-
       CallbackObject *cbobj = dr->get_cull_callback();
       CallbackObject *cbobj = dr->get_cull_callback();
       if (cbobj != (CallbackObject *)NULL) {
       if (cbobj != (CallbackObject *)NULL) {
         // Issue the cull callback on this DisplayRegion.
         // Issue the cull callback on this DisplayRegion.
@@ -1372,10 +1372,6 @@ cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr,
       gsg->end_scene();
       gsg->end_scene();
     }
     }
   }
   }
-
-  if (dr_reader != (DisplayRegionPipelineReader *)NULL) {
-    delete dr_reader;
-  }
 }
 }
 
 
 /**
 /**
@@ -1399,27 +1395,41 @@ cull_to_bins(const 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()) {
+      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();
       for (int i = 0; i < num_display_regions; ++i) {
       for (int i = 0; i < num_display_regions; ++i) {
         DisplayRegion *dr = win->get_active_display_region(i);
         DisplayRegion *dr = win->get_active_display_region(i);
-        if (dr != (DisplayRegion *)NULL) {
-          DisplayRegionPipelineReader *dr_reader =
-            new DisplayRegionPipelineReader(dr, current_thread);
-
+        if (dr != nullptr) {
+          PT(SceneSetup) scene_setup;
+          PT(CullResult) cull_result;
           CullKey key;
           CullKey key;
-          key._gsg = win->get_gsg();
-          key._camera = dr_reader->get_camera();
-          key._lens_index = dr_reader->get_lens_index();
+          {
+            PStatTimer timer(_cull_setup_pcollector, current_thread);
+            DisplayRegionPipelineReader dr_reader(dr, current_thread);
+            scene_setup = setup_scene(gsg, &dr_reader);
+            if (scene_setup == nullptr) {
+              continue;
+            }
+
+            key._gsg = gsg;
+            key._camera = dr_reader.get_camera();
+            key._lens_index = dr_reader.get_lens_index();
+          }
 
 
-          AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(key, (DisplayRegion *)NULL)).first;
-          if ((*aci).second == NULL) {
+          AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(move(key), nullptr)).first;
+          if ((*aci).second == nullptr) {
             // We have not used this camera already in this thread.  Perform
             // We have not used this camera already in this thread.  Perform
             // the cull operation.
             // the cull operation.
-            delete dr_reader;
-            dr_reader = NULL;
+            cull_result = dr->get_cull_result(current_thread);
+            if (cull_result != nullptr) {
+              cull_result = cull_result->make_next();
+            } else {
+              // This DisplayRegion has no cull results; draw it.
+              cull_result = new CullResult(gsg, dr->get_draw_region_pcollector());
+            }
             (*aci).second = dr;
             (*aci).second = dr;
-            cull_to_bins(win, dr, current_thread);
+            cull_to_bins(win, gsg, dr, scene_setup, cull_result, current_thread);
 
 
           } else {
           } else {
             // We have already culled a scene using this camera in this
             // We have already culled a scene using this camera in this
@@ -1429,14 +1439,11 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
             // image.)  Of course, the cull result will be the same, so just
             // image.)  Of course, the cull result will be the same, so just
             // use the result from the other DisplayRegion.
             // use the result from the other DisplayRegion.
             DisplayRegion *other_dr = (*aci).second;
             DisplayRegion *other_dr = (*aci).second;
-            dr->set_cull_result(other_dr->get_cull_result(current_thread),
-                                setup_scene(win->get_gsg(), dr_reader),
-                                current_thread);
+            cull_result = other_dr->get_cull_result(current_thread);
           }
           }
 
 
-          if (dr_reader != (DisplayRegionPipelineReader *)NULL) {
-            delete dr_reader;
-          }
+          // Save the results for next frame.
+          dr->set_cull_result(MOVE(cull_result), MOVE(scene_setup), current_thread);
         }
         }
       }
       }
     }
     }
@@ -1447,50 +1454,26 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
  * Called only within the inner loop of cull_to_bins(), above.
  * Called only within the inner loop of cull_to_bins(), above.
  */
  */
 void GraphicsEngine::
 void GraphicsEngine::
-cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
-  GraphicsStateGuardian *gsg = win->get_gsg();
-  if (gsg == (GraphicsStateGuardian *)NULL) {
-    return;
-  }
-
-  PT(CullResult) cull_result;
-  PT(SceneSetup) scene_setup;
-  {
-    PStatTimer timer(_cull_setup_pcollector, current_thread);
-    DisplayRegionPipelineReader dr_reader(dr, current_thread);
-    scene_setup = setup_scene(gsg, &dr_reader);
-    cull_result = dr->get_cull_result(current_thread);
-
-    if (cull_result != (CullResult *)NULL) {
-      cull_result = cull_result->make_next();
+cull_to_bins(GraphicsOutput *win, GraphicsStateGuardian *gsg,
+             DisplayRegion *dr, SceneSetup *scene_setup,
+             CullResult *cull_result, Thread *current_thread) {
 
 
-    } else {
-      // This DisplayRegion has no cull results; draw it.
-      cull_result = new CullResult(gsg, dr->get_draw_region_pcollector());
-    }
-  }
-
-  if (scene_setup != (SceneSetup *)NULL) {
-    BinCullHandler cull_handler(cull_result);
-    CallbackObject *cbobj = dr->get_cull_callback();
-    if (cbobj != (CallbackObject *)NULL) {
-      // Issue the cull callback on this DisplayRegion.
-      DisplayRegionCullCallbackData cbdata(&cull_handler, scene_setup);
-      cbobj->do_callback(&cbdata);
+  BinCullHandler cull_handler(cull_result);
+  CallbackObject *cbobj = dr->get_cull_callback();
+  if (cbobj != (CallbackObject *)NULL) {
+    // Issue the cull callback on this DisplayRegion.
+    DisplayRegionCullCallbackData cbdata(&cull_handler, scene_setup);
+    cbobj->do_callback(&cbdata);
 
 
-      // The callback has taken care of the culling.
+    // The callback has taken care of the culling.
 
 
-    } else {
-      // Perform the cull normally.
-      dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
-    }
-
-    PStatTimer timer(_cull_sort_pcollector, current_thread);
-    cull_result->finish_cull(scene_setup, current_thread);
+  } else {
+    // Perform the cull normally.
+    dr->do_cull(&cull_handler, scene_setup, gsg, current_thread);
   }
   }
 
 
-  // Save the results for next frame.
-  dr->set_cull_result(MOVE(cull_result), MOVE(scene_setup), current_thread);
+  PStatTimer timer(_cull_sort_pcollector, current_thread);
+  cull_result->finish_cull(scene_setup, current_thread);
 }
 }
 
 
 /**
 /**
@@ -1538,7 +1521,7 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
           for (int i = 0; i < num_display_regions; ++i) {
           for (int i = 0; i < num_display_regions; ++i) {
             DisplayRegion *dr = win->get_active_display_region(i);
             DisplayRegion *dr = win->get_active_display_region(i);
             if (dr != (DisplayRegion *)NULL) {
             if (dr != (DisplayRegion *)NULL) {
-              draw_bins(win, dr, current_thread);
+              do_draw(win, gsg, dr, current_thread);
             }
             }
           }
           }
         }
         }
@@ -1582,22 +1565,6 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   }
   }
 }
 }
 
 
-/**
- * This variant on draw_bins() is only called from draw_bins(), above.  It
- * draws the cull result for a particular DisplayRegion.
- */
-void GraphicsEngine::
-draw_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
-  GraphicsStateGuardian *gsg = win->get_gsg();
-  if (gsg == (GraphicsStateGuardian *)NULL) {
-    return;
-  }
-
-  PT(CullResult) cull_result = dr->get_cull_result(current_thread);
-  PT(SceneSetup) scene_setup = dr->get_scene_setup(current_thread);
-  do_draw(cull_result, scene_setup, win, dr, current_thread);
-}
-
 /**
 /**
  * Called in the draw thread, this calls make_context() on each window on the
  * Called in the draw thread, this calls make_context() on each window on the
  * list to guarantee its gsg and graphics context both get created.
  * list to guarantee its gsg and graphics context both get created.
@@ -1899,15 +1866,20 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
  * Draws the previously-culled scene.
  * Draws the previously-culled scene.
  */
  */
 void GraphicsEngine::
 void GraphicsEngine::
-do_draw(CullResult *cull_result, SceneSetup *scene_setup,
-        GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread) {
-
-  CallbackObject *cbobj;
-  GraphicsStateGuardian *gsg = win->get_gsg();
-
+do_draw(GraphicsOutput *win, GraphicsStateGuardian *gsg, DisplayRegion *dr, Thread *current_thread) {
   // Statistics
   // Statistics
   PStatGPUTimer timer(gsg, dr->get_draw_region_pcollector(), current_thread);
   PStatGPUTimer timer(gsg, dr->get_draw_region_pcollector(), current_thread);
 
 
+  PT(CullResult) cull_result;
+  PT(SceneSetup) scene_setup;
+  {
+    DisplayRegion::CDCullReader cdata(dr->_cycler_cull, current_thread);
+    cull_result = cdata->_cull_result;
+    scene_setup = cdata->_scene_setup;
+  }
+
+  CallbackObject *cbobj;
+
   {
   {
     DisplayRegionPipelineReader dr_reader(dr, current_thread);
     DisplayRegionPipelineReader dr_reader(dr, current_thread);
     win->change_scenes(&dr_reader);
     win->change_scenes(&dr_reader);

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

@@ -147,9 +147,10 @@ private:
                               Thread *current_thread);
                               Thread *current_thread);
 
 
   void cull_to_bins(const Windows &wlist, Thread *current_thread);
   void cull_to_bins(const Windows &wlist, Thread *current_thread);
-  void cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
+  void cull_to_bins(GraphicsOutput *win, GraphicsStateGuardian *gsg,
+                    DisplayRegion *dr, SceneSetup *scene_setup,
+                    CullResult *cull_result, Thread *current_thread);
   void draw_bins(const Windows &wlist, Thread *current_thread);
   void draw_bins(const Windows &wlist, Thread *current_thread);
-  void draw_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
   void make_contexts(const Windows &wlist, Thread *current_thread);
   void make_contexts(const Windows &wlist, Thread *current_thread);
 
 
   void process_events(const Windows &wlist, Thread *current_thread);
   void process_events(const Windows &wlist, Thread *current_thread);
@@ -162,8 +163,8 @@ private:
 
 
   PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg,
   PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg,
                              DisplayRegionPipelineReader *dr);
                              DisplayRegionPipelineReader *dr);
-  void do_draw(CullResult *cull_result, SceneSetup *scene_setup,
-               GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
+  void do_draw(GraphicsOutput *win, GraphicsStateGuardian *gsg,
+               DisplayRegion *dr, Thread *current_thread);
 
 
   void do_add_window(GraphicsOutput *window,
   void do_add_window(GraphicsOutput *window,
                      const GraphicsThreadingModel &threading_model);
                      const GraphicsThreadingModel &threading_model);

+ 154 - 16
panda/src/display/graphicsPipe.cxx

@@ -18,6 +18,89 @@
 #include "mutexHolder.h"
 #include "mutexHolder.h"
 #include "displayInformation.h"
 #include "displayInformation.h"
 
 
+#ifdef IS_LINUX
+#include <sys/sysinfo.h>
+#include <unistd.h>
+#endif
+
+#if defined(IS_OSX) || defined(IS_FREEBSD)
+#include <sys/sysctl.h>
+#include <unistd.h>
+#endif
+
+#if defined(__GNUC__) && !defined(__APPLE__)
+// GCC and Clang offer a useful cpuid.h header.
+#include <cpuid.h>
+#endif
+
+#ifdef _MSC_VER
+// MSVC has a __cpuid intrinsic.
+#include <intrin.h>
+#endif
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+#endif
+
+union cpuid_info {
+  char str[16];
+  struct {
+    uint32_t eax, ebx, ecx, edx;
+  };
+};
+
+/**
+ * Returns the highest cpuid leaf that is supported by the CPU.
+ */
+static inline uint32_t get_cpuid_max(uint32_t leaf) {
+#if defined(__GNUC__) && !defined(__APPLE__)
+  return __get_cpuid_max(leaf, 0);
+#elif defined(_MSC_VER)
+  uint32_t p[4] = {0};
+  __cpuid((int *)p, leaf);
+  return p[0];
+#else
+  unsigned int eax = 0;
+  __asm__ ("cpuid\n\t"
+           : "=a" (eax)
+           : "0" (leaf));
+  return eax;
+#endif
+}
+
+/**
+ * Gets cpuid info for the given leaf.
+ */
+static inline void get_cpuid(uint32_t leaf, cpuid_info &info) {
+#if defined(__GNUC__) && !defined(__APPLE__)
+  __cpuid(leaf, info.eax, info.ebx, info.ecx, info.edx);
+#elif defined(_MSC_VER)
+  __cpuid((int *)info.str, leaf);
+#else
+  __asm__ ("cpuid\n\t"
+           : "=a" (info.eax), "=b" (info.ebx), "=c" (info.ecx), "=d" (info.edx)
+           : "0" (leaf));
+#endif
+}
+
+#ifdef IS_LINUX
+/**
+ * Updates the current memory usage statistics in the DisplayInformation.
+ */
+static void update_memory_info(DisplayInformation *info) {
+  struct sysinfo meminfo;
+  if (sysinfo(&meminfo) == 0) {
+    info->_physical_memory = meminfo.totalram;
+    info->_available_physical_memory = meminfo.freeram;
+    info->_page_file_size = meminfo.totalswap;
+    info->_available_page_file_size = meminfo.freeswap;
+  }
+}
+#endif
+
 TypeHandle GraphicsPipe::_type_handle;
 TypeHandle GraphicsPipe::_type_handle;
 
 
 /**
 /**
@@ -38,24 +121,79 @@ GraphicsPipe() :
   _display_width = 0;
   _display_width = 0;
   _display_height = 0;
   _display_height = 0;
 
 
-  _display_information = new DisplayInformation ( );
-}
+  _display_information = new DisplayInformation();
 
 
-/**
- * Don't try to copy GraphicsPipes.
- */
-GraphicsPipe::
-GraphicsPipe(const GraphicsPipe &) {
-  _is_valid = false;
-  nassertv(false);
-}
+  cpuid_info info;
+  const uint32_t max_cpuid = get_cpuid_max(0);
+  const uint32_t max_extended = get_cpuid_max(0x80000000);
 
 
-/**
- * Don't try to copy GraphicsPipes.
- */
-void GraphicsPipe::
-operator = (const GraphicsPipe &) {
-  nassertv(false);
+  if (max_cpuid >= 1) {
+    get_cpuid(0, info);
+    swap(info.ecx, info.edx);
+    _display_information->_cpu_vendor_string = string(info.str + 4, 12);
+
+    get_cpuid(1, info);
+    _display_information->_cpu_version_information = info.eax;
+    _display_information->_cpu_brand_index = info.ebx & 0xff;
+  }
+
+  if (max_extended >= 0x80000004) {
+    char brand[49];
+    get_cpuid(0x80000002, info);
+    memcpy(brand, info.str, 16);
+    get_cpuid(0x80000003, info);
+    memcpy(brand + 16, info.str, 16);
+    get_cpuid(0x80000004, info);
+    memcpy(brand + 32, info.str, 16);
+    brand[48] = 0;
+    _display_information->_cpu_brand_string = brand;
+  }
+
+#if defined(IS_OSX)
+  // macOS exposes a lot of useful information through sysctl.
+  size_t len = sizeof(uint64_t);
+  sysctlbyname("hw.memsize", &_display_information->_physical_memory, &len, NULL, 0);
+  len = sizeof(uint64_t);
+  sysctlbyname("hw.cpufrequency", &_display_information->_cpu_frequency, &len, NULL, 0);
+  len = sizeof(uint64_t);
+  sysctlbyname("hw.cpufrequency", &_display_information->_current_cpu_frequency, &len, NULL, 0);
+  len = sizeof(uint64_t);
+  sysctlbyname("hw.cpufrequency_max", &_display_information->_maximum_cpu_frequency, &len, NULL, 0);
+  len = sizeof(int);
+  sysctlbyname("hw.physicalcpu", &_display_information->_num_cpu_cores, &len, NULL, 0);
+  len = sizeof(int);
+  sysctlbyname("hw.logicalcpu", &_display_information->_num_logical_cpus, &len, NULL, 0);
+
+#elif defined(IS_LINUX)
+  _display_information->_get_memory_information_function = &update_memory_info;
+  update_memory_info(_display_information);
+
+#elif defined(IS_FREEBSD)
+  size_t len = sizeof(uint64_t);
+  sysctlbyname("hw.physmem", &_display_information->_physical_memory, &len, NULL, 0);
+  len = sizeof(uint64_t);
+  sysctlbyname("vm.swap_total", &_display_information->_page_file_size, &len, NULL, 0);
+
+#elif defined(_WIN32)
+  MEMORYSTATUSEX status;
+  status.dwLength = sizeof(MEMORYSTATUSEX);
+  if (GlobalMemoryStatusEx(&status)) {
+    _display_information->_physical_memory = status.ullTotalPhys;
+    _display_information->_available_physical_memory = status.ullAvailPhys;
+    _display_information->_page_file_size = status.ullTotalPageFile;
+    _display_information->_available_page_file_size = status.ullAvailPageFile;
+    _display_information->_process_virtual_memory = status.ullTotalVirtual;
+    _display_information->_available_process_virtual_memory = status.ullAvailVirtual;
+    _display_information->_memory_load = status.dwMemoryLoad;
+  }
+#endif
+
+#if defined(IS_LINUX) || defined(IS_FREEBSD)
+  long nproc = sysconf(_SC_NPROCESSORS_CONF);
+  if (nproc > 0) {
+    _display_information->_num_logical_cpus = nproc;
+  }
+#endif
 }
 }
 
 
 /**
 /**

+ 2 - 2
panda/src/display/graphicsPipe.h

@@ -53,8 +53,8 @@ class EXPCL_PANDA_DISPLAY GraphicsPipe : public TypedReferenceCount {
 protected:
 protected:
   GraphicsPipe();
   GraphicsPipe();
 private:
 private:
-  GraphicsPipe(const GraphicsPipe &copy);
-  void operator = (const GraphicsPipe &copy);
+  GraphicsPipe(const GraphicsPipe &copy) DELETED;
+  GraphicsPipe &operator = (const GraphicsPipe &copy) DELETED_ASSIGN;
 
 
 PUBLISHED:
 PUBLISHED:
   virtual ~GraphicsPipe();
   virtual ~GraphicsPipe();

+ 8 - 0
panda/src/display/graphicsStateGuardian.I

@@ -538,6 +538,14 @@ get_supports_depth_stencil() const {
   return _supports_depth_stencil;
   return _supports_depth_stencil;
 }
 }
 
 
+/**
+ * Returns true if this particular GSG supports luminance textures.
+ */
+INLINE bool GraphicsStateGuardian::
+get_supports_luminance_texture() const {
+  return _supports_luminance_texture;
+}
+
 /**
 /**
  * Returns true if this particular GSG supports the filter mode FT_shadow for
  * Returns true if this particular GSG supports the filter mode FT_shadow for
  * depth textures.
  * depth textures.

+ 3 - 0
panda/src/display/graphicsStateGuardian.cxx

@@ -253,6 +253,9 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
   _supports_geometry_instancing = false;
   _supports_geometry_instancing = false;
   _supports_indirect_draw = false;
   _supports_indirect_draw = false;
 
 
+  // We are safe assuming it has luminance support
+  _supports_luminance_texture = true;
+
   // Assume a maximum of 1 render target in absence of MRT.
   // Assume a maximum of 1 render target in absence of MRT.
   _max_color_targets = 1;
   _max_color_targets = 1;
   _supports_dual_source_blending = false;
   _supports_dual_source_blending = false;

+ 3 - 0
panda/src/display/graphicsStateGuardian.h

@@ -154,6 +154,7 @@ PUBLISHED:
   INLINE bool get_supports_generate_mipmap() const;
   INLINE bool get_supports_generate_mipmap() const;
   INLINE bool get_supports_depth_texture() const;
   INLINE bool get_supports_depth_texture() const;
   INLINE bool get_supports_depth_stencil() const;
   INLINE bool get_supports_depth_stencil() const;
+  INLINE bool get_supports_luminance_texture() const;
   INLINE bool get_supports_shadow_filter() const;
   INLINE bool get_supports_shadow_filter() const;
   INLINE bool get_supports_sampler_objects() const;
   INLINE bool get_supports_sampler_objects() const;
   INLINE bool get_supports_basic_shaders() const;
   INLINE bool get_supports_basic_shaders() const;
@@ -203,6 +204,7 @@ PUBLISHED:
   MAKE_PROPERTY(supports_generate_mipmap, get_supports_generate_mipmap);
   MAKE_PROPERTY(supports_generate_mipmap, get_supports_generate_mipmap);
   MAKE_PROPERTY(supports_depth_texture, get_supports_depth_texture);
   MAKE_PROPERTY(supports_depth_texture, get_supports_depth_texture);
   MAKE_PROPERTY(supports_depth_stencil, get_supports_depth_stencil);
   MAKE_PROPERTY(supports_depth_stencil, get_supports_depth_stencil);
+  MAKE_PROPERTY(supports_luminance_texture, get_supports_luminance_texture);
   MAKE_PROPERTY(supports_shadow_filter, get_supports_shadow_filter);
   MAKE_PROPERTY(supports_shadow_filter, get_supports_shadow_filter);
   MAKE_PROPERTY(supports_sampler_objects, get_supports_sampler_objects);
   MAKE_PROPERTY(supports_sampler_objects, get_supports_sampler_objects);
   MAKE_PROPERTY(supports_basic_shaders, get_supports_basic_shaders);
   MAKE_PROPERTY(supports_basic_shaders, get_supports_basic_shaders);
@@ -597,6 +599,7 @@ protected:
   bool _supports_generate_mipmap;
   bool _supports_generate_mipmap;
   bool _supports_depth_texture;
   bool _supports_depth_texture;
   bool _supports_depth_stencil;
   bool _supports_depth_stencil;
+  bool _supports_luminance_texture;
   bool _supports_shadow_filter;
   bool _supports_shadow_filter;
   bool _supports_sampler_objects;
   bool _supports_sampler_objects;
   bool _supports_basic_shaders;
   bool _supports_basic_shaders;

+ 0 - 8
panda/src/downloader/bioPtr.I

@@ -18,14 +18,6 @@ INLINE BioPtr::
 BioPtr(BIO *bio) : _bio(bio) {
 BioPtr(BIO *bio) : _bio(bio) {
 }
 }
 
 
-/**
- *
- */
-INLINE bool BioPtr::
-should_retry() const {
-  return (_bio != NULL) && BIO_should_retry(_bio);
-}
-
 /**
 /**
  *
  *
  */
  */

+ 12 - 1
panda/src/downloader/bioPtr.cxx

@@ -18,6 +18,9 @@
 #include "urlSpec.h"
 #include "urlSpec.h"
 #include "config_downloader.h"
 #include "config_downloader.h"
 
 
+#include "openSSLWrapper.h"  // must be included before any other openssl.
+#include "openssl/ssl.h"
+
 #ifdef _WIN32
 #ifdef _WIN32
 #include <winsock2.h>
 #include <winsock2.h>
 #else
 #else
@@ -199,7 +202,7 @@ connect() {
 
 
     if (result != 0 && BIO_sock_should_retry(-1)) {
     if (result != 0 && BIO_sock_should_retry(-1)) {
       // It's still in progress; we should retry later.  This causes
       // It's still in progress; we should retry later.  This causes
-      // should_reply() to return true.
+      // should_retry() to return true.
       BIO_set_flags(_bio, BIO_FLAGS_SHOULD_RETRY);
       BIO_set_flags(_bio, BIO_FLAGS_SHOULD_RETRY);
       _connecting = true;
       _connecting = true;
       return false;
       return false;
@@ -218,6 +221,14 @@ connect() {
   return true;
   return true;
 }
 }
 
 
+/**
+ *
+ */
+bool BioPtr::
+should_retry() const {
+  return (_bio != NULL) && BIO_should_retry(_bio);
+}
+
 /**
 /**
  *
  *
  */
  */

+ 3 - 7
panda/src/downloader/bioPtr.h

@@ -19,13 +19,7 @@
 // This module is not compiled if OpenSSL is not available.
 // This module is not compiled if OpenSSL is not available.
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
-#ifndef OPENSSL_NO_KRB5
-#define OPENSSL_NO_KRB5
-#endif
-
 #include "referenceCount.h"
 #include "referenceCount.h"
-#include "openSSLWrapper.h"  // must be included before any other openssl.
-#include "openssl/ssl.h"
 
 
 #ifdef _WIN32
 #ifdef _WIN32
 #include <winsock2.h>
 #include <winsock2.h>
@@ -35,6 +29,8 @@
 #include <netinet/in.h>
 #include <netinet/in.h>
 #endif
 #endif
 
 
+typedef struct bio_st BIO;
+
 class URLSpec;
 class URLSpec;
 
 
 /**
 /**
@@ -52,7 +48,7 @@ public:
   void set_nbio(bool nbio);
   void set_nbio(bool nbio);
   bool connect();
   bool connect();
 
 
-  INLINE bool should_retry() const;
+  bool should_retry() const;
 
 
   INLINE BIO &operator *() const;
   INLINE BIO &operator *() const;
   INLINE BIO *operator -> () const;
   INLINE BIO *operator -> () const;

+ 0 - 6
panda/src/downloader/bioStreamBuf.h

@@ -19,14 +19,8 @@
 // This module is not compiled if OpenSSL is not available.
 // This module is not compiled if OpenSSL is not available.
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
-#ifndef OPENSSL_NO_KRB5
-#define OPENSSL_NO_KRB5
-#endif
-
 #include "bioPtr.h"
 #include "bioPtr.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
-#include "openSSLWrapper.h"  // must be included before any other openssl.
-#include "openssl/ssl.h"
 
 
 /**
 /**
  * The streambuf object that implements IBioStream.
  * The streambuf object that implements IBioStream.

+ 0 - 6
panda/src/downloader/bioStreamPtr.h

@@ -19,14 +19,8 @@
 // This module is not compiled if OpenSSL is not available.
 // This module is not compiled if OpenSSL is not available.
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
-#ifndef OPENSSL_NO_KRB5
-#define OPENSSL_NO_KRB5
-#endif
-
 #include "bioStream.h"
 #include "bioStream.h"
 #include "referenceCount.h"
 #include "referenceCount.h"
-#include "openSSLWrapper.h"  // must be included before any other openssl.
-#include "openssl/ssl.h"
 
 
 /**
 /**
  * A wrapper around an BioStream object to make a reference-counting pointer
  * A wrapper around an BioStream object to make a reference-counting pointer

+ 10 - 0
panda/src/downloader/httpChannel.cxx

@@ -27,6 +27,8 @@
 
 
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
+#include "openSSLWrapper.h"
+
 #if defined(WIN32_VC) || defined(WIN64_VC)
 #if defined(WIN32_VC) || defined(WIN64_VC)
   #include <WinSock2.h>
   #include <WinSock2.h>
   #include <windows.h>  // for select()
   #include <windows.h>  // for select()
@@ -1474,6 +1476,14 @@ run_setup_ssl() {
     return false;
     return false;
   }
   }
 
 
+  string hostname = _request.get_url().get_server();
+  result = SSL_set_tlsext_host_name(ssl, hostname.c_str());
+  if (result == 0) {
+    downloader_cat.error()
+      << _NOTIFY_HTTP_CHANNEL_ID
+      << "Could not set TLS SNI hostname to '" << hostname << "'\n";
+  }
+
 /*
 /*
  * It would be nice to use something like SSL_set_client_cert_cb() here to set
  * It would be nice to use something like SSL_set_client_cert_cb() here to set
  * a callback to provide the certificate should it be requested, or even to
  * a callback to provide the certificate should it be requested, or even to

+ 2 - 6
panda/src/downloader/httpChannel.h

@@ -22,10 +22,6 @@
 
 
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
-#ifndef OPENSSL_NO_KRB5
-#define OPENSSL_NO_KRB5
-#endif
-
 #include "httpClient.h"
 #include "httpClient.h"
 #include "httpEnum.h"
 #include "httpEnum.h"
 #include "urlSpec.h"
 #include "urlSpec.h"
@@ -37,10 +33,10 @@
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "config_downloader.h"
 #include "config_downloader.h"
 #include "filename.h"
 #include "filename.h"
-#include "openSSLWrapper.h"  // must be included before any other openssl.
-#include "openssl/ssl.h"
 #include "typedReferenceCount.h"
 #include "typedReferenceCount.h"
 
 
+typedef struct bio_st BIO;
+
 class Ramfile;
 class Ramfile;
 class HTTPClient;
 class HTTPClient;
 
 

+ 64 - 62
panda/src/downloader/httpClient.cxx

@@ -24,6 +24,8 @@
 
 
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 
 
+#include "openSSLWrapper.h"
+
 PT(HTTPClient) HTTPClient::_global_ptr;
 PT(HTTPClient) HTTPClient::_global_ptr;
 
 
 /**
 /**
@@ -68,6 +70,68 @@ tokenize(const string &str, vector_string &words, const string &delimiters) {
   words.push_back(string());
   words.push_back(string());
 }
 }
 
 
+#ifndef NDEBUG
+/**
+ * This method is attached as a callback for SSL messages only when debug
+ * output is enabled.
+ */
+static void
+ssl_msg_callback(int write_p, int version, int content_type,
+                 const void *, size_t len, SSL *, void *) {
+  ostringstream describe;
+  if (write_p) {
+    describe << "sent ";
+  } else {
+    describe << "received ";
+  }
+  switch (version) {
+  case SSL2_VERSION:
+    describe << "SSL 2.0 ";
+    break;
+
+  case SSL3_VERSION:
+    describe << "SSL 3.0 ";
+    break;
+
+  case TLS1_VERSION:
+    describe << "TLS 1.0 ";
+    break;
+
+  default:
+    describe << "unknown protocol ";
+  }
+
+  describe << "message: ";
+
+  if (version != SSL2_VERSION) {
+    switch (content_type) {
+    case 20:
+      describe << "change cipher spec, ";
+      break;
+
+    case 21:
+      describe << "alert, ";
+      break;
+
+    case 22:
+      describe << "handshake, ";
+      break;
+
+    case 23:
+      describe << "application data, ";
+      break;
+
+    default:
+      describe << "unknown content type, ";
+    }
+  }
+
+  describe << len << " bytes.\n";
+
+  downloader_cat.debug() << describe.str();
+}
+#endif  // !defined(NDEBUG)
+
 /**
 /**
  *
  *
  */
  */
@@ -1564,68 +1628,6 @@ split_whitespace(string &a, string &b, const string &c) {
   b = c.substr(p);
   b = c.substr(p);
 }
 }
 
 
-#ifndef NDEBUG
-/**
- * This method is attached as a callback for SSL messages only when debug
- * output is enabled.
- */
-void HTTPClient::
-ssl_msg_callback(int write_p, int version, int content_type,
-                 const void *, size_t len, SSL *, void *) {
-  ostringstream describe;
-  if (write_p) {
-    describe << "sent ";
-  } else {
-    describe << "received ";
-  }
-  switch (version) {
-  case SSL2_VERSION:
-    describe << "SSL 2.0 ";
-    break;
-
-  case SSL3_VERSION:
-    describe << "SSL 3.0 ";
-    break;
-
-  case TLS1_VERSION:
-    describe << "TLS 1.0 ";
-    break;
-
-  default:
-    describe << "unknown protocol ";
-  }
-
-  describe << "message: ";
-
-  if (version != SSL2_VERSION) {
-    switch (content_type) {
-    case 20:
-      describe << "change cipher spec, ";
-      break;
-
-    case 21:
-      describe << "alert, ";
-      break;
-
-    case 22:
-      describe << "handshake, ";
-      break;
-
-    case 23:
-      describe << "application data, ";
-      break;
-
-    default:
-      describe << "unknown content type, ";
-    }
-  }
-
-  describe << len << " bytes.\n";
-
-  downloader_cat.debug() << describe.str();
-}
-#endif  // !defined(NDEBUG)
-
 /**
 /**
  *
  *
  */
  */

+ 5 - 7
panda/src/downloader/httpClient.h

@@ -32,7 +32,11 @@
 #include "pmap.h"
 #include "pmap.h"
 #include "pset.h"
 #include "pset.h"
 #include "referenceCount.h"
 #include "referenceCount.h"
-#include "openSSLWrapper.h"
+
+typedef struct ssl_ctx_st SSL_CTX;
+typedef struct x509_st X509;
+typedef struct X509_name_st X509_NAME;
+typedef struct evp_pkey_st EVP_PKEY;
 
 
 class Filename;
 class Filename;
 class HTTPChannel;
 class HTTPChannel;
@@ -155,12 +159,6 @@ private:
 
 
   static void split_whitespace(string &a, string &b, const string &c);
   static void split_whitespace(string &a, string &b, const string &c);
 
 
-#ifndef NDEBUG
-  static void ssl_msg_callback(int write_p, int version, int content_type,
-                               const void *buf, size_t len, SSL *ssl,
-                               void *arg);
-#endif
-
   typedef pvector<URLSpec> Proxies;
   typedef pvector<URLSpec> Proxies;
   typedef pmap<string, Proxies> ProxiesByScheme;
   typedef pmap<string, Proxies> ProxiesByScheme;
   ProxiesByScheme _proxies_by_scheme;
   ProxiesByScheme _proxies_by_scheme;

+ 8 - 4
panda/src/egg2pg/eggSaver.cxx

@@ -482,7 +482,7 @@ convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
       } else if (child->is_of_type(CollisionSphere::get_class_type())) {
       } else if (child->is_of_type(CollisionSphere::get_class_type())) {
         CPT(CollisionSphere) sphere = DCAST(CollisionSphere, child);
         CPT(CollisionSphere) sphere = DCAST(CollisionSphere, child);
         LPoint3 center = sphere->get_center();
         LPoint3 center = sphere->get_center();
-        LVector3 offset(sphere->get_radius(), 0, 0);
+        PN_stdfloat radius = sphere->get_radius();
 
 
         EggGroup *egg_sphere;
         EggGroup *egg_sphere;
         if (num_solids == 1) {
         if (num_solids == 1) {
@@ -499,15 +499,19 @@ convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
         }
         }
         egg_sphere->set_collide_flags(flags);
         egg_sphere->set_collide_flags(flags);
 
 
-        EggVertex ev1, ev2;
-        ev1.set_pos(LCAST(double, (center + offset) * net_mat));
-        ev2.set_pos(LCAST(double, (center - offset) * net_mat));
+        EggVertex ev1, ev2, ev3, ev4;
+        ev1.set_pos(LCAST(double, (center + LVector3(radius, 0, 0)) * net_mat));
+        ev2.set_pos(LCAST(double, (center + LVector3(0, radius, 0)) * net_mat));
+        ev3.set_pos(LCAST(double, (center + LVector3(-radius, 0, 0)) * net_mat));
+        ev4.set_pos(LCAST(double, (center + LVector3(0, -radius, 0)) * net_mat));
 
 
         EggPolygon *egg_poly = new EggPolygon;
         EggPolygon *egg_poly = new EggPolygon;
         egg_sphere->add_child(egg_poly);
         egg_sphere->add_child(egg_poly);
 
 
         egg_poly->add_vertex(cvpool->create_unique_vertex(ev1));
         egg_poly->add_vertex(cvpool->create_unique_vertex(ev1));
         egg_poly->add_vertex(cvpool->create_unique_vertex(ev2));
         egg_poly->add_vertex(cvpool->create_unique_vertex(ev2));
+        egg_poly->add_vertex(cvpool->create_unique_vertex(ev3));
+        egg_poly->add_vertex(cvpool->create_unique_vertex(ev4));
 
 
       } else if (child->is_of_type(CollisionPlane::get_class_type())) {
       } else if (child->is_of_type(CollisionPlane::get_class_type())) {
         LPlane plane = DCAST(CollisionPlane, child)->get_plane();
         LPlane plane = DCAST(CollisionPlane, child)->get_plane();

+ 2 - 37
panda/src/express/multifile.cxx

@@ -26,6 +26,8 @@
 #include <iterator>
 #include <iterator>
 #include <time.h>
 #include <time.h>
 
 
+#include "openSSLWrapper.h"
+
 // This sequence of bytes begins each Multifile to identify it as a Multifile.
 // This sequence of bytes begins each Multifile to identify it as a Multifile.
 const char Multifile::_header[] = "pmf\0\n\r";
 const char Multifile::_header[] = "pmf\0\n\r";
 const size_t Multifile::_header_size = 6;
 const size_t Multifile::_header_size = 6;
@@ -768,43 +770,6 @@ add_signature(const Filename &composite, const string &password) {
 }
 }
 #endif  // HAVE_OPENSSL
 #endif  // HAVE_OPENSSL
 
 
-#ifdef HAVE_OPENSSL
-/**
- * Adds a new signature to the Multifile.  This signature associates the
- * indicated certificate with the current contents of the Multifile.  When the
- * Multifile is read later, the signature will still be present only if the
- * Multifile is unchanged; any subsequent changes to the Multifile will
- * automatically invalidate and remove the signature.
- *
- * If chain is non-NULL, it represents the certificate chain that validates
- * the certificate.
- *
- * The specified private key must match the certificate, and the Multifile
- * must be open in read-write mode.  The private key is only used for
- * generating the signature; it is not written to the Multifile and cannot be
- * retrieved from the Multifile later.  (However, the certificate *can* be
- * retrieved from the Multifile later, to identify the entity that created the
- * signature.)
- *
- * This implicitly causes a repack() operation if one is needed.  Returns true
- * on success, false on failure.
- */
-bool Multifile::
-add_signature(X509 *certificate, STACK_OF(X509) *chain, EVP_PKEY *pkey) {
-  // Convert the certificate and chain into our own CertChain structure.
-  CertChain cert_chain;
-  cert_chain.push_back(CertRecord(certificate));
-  if (chain != NULL) {
-    int num = sk_X509_num(chain);
-    for (int i = 0; i < num; ++i) {
-      cert_chain.push_back(CertRecord((X509 *)sk_X509_value(chain, i)));
-    }
-  }
-
-  return add_signature(cert_chain, pkey);
-}
-#endif  // HAVE_OPENSSL
-
 #ifdef HAVE_OPENSSL
 #ifdef HAVE_OPENSSL
 /**
 /**
  * Adds a new signature to the Multifile.  This signature associates the
  * Adds a new signature to the Multifile.  This signature associates the

+ 5 - 2
panda/src/express/multifile.h

@@ -24,7 +24,11 @@
 #include "indirectLess.h"
 #include "indirectLess.h"
 #include "referenceCount.h"
 #include "referenceCount.h"
 #include "pvector.h"
 #include "pvector.h"
-#include "openSSLWrapper.h"
+
+#ifdef HAVE_OPENSSL
+typedef struct x509_st X509;
+typedef struct evp_pkey_st EVP_PKEY;
+#endif
 
 
 /**
 /**
  * A file that contains a set of files.
  * A file that contains a set of files.
@@ -148,7 +152,6 @@ public:
   };
   };
   typedef pvector<CertRecord> CertChain;
   typedef pvector<CertRecord> CertChain;
 
 
-  bool add_signature(X509 *certificate, STACK_OF(X509) *chain, EVP_PKEY *pkey);
   bool add_signature(const CertChain &chain, EVP_PKEY *pkey);
   bool add_signature(const CertChain &chain, EVP_PKEY *pkey);
 
 
   const CertChain &get_signature(int n) const;
   const CertChain &get_signature(int n) const;

+ 12 - 7
panda/src/glstuff/glCgShaderContext_src.cxx

@@ -145,7 +145,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
 
 
     if (cgGetParameterBaseResource(p) == CG_ATTR0) {
     if (cgGetParameterBaseResource(p) == CG_ATTR0) {
       // The Cg toolkit claims that it is bound to a generic vertex attribute.
       // The Cg toolkit claims that it is bound to a generic vertex attribute.
-      if (_glsl_program != 0) {
+      if (_glgsg->has_fixed_function_pipeline() && _glsl_program != 0) {
         // This is where the Cg glslv compiler lies, making the stupid
         // This is where the Cg glslv compiler lies, making the stupid
         // assumption that we're using an NVIDIA card where generic attributes
         // assumption that we're using an NVIDIA card where generic attributes
         // are aliased with conventional vertex attributes.  Instead, it
         // are aliased with conventional vertex attributes.  Instead, it
@@ -246,7 +246,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
       // A conventional texture coordinate set.
       // A conventional texture coordinate set.
       loc = CA_texcoord + cgGetParameterResourceIndex(p);
       loc = CA_texcoord + cgGetParameterResourceIndex(p);
 
 
-    } else {
+    } else if (_glgsg->has_fixed_function_pipeline()) {
       // Some other conventional vertex attribute.
       // Some other conventional vertex attribute.
       switch (res) {
       switch (res) {
       case CG_POSITION0:
       case CG_POSITION0:
@@ -276,6 +276,14 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
         GLCAT.error(false) << ".\n";
         GLCAT.error(false) << ".\n";
         loc = CA_unknown;
         loc = CA_unknown;
       }
       }
+    } else {
+      GLCAT.error()
+        << "Cg varying " << cgGetParameterName(p);
+      if (cgGetParameterSemantic(p)) {
+        GLCAT.error(false) << " : " << cgGetParameterSemantic(p);
+      }
+      GLCAT.error(false) << " is bound to a conventional vertex attribute, "
+                            "but the compatibility profile is not enabled.\n";
     }
     }
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
@@ -916,8 +924,7 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
       } else {
       } else {
         // There is no vertex column with this name; disable the attribute
         // There is no vertex column with this name; disable the attribute
         // array.
         // array.
-#ifdef SUPPORT_FIXED_FUNCTION
-        if (p == 0) {
+        if (_glgsg->has_fixed_function_pipeline() && p == 0) {
           // NOTE: if we disable attribute 0 in compatibility profile, the
           // NOTE: if we disable attribute 0 in compatibility profile, the
           // object will disappear.  In GLSL we fix this by forcing the vertex
           // object will disappear.  In GLSL we fix this by forcing the vertex
           // column to be at 0, but we don't have control over that with Cg.
           // column to be at 0, but we don't have control over that with Cg.
@@ -930,9 +937,7 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
             _glgsg->_glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
             _glgsg->_glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
           }
           }
 
 
-        } else
-#endif  // SUPPORT_FIXED_FUNCTION
-        if (p >= 0) {
+        } else if (p >= 0) {
           _glgsg->disable_vertex_attrib_array(p);
           _glgsg->disable_vertex_attrib_array(p);
 
 
           if (p == _color_attrib_index) {
           if (p == _color_attrib_index) {

+ 7 - 2
panda/src/glstuff/glGraphicsBuffer_src.cxx

@@ -269,6 +269,9 @@ begin_frame(FrameMode mode, Thread *current_thread) {
       }
       }
     }
     }
 #endif
 #endif
+  } else if (mode == FM_refresh) {
+    // Just bind the FBO.
+    rebuild_bitplanes();
   }
   }
 
 
   _gsg->set_current_properties(&get_fb_properties());
   _gsg->set_current_properties(&get_fb_properties());
@@ -1162,8 +1165,10 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) {
   glgsg->apply_texture(gtc);
   glgsg->apply_texture(gtc);
 
 
 #if !defined(OPENGLES) && defined(SUPPORT_FIXED_FUNCTION)
 #if !defined(OPENGLES) && defined(SUPPORT_FIXED_FUNCTION)
-  GLclampf priority = 1.0f;
-  glPrioritizeTextures(1, &gtc->_index, &priority);
+  if (glgsg->has_fixed_function_pipeline()) {
+    GLclampf priority = 1.0f;
+    glPrioritizeTextures(1, &gtc->_index, &priority);
+  }
 #endif
 #endif
 
 
 #ifndef OPENGLES
 #ifndef OPENGLES

+ 28 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.I

@@ -130,6 +130,33 @@ get_gl_version_minor() const {
   return _gl_version_minor;
   return _gl_version_minor;
 }
 }
 
 
+/**
+ * Returns whether a core profile or a compatibility mode is considered.
+ */
+/*INLINE bool CLP(GraphicsStateGuardian)::
+has_core_profile() const {
+  return _core_profile;
+}*/
+
+/**
+ * Returns whether the fixed function pipeline is supported.
+ */
+INLINE bool CLP(GraphicsStateGuardian)::
+has_fixed_function_pipeline() const {
+#ifndef SUPPORT_FIXED_FUNCTION
+  return false;
+#elif defined(OPENGLES_1)
+  return true;
+#elif defined(OPENGLES)
+  return false;
+#else
+  // Otherwise, we can just check whether we are using a core profile or a
+  // compatibility mode. The variable _core_profile is already taking into
+  // account if a GL < 3.2 is considered (becoming false)
+  return !_core_profile;
+#endif
+}
+
 /**
 /**
  * Calls glFinish() if the config variable gl-finish is set True.
  * Calls glFinish() if the config variable gl-finish is set True.
  */
  */
@@ -363,7 +390,7 @@ enable_line_smooth(bool val) {
 INLINE void CLP(GraphicsStateGuardian)::
 INLINE void CLP(GraphicsStateGuardian)::
 enable_point_smooth(bool val) {
 enable_point_smooth(bool val) {
 #ifdef SUPPORT_FIXED_FUNCTION
 #ifdef SUPPORT_FIXED_FUNCTION
-  if (_point_smooth_enabled != val) {
+  if (has_fixed_function_pipeline() && _point_smooth_enabled != val) {
     _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
     _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
     _point_smooth_enabled = val;
     _point_smooth_enabled = val;
     if (val) {
     if (val) {

File diff suppressed because it is too large
+ 309 - 215
panda/src/glstuff/glGraphicsStateGuardian_src.cxx


+ 6 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -399,6 +399,7 @@ public:
   INLINE const string &get_gl_version() const;
   INLINE const string &get_gl_version() const;
   INLINE int get_gl_version_major() const;
   INLINE int get_gl_version_major() const;
   INLINE int get_gl_version_minor() const;
   INLINE int get_gl_version_minor() const;
+  INLINE bool has_fixed_function_pipeline() const;
 
 
   virtual void set_state_and_transform(const RenderState *state,
   virtual void set_state_and_transform(const RenderState *state,
                                        const TransformState *transform);
                                        const TransformState *transform);
@@ -719,6 +720,11 @@ protected:
 
 
   pset<string> _extensions;
   pset<string> _extensions;
 
 
+#ifndef OPENGLES
+  // True for non-compatibility GL 3.2+ contexts.
+  bool _core_profile;
+#endif
+
 public:
 public:
   bool _supports_point_parameters;
   bool _supports_point_parameters;
   PFNGLPOINTPARAMETERFVPROC _glPointParameterfv;
   PFNGLPOINTPARAMETERFVPROC _glPointParameterfv;

+ 2 - 2
panda/src/gobj/geomVertexArrayData.h

@@ -261,8 +261,8 @@ public:
 
 
   INLINE Thread *get_current_thread() const;
   INLINE Thread *get_current_thread() const;
 
 
-  INLINE const unsigned char *get_read_pointer(bool force) const;
-  unsigned char *get_write_pointer();
+  INLINE const unsigned char *get_read_pointer(bool force) const RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
+  unsigned char *get_write_pointer() RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
 
 
 PUBLISHED:
 PUBLISHED:
   INLINE const GeomVertexArrayData *get_object() const;
   INLINE const GeomVertexArrayData *get_object() const;

+ 18 - 10
panda/src/gobj/vertexDataBuffer.I

@@ -67,17 +67,22 @@ INLINE const unsigned char *VertexDataBuffer::
 get_read_pointer(bool force) const {
 get_read_pointer(bool force) const {
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
 
 
+  const unsigned char *ptr;
   if (_resident_data != (unsigned char *)NULL || _size == 0) {
   if (_resident_data != (unsigned char *)NULL || _size == 0) {
-    return _resident_data;
+    ptr = _resident_data;
+  } else {
+    nassertr(_block != (VertexDataBlock *)NULL, NULL);
+    nassertr(_reserved_size >= _size, NULL);
+
+    // We don't necessarily need to page the buffer all the way into independent
+    // status; it's sufficient just to return the block's pointer, which will
+    // force its page to resident status.
+    ptr = _block->get_pointer(force);
   }
   }
-
-  nassertr(_block != (VertexDataBlock *)NULL, NULL);
-  nassertr(_reserved_size >= _size, NULL);
-
-  // We don't necessarily need to page the buffer all the way into independent
-  // status; it's sufficient just to return the block's pointer, which will
-  // force its page to resident status.
-  return _block->get_pointer(force);
+#ifdef _DEBUG
+  assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
+#endif
+  return (const unsigned char *)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT);
 }
 }
 
 
 /**
 /**
@@ -91,7 +96,10 @@ get_write_pointer() {
     do_page_in();
     do_page_in();
   }
   }
   nassertr(_reserved_size >= _size, NULL);
   nassertr(_reserved_size >= _size, NULL);
-  return _resident_data;
+#ifdef _DEBUG
+  assert(((uintptr_t)_resident_data % MEMORY_HOOK_ALIGNMENT) == 0);
+#endif
+  return (unsigned char *)ASSUME_ALIGNED(_resident_data, MEMORY_HOOK_ALIGNMENT);
 }
 }
 
 
 /**
 /**

+ 11 - 20
panda/src/gobj/vertexDataBuffer.cxx

@@ -27,15 +27,13 @@ operator = (const VertexDataBuffer &copy) {
 
 
   if (_resident_data != (unsigned char *)NULL) {
   if (_resident_data != (unsigned char *)NULL) {
     nassertv(_reserved_size != 0);
     nassertv(_reserved_size != 0);
-    get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size);
-    PANDA_FREE_ARRAY(_resident_data);
+    get_class_type().deallocate_array(_resident_data);
     _resident_data = NULL;
     _resident_data = NULL;
   }
   }
   if (copy._resident_data != (unsigned char *)NULL && copy._size != 0) {
   if (copy._resident_data != (unsigned char *)NULL && copy._size != 0) {
     // We only allocate _size bytes, not the full _reserved_size allocated by
     // We only allocate _size bytes, not the full _reserved_size allocated by
     // the original copy.
     // the original copy.
-    get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)copy._size);
-    _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(copy._size);
+    _resident_data = (unsigned char *)get_class_type().allocate_array(copy._size);
     memcpy(_resident_data, copy._resident_data, copy._size);
     memcpy(_resident_data, copy._resident_data, copy._size);
   }
   }
   _size = copy._size;
   _size = copy._size;
@@ -55,17 +53,16 @@ swap(VertexDataBuffer &other) {
   unsigned char *resident_data = _resident_data;
   unsigned char *resident_data = _resident_data;
   size_t size = _size;
   size_t size = _size;
   size_t reserved_size = _reserved_size;
   size_t reserved_size = _reserved_size;
-  PT(VertexDataBlock) block = _block;
+
+  _block.swap(other._block);
 
 
   _resident_data = other._resident_data;
   _resident_data = other._resident_data;
   _size = other._size;
   _size = other._size;
   _reserved_size = other._reserved_size;
   _reserved_size = other._reserved_size;
-  _block = other._block;
 
 
   other._resident_data = resident_data;
   other._resident_data = resident_data;
   other._size = size;
   other._size = size;
   other._reserved_size = reserved_size;
   other._reserved_size = reserved_size;
-  other._block = block;
   nassertv(_reserved_size >= _size);
   nassertv(_reserved_size >= _size);
 }
 }
 
 
@@ -94,13 +91,12 @@ do_clean_realloc(size_t reserved_size) {
       do_page_in();
       do_page_in();
     }
     }
 
 
-    get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)reserved_size - (int)_reserved_size);
     if (_reserved_size == 0) {
     if (_reserved_size == 0) {
       nassertv(_resident_data == (unsigned char *)NULL);
       nassertv(_resident_data == (unsigned char *)NULL);
-      _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(reserved_size);
+      _resident_data = (unsigned char *)get_class_type().allocate_array(reserved_size);
     } else {
     } else {
       nassertv(_resident_data != (unsigned char *)NULL);
       nassertv(_resident_data != (unsigned char *)NULL);
-      _resident_data = (unsigned char *)PANDA_REALLOC_ARRAY(_resident_data, reserved_size);
+      _resident_data = (unsigned char *)get_class_type().reallocate_array(_resident_data, reserved_size);
     }
     }
     nassertv(_resident_data != (unsigned char *)NULL);
     nassertv(_resident_data != (unsigned char *)NULL);
     _reserved_size = reserved_size;
     _reserved_size = reserved_size;
@@ -129,16 +125,14 @@ do_unclean_realloc(size_t reserved_size) {
     if (_resident_data != (unsigned char *)NULL) {
     if (_resident_data != (unsigned char *)NULL) {
       nassertv(_reserved_size != 0);
       nassertv(_reserved_size != 0);
 
 
-      get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size);
-      PANDA_FREE_ARRAY(_resident_data);
+      get_class_type().deallocate_array(_resident_data);
       _resident_data = NULL;
       _resident_data = NULL;
       _reserved_size = 0;
       _reserved_size = 0;
     }
     }
 
 
     if (reserved_size != 0) {
     if (reserved_size != 0) {
-      get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)reserved_size);
       nassertv(_resident_data == (unsigned char *)NULL);
       nassertv(_resident_data == (unsigned char *)NULL);
-      _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(reserved_size);
+      _resident_data = (unsigned char *)get_class_type().allocate_array(reserved_size);
     }
     }
 
 
     _reserved_size = reserved_size;
     _reserved_size = reserved_size;
@@ -166,8 +160,7 @@ do_page_out(VertexDataBook &book) {
   if (_size == 0) {
   if (_size == 0) {
     // It's an empty buffer.  Just deallocate it; don't bother to create a
     // It's an empty buffer.  Just deallocate it; don't bother to create a
     // block.
     // block.
-    get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size);
-    PANDA_FREE_ARRAY(_resident_data);
+    get_class_type().deallocate_array(_resident_data);
     _resident_data = NULL;
     _resident_data = NULL;
     _reserved_size = 0;
     _reserved_size = 0;
 
 
@@ -180,8 +173,7 @@ do_page_out(VertexDataBook &book) {
     nassertv(pointer != (unsigned char *)NULL);
     nassertv(pointer != (unsigned char *)NULL);
     memcpy(pointer, _resident_data, _size);
     memcpy(pointer, _resident_data, _size);
 
 
-    get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_reserved_size);
-    PANDA_FREE_ARRAY(_resident_data);
+    get_class_type().deallocate_array(_resident_data);
     _resident_data = NULL;
     _resident_data = NULL;
 
 
     _reserved_size = _size;
     _reserved_size = _size;
@@ -205,8 +197,7 @@ do_page_in() {
   nassertv(_block != (VertexDataBlock *)NULL);
   nassertv(_block != (VertexDataBlock *)NULL);
   nassertv(_reserved_size == _size);
   nassertv(_reserved_size == _size);
 
 
-  get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)_size);
-  _resident_data = (unsigned char *)PANDA_MALLOC_ARRAY(_size);
+  _resident_data = (unsigned char *)get_class_type().allocate_array(_size);
   nassertv(_resident_data != (unsigned char *)NULL);
   nassertv(_resident_data != (unsigned char *)NULL);
 
 
   memcpy(_resident_data, _block->get_pointer(true), _size);
   memcpy(_resident_data, _block->get_pointer(true), _size);

+ 2 - 2
panda/src/gobj/vertexDataBuffer.h

@@ -57,8 +57,8 @@ public:
   void operator = (const VertexDataBuffer &copy);
   void operator = (const VertexDataBuffer &copy);
   INLINE ~VertexDataBuffer();
   INLINE ~VertexDataBuffer();
 
 
-  INLINE const unsigned char *get_read_pointer(bool force) const;
-  INLINE unsigned char *get_write_pointer();
+  INLINE const unsigned char *get_read_pointer(bool force) const RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
+  INLINE unsigned char *get_write_pointer() RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
 
 
   INLINE size_t get_size() const;
   INLINE size_t get_size() const;
   INLINE size_t get_reserved_size() const;
   INLINE size_t get_reserved_size() const;

+ 33 - 28
panda/src/grutil/meshDrawer.cxx

@@ -33,7 +33,7 @@
 TypeHandle MeshDrawer::_type_handle;
 TypeHandle MeshDrawer::_type_handle;
 
 
 PN_stdfloat randFloat() {
 PN_stdfloat randFloat() {
-  return ((PN_stdfloat) rand() / (PN_stdfloat) 0x7fffffff);
+  return ((PN_stdfloat)rand() / (PN_stdfloat)RAND_MAX);
 }
 }
 
 
 /**
 /**
@@ -42,39 +42,43 @@ PN_stdfloat randFloat() {
 void MeshDrawer::generator(int budget) {
 void MeshDrawer::generator(int budget) {
   // create enough triangles for budget:
   // create enough triangles for budget:
   _vdata = new GeomVertexData(_root.get_name(), GeomVertexFormat::get_v3n3c4t2(), Geom::UH_static);//UH_dynamic);
   _vdata = new GeomVertexData(_root.get_name(), GeomVertexFormat::get_v3n3c4t2(), Geom::UH_static);//UH_dynamic);
-  GeomVertexWriter *tvertex = new GeomVertexWriter(_vdata, "vertex");
-  GeomVertexWriter *tnormal = new GeomVertexWriter(_vdata, "normal");
-  GeomVertexWriter *tuv = new GeomVertexWriter(_vdata, "texcoord");
-  GeomVertexWriter *tcolor = new GeomVertexWriter(_vdata, "color");
-  _prim = new GeomTriangles(Geom::UH_static);
-
-  // iterate and fill _up a geom with random data so that it will not be
-  // optimized out by panda3d system
-  for(int i = 0; i < budget; i++) {
-    for( int vert = 0; vert < 3; vert++) {
-      LVector3 vec3 = LVector3(randFloat()+1000,randFloat(),randFloat())*.001;
-      LVector4 vec4 = LVector4(1,1,1,randFloat());
-      LVector2 vec2 = LVector2(0,randFloat());
-      tvertex->add_data3(vec3);
-      tcolor->add_data4(vec4);
-      tuv->add_data2(vec2);
-      tnormal->add_data3(vec3);
+  _vdata->unclean_set_num_rows(budget * 3);
+
+  {
+    GeomVertexWriter tvertex(_vdata, "vertex");
+    GeomVertexWriter tnormal(_vdata, "normal");
+    GeomVertexWriter tuv(_vdata, "texcoord");
+    GeomVertexWriter tcolor(_vdata, "color");
+
+    // iterate and fill _up a geom with random data so that it will not be
+    // optimized out by panda3d system
+    for (int i = 0; i < budget; i++) {
+      for (int vert = 0; vert < 3; vert++) {
+        LVector3 vec3 = LVector3(randFloat()+1000,randFloat(),randFloat())*.001;
+        LVector4 vec4 = LVector4(1,1,1,randFloat());
+        LVector2 vec2 = LVector2(0,randFloat());
+        tvertex.set_data3(vec3);
+        tcolor.set_data4(vec4);
+        tuv.set_data2(vec2);
+        tnormal.set_data3(vec3);
+      }
     }
     }
-    _prim->add_vertices(i * 3, i * 3 + 1, i * 3 + 2);
   }
   }
+
   // create our node and attach it to this node path
   // create our node and attach it to this node path
+  _prim = new GeomTriangles(Geom::UH_static);
+  _prim->add_next_vertices(budget * 3);
   _prim->close_primitive();
   _prim->close_primitive();
   _geom = new Geom(_vdata);
   _geom = new Geom(_vdata);
   _geom->add_primitive(_prim);
   _geom->add_primitive(_prim);
-  _geomnode = new GeomNode("__MeshDrawer_GeomNode");
+  if (_geomnode == NULL) {
+    _geomnode = new GeomNode("__MeshDrawer_GeomNode");
+    _root.attach_new_node(_geomnode);
+  } else {
+    _geomnode->remove_all_geoms();
+  }
   _geomnode->add_geom(_geom);
   _geomnode->add_geom(_geom);
-  _root.attach_new_node(_geomnode);
   _last_clear_index = budget;
   _last_clear_index = budget;
-
-  delete tvertex;
-  delete tnormal;
-  delete tuv;
-  delete tcolor;
 }
 }
 
 
 /**
 /**
@@ -451,8 +455,9 @@ link_segment(const LVector3 &pos, const LVector4 &frame,
   LVector3 cam_stop3d = _camera.get_relative_point(_render, stop);
   LVector3 cam_stop3d = _camera.get_relative_point(_render, stop);
   LPoint2 cam_stop2d = LVector2();
   LPoint2 cam_stop2d = LVector2();
 
 
-  PT(Camera) camera = DCAST(Camera, _camera.node());
-  PT(Lens) lens = camera->get_lens();
+  const Camera *camera;
+  DCAST_INTO_V(camera, _camera.node());
+  const Lens *lens = camera->get_lens();
 
 
   lens->project(cam_start3d, cam_start2d);
   lens->project(cam_start3d, cam_start2d);
   lens->project(cam_stop3d, cam_stop2d);
   lens->project(cam_stop3d, cam_stop2d);

+ 1 - 1
panda/src/linmath/lsimpleMatrix.h

@@ -58,7 +58,7 @@ private:
 #endif  // HAVE_EIGEN
 #endif  // HAVE_EIGEN
 
 
 // This is as good a place as any to define this alignment macro.
 // This is as good a place as any to define this alignment macro.
-#if defined(LINMATH_ALIGN) && defined(HAVE_EIGEN) && defined(__AVX__)
+#if defined(LINMATH_ALIGN) && defined(HAVE_EIGEN) && defined(__AVX__) && defined(STDFLOAT_DOUBLE)
 #define ALIGN_LINMATH ALIGN_32BYTE
 #define ALIGN_LINMATH ALIGN_32BYTE
 #elif defined(LINMATH_ALIGN)
 #elif defined(LINMATH_ALIGN)
 #define ALIGN_LINMATH ALIGN_16BYTE
 #define ALIGN_LINMATH ALIGN_16BYTE

+ 3 - 1
panda/src/parametrics/hermiteCurve.h

@@ -163,7 +163,9 @@ public:
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    register_type(_type_handle, "HermiteCurve");
+    PiecewiseCurve::init_type();
+    register_type(_type_handle, "HermiteCurve",
+                  PiecewiseCurve::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 2 - 2
panda/src/parametrics/parametricCurveCollection.h

@@ -11,8 +11,8 @@
  * @date 2001-03-04
  * @date 2001-03-04
  */
  */
 
 
-#ifndef NODEPATHCOLLECTION_H
-#define NODEPATHCOLLECTION_H
+#ifndef PARAMETRICCURVECOLLECTION_H
+#define PARAMETRICCURVECOLLECTION_H
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 
 

+ 2 - 0
panda/src/pgraph/nodePath.h

@@ -659,6 +659,8 @@ PUBLISHED:
   INLINE void set_shader_input(CPT_InternalName id, PN_stdfloat n1, PN_stdfloat n2=0,
   INLINE void set_shader_input(CPT_InternalName id, PN_stdfloat n1, PN_stdfloat n2=0,
                                PN_stdfloat n3=0, PN_stdfloat n4=0, int priority=0);
                                PN_stdfloat n3=0, PN_stdfloat n4=0, int priority=0);
 
 
+  EXTENSION(void set_shader_inputs(PyObject *args, PyObject *kwargs));
+
   void clear_shader_input(CPT_InternalName id);
   void clear_shader_input(CPT_InternalName id);
   void set_instance_count(int instance_count);
   void set_instance_count(int instance_count);
 
 

+ 216 - 0
panda/src/pgraph/nodePath_ext.cxx

@@ -13,6 +13,7 @@
 
 
 #include "nodePath_ext.h"
 #include "nodePath_ext.h"
 #include "typedWritable_ext.h"
 #include "typedWritable_ext.h"
+#include "shaderAttrib.h"
 
 
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
 
 
@@ -24,6 +25,35 @@ extern struct Dtool_PyTypedObject Dtool_LPoint3d;
 #else
 #else
 extern struct Dtool_PyTypedObject Dtool_LPoint3f;
 extern struct Dtool_PyTypedObject Dtool_LPoint3f;
 #endif
 #endif
+extern struct Dtool_PyTypedObject Dtool_Texture;
+extern struct Dtool_PyTypedObject Dtool_NodePath;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_float;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_double;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_int;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4f;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3f;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2f;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLMatrix4f;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LMatrix3f;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4d;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3d;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2d;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLMatrix4d;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LMatrix3d;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_UnalignedLVecBase4i;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase3i;
+extern struct Dtool_PyTypedObject Dtool_PointerToArray_LVecBase2i;
+extern struct Dtool_PyTypedObject Dtool_LVecBase4f;
+extern struct Dtool_PyTypedObject Dtool_LVecBase3f;
+extern struct Dtool_PyTypedObject Dtool_LVecBase2f;
+extern struct Dtool_PyTypedObject Dtool_LVecBase4d;
+extern struct Dtool_PyTypedObject Dtool_LVecBase3d;
+extern struct Dtool_PyTypedObject Dtool_LVecBase2d;
+extern struct Dtool_PyTypedObject Dtool_LVecBase4i;
+extern struct Dtool_PyTypedObject Dtool_LVecBase3i;
+extern struct Dtool_PyTypedObject Dtool_LVecBase2i;
+extern struct Dtool_PyTypedObject Dtool_ShaderBuffer;
+extern struct Dtool_PyTypedObject Dtool_ParamValueBase;
 #endif  // CPPPARSER
 #endif  // CPPPARSER
 
 
 /**
 /**
@@ -211,6 +241,192 @@ py_decode_NodePath_from_bam_stream_persist(PyObject *unpickler, const string &da
   return NodePath::decode_from_bam_stream(data, reader);
   return NodePath::decode_from_bam_stream(data, reader);
 }
 }
 
 
+/**
+ * Sets multiple shader inputs at the same time.  This can be significantly
+ * more efficient if many inputs need to be set at the same time.
+ */
+void Extension<NodePath>::
+set_shader_inputs(PyObject *args, PyObject *kwargs) {
+  if (PyObject_Size(args) > 0) {
+    Dtool_Raise_TypeError("NodePath.set_shader_inputs takes only keyword arguments");
+    return;
+  }
+
+  PT(PandaNode) node = _this->node();
+  CPT(RenderAttrib) prev_attrib = node->get_attrib(ShaderAttrib::get_class_slot());
+  PT(ShaderAttrib) attrib;
+  if (prev_attrib == nullptr) {
+    attrib = new ShaderAttrib();
+  } else {
+    attrib = new ShaderAttrib(*(const ShaderAttrib *)prev_attrib.p());
+  }
+
+  PyObject *key, *value;
+  Py_ssize_t pos = 0;
+
+  while (PyDict_Next(kwargs, &pos, &key, &value)) {
+    char *buffer;
+    Py_ssize_t length;
+#if PY_MAJOR_VERSION >= 3
+    buffer = (char *)PyUnicode_AsUTF8AndSize(key, &length);
+    if (buffer == nullptr) {
+#else
+    if (PyString_AsStringAndSize(key, &buffer, &length) == -1) {
+#endif
+      Dtool_Raise_TypeError("NodePath.set_shader_inputs accepts only string keywords");
+      return;
+    }
+
+    CPT_InternalName name(string(buffer, length));
+    ShaderInput *input = nullptr;
+
+    if (PyTuple_CheckExact(value)) {
+      // A tuple is interpreted as a vector.
+      Py_ssize_t size = PyTuple_GET_SIZE(value);
+      if (size > 4) {
+        Dtool_Raise_TypeError("NodePath.set_shader_inputs tuple input should not have more than 4 scalars");
+        return;
+      }
+      // If any of them is a float, we are storing it as a float vector.
+      bool is_float = false;
+      for (Py_ssize_t i = 0; i < size; ++i) {
+        if (PyFloat_CheckExact(PyTuple_GET_ITEM(value, i))) {
+          is_float = true;
+          break;
+        }
+      }
+      if (is_float) {
+        LVecBase4 vec(0);
+        for (Py_ssize_t i = 0; i < size; ++i) {
+          vec[i] = (PN_stdfloat)PyFloat_AsDouble(PyTuple_GET_ITEM(value, i));
+        }
+        input = new ShaderInput(name, vec);
+      } else {
+        LVecBase4i vec(0);
+        for (Py_ssize_t i = 0; i < size; ++i) {
+          vec[i] = (int)PyLong_AsLong(PyTuple_GET_ITEM(value, i));
+        }
+        input = new ShaderInput(name, vec);
+      }
+
+    } else if (DtoolCanThisBeAPandaInstance(value)) {
+      Dtool_PyInstDef *inst = (Dtool_PyInstDef *)value;
+      void *ptr;
+
+      if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_Texture))) {
+        input = new ShaderInput(name, (Texture *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_NodePath))) {
+        input = new ShaderInput(name, *(const NodePath *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_float))) {
+        input = new ShaderInput(name, *(const PTA_float *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_double))) {
+        input = new ShaderInput(name, *(const PTA_double *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_int))) {
+        input = new ShaderInput(name, *(const PTA_int *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4f))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase4f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3f))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase3f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2f))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase2f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4f))) {
+        input = new ShaderInput(name, *(const PTA_LMatrix4f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3f))) {
+        input = new ShaderInput(name, *(const PTA_LMatrix3f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4d))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase4d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3d))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase3d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2d))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase2d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLMatrix4d))) {
+        input = new ShaderInput(name, *(const PTA_LMatrix4d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LMatrix3d))) {
+        input = new ShaderInput(name, *(const PTA_LMatrix3d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_UnalignedLVecBase4i))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase4i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase3i))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase3i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_PointerToArray_LVecBase2i))) {
+        input = new ShaderInput(name, *(const PTA_LVecBase2i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4f))) {
+        input = new ShaderInput(name, *(const LVecBase4f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3f))) {
+        input = new ShaderInput(name, *(const LVecBase3f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2f))) {
+        input = new ShaderInput(name, *(const LVecBase2f *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4d))) {
+        input = new ShaderInput(name, *(const LVecBase4d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3d))) {
+        input = new ShaderInput(name, *(const LVecBase3d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2d))) {
+        input = new ShaderInput(name, *(const LVecBase2d *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase4i))) {
+        input = new ShaderInput(name, *(const LVecBase4i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase3i))) {
+        input = new ShaderInput(name, *(const LVecBase3i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_LVecBase2i))) {
+        input = new ShaderInput(name, *(const LVecBase2i *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ShaderBuffer))) {
+        input = new ShaderInput(name, (ShaderBuffer *)ptr);
+
+      } else if ((ptr = inst->_My_Type->_Dtool_UpcastInterface(value, &Dtool_ParamValueBase))) {
+        input = new ShaderInput(name, (ParamValueBase *)ptr);
+
+      } else {
+        Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs");
+        return;
+      }
+
+    } else if (PyFloat_Check(value)) {
+      input = new ShaderInput(name, LVecBase4(PyFloat_AS_DOUBLE(value), 0, 0, 0));
+
+#if PY_MAJOR_VERSION < 3
+    } else if (PyInt_Check(value)) {
+      input = new ShaderInput(name, LVecBase4i((int)PyInt_AS_LONG(value), 0, 0, 0));
+#endif
+
+    } else if (PyLong_Check(value)) {
+      input = new ShaderInput(name, LVecBase4i((int)PyLong_AsLong(value), 0, 0, 0));
+
+    } else {
+      Dtool_Raise_TypeError("unknown type passed to NodePath.set_shader_inputs");
+      return;
+    }
+
+    attrib->_inputs[move(name)] = input;
+  }
+
+  node->set_attrib(ShaderAttrib::return_new(attrib));
+}
+
 /**
 /**
  * Returns the tight bounds as a 2-tuple of LPoint3 objects.  This is a
  * Returns the tight bounds as a 2-tuple of LPoint3 objects.  This is a
  * convenience function for Python users, among which the use of
  * convenience function for Python users, among which the use of

+ 2 - 0
panda/src/pgraph/nodePath_ext.h

@@ -49,6 +49,8 @@ public:
   // This is defined to implement cycle detection in Python tags.
   // This is defined to implement cycle detection in Python tags.
   INLINE int __traverse__(visitproc visit, void *arg);
   INLINE int __traverse__(visitproc visit, void *arg);
 
 
+  void set_shader_inputs(PyObject *args, PyObject *kwargs);
+
   PyObject *get_tight_bounds(const NodePath &other = NodePath()) const;
   PyObject *get_tight_bounds(const NodePath &other = NodePath()) const;
 };
 };
 
 

+ 2 - 4
panda/src/pgraph/pandaNode.h

@@ -799,12 +799,10 @@ public:
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedWritable::init_type();
-    ReferenceCount::init_type();
+    TypedWritableReferenceCount::init_type();
     Namable::init_type();
     Namable::init_type();
     register_type(_type_handle, "PandaNode",
     register_type(_type_handle, "PandaNode",
-                  TypedWritable::get_class_type(),
-                  ReferenceCount::get_class_type(),
+                  TypedWritableReferenceCount::get_class_type(),
                   Namable::get_class_type());
                   Namable::get_class_type());
     CData::init_type();
     CData::init_type();
     Down::init_type();
     Down::init_type();

+ 3 - 0
panda/src/pgraph/shaderAttrib.h

@@ -31,6 +31,7 @@
 #include "pta_LVecBase4.h"
 #include "pta_LVecBase4.h"
 #include "pta_LVecBase3.h"
 #include "pta_LVecBase3.h"
 #include "pta_LVecBase2.h"
 #include "pta_LVecBase2.h"
+#include "extension.h"
 
 
 /**
 /**
  *
  *
@@ -147,6 +148,8 @@ private:
   typedef pmap<CPT_InternalName, CPT(ShaderInput)> Inputs;
   typedef pmap<CPT_InternalName, CPT(ShaderInput)> Inputs;
   Inputs _inputs;
   Inputs _inputs;
 
 
+  friend class Extension<NodePath>;
+
 PUBLISHED:
 PUBLISHED:
   static int get_class_slot() {
   static int get_class_slot() {
     return _attrib_slot;
     return _attrib_slot;

+ 4 - 4
panda/src/pgraphnodes/shaderGenerator.h

@@ -151,9 +151,9 @@ public:
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedObject::init_type();
+    TypedReferenceCount::init_type();
     register_type(_type_handle, "ShaderGenerator",
     register_type(_type_handle, "ShaderGenerator",
-                  TypedObject::get_class_type());
+                  TypedReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();
@@ -173,9 +173,9 @@ public:
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedObject::init_type();
+    TypedReferenceCount::init_type();
     register_type(_type_handle, "ShaderGenerator",
     register_type(_type_handle, "ShaderGenerator",
-                  TypedObject::get_class_type());
+                  TypedReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 2 - 4
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -2612,12 +2612,10 @@ setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) {
 
 
   if (gltex->total_bytecount != total_bytecount) {
   if (gltex->total_bytecount != total_bytecount) {
     if (gltex->allocated_buffer != NULL) {
     if (gltex->allocated_buffer != NULL) {
-      PANDA_FREE_ARRAY(gltex->allocated_buffer);
-      TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
+      TinyTextureContext::get_class_type().deallocate_array(gltex->allocated_buffer);
     }
     }
-    gltex->allocated_buffer = PANDA_MALLOC_ARRAY(total_bytecount);
+    gltex->allocated_buffer = TinyTextureContext::get_class_type().allocate_array(total_bytecount);
     gltex->total_bytecount = total_bytecount;
     gltex->total_bytecount = total_bytecount;
-    TinyTextureContext::get_class_type().inc_memory_usage(TypeHandle::MC_array, total_bytecount);
   }
   }
 
 
   char *next_buffer = (char *)gltex->allocated_buffer;
   char *next_buffer = (char *)gltex->allocated_buffer;

+ 2 - 4
panda/src/tinydisplay/tinyTextureContext.cxx

@@ -24,8 +24,7 @@ TinyTextureContext::
   GLTexture *gltex = &_gltex;
   GLTexture *gltex = &_gltex;
   if (gltex->allocated_buffer != NULL) {
   if (gltex->allocated_buffer != NULL) {
     nassertv(gltex->num_levels != 0);
     nassertv(gltex->num_levels != 0);
-    TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
-    PANDA_FREE_ARRAY(gltex->allocated_buffer);
+    get_class_type().deallocate_array(gltex->allocated_buffer);
     gltex->allocated_buffer = NULL;
     gltex->allocated_buffer = NULL;
     gltex->total_bytecount = 0;
     gltex->total_bytecount = 0;
     gltex->num_levels = 0;
     gltex->num_levels = 0;
@@ -51,8 +50,7 @@ evict_lru() {
   GLTexture *gltex = &_gltex;
   GLTexture *gltex = &_gltex;
   if (gltex->allocated_buffer != NULL) {
   if (gltex->allocated_buffer != NULL) {
     nassertv(gltex->num_levels != 0);
     nassertv(gltex->num_levels != 0);
-    TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
-    PANDA_FREE_ARRAY(gltex->allocated_buffer);
+    get_class_type().deallocate_array(gltex->allocated_buffer);
     gltex->allocated_buffer = NULL;
     gltex->allocated_buffer = NULL;
     gltex->total_bytecount = 0;
     gltex->total_bytecount = 0;
     gltex->num_levels = 0;
     gltex->num_levels = 0;

+ 2 - 493
panda/src/windisplay/winGraphicsPipe.cxx

@@ -20,10 +20,7 @@
 
 
 #include "psapi.h"
 #include "psapi.h"
 #include "powrprof.h"
 #include "powrprof.h"
-
-#ifdef _WIN64
 #include <intrin.h>
 #include <intrin.h>
-#endif
 
 
 TypeHandle WinGraphicsPipe::_type_handle;
 TypeHandle WinGraphicsPipe::_type_handle;
 
 
@@ -99,443 +96,6 @@ void get_memory_information (DisplayInformation *display_information) {
   }
   }
 }
 }
 
 
-typedef union {
-  uint64_t long_integer;
-}
-LONG_INTEGER;
-
-uint64_t cpu_time_function (void) {
-#ifdef _WIN64
-  return __rdtsc();
-#else
-  LONG_INTEGER long_integer;
-  LONG_INTEGER *long_integer_pointer;
-
-  long_integer_pointer = &long_integer;
-
-  __asm {
-      mov   ebx,[long_integer_pointer]
-      rdtsc
-      mov   [ebx + 0], eax
-      mov   [ebx + 4], edx
-  }
-
-  return long_integer.long_integer;
-#endif
-}
-
-typedef union {
-  struct {
-    union {
-      struct {
-        unsigned char al;
-        unsigned char ah;
-      };
-      unsigned int eax;
-    };
-    unsigned int ebx;
-    unsigned int ecx;
-    unsigned int edx;
-  };
-} CPU_ID_REGISTERS;
-
-typedef struct {
-  union {
-    struct {
-      int maximum_cpu_id_input;
-      char cpu_vendor [16];
-    };
-
-    CPU_ID_REGISTERS cpu_id_registers_0;
-  };
-
-  union {
-    CPU_ID_REGISTERS cpu_id_registers_1;
-
-    struct {
-      // eax
-      union {
-        unsigned int eax;
-        unsigned int version_information;
-        struct {
-          unsigned int stepping_id : 4;
-          unsigned int model : 4;
-          unsigned int family : 4;
-          unsigned int processor_type : 2;
-          unsigned int reserved_0 : 2;
-          unsigned int extended_model_id : 4;
-          unsigned int extended_family_id : 8;
-          unsigned int reserved_1 : 4;
-        };
-      };
-
-      // ebx
-      union {
-        unsigned int ebx;
-        struct {
-          unsigned int brand_index : 8;
-          unsigned int clflush : 8;
-          unsigned int maximum_logical_processors : 8;
-          unsigned int initial_apic_id : 8;
-        };
-      };
-
-      // ecx
-      union {
-        unsigned int ecx;
-        struct {
-          unsigned int sse3 : 1;
-          unsigned int reserved_1_to_2 : 2;
-          unsigned int monitor : 1;
-          unsigned int ds_cpl : 1;
-          unsigned int vmx : 1;
-          unsigned int reserved_6 : 1;
-          unsigned int est : 1;
-          unsigned int tm2 : 1;
-          unsigned int reserved_9 : 1;
-          unsigned int cnxt_id : 1;
-          unsigned int reserved_11_to_12 : 2;
-          unsigned int cmpxchg16b : 1;
-          unsigned int xtpr_disable : 1;
-          unsigned int reserved_15_to_31 : 17;
-        };
-      };
-
-      // edx
-      union {
-        unsigned int edx;
-        struct {
-          unsigned int fpu : 1;
-          unsigned int vme : 1;
-          unsigned int de : 1;
-          unsigned int pse : 1;
-          unsigned int tsc : 1;
-          unsigned int msr : 1;
-          unsigned int pae : 1;
-          unsigned int mce : 1;
-          unsigned int cx8 : 1;
-          unsigned int apic : 1;
-          unsigned int reserved_10 : 1;
-          unsigned int sep : 1;
-          unsigned int mtrr : 1;
-          unsigned int pge : 1;
-          unsigned int mca : 1;
-          unsigned int cmov : 1;
-          unsigned int pat : 1;
-          unsigned int pse_36 : 1;
-          unsigned int psn : 1;
-          unsigned int cflush : 1;
-          unsigned int reserved_20 : 1;
-          unsigned int ds : 1;
-          unsigned int acpi : 1;
-          unsigned int mmx : 1;
-          unsigned int fxsr : 1;
-          unsigned int sse : 1;
-          unsigned int sse2 : 1;
-          unsigned int ss : 1;
-          unsigned int htt : 1;
-          unsigned int tm : 1;
-          unsigned int reserved_30 : 1;
-          unsigned int pbe : 1;
-        };
-      };
-    };
-  };
-
-  #define MAXIMUM_2 8
-  #define MAXIMUM_CHARACTERS (MAXIMUM_2 * sizeof(CPU_ID_REGISTERS))
-
-  union {
-    CPU_ID_REGISTERS cpu_id_registers_2;
-    unsigned char character_array_2 [MAXIMUM_CHARACTERS];
-    CPU_ID_REGISTERS cpu_id_registers_2_array [MAXIMUM_2];
-  };
-
-  union {
-    CPU_ID_REGISTERS cpu_id_registers_0x80000000;
-  };
-
-  union {
-    CPU_ID_REGISTERS cpu_id_registers_0x80000001;
-  };
-
-  union {
-    char cpu_brand_string [sizeof(CPU_ID_REGISTERS) * 3];
-    struct {
-      CPU_ID_REGISTERS cpu_id_registers_0x80000002;
-      CPU_ID_REGISTERS cpu_id_registers_0x80000003;
-      CPU_ID_REGISTERS cpu_id_registers_0x80000004;
-    };
-  };
-
-  union {
-    struct {
-      unsigned int eax;
-      unsigned int ebx;
-      union {
-        unsigned int ecx;
-        struct {
-          unsigned int l1_data_cache_line_size : 8;
-          unsigned int l1_data_reserved_8_to_15 : 8;
-          unsigned int l1_data_associativity : 8;
-          unsigned int l1_data_cache_size : 8;
-        };
-      };
-      union {
-        unsigned int edx;
-        struct {
-          unsigned int l1_code_cache_line_size : 8;
-          unsigned int l1_code_reserved_8_to_15 : 8;
-          unsigned int l1_code_associativity : 8;
-          unsigned int l1_code_cache_size : 8;
-        };
-      };
-    };
-    CPU_ID_REGISTERS cpu_id_registers_0x80000005;
-  };
-
-  union {
-    struct {
-      unsigned int eax;
-      unsigned int ebx;
-      union {
-        unsigned int ecx;
-        struct {
-          unsigned int l2_cache_line_size : 8;
-          unsigned int l2_reserved_8_to_11 : 4;
-          unsigned int l2_associativity : 4;
-          unsigned int l2_cache_size : 16;
-        };
-      };
-      unsigned int edx;
-    };
-    CPU_ID_REGISTERS cpu_id_registers_0x80000006;
-  };
-
-  CPU_ID_REGISTERS cpu_id_registers_0x80000008;
-
-  unsigned int cache_line_size;
-  unsigned int log_base_2_cache_line_size;
-} CPU_ID;
-
-typedef struct {
-  CPU_ID_REGISTERS cpu_id_registers_0;
-  CPU_ID_REGISTERS cpu_id_registers_1;
-
-  CPU_ID_REGISTERS cpu_id_registers_0x80000000;
-  CPU_ID_REGISTERS cpu_id_registers_0x80000001;
-  CPU_ID_REGISTERS cpu_id_registers_0x80000002;
-  CPU_ID_REGISTERS cpu_id_registers_0x80000003;
-  CPU_ID_REGISTERS cpu_id_registers_0x80000004;
-
-  CPU_ID_REGISTERS cpu_id_registers_0x80000006;
-
-  CPU_ID_REGISTERS cpu_id_registers_0x80000008;
-} CPU_ID_BINARY_DATA;
-
-void cpu_id_to_cpu_id_binary_data (CPU_ID *cpu_id, CPU_ID_BINARY_DATA *cpu_id_binary_data) {
-  cpu_id_binary_data->cpu_id_registers_0 = cpu_id->cpu_id_registers_0;
-  cpu_id_binary_data->cpu_id_registers_1 = cpu_id->cpu_id_registers_1;
-  cpu_id_binary_data->cpu_id_registers_0x80000000 = cpu_id->cpu_id_registers_0x80000000;
-  cpu_id_binary_data->cpu_id_registers_0x80000001 = cpu_id->cpu_id_registers_0x80000001;
-  cpu_id_binary_data->cpu_id_registers_0x80000002 = cpu_id->cpu_id_registers_0x80000002;
-  cpu_id_binary_data->cpu_id_registers_0x80000003 = cpu_id->cpu_id_registers_0x80000003;
-  cpu_id_binary_data->cpu_id_registers_0x80000004 = cpu_id->cpu_id_registers_0x80000004;
-  cpu_id_binary_data->cpu_id_registers_0x80000006 = cpu_id->cpu_id_registers_0x80000006;
-  cpu_id_binary_data->cpu_id_registers_0x80000008 = cpu_id->cpu_id_registers_0x80000008;
-}
-
-void cpu_id_binary_data_to_cpu_id (CPU_ID_BINARY_DATA *cpu_id_binary_data, CPU_ID *cpu_id) {
-  memset (cpu_id, 0, sizeof(CPU_ID));
-
-  cpu_id->cpu_id_registers_0 = cpu_id_binary_data->cpu_id_registers_0;
-  cpu_id->cpu_id_registers_1 = cpu_id_binary_data->cpu_id_registers_1;
-  cpu_id->cpu_id_registers_0x80000000 = cpu_id_binary_data->cpu_id_registers_0x80000000;
-  cpu_id->cpu_id_registers_0x80000001 = cpu_id_binary_data->cpu_id_registers_0x80000001;
-  cpu_id->cpu_id_registers_0x80000002 = cpu_id_binary_data->cpu_id_registers_0x80000002;
-  cpu_id->cpu_id_registers_0x80000003 = cpu_id_binary_data->cpu_id_registers_0x80000003;
-  cpu_id->cpu_id_registers_0x80000004 = cpu_id_binary_data->cpu_id_registers_0x80000004;
-  cpu_id->cpu_id_registers_0x80000006 = cpu_id_binary_data->cpu_id_registers_0x80000006;
-  cpu_id->cpu_id_registers_0x80000008 = cpu_id_binary_data->cpu_id_registers_0x80000008;
-}
-
-int cpuid(int input_eax, CPU_ID_REGISTERS *cpu_id_registers) {
-  int state;
-
-  state = false;
-  __try {
-    if (input_eax == 0) {
-      // the order of ecx and edx is swapped when saved to make a proper
-      // vendor string
-#ifdef _WIN64
-      __cpuid((int*)cpu_id_registers, input_eax);
-      unsigned int tmp = cpu_id_registers->edx;
-      cpu_id_registers->edx = cpu_id_registers->ecx;
-      cpu_id_registers->ecx = tmp;
-#else
-      __asm {
-          mov   eax, [input_eax]
-          mov   edi, [cpu_id_registers]
-
-          cpuid
-
-          mov   [edi + 0], eax
-          mov   [edi + 4], ebx
-          mov   [edi + 8], edx
-          mov   [edi + 12], ecx
-      }
-#endif
-    } else {
-#ifdef _WIN64
-      __cpuid((int*)cpu_id_registers, input_eax);
-#else
-      __asm {
-          mov   eax, [input_eax]
-          mov   edi, [cpu_id_registers]
-
-          cpuid
-
-          mov   [edi + 0], eax
-          mov   [edi + 4], ebx
-          mov   [edi + 8], ecx
-          mov   [edi + 12], edx
-      }
-#endif
-    }
-
-    state = true;
-  }
-  __except (1) {
-    state = false;
-  }
-
-  return state;
-}
-
-void parse_cpu_id(CPU_ID *cpu_id) {
-  printf("CPUID\n");
-  printf("  vendor = %s\n", cpu_id->cpu_vendor);
-  printf("  brand string %s\n", cpu_id->cpu_brand_string);
-  printf("  maximum_cpu_id_input = %u\n", cpu_id->maximum_cpu_id_input);
-  printf("  maximum extended information = 0x%X\n", cpu_id->cpu_id_registers_0x80000000.eax);
-
-  printf("  MMX  = %u\n", cpu_id->mmx);
-  printf("  SSE  = %u\n", cpu_id->sse);
-  printf("  SSE2 = %u\n", cpu_id->sse2);
-  printf("  SSE3 = %u\n", cpu_id->sse3);
-
-  printf("  EST  = %u\n", cpu_id->est);
-
-  if (cpu_id->maximum_cpu_id_input >= 1) {
-    printf("  version_information\n");
-    printf("    stepping_id %u\n", cpu_id->stepping_id);
-    printf("    model %u\n", cpu_id->model);
-    printf("    family %u\n", cpu_id->family);
-    printf("    processor_type %u\n", cpu_id->processor_type);
-    printf("    extended_model_id %u\n", cpu_id->extended_model_id);
-    printf("    extended_family_id %u\n", cpu_id->extended_family_id);
-
-    printf("    brand_index %u\n", cpu_id->brand_index);
-    printf("    clflush %u\n", cpu_id->clflush);
-    printf("    maximum_logical_processors %u\n", cpu_id->maximum_logical_processors);
-    printf("    initial_apic_id %u\n", cpu_id->initial_apic_id);
-
-// printf("  cache_line_size %u\n", cpu_id->cache_line_size); printf("
-// log_base_2_cache_line_size %u\n", cpu_id->log_base_2_cache_line_size);
-  }
-
-  if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000005) {
-    printf("  l1_data_cache_line_size %d\n", cpu_id->l1_data_cache_line_size);
-    printf("  l1_data_associativity %d\n", cpu_id->l1_data_associativity);
-    printf("  l1_data_cache_size %dK\n", cpu_id->l1_data_cache_size);
-
-    printf("  l1_code_cache_line_size %d\n", cpu_id->l1_code_cache_line_size);
-    printf("  l1_code_associativity %d\n", cpu_id->l1_code_associativity);
-    printf("  l1_code_cache_size %dK\n", cpu_id->l1_code_cache_size);
-  }
-
-  if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000006) {
-    printf("  l2_cache_line_size %d\n", cpu_id->l2_cache_line_size);
-    printf("  l2_associativity %d\n", cpu_id->l2_associativity);
-    printf("  l2_cache_size %dK\n", cpu_id->l2_cache_size);
-  }
-}
-
-int initialize_cpu_id(CPU_ID *cpu_id) {
-  int debug = false;
-  memset(cpu_id, 0, sizeof(CPU_ID));
-
-  if (cpuid(0, &cpu_id->cpu_id_registers_0)) {
-    if (cpu_id->maximum_cpu_id_input >= 1) {
-      cpuid(1, &cpu_id->cpu_id_registers_1);
-    }
-    if (cpu_id->maximum_cpu_id_input >= 2) {
-      unsigned int index;
-
-      cpuid(2, &cpu_id->cpu_id_registers_2);
-      if (debug) {
-        printf("  al = %u\n", cpu_id->cpu_id_registers_2.al);
-      }
-
-      for (index = 1; index < cpu_id->cpu_id_registers_2.al && index < MAXIMUM_2; index++) {
-        cpuid(2, &cpu_id->cpu_id_registers_2_array [index]);
-      }
-
-      for (index = 1; index < MAXIMUM_CHARACTERS; index++) {
-        if (cpu_id->character_array_2 [index]) {
-          if (debug) {
-            printf("  cache/TLB byte = %X\n", cpu_id->character_array_2 [index]);
-          }
-          switch (cpu_id->character_array_2 [index]) {
-          case 0x0A:
-          case 0x0C:
-            cpu_id->cache_line_size = 32;
-            cpu_id->log_base_2_cache_line_size = 5;
-            break;
-
-          case 0x2C:
-          case 0x60:
-          case 0x66:
-          case 0x67:
-          case 0x68:
-            cpu_id->cache_line_size = 64;
-            cpu_id->log_base_2_cache_line_size = 6;
-            break;
-          }
-        }
-      }
-    }
-
-    cpuid(0x80000000, &cpu_id->cpu_id_registers_0x80000000);
-
-    if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000001) {
-      cpuid(0x80000001, &cpu_id->cpu_id_registers_0x80000001);
-    }
-
-    if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000004) {
-      cpuid(0x80000002, &cpu_id->cpu_id_registers_0x80000002);
-      cpuid(0x80000003, &cpu_id->cpu_id_registers_0x80000003);
-      cpuid(0x80000004, &cpu_id->cpu_id_registers_0x80000004);
-    }
-
-    if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000005) {
-      cpuid(0x80000005, &cpu_id->cpu_id_registers_0x80000005);
-    }
-
-    if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000006) {
-      cpuid(0x80000006, &cpu_id->cpu_id_registers_0x80000006);
-    }
-
-    if (cpu_id->cpu_id_registers_0x80000000.eax >= 0x80000008) {
-      cpuid(0x80000008, &cpu_id->cpu_id_registers_0x80000008);
-    }
-
-    return true;
-  }
-
-  return false;
-}
-
 int update_cpu_frequency_function(int processor_number, DisplayInformation *display_information) {
 int update_cpu_frequency_function(int processor_number, DisplayInformation *display_information) {
   int update;
   int update;
 
 
@@ -776,9 +336,6 @@ lookup_cpu_data() {
   // set callback for memory function
   // set callback for memory function
   _display_information->_get_memory_information_function = get_memory_information;
   _display_information->_get_memory_information_function = get_memory_information;
 
 
-  // set callback for cpu time function
-  _display_information->_cpu_time_function = cpu_time_function;
-
   // determine CPU frequency
   // determine CPU frequency
   uint64_t time;
   uint64_t time;
   uint64_t end_time;
   uint64_t end_time;
@@ -803,12 +360,12 @@ lookup_cpu_data() {
   if (QueryPerformanceFrequency(&frequency)) {
   if (QueryPerformanceFrequency(&frequency)) {
     if (frequency.QuadPart > 0) {
     if (frequency.QuadPart > 0) {
       if (QueryPerformanceCounter (&counter)) {
       if (QueryPerformanceCounter (&counter)) {
-        time = cpu_time_function();
+        time = __rdtsc();
         end.QuadPart = counter.QuadPart + frequency.QuadPart;
         end.QuadPart = counter.QuadPart + frequency.QuadPart;
         while (QueryPerformanceCounter (&counter) && counter.QuadPart < end.QuadPart) {
         while (QueryPerformanceCounter (&counter) && counter.QuadPart < end.QuadPart) {
 
 
         }
         }
-        end_time = cpu_time_function();
+        end_time = __rdtsc();
 
 
         _display_information->_cpu_frequency = end_time - time;
         _display_information->_cpu_frequency = end_time - time;
       }
       }
@@ -821,54 +378,6 @@ lookup_cpu_data() {
   sprintf(string, "CPU frequency: %I64d\n", _display_information->_cpu_frequency);
   sprintf(string, "CPU frequency: %I64d\n", _display_information->_cpu_frequency);
   windisplay_cat.info() << string;
   windisplay_cat.info() << string;
 
 
-
-  // CPUID
-  CPU_ID cpu_id;
-
-  windisplay_cat.info() << "start CPU ID\n";
-
-  if (initialize_cpu_id(&cpu_id)) {
-    CPU_ID_BINARY_DATA *cpu_id_binary_data;
-
-    cpu_id_binary_data = new (CPU_ID_BINARY_DATA);
-    if (cpu_id_binary_data) {
-      cpu_id_to_cpu_id_binary_data(&cpu_id, cpu_id_binary_data);
-      _display_information->_cpu_id_size = sizeof(CPU_ID_BINARY_DATA) / sizeof(unsigned int);
-      _display_information->_cpu_id_data = (unsigned int *) cpu_id_binary_data;
-
-      _display_information->_cpu_vendor_string = strdup(cpu_id.cpu_vendor);
-      _display_information->_cpu_brand_string = strdup(cpu_id.cpu_brand_string);
-      _display_information->_cpu_version_information = cpu_id.version_information;
-      _display_information->_cpu_brand_index = cpu_id.brand_index;
-
-      if (windisplay_cat.is_debug()) {
-        windisplay_cat.debug()
-          << hex << _display_information->_cpu_id_version << dec << "|";
-
-        int index;
-        for (index = 0; index < _display_information->_cpu_id_size; ++index) {
-          unsigned int data;
-          data = _display_information->_cpu_id_data[index];
-
-          windisplay_cat.debug(false)
-            << hex << data << dec;
-          if (index < _display_information->_cpu_id_size - 1) {
-            windisplay_cat.debug(false)
-              << "|";
-          }
-        }
-        windisplay_cat.debug(false)
-          << "\n";
-      }
-    }
-
-    if (windisplay_cat.is_debug()) {
-      parse_cpu_id(&cpu_id);
-    }
-  }
-
-  windisplay_cat.info() << "end CPU ID\n";
-
   // Number of CPU's
   // Number of CPU's
   count_number_of_cpus(_display_information);
   count_number_of_cpus(_display_information);
 }
 }

+ 6 - 6
samples/chessboard/main.py

@@ -20,7 +20,7 @@ from direct.showbase.DirectObject import DirectObject
 from direct.task.Task import Task
 from direct.task.Task import Task
 import sys
 import sys
 
 
-# First we define some contants for the colors
+# First we define some constants for the colors
 BLACK = (0, 0, 0, 1)
 BLACK = (0, 0, 0, 1)
 WHITE = (1, 1, 1, 1)
 WHITE = (1, 1, 1, 1)
 HIGHLIGHT = (0, 1, 1, 1)
 HIGHLIGHT = (0, 1, 1, 1)
@@ -33,7 +33,7 @@ PIECEBLACK = (.15, .15, .15, 1)
 # This is how we know where to position an object in 3D space based on a 2D mouse
 # This is how we know where to position an object in 3D space based on a 2D mouse
 # position. It also assumes that we are dragging in the XY plane.
 # position. It also assumes that we are dragging in the XY plane.
 #
 #
-# This is derived from the mathmatical of a plane, solved for a given point
+# This is derived from the mathematical of a plane, solved for a given point
 def PointAtZ(z, point, vec):
 def PointAtZ(z, point, vec):
     return point + vec * ((z - point.getZ()) / vec.getZ())
     return point + vec * ((z - point.getZ()) / vec.getZ())
 
 
@@ -41,7 +41,7 @@ def PointAtZ(z, point, vec):
 def SquarePos(i):
 def SquarePos(i):
     return LPoint3((i % 8) - 3.5, int(i // 8) - 3.5, 0)
     return LPoint3((i % 8) - 3.5, int(i // 8) - 3.5, 0)
 
 
-# Helper function for determining wheter a square should be white or black
+# Helper function for determining whether a square should be white or black
 # The modulo operations (%) generate the every-other pattern of a chess-board
 # The modulo operations (%) generate the every-other pattern of a chess-board
 def SquareColor(i):
 def SquareColor(i):
     if (i + ((i // 8) % 2)) % 2:
     if (i + ((i // 8) % 2)) % 2:
@@ -84,7 +84,7 @@ class ChessboardDemo(ShowBase):
         # relative to it
         # relative to it
         self.pickerNP = camera.attachNewNode(self.pickerNode)
         self.pickerNP = camera.attachNewNode(self.pickerNode)
         # Everything to be picked will use bit 1. This way if we were doing other
         # Everything to be picked will use bit 1. This way if we were doing other
-        # collision we could seperate it
+        # collision we could separate it
         self.pickerNode.setFromCollideMask(BitMask32.bit(1))
         self.pickerNode.setFromCollideMask(BitMask32.bit(1))
         self.pickerRay = CollisionRay()  # Make our ray
         self.pickerRay = CollisionRay()  # Make our ray
         # Add it to the collision node
         # Add it to the collision node
@@ -96,7 +96,7 @@ class ChessboardDemo(ShowBase):
         # Now we create the chess board and its pieces
         # Now we create the chess board and its pieces
 
 
         # We will attach all of the squares to their own root. This way we can do the
         # We will attach all of the squares to their own root. This way we can do the
-        # collision pass just on the sqaures and save the time of checking the rest
+        # collision pass just on the squares and save the time of checking the rest
         # of the scene
         # of the scene
         self.squareRoot = render.attachNewNode("squareRoot")
         self.squareRoot = render.attachNewNode("squareRoot")
 
 
@@ -240,7 +240,7 @@ class ChessboardDemo(ShowBase):
         render.setLight(render.attachNewNode(ambientLight))
         render.setLight(render.attachNewNode(ambientLight))
 
 
 
 
-# Class for a piece. This just handels loading the model and setting initial
+# Class for a piece. This just handles loading the model and setting initial
 # position and color
 # position and color
 class Piece(object):
 class Piece(object):
     def __init__(self, square, color):
     def __init__(self, square, color):

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