Browse Source

Merge branch 'master' into cmake

Sam Edwards 10 years ago
parent
commit
8b876843d4
100 changed files with 3421 additions and 2384 deletions
  1. 26 2
      README.md
  2. 6 1
      contrib/src/ai/Sources.pp
  3. 4 5
      direct/src/doc/dcPacker.txt
  4. 24 11
      direct/src/http/favicon.ico
  5. 1 1
      direct/src/p3d/panda3d.pdef
  6. 2 3
      direct/src/p3d/ppackage.py
  7. 8 0
      direct/src/plugin/fileSpec.I
  8. 25 1
      direct/src/plugin/p3dDownload.I
  9. 10 3
      direct/src/plugin/p3dPackage.I
  10. 1 1
      direct/src/plugin_npapi/startup.cxx
  11. 2 2
      direct/src/plugin_standalone/p3dEmbed.h
  12. 2 2
      direct/src/plugin_standalone/panda3d.h
  13. 4 3
      direct/src/plugin_standalone/panda3dBase.h
  14. 2 2
      direct/src/showutil/FreezeTool.py
  15. 111 0
      doc/ReleaseNotes
  16. 1 2
      dtool/Config.Cygwin64.pp
  17. 237 236
      dtool/metalibs/dtoolconfig/pydtool.cxx
  18. 13 5
      dtool/pptempl/PythonPackageInit.pp
  19. 1 1
      dtool/src/cppparser/cppInstance.cxx
  20. 13 0
      dtool/src/cppparser/cppTypedefType.cxx
  21. 1 1
      dtool/src/dtoolbase/addHash.I
  22. 1 1
      dtool/src/dtoolbase/atomicAdjustGccImpl.h
  23. 0 6
      dtool/src/dtoolbase/atomicAdjustI386Impl.cxx
  24. 1 1
      dtool/src/dtoolbase/atomicAdjustI386Impl.h
  25. 1 0
      dtool/src/dtoolbase/dtool_platform.h
  26. 2 2
      dtool/src/dtoolbase/pallocator.T
  27. 435 0
      dtool/src/dtoolbase/pdtoa.c
  28. 24 0
      dtool/src/dtoolbase/pdtoa.h
  29. 13 0
      dtool/src/dtoolbase/plist.h
  30. 2 2
      dtool/src/dtoolbase/pstrtod.cxx
  31. 2 2
      dtool/src/dtoolbase/typeHandle.cxx
  32. 4 4
      dtool/src/dtoolbase/typeHandle.h
  33. 78 0
      dtool/src/dtoolutil/preprocess_argv.cxx
  34. 9 1
      dtool/src/dtoolutil/string_utils.h
  35. 19 12
      dtool/src/dtoolutil/win32ArgParser.cxx
  36. 5 15
      dtool/src/interrogatedb/py_panda.h
  37. 2 4
      dtool/src/prc/configVariableDouble.cxx
  38. 2 4
      dtool/src/prc/configVariableInt.cxx
  39. 2 4
      dtool/src/prc/configVariableInt64.cxx
  40. 3 0
      makepanda/installpanda.py
  41. 140 112
      makepanda/makepanda.py
  42. 87 39
      makepanda/makepandacore.py
  43. 12 8
      panda/metalibs/pandadx9/Sources.pp
  44. 170 21
      panda/src/bullet/bulletBodyNode.cxx
  45. 13 3
      panda/src/bullet/bulletBodyNode.h
  46. 64 1
      panda/src/bullet/bulletBoxShape.cxx
  47. 11 1
      panda/src/bullet/bulletBoxShape.h
  48. 100 4
      panda/src/bullet/bulletConvexHullShape.cxx
  49. 8 2
      panda/src/bullet/bulletConvexHullShape.h
  50. 67 0
      panda/src/bullet/bulletDebugNode.cxx
  51. 8 1
      panda/src/bullet/bulletDebugNode.h
  52. 68 1
      panda/src/bullet/bulletPlaneShape.cxx
  53. 11 1
      panda/src/bullet/bulletPlaneShape.h
  54. 99 0
      panda/src/bullet/bulletRigidBodyNode.cxx
  55. 11 2
      panda/src/bullet/bulletRigidBodyNode.h
  56. 5 3
      panda/src/bullet/bulletShape.h
  57. 61 1
      panda/src/bullet/bulletSphereShape.cxx
  58. 11 1
      panda/src/bullet/bulletSphereShape.h
  59. 122 0
      panda/src/bullet/bulletTriangleMesh.cxx
  60. 12 5
      panda/src/bullet/bulletTriangleMesh.h
  61. 116 1
      panda/src/bullet/bulletTriangleMeshShape.cxx
  62. 16 1
      panda/src/bullet/bulletTriangleMeshShape.h
  63. 10 0
      panda/src/bullet/config_bullet.cxx
  64. 2 2
      panda/src/cocoadisplay/cocoaGraphicsWindow.mm
  65. 0 3
      panda/src/collide/collisionFloorMesh.I
  66. 1 1
      panda/src/display/config_display.cxx
  67. 17 9
      panda/src/display/get_x11.h
  68. 2 0
      panda/src/display/graphicsDevice.I
  69. 48 0
      panda/src/display/graphicsOutput.I
  70. 3 0
      panda/src/display/graphicsOutput.h
  71. 26 0
      panda/src/display/graphicsStateGuardian.I
  72. 2 0
      panda/src/display/graphicsStateGuardian.cxx
  73. 4 0
      panda/src/display/graphicsStateGuardian.h
  74. 4 18
      panda/src/display/graphicsWindow.cxx
  75. 0 1229
      panda/src/display/lru.cxx
  76. 0 269
      panda/src/display/lru.h
  77. 0 1
      panda/src/display/p3display_composite2.cxx
  78. 13 0
      panda/src/display/standardMunger.I
  79. 2 0
      panda/src/display/standardMunger.cxx
  80. 2 0
      panda/src/display/standardMunger.h
  81. 1 0
      panda/src/display/subprocessWindowBuffer.cxx
  82. 23 12
      panda/src/display/windowProperties.I
  83. 4 0
      panda/src/display/windowProperties.cxx
  84. 1 0
      panda/src/display/windowProperties.h
  85. 0 2
      panda/src/distort/oSphereLens.I
  86. 0 2
      panda/src/dxgsg9/dxIndexBufferContext9.I
  87. 11 5
      panda/src/dxgsg9/dxVertexBufferContext9.I
  88. 1 0
      panda/src/egg2pg/eggSaver.I
  89. 2 1
      panda/src/express/config_express.h
  90. 1 1
      panda/src/express/copy_stream.cxx
  91. 7 0
      panda/src/express/windowsRegistry.cxx
  92. 1 0
      panda/src/glesgsg/glesgsg.h
  93. 4 3
      panda/src/glesgsg/panda_esglext.h
  94. 121 13
      panda/src/glstuff/glCgShaderContext_src.I
  95. 6 0
      panda/src/glstuff/glGeomMunger_src.h
  96. 52 28
      panda/src/glstuff/glGraphicsStateGuardian_src.I
  97. 354 121
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  98. 60 12
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  99. 319 102
      panda/src/glstuff/glShaderContext_src.I
  100. 6 2
      panda/src/glstuff/glShaderContext_src.h

+ 26 - 2
README.md

@@ -29,8 +29,10 @@ need Microsoft Visual Studio to build Panda3D, though - the relevant compilers
 are included as part of the Windows 7.1 SDK.
 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 here:
-https://www.panda3d.org/forums/viewtopic.php?f=9&t=16346
+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:
+https://www.panda3d.org/download/panda3d-1.9.0/panda3d-1.9.0-tools-win32.zip
+https://www.panda3d.org/download/panda3d-1.9.0/panda3d-1.9.0-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:
@@ -81,3 +83,25 @@ your system.  Careful: it is not easy to uninstall Panda3D in this way!
 ```bash
 ```bash
 python2.7 makepanda/installpanda.py --prefix=/usr/local
 python2.7 makepanda/installpanda.py --prefix=/usr/local
 ```
 ```
+
+Mac OS X
+--------
+
+On Mac OS X, all you need to compile Panda3D is a set of precompiled
+thirdparty packages, which can be acquired from here:
+https://www.panda3d.org/download/panda3d-1.9.0/panda3d-1.9.0-tools-mac.tar.gz
+
+After placing the thirdparty directory inside the panda3d source directory,
+you may build Panda3D using a command like the following:
+
+```bash
+python makepanda/makepanda.py --everything --installer
+```
+
+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
+by the release number, eg. 10.6 or 10.7.
+
+If the build was successful, makepanda will have generated a .dmg file in
+the source directory containing the installer.  Simply open it and run the
+package file in order to install the SDK onto your system.

+ 6 - 1
contrib/src/ai/Sources.pp

@@ -203,6 +203,11 @@ def processType(handle, type):
             if docstring:
             if docstring:
                 print >>handle, docstring
                 print >>handle, docstring
             print >>handle, interrogate_type_enum_value_name(type, i_value), "=", interrogate_type_enum_value(type, i_value), ","
             print >>handle, interrogate_type_enum_value_name(type, i_value), "=", interrogate_type_enum_value(type, i_value), ","
+
+    elif interrogate_type_is_typedef(type):
+        wrapped_type = translated_type_name(interrogate_type_wrapped_type(type))
+        print >>handle, "typedef %s %s;" % (wrapped_type, typename)
+        return
     else:
     else:
         if interrogate_type_is_struct(type):
         if interrogate_type_is_struct(type):
             classtype = "struct"
             classtype = "struct"
@@ -211,7 +216,7 @@ def processType(handle, type):
         elif interrogate_type_is_union(type):
         elif interrogate_type_is_union(type):
             classtype = "union"
             classtype = "union"
         else:
         else:
-            print "I don't know what type %s is" % typename
+            print "I don't know what type %s is" % interrogate_type_true_name(type)
             return
             return
         
         
         if len(derivations) > 0:
         if len(derivations) > 0:

+ 4 - 5
direct/src/doc/dcPacker.txt

@@ -107,14 +107,13 @@ def Dtool_PreloadDLL(module):
 # Dtool_FindModule to find our panda3d.core module.  However, we
 # Dtool_FindModule to find our panda3d.core module.  However, we
 # should be able to import it.  To differentiate the old-style Panda
 # should be able to import it.  To differentiate the old-style Panda
 # build (with .dll's) from the new-style Panda build (with .pyd's), we
 # build (with .dll's) from the new-style Panda build (with .pyd's), we
-# first try to import libpandaexpress directly; if it succeeds we're
-# in an old-style build, and if it fails we must be in a new-style
-# build.
+# first try to import panda3d.core directly; if it succeeds we're in a
+# new-style build, and if it fails we must be in an old-style build.
 try:
 try:
+    from panda3d.core import *
+except ImportError:
     Dtool_PreloadDLL("libpandaexpress")
     Dtool_PreloadDLL("libpandaexpress")
     from libpandaexpress import *
     from libpandaexpress import *
-except ImportError:
-    from panda3d.core import *
 
 
 def Dtool_ObjectToDict(cls, name, obj):
 def Dtool_ObjectToDict(cls, name, obj):
     cls.DtoolClassDict[name] = obj;
     cls.DtoolClassDict[name] = obj;

+ 24 - 11
direct/src/http/favicon.ico


+ 1 - 1
direct/src/p3d/panda3d.pdef

@@ -319,7 +319,7 @@ elif deploy_mode == 'installer':
     del i
     del i
 
 
 elif deploy_mode == 'html':
 elif deploy_mode == 'html':
-    w, h = tokens.get("width", 640), tokens.get("height", 480)
+    w, h = tokens.get("width", 800), tokens.get("height", 600)
     if "data" not in tokens:
     if "data" not in tokens:
         tokens["data"] = appFilename.getBasename()
         tokens["data"] = appFilename.getBasename()
 
 

+ 2 - 3
direct/src/p3d/ppackage.py

@@ -90,7 +90,7 @@ Options:
      each supported architecture).  On other platforms, this option
      each supported architecture).  On other platforms, this option
      does nothing.  This is therefore safe to apply in all cases, if
      does nothing.  This is therefore safe to apply in all cases, if
      you wish to take advantage of universal binaries.  This is
      you wish to take advantage of universal binaries.  This is
-     equivalent to "-P osx_ppc -P osx_i386" on Mac platforms.
+     equivalent to "-P osx_i386 -P osx_amd64" on Mac platforms.
 
 
   -P platform
   -P platform
      Specify the platform to masquerade as.  The default is whatever
      Specify the platform to masquerade as.  The default is whatever
@@ -215,8 +215,7 @@ if universalBinaries:
         print '\nYou may not specify both -u and -P.\n'
         print '\nYou may not specify both -u and -P.\n'
         sys.exit(1)
         sys.exit(1)
     if PandaSystem.getPlatform().startswith('osx_'):
     if PandaSystem.getPlatform().startswith('osx_'):
-        # Maybe soon we'll add osx_x86_64 to this default list.
-        platforms = ['osx_i386', 'osx_ppc']
+        platforms = ['osx_i386', 'osx_amd64']
 
 
 if not platforms:
 if not platforms:
     platforms = [PandaSystem.getPlatform()]
     platforms = [PandaSystem.getPlatform()]

+ 8 - 0
direct/src/plugin/fileSpec.I

@@ -157,6 +157,10 @@ AuthDialog(const string &cert_filename, const string &cert_dir) :
   _stack = NULL;
   _stack = NULL;
   _verify_result = -1;
   _verify_result = -1;
 
 
+  // Center the window on the screen.
+  position((Fl::w() - w()) / 2, (Fl::h() - h()) / 2);
+  set_modal();
+
   read_cert_file(cert_filename);
   read_cert_file(cert_filename);
   get_friendly_name();
   get_friendly_name();
   verify_cert();
   verify_cert();
@@ -583,6 +587,10 @@ ViewCertDialog(AuthDialog *auth_dialog, X509 *cert) :
   _auth_dialog(auth_dialog),
   _auth_dialog(auth_dialog),
   _cert(cert)
   _cert(cert)
 {
 {
+  // Center the window on the screen.
+  position((Fl::w() - w()) / 2, (Fl::h() - h()) / 2);
+  set_modal();
+
   layout();
   layout();
 }
 }
 
 

+ 25 - 1
direct/src/plugin/p3dDownload.I

@@ -45,6 +45,10 @@
 #include <dirent.h>
 #include <dirent.h>
 #endif
 #endif
 
 
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
+
 #include <stdio.h>
 #include <stdio.h>
 
 
 static ofstream logfile;
 static ofstream logfile;
@@ -230,9 +234,29 @@ initialize(int api_version, const string &contents_filename,
       _supported_platforms.push_back("win_i386");
       _supported_platforms.push_back("win_i386");
       _supported_platforms.push_back("win32");
       _supported_platforms.push_back("win32");
     }
     }
+#elif defined(__APPLE__)
+    if (_platform == "osx_amd64") {
+      _supported_platforms.push_back("osx_amd64");
+      _supported_platforms.push_back("osx_i386");
+
+    } else if (_platform == "osx_i386") {
+      // This is a 32-bit process, but determine if the underlying OS
+      // supports 64-bit.
+
+      int mib[2] = { CTL_HW, HW_MACHINE };
+      char machine[512];
+      size_t len = 511;
+      if (sysctl(mib, 2, (void *)machine, &len, NULL, 0) == 0) {
+        if (strcmp(machine, "x86_64") == 0) {
+          _supported_platforms.push_back("osx_amd64");
+        }
+      }
+
+      _supported_platforms.push_back("osx_i386");
+    }
 #endif  // _WIN32
 #endif  // _WIN32
 
 
-    // TODO: OSX, Linux multiplatform support.  Just add the
+    // TODO: Linux multiplatform support.  Just add the
     // appropriate platform strings to _supported_platforms.
     // appropriate platform strings to _supported_platforms.
   }
   }
 
 

+ 10 - 3
direct/src/plugin/p3dPackage.I

@@ -461,7 +461,10 @@ def makeInstaller():
 
 
         infoFilename = None
         infoFilename = None
         descriptionFilename = None
         descriptionFilename = None
-        packagemaker = "/Developer/usr/bin/packagemaker"
+        packagemaker = "/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker"
+        if not os.path.exists(packagemaker):
+            packagemaker = "/Developer/usr/bin/packagemaker"
+
         if os.path.exists(packagemaker):
         if os.path.exists(packagemaker):
             # PackageMaker 3.0 or better, e.g. OSX 10.5.
             # PackageMaker 3.0 or better, e.g. OSX 10.5.
             CMD = packagemaker
             CMD = packagemaker
@@ -469,7 +472,7 @@ def makeInstaller():
             CMD += ' --version "%s"' % options.version
             CMD += ' --version "%s"' % options.version
             CMD += ' --title "%s"' % options.long_name
             CMD += ' --title "%s"' % options.long_name
             CMD += ' --out "%s"' % (pkgname)
             CMD += ' --out "%s"' % (pkgname)
-            CMD += ' --target 10.4' # The earliest version of OSX supported by Panda
+            CMD += ' --target 10.5' # The earliest version of OSX supported by Panda
             CMD += ' --domain system'
             CMD += ' --domain system'
             CMD += ' --root "%s"' % tmproot
             CMD += ' --root "%s"' % tmproot
             CMD += ' --resources "%s"' % tmpresdir
             CMD += ' --resources "%s"' % tmpresdir
@@ -520,7 +523,11 @@ def makeInstaller():
         
         
         # Pack the .pkg into a .dmg
         # Pack the .pkg into a .dmg
         if not os.path.exists(tmproot): os.makedirs(tmproot)
         if not os.path.exists(tmproot): os.makedirs(tmproot)
-        shutil.copytree(pkgname, os.path.join(tmproot, pkgname))
+        if os.path.isdir(pkgname):
+            shutil.copytree(pkgname, os.path.join(tmproot, pkgname))
+        else:
+            shutil.copyfile(pkgname, os.path.join(tmproot, pkgname))
+
         tmpdmg = tempfile.mktemp('', 'p3d-setup') + ".dmg"
         tmpdmg = tempfile.mktemp('', 'p3d-setup') + ".dmg"
         CMD = 'hdiutil create "%s" -srcfolder "%s"' % (tmpdmg, tmproot)
         CMD = 'hdiutil create "%s" -srcfolder "%s"' % (tmpdmg, tmproot)
         print ""
         print ""

+ 1 - 1
direct/src/plugin_npapi/startup.cxx

@@ -233,7 +233,7 @@ NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) {
   if (pluginFuncs->size == 0) {
   if (pluginFuncs->size == 0) {
     pluginFuncs->size = sizeof(*pluginFuncs);
     pluginFuncs->size = sizeof(*pluginFuncs);
   }
   }
-  if (pluginFuncs->size < sizeof(*pluginFuncs)) {
+  if (pluginFuncs->size < offsetof(NPPluginFuncs, gotfocus)) {
     nout << "Invalid NPPPluginFuncs size\n";
     nout << "Invalid NPPPluginFuncs size\n";
     return NPERR_INVALID_FUNCTABLE_ERROR;
     return NPERR_INVALID_FUNCTABLE_ERROR;
   }
   }

+ 2 - 2
direct/src/plugin_standalone/p3dEmbed.h

@@ -226,8 +226,8 @@ run_command_line(int argc, char *argv[]) {
       // The user asked for an embedded window.  Create a toplevel
       // The user asked for an embedded window.  Create a toplevel
       // window to be its parent, of the requested size.
       // window to be its parent, of the requested size.
       if (_win_width == 0 && _win_height == 0) {
       if (_win_width == 0 && _win_height == 0) {
-        _win_width = 640;
-        _win_height = 480;
+        _win_width = 800;
+        _win_height = 600;
       }
       }
       
       
       make_parent_window();
       make_parent_window();

+ 2 - 2
direct/src/plugin_standalone/panda3d.h

@@ -62,8 +62,8 @@ Panda3DBase(bool console_environment) {
 
 
   _win_x = -1;
   _win_x = -1;
   _win_y = -1;
   _win_y = -1;
-  _win_width = 640;
-  _win_height = 480;
+  _win_width = 800;
+  _win_height = 600;
   _got_win_size = false;
   _got_win_size = false;
 
 
   _exit_with_last_instance = true;
   _exit_with_last_instance = true;

+ 4 - 3
direct/src/plugin_standalone/panda3dBase.h

@@ -1429,11 +1429,12 @@ dtoolSuperBase = None
 
 
 def _getDtoolSuperBase():
 def _getDtoolSuperBase():
     global dtoolSuperBase
     global dtoolSuperBase
-    from panda3d.core import PandaNode
-    dtoolSuperBase = PandaNode('').__class__.__bases__[0].__bases__[0].__bases__[0]
+    from panda3d.core import TypedObject
+    dtoolSuperBase = TypedObject.__bases__[0]
     assert repr(dtoolSuperBase) == "<type 'libdtoolconfig.DTOOL_SUPER_BASE111'>" \
     assert repr(dtoolSuperBase) == "<type 'libdtoolconfig.DTOOL_SUPER_BASE111'>" \
         or repr(dtoolSuperBase) == "<type 'libdtoolconfig.DTOOL_SUPPER_BASE111'>" \
         or repr(dtoolSuperBase) == "<type 'libdtoolconfig.DTOOL_SUPPER_BASE111'>" \
-        or repr(dtoolSuperBase) == "<type 'dtoolconfig.DTOOL_SUPER_BASE111'>"
+        or repr(dtoolSuperBase) == "<type 'dtoolconfig.DTOOL_SUPER_BASE111'>" \
+        or repr(dtoolSuperBase) == "<type 'dtoolconfig.DTOOL_SUPER_BASE'>"
 
 
 safeReprNotify = None
 safeReprNotify = None
 
 

+ 2 - 2
direct/src/showutil/FreezeTool.py

@@ -143,8 +143,8 @@ class CompilationEnvironment:
                 self.arch = '-arch i386'
                 self.arch = '-arch i386'
             elif proc == 'ppc':
             elif proc == 'ppc':
                 self.arch = '-arch ppc'
                 self.arch = '-arch ppc'
-            elif proc == 'x86_64':
-                self.arch = '-arch x86_x64'
+            elif proc == 'amd64':
+                self.arch = '-arch x86_64'
             self.compileObj = "gcc -fPIC -c %(arch)s -o %(basename)s.o -O2 -I%(pythonIPath)s %(filename)s"
             self.compileObj = "gcc -fPIC -c %(arch)s -o %(basename)s.o -O2 -I%(pythonIPath)s %(filename)s"
             self.linkExe = "gcc %(arch)s -o %(basename)s %(basename)s.o -framework Python"
             self.linkExe = "gcc %(arch)s -o %(basename)s %(basename)s.o -framework Python"
             self.linkDll = "gcc %(arch)s -undefined dynamic_lookup -bundle -o %(basename)s.so %(basename)s.o"
             self.linkDll = "gcc %(arch)s -undefined dynamic_lookup -bundle -o %(basename)s.so %(basename)s.o"

+ 111 - 0
doc/ReleaseNotes

@@ -1,3 +1,114 @@
+------------------------  RELEASE 1.9.0  ------------------------
+
+This is a major release with many exciting new features!
+Beware of bugs.
+
+The list below contains a subset of the changes introduced:
+
+* We now offer 64-bit Windows and Mac OS X builds.
+* Switch to MSVC 2010; no more assembly manifests.
+* Cocoa port for better Mac OS X support, esp. newer versions.
+* We now compile the Python modules into panda3d/*.pyd modules;
+  no more imp.load_dynamic hackery needed.
+* Support for GPU profiling in OpenGL, see pstats-gpu-timing
+* sRGB framebuffers, see framebuffer-srgb
+* sRGB texture support, see Texture::F_srgb et al.
+* Integer vector support, including passing to shaders
+* Native .ogg vorbis and .wav loader (does not require ffmpeg)
+* FFmpeg support is a separate plug-in module now, libp3ffmpeg.
+* Sample programs are now part of the source code repository
+* Can be built with Python 3 (highly experimental)
+* Improvements to Windows installer
+* M_filled_wireframe rendering mode
+* Support specifying sampler state separate from textures
+* Support for bindless texture clearing
+* Texture LOD bias and min/max LOD settings
+* Framebuffer properties allows separate red/green/blue bits
+* Explicit float color and float depth specification in fbprops
+* Coverage samples settable via FrameBufferProperties
+* Stereo buffer implementation in OpenGL via FBOs
+* Support enumeration of pixel formats in WebcamVideo
+* Frame rate meter can be configured to show milliseconds
+* Changes to improve font crispness with default settings
+* Fix assertion error when using more than one GraphicsEngine
+* raw-w, raw-a, etc. keyboard events for layout-independent input
+* Allow querying active keyboard layout via win.get_keyboard_map()
+* Distinguish between lmeta and rmeta keys on Mac OS X
+* Floating-point image manipulation API, support float tiffs
+* Various new 16-bit and 32-bit and int texture formats
+* Man pages are now available for the majority of utilities
+
+Pipeline:
+* Fix bugs with <Collide> group transformations in .egg
+* Don't create unnecessary intermediate node when loading .egg
+* bam2egg supports materials, and correctly converts animations
+* dae2egg has some skeletal animation support
+* Support Maya versions up to 2015
+
+OpenGL renderer changes:
+* Error checking is now OFF by default for performance reasons,
+    set gl-check-errors or gl-debug to true to enable.
+* GL 4.2 shader_image_load_store support (incl. multi-bind)
+* Layered render-to-texture (using geometry shaders)
+* Seamless cube maps (on by default), see gl-cube-map-seamless
+* Added gl-debug for improved debug output support
+* Added GL object labels when gl-debug is enabled
+* gl-dump-compiled-shaders can be used to dump program binaries
+* Direct3D-style NT_packed_dabc vertex arrays now directly supported
+* Native rendering of line strips, using primitive restart
+* Immutable texture storage support (disabled by default)
+* Bindless texture support (disabled by default)
+* Specular component is now computed separately in FFP
+
+Shader system:
+* Support for tessellation shaders
+* Support for compute shaders via ComputeNode
+* GLSL preprocessor with "#pragma include" support
+* Much better coverage of shader inputs in GLSL
+* GLSL error messages now show source filename
+* Fixes apiclip_of_x shader inputs
+* Matrices can be passed directly to setShaderInput
+* Support binding images to shaders
+* Viewport array support
+
+Optimizations and performance improvements:
+* Use of C++11 move semantics to reduce refcounting overhead
+* Build with Eigen by default for faster linear math
+* Dramatic overhead reduction of generated bindings
+* Streamline culling process
+* Tighter bounding volume generation
+* Take advantage of CPU features for bit operations
+* Circumvent bounding volume generation when not required
+* Optimizations for interned strings
+* Use of GCC atomics should improve 64-bit Linux performance
+
+API features:
+* Buffer protocol support for textures and arrays
+* Interrogate supports various C++11 features
+* Expose TextGlyph interfaces for making custom text renderers
+* Better handling of default arguments for many functions
+* Cyclic references can sometimes be tracked through tasks
+* ShowBase clean teardown possible
+* API documentation is more accurate
+* Improve interfaces for interop with other applications
+
+Deprecated features:
+* Use of pandac.PandaModules is discouraged; use panda3d.core
+* Deprecate DirectStart and global run() function; use ShowBase
+* Remove old decal system
+* Remove Direct3D 8 renderer
+* Remove M_light_vector tex gen mode and FFP-based bump mapping
+
+Bug fixes:
+* Various point rendering issues are fixed now
+* Fix pview issue with 1-frame and/or multiple animations
+* Fixes for multisampling in FBOs
+* Fix aspect ratio of frame rate meter
+* Support NaN and infinity values in Config.prc variables
+* Fixes for webcams on Linux that do not output Huffman tables
+* Better support for non-basic Cg shaders on non-NVIDIA cards
+* Many others
+
 ------------------------  RELEASE 1.8.1  ------------------------
 ------------------------  RELEASE 1.8.1  ------------------------
 
 
 This is a bugfix release, fixing many issues in 1.8.0.
 This is a bugfix release, fixing many issues in 1.8.0.

+ 1 - 2
dtool/Config.Cygwin64.pp

@@ -44,5 +44,4 @@
 // integers, but by convention it will consist of four integers, with
 // integers, but by convention it will consist of four integers, with
 // the first three matching the plugin version, and the fourth integer
 // the first three matching the plugin version, and the fourth integer
 // being incremented with each new Core API revision.
 // being incremented with each new Core API revision.
-#define P3D_COREAPI_VERSION $[P3D_PLUGIN_VERSION] 1
-
+#define P3D_COREAPI_VERSION $[P3D_PLUGIN_VERSION] 2

File diff suppressed because it is too large
+ 237 - 236
dtool/metalibs/dtoolconfig/pydtool.cxx


+ 13 - 5
dtool/pptempl/PythonPackageInit.pp

@@ -26,6 +26,7 @@
 #include "cppFunctionGroup.h"
 #include "cppFunctionGroup.h"
 #include "cppFunctionType.h"
 #include "cppFunctionType.h"
 #include "cppBison.h"
 #include "cppBison.h"
+#include "pdtoa.h"
 
 
 #include <assert.h>
 #include <assert.h>
 
 
@@ -1079,7 +1080,13 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     break;
     break;
 
 
   case T_real:
   case T_real:
-    out << _u._real;
+    {
+      // We use our own dtoa implementation here because it guarantees
+      // to never format the number as an integer.
+      char buffer[32];
+      pdtoa(_u._real, buffer);
+      out << buffer;
+    }
     break;
     break;
 
 
   case T_string:
   case T_string:
@@ -1155,14 +1162,15 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const {
     break;
     break;
 
 
   case T_construct:
   case T_construct:
-    out << "(" << _u._typecast._to->get_typedef_name(scope)
-        << "(";
+    _u._typecast._to->output(out, indent_level, scope, false);
+    out << "(";
     _u._typecast._op1->output(out, indent_level, scope, false);
     _u._typecast._op1->output(out, indent_level, scope, false);
-    out << "))";
+    out << ")";
     break;
     break;
 
 
   case T_default_construct:
   case T_default_construct:
-    out << "(" << _u._typecast._to->get_typedef_name(scope) << "())";
+    _u._typecast._to->output(out, indent_level, scope, false);
+    out << "()";
     break;
     break;
 
 
   case T_new:
   case T_new:

+ 1 - 1
dtool/src/cppparser/cppInstance.cxx

@@ -558,7 +558,7 @@ output(ostream &out, int indent_level, CPPScope *scope, bool complete,
     out << " = 0";
     out << " = 0";
   }
   }
   if (_initializer != NULL) {
   if (_initializer != NULL) {
-    out << " = (" << *_initializer << ")";
+    out << " = " << *_initializer;
   }
   }
 }
 }
 
 

+ 13 - 0
dtool/src/cppparser/cppTypedefType.cxx

@@ -204,6 +204,19 @@ CPPDeclaration *CPPTypedefType::
 substitute_decl(CPPDeclaration::SubstDecl &subst,
 substitute_decl(CPPDeclaration::SubstDecl &subst,
                 CPPScope *current_scope, CPPScope *global_scope) {
                 CPPScope *current_scope, CPPScope *global_scope) {
 
 
+  if (_ident != NULL && _ident->get_scope(current_scope, global_scope) == global_scope) {
+    // Hack... I know that size_t etc is supposed to work fine, so
+    // preserve these top-level typedefs.
+    CPPDeclaration *top =
+      CPPType::substitute_decl(subst, current_scope, global_scope);
+    if (top != this) {
+      return top;
+    }
+    top = new CPPTypedefType(*this);
+    subst.insert(SubstDecl::value_type(this, top));
+    return top;
+  }
+
   return _type->substitute_decl(subst, current_scope, global_scope);
   return _type->substitute_decl(subst, current_scope, global_scope);
 
 
   // Bah, this doesn't seem to work, and I can't figure out why.
   // Bah, this doesn't seem to work, and I can't figure out why.

+ 1 - 1
dtool/src/dtoolbase/addHash.I

@@ -31,7 +31,7 @@ struct AtomicAdjust {
 #include "atomicAdjustDummyImpl.h"
 #include "atomicAdjustDummyImpl.h"
 typedef AtomicAdjustDummyImpl AtomicAdjust;
 typedef AtomicAdjustDummyImpl AtomicAdjust;
 
 
-#elif defined(__i386__) || defined(_M_IX86)
+#elif (defined(__i386__) || defined(_M_IX86)) && !defined(__APPLE__)
 // For an i386 architecture, we'll always use the i386 implementation.
 // For an i386 architecture, we'll always use the i386 implementation.
 // It should be safe for any OS, and it might be a bit faster than
 // It should be safe for any OS, and it might be a bit faster than
 // any OS-provided calls.
 // any OS-provided calls.

+ 1 - 1
dtool/src/dtoolbase/atomicAdjustGccImpl.h

@@ -26,7 +26,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_DTOOL AtomicAdjustGccImpl {
 class EXPCL_DTOOL AtomicAdjustGccImpl {
 public:
 public:
-#if __GCC_ATOMIC_LONG_LOCK_FREE > __GCC_ATOMIC_INT_LOCK_FREE
+#if __GCC_ATOMIC_LONG_LOCK_FREE >= __GCC_ATOMIC_INT_LOCK_FREE
   // If the long can be more lock-free than int, use it instead.
   // If the long can be more lock-free than int, use it instead.
   typedef __attribute__ ((aligned (__SIZEOF_LONG__))) long Integer;
   typedef __attribute__ ((aligned (__SIZEOF_LONG__))) long Integer;
 #else
 #else

+ 0 - 6
dtool/src/dtoolbase/atomicAdjustI386Impl.cxx

@@ -12,10 +12,4 @@
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
-#include "selectThreadImpl.h"
-
-#ifdef __i386__
-
 #include "atomicAdjustI386Impl.h"
 #include "atomicAdjustI386Impl.h"
-
-#endif  // __i386__

+ 1 - 1
dtool/src/dtoolbase/atomicAdjustI386Impl.h

@@ -18,7 +18,7 @@
 #include "dtoolbase.h"
 #include "dtoolbase.h"
 #include "selectThreadImpl.h"
 #include "selectThreadImpl.h"
 
 
-#if defined(__i386__) || defined(_M_IX86)
+#if (defined(__i386__) || defined(_M_IX86)) && !defined(__APPLE__)
 
 
 #include "numeric_types.h"
 #include "numeric_types.h"
 
 

+ 1 - 0
dtool/src/dtoolbase/dtool_platform.h

@@ -2,6 +2,7 @@
 #include "mutexWin32Impl.cxx"
 #include "mutexWin32Impl.cxx"
 #include "mutexSpinlockImpl.cxx"
 #include "mutexSpinlockImpl.cxx"
 #include "neverFreeMemory.cxx"
 #include "neverFreeMemory.cxx"
+#include "pdtoa.c"
 #include "pstrtod.cxx"
 #include "pstrtod.cxx"
 #include "register_type.cxx"
 #include "register_type.cxx"
 #include "typeHandle.cxx"
 #include "typeHandle.cxx"

+ 2 - 2
dtool/src/dtoolbase/pallocator.T

@@ -51,7 +51,7 @@ allocate(TYPENAME pallocator_array<Type>::size_type n, TYPENAME allocator<void>:
   size_t alloc_size = n * sizeof(Type);
   size_t alloc_size = n * sizeof(Type);
   // We also need to store the total number of bytes we allocated.
   // We also need to store the total number of bytes we allocated.
   alloc_size += header_reserved_bytes;
   alloc_size += header_reserved_bytes;
-  _type_handle.inc_memory_usage(TypeHandle::MC_array, (int)alloc_size);
+  _type_handle.inc_memory_usage(TypeHandle::MC_array, alloc_size);
   void *ptr = (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(alloc_size);
   void *ptr = (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(alloc_size);
   *((size_t *)ptr) = alloc_size;
   *((size_t *)ptr) = alloc_size;
   return (TYPENAME pallocator_array<Type>::pointer)(((char *)ptr) + header_reserved_bytes);
   return (TYPENAME pallocator_array<Type>::pointer)(((char *)ptr) + header_reserved_bytes);
@@ -69,7 +69,7 @@ deallocate(TYPENAME pallocator_array<Type>::pointer p, TYPENAME pallocator_array
   const size_t header_reserved_bytes = MemoryHook::get_header_reserved_bytes();
   const size_t header_reserved_bytes = MemoryHook::get_header_reserved_bytes();
   void *ptr = (void *)((char *)p - header_reserved_bytes);
   void *ptr = (void *)((char *)p - header_reserved_bytes);
   size_t alloc_size = *((size_t *)ptr);
   size_t alloc_size = *((size_t *)ptr);
-  _type_handle.dec_memory_usage(TypeHandle::MC_array, (int)alloc_size);
+  _type_handle.dec_memory_usage(TypeHandle::MC_array, alloc_size);
   PANDA_FREE_ARRAY(ptr);
   PANDA_FREE_ARRAY(ptr);
 #else
 #else
   free(p);
   free(p);

+ 435 - 0
dtool/src/dtoolbase/pdtoa.c

@@ -0,0 +1,435 @@
+/*
+See pdtoa.h for explanation.
+
+Copyright (C) 2014 Milo Yip
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "pdtoa.h"
+#include "cmath.h"
+
+#include <assert.h>
+#include <math.h>
+#include <stdint.h>
+
+#if defined(_MSC_VER)
+#include <intrin.h>
+#endif
+
+#define UINT64_C2(h, l) ((static_cast<uint64_t>(h) << 32) | static_cast<uint64_t>(l))
+
+struct DiyFp {
+  DiyFp() {}
+
+  DiyFp(uint64_t f, int e) : f(f), e(e) {}
+
+  DiyFp(double d) {
+    union {
+      double d;
+      uint64_t u64;
+    } u = { d };
+
+    int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize;
+    uint64_t significand = (u.u64 & kDpSignificandMask);
+    if (biased_e != 0) {
+      f = significand + kDpHiddenBit;
+      e = biased_e - kDpExponentBias;
+    }
+    else {
+      f = significand;
+      e = kDpMinExponent + 1;
+    }
+  }
+
+  DiyFp operator-(const DiyFp& rhs) const {
+    assert(e == rhs.e);
+    assert(f >= rhs.f);
+    return DiyFp(f - rhs.f, e);
+  }
+
+  DiyFp operator*(const DiyFp& rhs) const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+    uint64_t h;
+    uint64_t l = _umul128(f, rhs.f, &h);
+    if (l & (uint64_t(1) << 63)) // rounding
+      h++;
+    return DiyFp(h, e + rhs.e + 64);
+#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
+    unsigned __int128 p = static_cast<unsigned __int128>(f) * static_cast<unsigned __int128>(rhs.f);
+    uint64_t h = p >> 64;
+    uint64_t l = static_cast<uint64_t>(p);
+    if (l & (uint64_t(1) << 63)) // rounding
+      h++;
+    return DiyFp(h, e + rhs.e + 64);
+#else
+    const uint64_t M32 = 0xFFFFFFFF;
+    const uint64_t a = f >> 32;
+    const uint64_t b = f & M32;
+    const uint64_t c = rhs.f >> 32;
+    const uint64_t d = rhs.f & M32;
+    const uint64_t ac = a * c;
+    const uint64_t bc = b * c;
+    const uint64_t ad = a * d;
+    const uint64_t bd = b * d;
+    uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
+    tmp += 1U << 31;  /// mult_round
+    return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
+#endif
+  }
+
+  DiyFp Normalize() const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+    unsigned long index;
+    _BitScanReverse64(&index, f);
+    return DiyFp(f << (63 - index), e - (63 - index));
+#elif defined(__GNUC__)
+    int s = __builtin_clzll(f);
+    return DiyFp(f << s, e - s);
+#else
+    DiyFp res = *this;
+    while (!(res.f & kDpHiddenBit)) {
+      res.f <<= 1;
+      res.e--;
+    }
+    res.f <<= (kDiySignificandSize - kDpSignificandSize - 1);
+    res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 1);
+    return res;
+#endif
+  }
+
+  DiyFp NormalizeBoundary() const {
+#if defined(_MSC_VER) && defined(_M_AMD64)
+    unsigned long index;
+    _BitScanReverse64(&index, f);
+    return DiyFp (f << (63 - index), e - (63 - index));
+#else
+    DiyFp res = *this;
+    while (!(res.f & (kDpHiddenBit << 1))) {
+      res.f <<= 1;
+      res.e--;
+    }
+    res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
+    res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
+    return res;
+#endif
+  }
+
+  void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
+    DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
+    DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
+    mi.f <<= mi.e - pl.e;
+    mi.e = pl.e;
+    *plus = pl;
+    *minus = mi;
+  }
+
+  static const int kDiySignificandSize = 64;
+  static const int kDpSignificandSize = 52;
+  static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
+  static const int kDpMinExponent = -kDpExponentBias;
+  static const uint64_t kDpExponentMask = UINT64_C2(0x7FF00000, 0x00000000);
+  static const uint64_t kDpSignificandMask = UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
+  static const uint64_t kDpHiddenBit = UINT64_C2(0x00100000, 0x00000000);
+
+  uint64_t f;
+  int e;
+};
+
+inline static DiyFp GetCachedPower(int e, int* K) {
+  // 10^-348, 10^-340, ..., 10^340
+  static const uint64_t kCachedPowers_F[] = {
+    UINT64_C2(0xfa8fd5a0, 0x081c0288), UINT64_C2(0xbaaee17f, 0xa23ebf76),
+    UINT64_C2(0x8b16fb20, 0x3055ac76), UINT64_C2(0xcf42894a, 0x5dce35ea),
+    UINT64_C2(0x9a6bb0aa, 0x55653b2d), UINT64_C2(0xe61acf03, 0x3d1a45df),
+    UINT64_C2(0xab70fe17, 0xc79ac6ca), UINT64_C2(0xff77b1fc, 0xbebcdc4f),
+    UINT64_C2(0xbe5691ef, 0x416bd60c), UINT64_C2(0x8dd01fad, 0x907ffc3c),
+    UINT64_C2(0xd3515c28, 0x31559a83), UINT64_C2(0x9d71ac8f, 0xada6c9b5),
+    UINT64_C2(0xea9c2277, 0x23ee8bcb), UINT64_C2(0xaecc4991, 0x4078536d),
+    UINT64_C2(0x823c1279, 0x5db6ce57), UINT64_C2(0xc2109436, 0x4dfb5637),
+    UINT64_C2(0x9096ea6f, 0x3848984f), UINT64_C2(0xd77485cb, 0x25823ac7),
+    UINT64_C2(0xa086cfcd, 0x97bf97f4), UINT64_C2(0xef340a98, 0x172aace5),
+    UINT64_C2(0xb23867fb, 0x2a35b28e), UINT64_C2(0x84c8d4df, 0xd2c63f3b),
+    UINT64_C2(0xc5dd4427, 0x1ad3cdba), UINT64_C2(0x936b9fce, 0xbb25c996),
+    UINT64_C2(0xdbac6c24, 0x7d62a584), UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
+    UINT64_C2(0xf3e2f893, 0xdec3f126), UINT64_C2(0xb5b5ada8, 0xaaff80b8),
+    UINT64_C2(0x87625f05, 0x6c7c4a8b), UINT64_C2(0xc9bcff60, 0x34c13053),
+    UINT64_C2(0x964e858c, 0x91ba2655), UINT64_C2(0xdff97724, 0x70297ebd),
+    UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), UINT64_C2(0xf8a95fcf, 0x88747d94),
+    UINT64_C2(0xb9447093, 0x8fa89bcf), UINT64_C2(0x8a08f0f8, 0xbf0f156b),
+    UINT64_C2(0xcdb02555, 0x653131b6), UINT64_C2(0x993fe2c6, 0xd07b7fac),
+    UINT64_C2(0xe45c10c4, 0x2a2b3b06), UINT64_C2(0xaa242499, 0x697392d3),
+    UINT64_C2(0xfd87b5f2, 0x8300ca0e), UINT64_C2(0xbce50864, 0x92111aeb),
+    UINT64_C2(0x8cbccc09, 0x6f5088cc), UINT64_C2(0xd1b71758, 0xe219652c),
+    UINT64_C2(0x9c400000, 0x00000000), UINT64_C2(0xe8d4a510, 0x00000000),
+    UINT64_C2(0xad78ebc5, 0xac620000), UINT64_C2(0x813f3978, 0xf8940984),
+    UINT64_C2(0xc097ce7b, 0xc90715b3), UINT64_C2(0x8f7e32ce, 0x7bea5c70),
+    UINT64_C2(0xd5d238a4, 0xabe98068), UINT64_C2(0x9f4f2726, 0x179a2245),
+    UINT64_C2(0xed63a231, 0xd4c4fb27), UINT64_C2(0xb0de6538, 0x8cc8ada8),
+    UINT64_C2(0x83c7088e, 0x1aab65db), UINT64_C2(0xc45d1df9, 0x42711d9a),
+    UINT64_C2(0x924d692c, 0xa61be758), UINT64_C2(0xda01ee64, 0x1a708dea),
+    UINT64_C2(0xa26da399, 0x9aef774a), UINT64_C2(0xf209787b, 0xb47d6b85),
+    UINT64_C2(0xb454e4a1, 0x79dd1877), UINT64_C2(0x865b8692, 0x5b9bc5c2),
+    UINT64_C2(0xc83553c5, 0xc8965d3d), UINT64_C2(0x952ab45c, 0xfa97a0b3),
+    UINT64_C2(0xde469fbd, 0x99a05fe3), UINT64_C2(0xa59bc234, 0xdb398c25),
+    UINT64_C2(0xf6c69a72, 0xa3989f5c), UINT64_C2(0xb7dcbf53, 0x54e9bece),
+    UINT64_C2(0x88fcf317, 0xf22241e2), UINT64_C2(0xcc20ce9b, 0xd35c78a5),
+    UINT64_C2(0x98165af3, 0x7b2153df), UINT64_C2(0xe2a0b5dc, 0x971f303a),
+    UINT64_C2(0xa8d9d153, 0x5ce3b396), UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
+    UINT64_C2(0xbb764c4c, 0xa7a44410), UINT64_C2(0x8bab8eef, 0xb6409c1a),
+    UINT64_C2(0xd01fef10, 0xa657842c), UINT64_C2(0x9b10a4e5, 0xe9913129),
+    UINT64_C2(0xe7109bfb, 0xa19c0c9d), UINT64_C2(0xac2820d9, 0x623bf429),
+    UINT64_C2(0x80444b5e, 0x7aa7cf85), UINT64_C2(0xbf21e440, 0x03acdd2d),
+    UINT64_C2(0x8e679c2f, 0x5e44ff8f), UINT64_C2(0xd433179d, 0x9c8cb841),
+    UINT64_C2(0x9e19db92, 0xb4e31ba9), UINT64_C2(0xeb96bf6e, 0xbadf77d9),
+    UINT64_C2(0xaf87023b, 0x9bf0ee6b)
+  };
+  static const int16_t kCachedPowers_E[] = {
+    -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007,  -980,
+     -954,  -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715,
+     -688,  -661,  -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449,
+     -422,  -396,  -369,  -343,  -316,  -289,  -263,  -236,  -210,  -183,
+     -157,  -130,  -103,   -77,   -50,   -24,     3,    30,    56,    83,
+      109,   136,   162,   189,   216,   242,   269,   295,   322,   348,
+      375,   402,   428,   455,   481,   508,   534,   561,   588,   614,
+      641,   667,   694,   720,   747,   774,   800,   827,   853,   880,
+      907,   933,   960,   986,  1013,  1039,  1066
+  };
+
+  //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
+  double dk = (-61 - e) * 0.30102999566398114 + 347;  // dk must be positive, so can do ceiling in positive
+  int k = static_cast<int>(dk);
+  if (k != dk)
+    k++;
+
+  unsigned index = static_cast<unsigned>((k >> 3) + 1);
+  *K = -(-348 + static_cast<int>(index << 3));  // decimal exponent no need lookup table
+
+  assert(index < sizeof(kCachedPowers_F) / sizeof(kCachedPowers_F[0]));
+  return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
+}
+
+inline static void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
+  while (rest < wp_w && delta - rest >= ten_kappa &&
+       (rest + ten_kappa < wp_w ||  /// closer
+      wp_w - rest > rest + ten_kappa - wp_w)) {
+    buffer[len - 1]--;
+    rest += ten_kappa;
+  }
+}
+
+inline static unsigned CountDecimalDigit32(uint32_t n) {
+  // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
+  if (n < 10) return 1;
+  if (n < 100) return 2;
+  if (n < 1000) return 3;
+  if (n < 10000) return 4;
+  if (n < 100000) return 5;
+  if (n < 1000000) return 6;
+  if (n < 10000000) return 7;
+  if (n < 100000000) return 8;
+  if (n < 1000000000) return 9;
+  return 10;
+}
+
+inline static void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
+  static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
+  const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
+  const DiyFp wp_w = Mp - W;
+  uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
+  uint64_t p2 = Mp.f & (one.f - 1);
+  int kappa = static_cast<int>(CountDecimalDigit32(p1));
+  *len = 0;
+
+  while (kappa > 0) {
+    uint32_t d;
+    switch (kappa) {
+      case 10: d = p1 / 1000000000; p1 %= 1000000000; break;
+      case  9: d = p1 /  100000000; p1 %=  100000000; break;
+      case  8: d = p1 /   10000000; p1 %=   10000000; break;
+      case  7: d = p1 /    1000000; p1 %=    1000000; break;
+      case  6: d = p1 /     100000; p1 %=     100000; break;
+      case  5: d = p1 /      10000; p1 %=      10000; break;
+      case  4: d = p1 /       1000; p1 %=       1000; break;
+      case  3: d = p1 /        100; p1 %=        100; break;
+      case  2: d = p1 /         10; p1 %=         10; break;
+      case  1: d = p1;              p1 =           0; break;
+      default:
+#if defined(_MSC_VER)
+        __assume(0);
+#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+        __builtin_unreachable();
+#else
+        d = 0;
+#endif
+    }
+    if (d || *len)
+      buffer[(*len)++] = '0' + static_cast<char>(d);
+    kappa--;
+    uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
+    if (tmp <= delta) {
+      *K += kappa;
+      GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
+      return;
+    }
+  }
+
+  // kappa = 0
+  for (;;) {
+    p2 *= 10;
+    delta *= 10;
+    char d = static_cast<char>(p2 >> -one.e);
+    if (d || *len)
+      buffer[(*len)++] = '0' + d;
+    p2 &= one.f - 1;
+    kappa--;
+    if (p2 < delta) {
+      *K += kappa;
+      GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]);
+      return;
+    }
+  }
+}
+
+inline static void Grisu2(double value, char* buffer, int* length, int* K) {
+  const DiyFp v(value);
+  DiyFp w_m, w_p;
+  v.NormalizedBoundaries(&w_m, &w_p);
+
+  const DiyFp c_mk = GetCachedPower(w_p.e, K);
+  const DiyFp W = v.Normalize() * c_mk;
+  DiyFp Wp = w_p * c_mk;
+  DiyFp Wm = w_m * c_mk;
+  Wm.f++;
+  Wp.f--;
+  DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
+}
+
+static const char cDigitsLut[200] = {
+  '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
+  '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
+  '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
+  '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
+  '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
+  '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
+  '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
+  '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
+  '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
+  '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'
+};
+
+inline void WriteExponent(int K, char* buffer) {
+  if (K < 0) {
+    *buffer++ = '-';
+    K = -K;
+  }
+
+  if (K >= 100) {
+    *buffer++ = '0' + static_cast<char>(K / 100);
+    K %= 100;
+    const char* d = cDigitsLut + K * 2;
+    *buffer++ = d[0];
+    *buffer++ = d[1];
+  }
+  else if (K >= 10) {
+    const char* d = cDigitsLut + K * 2;
+    *buffer++ = d[0];
+    *buffer++ = d[1];
+  }
+  else
+    *buffer++ = '0' + static_cast<char>(K);
+
+  *buffer = '\0';
+}
+
+inline static void Prettify(char* buffer, int length, int k) {
+  const int kk = length + k;  // 10^(kk-1) <= v < 10^kk
+
+  if (length <= kk && kk <= 21) {
+    // 1234e7 -> 12340000000
+    for (int i = length; i < kk; i++)
+      buffer[i] = '0';
+    buffer[kk] = '.';
+    buffer[kk + 1] = '0';
+    buffer[kk + 2] = '\0';
+  }
+  else if (0 < kk && kk <= 21) {
+    // 1234e-2 -> 12.34
+    memmove(&buffer[kk + 1], &buffer[kk], length - kk);
+    buffer[kk] = '.';
+    buffer[length + 1] = '\0';
+  }
+  else if (-6 < kk && kk <= 0) {
+    // 1234e-6 -> 0.001234
+    const int offset = 2 - kk;
+    memmove(&buffer[offset], &buffer[0], length);
+    buffer[0] = '0';
+    buffer[1] = '.';
+    for (int i = 2; i < offset; i++)
+      buffer[i] = '0';
+    buffer[length + offset] = '\0';
+  }
+  else if (length == 1) {
+    // 1e30
+    buffer[1] = 'e';
+    WriteExponent(kk - 1, &buffer[2]);
+  }
+  else {
+    // 1234e30 -> 1.234e33
+    memmove(&buffer[2], &buffer[1], length - 1);
+    buffer[1] = '.';
+    buffer[length + 1] = 'e';
+    WriteExponent(kk - 1, &buffer[0 + length + 2]);
+  }
+}
+
+void pdtoa(double value, char *buffer) {
+#ifdef _MSC_VER
+  if (copysign(1.0, value) < 0) {
+#else
+  if (signbit(value)) {
+#endif
+    *buffer++ = '-';
+    value = -value;
+  }
+  if (cinf(value)) {
+    buffer[0] = 'i';
+    buffer[1] = 'n';
+    buffer[2] = 'f';
+    buffer[3] = '\0';
+  } else if (cnan(value)) {
+    buffer[0] = 'n';
+    buffer[1] = 'a';
+    buffer[2] = 'n';
+    buffer[3] = '\0';
+  } else if (value == 0.0) {
+    buffer[0] = '0';
+    buffer[1] = '.';
+    buffer[2] = '0';
+    buffer[3] = '\0';
+  } else if (value == 1.0) {
+    buffer[0] = '1';
+    buffer[1] = '.';
+    buffer[2] = '0';
+    buffer[3] = '\0';
+  } else {
+    int length, K;
+    Grisu2(value, buffer, &length, &K);
+    Prettify(buffer, length, K);
+  }
+}

+ 24 - 0
dtool/src/dtoolbase/pdtoa.h

@@ -0,0 +1,24 @@
+/*
+  This is a double-to-string conversion implementation by Milo Yip from:
+    https://github.com/miloyip/dtoa-benchmark
+
+  I introduced it because the ostringstream implementation is just too
+  darned slow, especially when compiled to JavaScript.
+*/
+
+#ifndef PDTOA_H
+#define PDTOA_H
+
+#include "dtoolsymbols.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EXPCL_DTOOL void pdtoa(double value, char *buffer);
+
+#ifdef __cplusplus
+};  /* end of extern "C" */
+#endif
+
+#endif  // PDTOA_H

+ 13 - 0
dtool/src/dtoolbase/plist.h

@@ -49,6 +49,19 @@ public:
   typedef TYPENAME base_class::const_iterator const_iterator;
   typedef TYPENAME base_class::const_iterator const_iterator;
   typedef TYPENAME base_class::reverse_iterator reverse_iterator;
   typedef TYPENAME base_class::reverse_iterator reverse_iterator;
   typedef TYPENAME base_class::const_reverse_iterator const_reverse_iterator;
   typedef TYPENAME base_class::const_reverse_iterator const_reverse_iterator;
+
+  // This exists because libc++'s remove implementation has a bug with
+  // Panda's allocator class.
+  INLINE void remove(const Type &val) {
+    iterator it = this->begin();
+    while (it != this->end()) {
+      if (*it == val) {
+        it = this->erase(it);
+      } else {
+        ++it;
+      }
+    }
+  };
 };
 };
 
 
 #endif  // USE_STL_ALLOCATOR
 #endif  // USE_STL_ALLOCATOR

+ 2 - 2
dtool/src/dtoolbase/pstrtod.cxx

@@ -132,9 +132,9 @@ pstrtod(const char *nptr, char **endptr) {
       }
       }
 
 
       if (esign == '-') {
       if (esign == '-') {
-        value /= pow(evalue, 10.0);
+        value /= pow(10.0, evalue);
       } else {
       } else {
-        value *= pow(evalue, 10.0);
+        value *= pow(10.0, evalue);
       }
       }
     }
     }
   }
   }

+ 2 - 2
dtool/src/dtoolbase/typeHandle.cxx

@@ -49,7 +49,7 @@ get_memory_usage(MemoryClass memory_class) const {
 //               allocated memory for objects of this type.
 //               allocated memory for objects of this type.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TypeHandle::
 void TypeHandle::
-inc_memory_usage(MemoryClass memory_class, int size) {
+inc_memory_usage(MemoryClass memory_class, size_t size) {
   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);
@@ -72,7 +72,7 @@ inc_memory_usage(MemoryClass memory_class, int size) {
 //               the total allocated memory for objects of this type.
 //               the total allocated memory for objects of this type.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TypeHandle::
 void TypeHandle::
-dec_memory_usage(MemoryClass memory_class, int size) {
+dec_memory_usage(MemoryClass memory_class, size_t size) {
   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);

+ 4 - 4
dtool/src/dtoolbase/typeHandle.h

@@ -125,12 +125,12 @@ PUBLISHED:
 
 
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   int get_memory_usage(MemoryClass memory_class) const;
   int get_memory_usage(MemoryClass memory_class) const;
-  void inc_memory_usage(MemoryClass memory_class, int size);
-  void dec_memory_usage(MemoryClass memory_class, int size);
+  void inc_memory_usage(MemoryClass memory_class, size_t size);
+  void dec_memory_usage(MemoryClass memory_class, size_t size);
 #else
 #else
   static CONSTEXPR int get_memory_usage(MemoryClass) { return 0; }
   static CONSTEXPR int get_memory_usage(MemoryClass) { return 0; }
-  INLINE void inc_memory_usage(MemoryClass, int) { }
-  INLINE void dec_memory_usage(MemoryClass, int) { }
+  INLINE void inc_memory_usage(MemoryClass, size_t) { }
+  INLINE void dec_memory_usage(MemoryClass, size_t) { }
 #endif  // DO_MEMORY_USAGE
 #endif  // DO_MEMORY_USAGE
 
 
   INLINE int get_index() const;
   INLINE int get_index() const;

+ 78 - 0
dtool/src/dtoolutil/preprocess_argv.cxx

@@ -20,3 +20,81 @@ format_string(const Thing &thing) {
   str << thing;
   str << thing;
   return str.str();
   return str.str();
 }
 }
+
+INLINE string
+format_string(const string &value) {
+  return value;
+}
+
+INLINE string
+format_string(float value) {
+  char buffer[32];
+  pdtoa(value, buffer);
+  return string(buffer);
+}
+
+INLINE string
+format_string(double value) {
+  char buffer[32];
+  pdtoa(value, buffer);
+  return string(buffer);
+}
+
+INLINE string
+format_string(unsigned int value) {
+  char buffer[11];
+  char *p = buffer + 10;
+  *p = 0;
+  do {
+    *--p = '0' + (value % 10);
+    value /= 10;
+  } while (value > 0);
+
+  return string(p);
+}
+
+INLINE string
+format_string(int value) {
+  char buffer[12];
+  char *p = buffer + 11;
+  *p = 0;
+
+  if (value < 0) {
+    unsigned int posv = (unsigned int)-value;
+    do {
+      *--p = '0' + (posv % 10);
+      posv /= 10;
+    } while (posv > 0);
+    *--p = '-';
+  } else {
+    do {
+      *--p = '0' + (value % 10);
+      value /= 10;
+    } while (value > 0);
+  }
+
+  return string(p);
+}
+
+INLINE string
+format_string(PN_int64 value) {
+  char buffer[21];
+  char *p = buffer + 20;
+  *p = 0;
+
+  if (value < 0) {
+    PN_uint64 posv = (PN_uint64)-value;
+    do {
+      *--p = '0' + (posv % 10);
+      posv /= 10;
+    } while (posv > 0);
+    *--p = '-';
+  } else {
+    do {
+      *--p = '0' + (value % 10);
+      value /= 10;
+    } while (value > 0);
+  }
+
+  return string(p);
+}

+ 9 - 1
dtool/src/dtoolutil/string_utils.h

@@ -19,6 +19,7 @@
 
 
 #include <string>
 #include <string>
 #include "vector_string.h"
 #include "vector_string.h"
+#include "pdtoa.h"
 
 
 // Case-insensitive string comparison, from Stroustrup's C++ third edition.
 // Case-insensitive string comparison, from Stroustrup's C++ third edition.
 // Works like strcmp().
 // Works like strcmp().
@@ -66,7 +67,14 @@ EXPCL_DTOOL bool string_to_stdfloat(const string &str, PN_stdfloat &result);
 template<class Thing>
 template<class Thing>
 INLINE string format_string(const Thing &thing);
 INLINE string format_string(const Thing &thing);
 
 
+// Fast specializations for some primitive types.
+INLINE string format_string(const string &value);
+INLINE string format_string(float value);
+INLINE string format_string(double value);
+INLINE string format_string(unsigned int value);
+INLINE string format_string(int value);
+INLINE string format_string(PN_int64 value);
+
 #include "string_utils.I"
 #include "string_utils.I"
 
 
 #endif
 #endif
-

+ 19 - 12
dtool/src/dtoolutil/win32ArgParser.cxx

@@ -2636,7 +2636,7 @@ write_module_class(ostream &out, Object *obj) {
     write_function_slot(out, 2, slots, "bf_getsegcount");
     write_function_slot(out, 2, slots, "bf_getsegcount");
     write_function_slot(out, 2, slots, "bf_getcharbuffer");
     write_function_slot(out, 2, slots, "bf_getcharbuffer");
     out << "#endif\n";
     out << "#endif\n";
-    out << "#if PY_MAJOR_VERSION >= 0x02060000\n";
+    out << "#if PY_VERSION_HEX >= 0x02060000\n";
     write_function_slot(out, 2, slots, "bf_getbuffer");
     write_function_slot(out, 2, slots, "bf_getbuffer");
     write_function_slot(out, 2, slots, "bf_releasebuffer");
     write_function_slot(out, 2, slots, "bf_releasebuffer");
     out << "#endif\n";
     out << "#endif\n";
@@ -4475,15 +4475,23 @@ write_function_instance(ostream &out, FunctionRemap *remap,
 
 
   // 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) {
-    if (pn > 0) {
-      expected_params += ", ";
+    ParameterRemap *param = remap->_parameters[pn]._remap;
+    CPPType *orig_type = param->get_orig_type();
+    CPPType *type = param->get_new_type();
+    CPPExpression *default_value = param->get_default_value();
+    string param_name = remap->get_parameter_name(pn);
+
+    if (!is_cpp_type_legal(orig_type)) {
+      // We can't wrap this.  We sometimes get here for default arguments.
+      // Just skip this parameter.
+      continue;
     }
     }
 
 
-    bool is_optional = false;
     // Has this remap been selected to consider optional arguments for
     // Has this remap been selected to consider optional arguments for
     // this parameter?  We can do that by adding a vertical bar to the
     // this parameter?  We can do that by adding a vertical bar to the
     // PyArg_ParseTuple format string, coupled with some extra logic
     // PyArg_ParseTuple format string, coupled with some extra logic
     // in the argument handling, below.
     // in the argument handling, below.
+    bool is_optional = false;
     if (remap->_has_this && !is_constructor) {
     if (remap->_has_this && !is_constructor) {
       if (pn > min_num_args) {
       if (pn > min_num_args) {
         is_optional = true;
         is_optional = true;
@@ -4500,11 +4508,9 @@ write_function_instance(ostream &out, FunctionRemap *remap,
       }
       }
     }
     }
 
 
-    ParameterRemap *param = remap->_parameters[pn]._remap;
-    CPPType *orig_type = param->get_orig_type();
-    CPPType *type = param->get_new_type();
-    CPPExpression *default_value = param->get_default_value();
-    string param_name = remap->get_parameter_name(pn);
+    if (pn > 0) {
+      expected_params += ", ";
+    }
 
 
     // This is the string to convert our local variable to the
     // This is the string to convert our local variable to the
     // appropriate C++ type.  Normally this is just a cast.
     // appropriate C++ type.  Normally this is just a cast.
@@ -6432,10 +6438,11 @@ is_remap_legal(FunctionRemap *remap) {
     return false;
     return false;
   }
   }
 
 
-  // all params must be legal
+  // all non-optional params must be legal
   for (int pn = 0; pn < (int)remap->_parameters.size(); pn++) {
   for (int pn = 0; pn < (int)remap->_parameters.size(); pn++) {
-    CPPType *orig_type = remap->_parameters[pn]._remap->get_orig_type();
-    if (!is_cpp_type_legal(orig_type)) {
+    ParameterRemap *param = remap->_parameters[pn]._remap;
+    CPPType *orig_type = param->get_orig_type();
+    if (param->get_default_value() == NULL && !is_cpp_type_legal(orig_type)) {
       return false;
       return false;
     }
     }
   }
   }

+ 5 - 15
dtool/src/interrogatedb/py_panda.h

@@ -16,7 +16,7 @@
 #include "configVariableCore.h"
 #include "configVariableCore.h"
 #include "config_prc.h"
 #include "config_prc.h"
 #include "pstrtod.h"
 #include "pstrtod.h"
-
+#include "string_utils.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ConfigDeclaration::Constructor
 //     Function: ConfigDeclaration::Constructor
@@ -93,11 +93,7 @@ set_string_word(int n, const string &value) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ConfigDeclaration::
 void ConfigDeclaration::
 set_bool_word(int n, bool value) {
 set_bool_word(int n, bool value) {
-  if (value) {
-    set_string_word(n, "1");
-  } else {
-    set_string_word(n, "0");
-  }
+  set_string_word(n, value ? "1" : "0");
 
 
   _words[n]._flags |= (F_checked_bool | F_valid_bool);
   _words[n]._flags |= (F_checked_bool | F_valid_bool);
   _words[n]._bool = value;
   _words[n]._bool = value;
@@ -112,9 +108,7 @@ set_bool_word(int n, bool value) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ConfigDeclaration::
 void ConfigDeclaration::
 set_int_word(int n, int value) {
 set_int_word(int n, int value) {
-  ostringstream strm;
-  strm << value;
-  set_string_word(n, strm.str());
+  set_string_word(n, format_string(value));
 
 
   _words[n]._flags |= (F_checked_int | F_valid_int);
   _words[n]._flags |= (F_checked_int | F_valid_int);
   _words[n]._int = value;
   _words[n]._int = value;
@@ -129,9 +123,7 @@ set_int_word(int n, int value) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ConfigDeclaration::
 void ConfigDeclaration::
 set_int64_word(int n, PN_int64 value) {
 set_int64_word(int n, PN_int64 value) {
-  ostringstream strm;
-  strm << value;
-  set_string_word(n, strm.str());
+  set_string_word(n, format_string(value));
 
 
   _words[n]._flags |= (F_checked_int64 | F_valid_int64);
   _words[n]._flags |= (F_checked_int64 | F_valid_int64);
   _words[n]._int_64 = value;
   _words[n]._int_64 = value;
@@ -146,9 +138,7 @@ set_int64_word(int n, PN_int64 value) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ConfigDeclaration::
 void ConfigDeclaration::
 set_double_word(int n, double value) {
 set_double_word(int n, double value) {
-  ostringstream strm;
-  strm << value;
-  set_string_word(n, strm.str());
+  set_string_word(n, format_string(value));
 
 
   _words[n]._flags |= (F_checked_double | F_valid_double);
   _words[n]._flags |= (F_checked_double | F_valid_double);
   _words[n]._double = value;
   _words[n]._double = value;

+ 2 - 4
dtool/src/prc/configVariableDouble.cxx

@@ -13,6 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "configVariableDouble.h"
 #include "configVariableDouble.h"
+#include "string_utils.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ConfigVariableDouble::set_default_value
 //     Function: ConfigVariableDouble::set_default_value
@@ -21,8 +22,5 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ConfigVariableDouble::
 void ConfigVariableDouble::
 set_default_value(double default_value) {
 set_default_value(double default_value) {
-  ostringstream strm;
-  strm << default_value;
-
-  _core->set_default_value(strm.str());
+  _core->set_default_value(format_string(default_value));
 }
 }

+ 2 - 4
dtool/src/prc/configVariableInt.cxx

@@ -13,6 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "configVariableInt.h"
 #include "configVariableInt.h"
+#include "string_utils.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ConfigVariableInt::set_default_value
 //     Function: ConfigVariableInt::set_default_value
@@ -21,8 +22,5 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ConfigVariableInt::
 void ConfigVariableInt::
 set_default_value(int default_value) {
 set_default_value(int default_value) {
-  ostringstream strm;
-  strm << default_value;
-
-  _core->set_default_value(strm.str());
+  _core->set_default_value(format_string(default_value));
 }
 }

+ 2 - 4
dtool/src/prc/configVariableInt64.cxx

@@ -13,6 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "configVariableInt64.h"
 #include "configVariableInt64.h"
+#include "string_utils.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ConfigVariableInt64::set_default_value
 //     Function: ConfigVariableInt64::set_default_value
@@ -21,8 +22,5 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ConfigVariableInt64::
 void ConfigVariableInt64::
 set_default_value(PN_int64 default_value) {
 set_default_value(PN_int64 default_value) {
-  ostringstream strm;
-  strm << default_value;
-
-  _core->set_default_value(strm.str());
+  _core->set_default_value(format_string(default_value));
 }
 }

+ 3 - 0
makepanda/installpanda.py

@@ -127,6 +127,9 @@ def GetLibDir():
     something like "lib" or "lib64" or in some cases, something
     something like "lib" or "lib64" or in some cases, something
     similar to "lib/x86_64-linux-gnu". """
     similar to "lib/x86_64-linux-gnu". """
 
 
+    if sys.platform == "darwin":
+        return "lib"
+
     # This one's a bit tricky.  Some systems require us to install
     # This one's a bit tricky.  Some systems require us to install
     # 64-bits libraries into /usr/lib64, some into /usr/lib.
     # 64-bits libraries into /usr/lib64, some into /usr/lib.
     # Debian forbids installing to lib64 nowadays, and the only distros
     # Debian forbids installing to lib64 nowadays, and the only distros

+ 140 - 112
makepanda/makepanda.py

@@ -67,7 +67,7 @@ MAJOR_VERSION=None
 COREAPI_VERSION=None
 COREAPI_VERSION=None
 PLUGIN_VERSION=None
 PLUGIN_VERSION=None
 OSXTARGET=None
 OSXTARGET=None
-UNIVERSAL=False
+OSX_ARCHS=[]
 HOST_URL=None
 HOST_URL=None
 global STRDXSDKVERSION, STRMSPLATFORMVERSION, BOOUSEINTELCOMPILER
 global STRDXSDKVERSION, STRMSPLATFORMVERSION, BOOUSEINTELCOMPILER
 STRDXSDKVERSION = 'default'
 STRDXSDKVERSION = 'default'
@@ -150,6 +150,9 @@ def usage(problem):
     for pkg in PkgListGet():
     for pkg in PkgListGet():
         p = pkg.lower()
         p = pkg.lower()
         print("  --use-%-9s   --no-%-9s (enable/disable use of %s)"%(p, p, pkg))
         print("  --use-%-9s   --no-%-9s (enable/disable use of %s)"%(p, p, pkg))
+    if sys.platform != 'win32':
+        print("  --<PKG>-incdir    (custom location for header files of thirdparty package)")
+        print("  --<PKG>-libdir    (custom location for library files of thirdparty package)")
     print("")
     print("")
     print("  --nothing         (disable every third-party lib)")
     print("  --nothing         (disable every third-party lib)")
     print("  --everything      (enable every third-party lib)")
     print("  --everything      (enable every third-party lib)")
@@ -165,7 +168,7 @@ def usage(problem):
 
 
 def parseopts(args):
 def parseopts(args):
     global INSTALLER,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION
     global INSTALLER,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION
-    global COMPRESSOR,THREADCOUNT,OSXTARGET,UNIVERSAL,HOST_URL
+    global COMPRESSOR,THREADCOUNT,OSXTARGET,OSX_ARCHS,HOST_URL
     global DEBVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX
     global DEBVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX
     global STRDXSDKVERSION, STRMSPLATFORMVERSION, BOOUSEINTELCOMPILER
     global STRDXSDKVERSION, STRMSPLATFORMVERSION, BOOUSEINTELCOMPILER
     longopts = [
     longopts = [
@@ -179,11 +182,15 @@ def parseopts(args):
     optimize = ""
     optimize = ""
     target = None
     target = None
     target_arch = None
     target_arch = None
-    for pkg in PkgListGet(): longopts.append("no-"+pkg.lower())
-    for pkg in PkgListGet(): longopts.append("use-"+pkg.lower())
+    universal = False
+    for pkg in PkgListGet():
+        longopts.append("use-" + pkg.lower())
+        longopts.append("no-" + pkg.lower())
+        longopts.append(pkg.lower() + "-incdir=")
+        longopts.append(pkg.lower() + "-libdir=")
     try:
     try:
         opts, extras = getopt.getopt(args, "", longopts)
         opts, extras = getopt.getopt(args, "", longopts)
-        for option,value in opts:
+        for option, value in opts:
             if (option=="--help"): raise Exception
             if (option=="--help"): raise Exception
             elif (option=="--optimize"): optimize=value
             elif (option=="--optimize"): optimize=value
             elif (option=="--installer"): INSTALLER=1
             elif (option=="--installer"): INSTALLER=1
@@ -197,7 +204,7 @@ def parseopts(args):
             elif (option=="--threads"): THREADCOUNT=int(value)
             elif (option=="--threads"): THREADCOUNT=int(value)
             elif (option=="--outputdir"): SetOutputDir(value.strip())
             elif (option=="--outputdir"): SetOutputDir(value.strip())
             elif (option=="--osxtarget"): OSXTARGET=value.strip()
             elif (option=="--osxtarget"): OSXTARGET=value.strip()
-            elif (option=="--universal"): UNIVERSAL=True
+            elif (option=="--universal"): universal = True
             elif (option=="--target"): target = value.strip()
             elif (option=="--target"): target = value.strip()
             elif (option=="--arch"): target_arch = value.strip()
             elif (option=="--arch"): target_arch = value.strip()
             elif (option=="--nocolor"): DisableColors()
             elif (option=="--nocolor"): DisableColors()
@@ -228,19 +235,25 @@ def parseopts(args):
             elif (option=="--use-icl"): BOOUSEINTELCOMPILER = True
             elif (option=="--use-icl"): BOOUSEINTELCOMPILER = True
             else:
             else:
                 for pkg in PkgListGet():
                 for pkg in PkgListGet():
-                    if (option=="--use-"+pkg.lower()):
+                    if option == "--use-" + pkg.lower():
                         PkgEnable(pkg)
                         PkgEnable(pkg)
                         break
                         break
-                for pkg in PkgListGet():
-                    if (option=="--no-"+pkg.lower()):
+                    elif option == "--no-" + pkg.lower():
                         PkgDisable(pkg)
                         PkgDisable(pkg)
                         break
                         break
-            if  (option=="--everything" or option.startswith("--use-")
-                or option=="--nothing" or option.startswith("--no-")):
+                    elif option == "--" + pkg.lower() + "-incdir":
+                        PkgSetCustomLocation(pkg)
+                        IncDirectory(pkg, value)
+                        break
+                    elif option == "--" + pkg.lower() + "-libdir":
+                        PkgSetCustomLocation(pkg)
+                        LibDirectory(pkg, value)
+                        break
+            if (option == "--everything" or option.startswith("--use-")
+                or option == "--nothing" or option.startswith("--no-")):
                 anything = 1
                 anything = 1
     except:
     except:
-        usage(0)
-        print("Exception while parsing commandline:", sys.exc_info()[0])
+        usage(sys.exc_info()[1])
 
 
     if not anything:
     if not anything:
         if RUNTIME:
         if RUNTIME:
@@ -252,23 +265,39 @@ def parseopts(args):
         usage("Options --runtime and --rtdist cannot be specified at the same time!")
         usage("Options --runtime and --rtdist cannot be specified at the same time!")
     if (optimize=="" and (RTDIST or RUNTIME)): optimize = "4"
     if (optimize=="" and (RTDIST or RUNTIME)): optimize = "4"
     elif (optimize==""): optimize = "3"
     elif (optimize==""): optimize = "3"
-    if (OSXTARGET != None and OSXTARGET.strip() == ""):
-        OSXTARGET = None
-    elif (OSXTARGET != None):
-        OSXTARGET = OSXTARGET.strip()
-        if (len(OSXTARGET) != 4 or not OSXTARGET.startswith("10.")):
-            usage("Invalid setting for OSXTARGET")
+
+    if OSXTARGET:
         try:
         try:
-            OSXTARGET = "10.%d" % (int(OSXTARGET[-1]))
+            maj, min = OSXTARGET.strip().split('.')
+            OSXTARGET = int(maj), int(min)
+            assert OSXTARGET[0] == 10
         except:
         except:
             usage("Invalid setting for OSXTARGET")
             usage("Invalid setting for OSXTARGET")
+    else:
+        OSXTARGET = None
 
 
-    if UNIVERSAL:
-        if not OSXTARGET:
-            exit("--universal requires --osxtarget")
+    if target is not None or target_arch is not None:
+        SetTarget(target, target_arch)
+
+    if universal:
         if target_arch:
         if target_arch:
             exit("--universal is incompatible with --arch")
             exit("--universal is incompatible with --arch")
 
 
+        OSX_ARCHS.append("i386")
+        if OSXTARGET:
+            osxver = OSXTARGET
+        else:
+            maj, min = platform.mac_ver()[0].split('.')[:2]
+            osxver = int(maj), int(min)
+
+        if osxver[1] < 6:
+            OSX_ARCHS.append("ppc")
+        else:
+            OSX_ARCHS.append("x86_64")
+
+    elif HasTargetArch():
+        OSX_ARCHS.append(GetTargetArch())
+
     try:
     try:
         SetOptimize(int(optimize))
         SetOptimize(int(optimize))
         assert GetOptimize() in [1, 2, 3, 4]
         assert GetOptimize() in [1, 2, 3, 4]
@@ -278,9 +307,6 @@ def parseopts(args):
     if GIT_COMMIT is not None and not re.match("^[a-f0-9]{40}$", GIT_COMMIT):
     if GIT_COMMIT is not None and not re.match("^[a-f0-9]{40}$", GIT_COMMIT):
         usage("Invalid SHA-1 hash given for --git-commit option!")
         usage("Invalid SHA-1 hash given for --git-commit option!")
 
 
-    if target is not None or target_arch is not None:
-        SetTarget(target, target_arch)
-
     is_win7 = False
     is_win7 = False
     if GetHost() == "windows":
     if GetHost() == "windows":
         if (STRMSPLATFORMVERSION not in ['winserver2003r2', 'win60A']):
         if (STRMSPLATFORMVERSION not in ['winserver2003r2', 'win60A']):
@@ -316,8 +342,8 @@ if ("LDFLAGS" in os.environ):
     LDFLAGS = os.environ["LDFLAGS"].strip()
     LDFLAGS = os.environ["LDFLAGS"].strip()
 
 
 os.environ["MAKEPANDA"] = os.path.abspath(sys.argv[0])
 os.environ["MAKEPANDA"] = os.path.abspath(sys.argv[0])
-if (GetHost() == "darwin" and OSXTARGET != None):
-    os.environ["MACOSX_DEPLOYMENT_TARGET"] = OSXTARGET
+if GetHost() == "darwin" and OSXTARGET is not None:
+    os.environ["MACOSX_DEPLOYMENT_TARGET"] = "%d.%d" % OSXTARGET
 
 
 ########################################################################
 ########################################################################
 ##
 ##
@@ -683,7 +709,7 @@ if (COMPILER=="GCC"):
     elif RUNTIME:
     elif RUNTIME:
         # We don't support Cocoa in the runtime yet.
         # We don't support Cocoa in the runtime yet.
         PkgDisable("COCOA")
         PkgDisable("COCOA")
-    if UNIVERSAL or GetTargetArch() == 'x86_64':
+    if 'x86_64' in OSX_ARCHS:
         # 64-bits OS X doesn't have Carbon.
         # 64-bits OS X doesn't have Carbon.
         PkgDisable("CARBON")
         PkgDisable("CARBON")
 
 
@@ -710,7 +736,7 @@ if (COMPILER=="GCC"):
     if (not RUNTIME):
     if (not RUNTIME):
         SmartPkgEnable("EIGEN",     "eigen3",    (), ("Eigen/Dense",), target_pkg = 'ALWAYS')
         SmartPkgEnable("EIGEN",     "eigen3",    (), ("Eigen/Dense",), target_pkg = 'ALWAYS')
         SmartPkgEnable("ARTOOLKIT", "",          ("AR"), "AR/ar.h")
         SmartPkgEnable("ARTOOLKIT", "",          ("AR"), "AR/ar.h")
-        SmartPkgEnable("FCOLLADA",  "",          ChooseLib(fcollada_libs, "FCOLLADA"), ("FCollada", "FCollada.h"))
+        SmartPkgEnable("FCOLLADA",  "",          ChooseLib(fcollada_libs, "FCOLLADA"), ("FCollada", "FCollada/FCollada.h"))
         SmartPkgEnable("FFMPEG",    ffmpeg_libs, ffmpeg_libs, ffmpeg_libs)
         SmartPkgEnable("FFMPEG",    ffmpeg_libs, ffmpeg_libs, ffmpeg_libs)
         SmartPkgEnable("SWSCALE",   "libswscale", "libswscale", ("libswscale", "libswscale/swscale.h"), target_pkg = "FFMPEG")
         SmartPkgEnable("SWSCALE",   "libswscale", "libswscale", ("libswscale", "libswscale/swscale.h"), target_pkg = "FFMPEG")
         SmartPkgEnable("SWRESAMPLE","libswresample", "libswresample", ("libswresample", "libswresample/swresample.h"), target_pkg = "FFMPEG")
         SmartPkgEnable("SWRESAMPLE","libswresample", "libswresample", ("libswresample", "libswresample/swresample.h"), target_pkg = "FFMPEG")
@@ -734,11 +760,12 @@ if (COMPILER=="GCC"):
 
 
         if GetTarget() == "darwin" and not PkgSkip("FFMPEG"):
         if GetTarget() == "darwin" and not PkgSkip("FFMPEG"):
             LibName("FFMPEG", "-Wl,-read_only_relocs,suppress")
             LibName("FFMPEG", "-Wl,-read_only_relocs,suppress")
+            LibName("FFMPEG", "-framework VideoDecodeAcceleration")
 
 
         cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV")
         cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV")
         if cv_lib == "opencv_core":
         if cv_lib == "opencv_core":
             OPENCV_VER_23 = True
             OPENCV_VER_23 = True
-            SmartPkgEnable("OPENCV", "opencv",   ("opencv_core"), ("opencv2/core/core.hpp"))
+            SmartPkgEnable("OPENCV", "opencv",   ("opencv_core", "opencv_highgui"), ("opencv2/core/core.hpp"))
         else:
         else:
             SmartPkgEnable("OPENCV", "opencv",   ("cv", "highgui", "cvaux", "ml", "cxcore"),
             SmartPkgEnable("OPENCV", "opencv",   ("cv", "highgui", "cvaux", "ml", "cxcore"),
                            ("opencv", "opencv/cv.h", "opencv/cxcore.h", "opencv/highgui.h"))
                            ("opencv", "opencv/cv.h", "opencv/cxcore.h", "opencv/highgui.h"))
@@ -752,8 +779,7 @@ if (COMPILER=="GCC"):
         SmartPkgEnable("ROCKET",    "",          rocket_libs, "Rocket/Core.h")
         SmartPkgEnable("ROCKET",    "",          rocket_libs, "Rocket/Core.h")
 
 
         if not PkgSkip("PYTHON"):
         if not PkgSkip("PYTHON"):
-            if GetHost() == "darwin" and GetTarget() == "darwin" and not RTDIST:
-                # Use the system Python framework in the standard Mac SDK.
+            if GetTarget() == "darwin" and not RTDIST and not PkgHasCustomLocation("PYTHON"):
                 LibName("PYTHON", "-framework Python")
                 LibName("PYTHON", "-framework Python")
             else:
             else:
                 SmartPkgEnable("PYTHON", "", SDK["PYTHONVERSION"], (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h"), tool = SDK["PYTHONVERSION"] + "-config")
                 SmartPkgEnable("PYTHON", "", SDK["PYTHONVERSION"], (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h"), tool = SDK["PYTHONVERSION"] + "-config")
@@ -1125,20 +1151,13 @@ def CompileCxx(obj,src,opts):
         # Mac-specific flags.
         # Mac-specific flags.
         if GetTarget() == "darwin":
         if GetTarget() == "darwin":
             cmd += " -Wno-deprecated-declarations"
             cmd += " -Wno-deprecated-declarations"
-            if (OSXTARGET != None):
+            if OSXTARGET is not None:
                 cmd += " -isysroot " + SDK["MACOSX"]
                 cmd += " -isysroot " + SDK["MACOSX"]
-                cmd += " -mmacosx-version-min=" + OSXTARGET
-
-            if UNIVERSAL:
-                cmd += " -arch i386"
-                if OSXTARGET:
-                    osxver = int(OSXTARGET[-1])
-                    if "NOPPC" not in opts and int(OSXTARGET[-1]) < 6:
-                        cmd += " -arch ppc"
-                    if int(OSXTARGET[-1]) >= 5:
-                        cmd += " -arch x86_64"
-            elif HasTargetArch():
-                cmd += " -arch %s" % (GetTargetArch())
+                cmd += " -mmacosx-version-min=%d.%d" % (OSXTARGET)
+
+            for arch in OSX_ARCHS:
+                if 'NOARCH:' + arch.upper() not in opts:
+                    cmd += " -arch %s" % arch
 
 
         if "SYSROOT" in SDK:
         if "SYSROOT" in SDK:
             cmd += ' --sysroot=%s -no-canonical-prefixes' % (SDK["SYSROOT"])
             cmd += ' --sysroot=%s -no-canonical-prefixes' % (SDK["SYSROOT"])
@@ -1587,20 +1606,13 @@ def CompileLink(dll, obj, opts):
         # Mac OS X specific flags.
         # Mac OS X specific flags.
         if GetTarget() == 'darwin':
         if GetTarget() == 'darwin':
             cmd += " -headerpad_max_install_names"
             cmd += " -headerpad_max_install_names"
-            if OSXTARGET != None:
+            if OSXTARGET is not None:
                 cmd += " -isysroot " + SDK["MACOSX"] + " -Wl,-syslibroot," + SDK["MACOSX"]
                 cmd += " -isysroot " + SDK["MACOSX"] + " -Wl,-syslibroot," + SDK["MACOSX"]
-                cmd += " -mmacosx-version-min=" + OSXTARGET
-
-            if UNIVERSAL:
-                cmd += " -arch i386"
-                if OSXTARGET:
-                    osxver = int(OSXTARGET[-1])
-                    if "NOPPC" not in opts and int(OSXTARGET[-1]) < 6:
-                        cmd += " -arch ppc"
-                    if int(OSXTARGET[-1]) >= 5:
-                        cmd += " -arch x86_64"
-            elif HasTargetArch():
-                cmd += " -arch %s" % (GetTargetArch())
+                cmd += " -mmacosx-version-min=%d.%d" % (OSXTARGET)
+
+            for arch in OSX_ARCHS:
+                if 'NOARCH:' + arch.upper() not in opts:
+                    cmd += " -arch %s" % arch
 
 
         if "SYSROOT" in SDK:
         if "SYSROOT" in SDK:
             cmd += " --sysroot=%s -no-canonical-prefixes" % (SDK["SYSROOT"])
             cmd += " --sysroot=%s -no-canonical-prefixes" % (SDK["SYSROOT"])
@@ -1820,10 +1832,13 @@ def Package(target, inputs, opts):
     command += "direct/src/p3d/ppackage.py"
     command += "direct/src/p3d/ppackage.py"
 
 
     if GetTarget() == "darwin":
     if GetTarget() == "darwin":
-        if SDK.get("MACOSX") is not None:
+        if SDK.get("MACOSX"):
             command += " -R \"%s\"" % SDK["MACOSX"]
             command += " -R \"%s\"" % SDK["MACOSX"]
-        if UNIVERSAL:
-            command += " -u"
+
+        for arch in OSX_ARCHS:
+            if arch == "x86_64":
+                arch = "amd64"
+            command += " -P osx_%s" % arch
 
 
     command += " -i \"" + GetOutputDir() + "/stage\""
     command += " -i \"" + GetOutputDir() + "/stage\""
     if (P3DSUFFIX):
     if (P3DSUFFIX):
@@ -2608,14 +2623,27 @@ if tp_dir is not None:
                 if (PkgSkip("PYTHON")==0 and os.path.exists(tp_pkg + "/bin/" + SDK["PYTHONVERSION"])):
                 if (PkgSkip("PYTHON")==0 and os.path.exists(tp_pkg + "/bin/" + SDK["PYTHONVERSION"])):
                     CopyAllFiles(GetOutputDir() + "/bin/", tp_pkg + "/bin/" + SDK["PYTHONVERSION"] + "/")
                     CopyAllFiles(GetOutputDir() + "/bin/", tp_pkg + "/bin/" + SDK["PYTHONVERSION"] + "/")
         else:
         else:
-            if os.path.exists(tp_pkg + "/lib"):
-                CopyAllFiles(GetOutputDir() + "/lib/", tp_pkg + "/lib/")
-                if (PkgSkip("PYTHON")==0 and os.path.exists(tp_pkg + "/lib/" + SDK["PYTHONVERSION"])):
-                    CopyAllFiles(GetOutputDir() + "/lib/", tp_pkg + "/lib/" + SDK["PYTHONVERSION"] + "/")
+            for tp_lib in glob.glob(tp_pkg + "/lib/*.so*"):
+                CopyFile(GetOutputDir() + "/lib/" + os.path.basename(tp_lib), tp_lib)
+
+            if not PkgSkip("PYTHON"):
+                for tp_lib in glob.glob(os.path.join(tp_pkg, "lib", SDK["PYTHONVERSION"], "*.so*")):
+                    CopyFile(GetOutputDir() + "/lib/" + os.path.basename(tp_lib), tp_lib)
+
+            if GetTarget() == 'darwin':
+                for tp_lib in glob.glob(tp_pkg + "/lib/*.dylib"):
+                    CopyFile(GetOutputDir() + "/lib/" + os.path.basename(tp_lib), tp_lib)
+
+                if not PkgSkip("PYTHON"):
+                    for tp_lib in glob.glob(os.path.join(tp_pkg, "lib", SDK["PYTHONVERSION"], "*.dylib")):
+                        CopyFile(GetOutputDir() + "/lib/" + os.path.basename(tp_lib), tp_lib)
+
+                for fwx in glob.glob(tp_pkg + "/*.framework"):
+                    CopyTree(GetOutputDir() + "/Frameworks/" + os.path.basename(fwx), fwx)
 
 
     if GetTarget() == 'windows':
     if GetTarget() == 'windows':
         CopyAllFiles(GetOutputDir() + "/bin/", tp_dir + "extras/bin/")
         CopyAllFiles(GetOutputDir() + "/bin/", tp_dir + "extras/bin/")
-        if PkgSkip("PYTHON") == 0:
+        if not PkgSkip("PYTHON"):
             pydll = "/" + SDK["PYTHONVERSION"].replace(".", "")
             pydll = "/" + SDK["PYTHONVERSION"].replace(".", "")
             if (GetOptimize() <= 2): pydll += "_d.dll"
             if (GetOptimize() <= 2): pydll += "_d.dll"
             else: pydll += ".dll"
             else: pydll += ".dll"
@@ -3745,7 +3773,6 @@ if (not RUNTIME):
 
 
   TargetAdd('core_module.obj', opts=['IMOD:panda3d.core', 'ILIB:core'])
   TargetAdd('core_module.obj', opts=['IMOD:panda3d.core', 'ILIB:core'])
 
 
-  OPTS=['WINSOCK2']
   TargetAdd('core.pyd', input='libp3downloader_igate.obj')
   TargetAdd('core.pyd', input='libp3downloader_igate.obj')
   TargetAdd('core.pyd', input='p3express_ext_composite.obj')
   TargetAdd('core.pyd', input='p3express_ext_composite.obj')
   TargetAdd('core.pyd', input='libp3express_igate.obj')
   TargetAdd('core.pyd', input='libp3express_igate.obj')
@@ -3795,7 +3822,7 @@ if (not RUNTIME):
   TargetAdd('core.pyd', input='core_module.obj')
   TargetAdd('core.pyd', input='core_module.obj')
   TargetAdd('core.pyd', input='libp3tinyxml.ilb')
   TargetAdd('core.pyd', input='libp3tinyxml.ilb')
   TargetAdd('core.pyd', input=COMMON_PANDA_LIBS)
   TargetAdd('core.pyd', input=COMMON_PANDA_LIBS)
-  TargetAdd('core.pyd', opts=OPTS)
+  TargetAdd('core.pyd', opts=['PYTHON', 'WINSOCK2'])
 
 
 #
 #
 # DIRECTORY: panda/src/vision/
 # DIRECTORY: panda/src/vision/
@@ -4166,7 +4193,7 @@ if (not RUNTIME):
 #
 #
 
 
 if (not RUNTIME and PkgSkip("GL")==0):
 if (not RUNTIME and PkgSkip("GL")==0):
-  OPTS=['DIR:panda/src/glgsg', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGL',  'NVIDIACG']
+  OPTS=['DIR:panda/src/glgsg', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGL', 'GL', 'NVIDIACG']
   TargetAdd('p3glgsg_config_glgsg.obj', opts=OPTS, input='config_glgsg.cxx')
   TargetAdd('p3glgsg_config_glgsg.obj', opts=OPTS, input='config_glgsg.cxx')
   TargetAdd('p3glgsg_glgsg.obj', opts=OPTS, input='glgsg.cxx')
   TargetAdd('p3glgsg_glgsg.obj', opts=OPTS, input='glgsg.cxx')
 
 
@@ -4175,7 +4202,7 @@ if (not RUNTIME and PkgSkip("GL")==0):
 #
 #
 
 
 if (not RUNTIME and PkgSkip("GLES")==0):
 if (not RUNTIME and PkgSkip("GLES")==0):
-  OPTS=['DIR:panda/src/glesgsg', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES']
+  OPTS=['DIR:panda/src/glesgsg', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES', 'GLES']
   TargetAdd('p3glesgsg_config_glesgsg.obj', opts=OPTS, input='config_glesgsg.cxx')
   TargetAdd('p3glesgsg_config_glesgsg.obj', opts=OPTS, input='config_glesgsg.cxx')
   TargetAdd('p3glesgsg_glesgsg.obj', opts=OPTS, input='glesgsg.cxx')
   TargetAdd('p3glesgsg_glesgsg.obj', opts=OPTS, input='glesgsg.cxx')
 
 
@@ -4184,7 +4211,7 @@ if (not RUNTIME and PkgSkip("GLES")==0):
 #
 #
 
 
 if (not RUNTIME and PkgSkip("GLES2")==0):
 if (not RUNTIME and PkgSkip("GLES2")==0):
-  OPTS=['DIR:panda/src/gles2gsg', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES2']
+  OPTS=['DIR:panda/src/gles2gsg', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES2', 'GLES2']
   TargetAdd('p3gles2gsg_config_gles2gsg.obj', opts=OPTS, input='config_gles2gsg.cxx')
   TargetAdd('p3gles2gsg_config_gles2gsg.obj', opts=OPTS, input='config_gles2gsg.cxx')
   TargetAdd('p3gles2gsg_gles2gsg.obj', opts=OPTS, input='gles2gsg.cxx')
   TargetAdd('p3gles2gsg_gles2gsg.obj', opts=OPTS, input='gles2gsg.cxx')
 
 
@@ -4429,10 +4456,10 @@ if (PkgSkip("BULLET")==0 and not RUNTIME):
 #
 #
 
 
 if (PkgSkip("PHYSX")==0):
 if (PkgSkip("PHYSX")==0):
-  OPTS=['DIR:panda/src/physx', 'BUILDING:PANDAPHYSX', 'PHYSX', 'NOPPC']
+  OPTS=['DIR:panda/src/physx', 'BUILDING:PANDAPHYSX', 'PHYSX', 'NOARCH:PPC']
   TargetAdd('p3physx_composite.obj', opts=OPTS, input='p3physx_composite.cxx')
   TargetAdd('p3physx_composite.obj', opts=OPTS, input='p3physx_composite.cxx')
 
 
-  OPTS=['DIR:panda/src/physx', 'PHYSX', 'NOPPC']
+  OPTS=['DIR:panda/src/physx', 'PHYSX', 'NOARCH:PPC']
   IGATEFILES=GetDirectoryContents('panda/src/physx', ["*.h", "*_composite*.cxx"])
   IGATEFILES=GetDirectoryContents('panda/src/physx', ["*.h", "*_composite*.cxx"])
   TargetAdd('libpandaphysx.in', opts=OPTS, input=IGATEFILES)
   TargetAdd('libpandaphysx.in', opts=OPTS, input=IGATEFILES)
   TargetAdd('libpandaphysx.in', opts=['IMOD:panda3d.physx', 'ILIB:libpandaphysx', 'SRCDIR:panda/src/physx'])
   TargetAdd('libpandaphysx.in', opts=['IMOD:panda3d.physx', 'ILIB:libpandaphysx', 'SRCDIR:panda/src/physx'])
@@ -4443,15 +4470,15 @@ if (PkgSkip("PHYSX")==0):
 #
 #
 
 
 if (PkgSkip("PHYSX")==0):
 if (PkgSkip("PHYSX")==0):
-  OPTS=['DIR:panda/metalibs/pandaphysx', 'BUILDING:PANDAPHYSX', 'PHYSX', 'NOPPC']
+  OPTS=['DIR:panda/metalibs/pandaphysx', 'BUILDING:PANDAPHYSX', 'PHYSX', 'NOARCH:PPC']
   TargetAdd('pandaphysx_pandaphysx.obj', opts=OPTS, input='pandaphysx.cxx')
   TargetAdd('pandaphysx_pandaphysx.obj', opts=OPTS, input='pandaphysx.cxx')
 
 
   TargetAdd('libpandaphysx.dll', input='pandaphysx_pandaphysx.obj')
   TargetAdd('libpandaphysx.dll', input='pandaphysx_pandaphysx.obj')
   TargetAdd('libpandaphysx.dll', input='p3physx_composite.obj')
   TargetAdd('libpandaphysx.dll', input='p3physx_composite.obj')
   TargetAdd('libpandaphysx.dll', input=COMMON_PANDA_LIBS)
   TargetAdd('libpandaphysx.dll', input=COMMON_PANDA_LIBS)
-  TargetAdd('libpandaphysx.dll', opts=['WINUSER', 'PHYSX', 'NOPPC'])
+  TargetAdd('libpandaphysx.dll', opts=['WINUSER', 'PHYSX', 'NOARCH:PPC'])
 
 
-  OPTS=['DIR:panda/metalibs/pandaphysx', 'PHYSX', 'NOPPC']
+  OPTS=['DIR:panda/metalibs/pandaphysx', 'PHYSX', 'NOARCH:PPC']
   TargetAdd('physx_module.obj', input='libpandaphysx.in')
   TargetAdd('physx_module.obj', input='libpandaphysx.in')
   TargetAdd('physx_module.obj', opts=OPTS)
   TargetAdd('physx_module.obj', opts=OPTS)
   TargetAdd('physx_module.obj', opts=['IMOD:panda3d.physx', 'ILIB:physx'])
   TargetAdd('physx_module.obj', opts=['IMOD:panda3d.physx', 'ILIB:physx'])
@@ -4461,7 +4488,7 @@ if (PkgSkip("PHYSX")==0):
   TargetAdd('physx.pyd', input='libpandaphysx.dll')
   TargetAdd('physx.pyd', input='libpandaphysx.dll')
   TargetAdd('physx.pyd', input='core.pyd')
   TargetAdd('physx.pyd', input='core.pyd')
   TargetAdd('physx.pyd', input=COMMON_PANDA_LIBS)
   TargetAdd('physx.pyd', input=COMMON_PANDA_LIBS)
-  TargetAdd('physx.pyd', opts=['PYTHON', 'WINUSER', 'PHYSX', 'NOPPC'])
+  TargetAdd('physx.pyd', opts=['PYTHON', 'WINUSER', 'PHYSX', 'NOARCH:PPC'])
 
 
 #
 #
 # DIRECTORY: panda/src/physics/
 # DIRECTORY: panda/src/physics/
@@ -4882,7 +4909,7 @@ if (RTDIST or RUNTIME):
       TargetAdd('p3dcert.exe', input='plugin_mkdir_complete.obj')
       TargetAdd('p3dcert.exe', input='plugin_mkdir_complete.obj')
       TargetAdd('p3dcert.exe', input='plugin_wstring_encode.obj')
       TargetAdd('p3dcert.exe', input='plugin_wstring_encode.obj')
       TargetAdd('p3dcert.exe', input='plugin_p3dCert.obj')
       TargetAdd('p3dcert.exe', input='plugin_p3dCert.obj')
-      OPTS=['OPENSSL', 'FLTK', 'WINCOMCTL', 'WINSOCK', 'WINGDI', 'WINUSER', 'ADVAPI', 'WINOLE', 'WINSHELL', 'SUBSYSTEM:WINDOWS']
+      OPTS=['OPENSSL', 'FLTK', 'X11', 'WINCOMCTL', 'WINSOCK', 'WINGDI', 'WINUSER', 'ADVAPI', 'WINOLE', 'WINSHELL', 'SUBSYSTEM:WINDOWS']
       if GetTarget() == 'darwin':
       if GetTarget() == 'darwin':
           OPTS += ['OPT:2']
           OPTS += ['OPT:2']
       TargetAdd('p3dcert.exe', opts=OPTS)
       TargetAdd('p3dcert.exe', opts=OPTS)
@@ -5853,9 +5880,18 @@ if (PkgSkip("PANDATOOL")==0):
 #
 #
 
 
 for VER in MAYAVERSIONS:
 for VER in MAYAVERSIONS:
-  VNUM=VER[4:]
-  if (PkgSkip(VER)==0) and (PkgSkip("PANDATOOL")==0):
-    OPTS=['DIR:pandatool/src/mayaprogs', 'DIR:pandatool/src/maya', 'DIR:pandatool/src/mayaegg', 'DIR:pandatool/src/cvscopy', 'BUILDING:MISC', VER]
+  VNUM = VER[4:]
+  if not PkgSkip(VER) and not PkgSkip("PANDATOOL"):
+    if GetTarget() == 'darwin' and int(VNUM) >= 2012:
+      ARCH_OPTS = ['NOARCH:PPC', 'NOARCH:I386']
+      if len(OSX_ARCHS) != 0 and 'x86_64' not in OSX_ARCHS:
+        continue
+    elif GetTarget() == 'darwin' and int(VNUM) >= 2009:
+      ARCH_OPTS = ['NOARCH:PPC']
+    else:
+      ARCH_OPTS = []
+
+    OPTS=['DIR:pandatool/src/mayaprogs', 'DIR:pandatool/src/maya', 'DIR:pandatool/src/mayaegg', 'DIR:pandatool/src/cvscopy', 'BUILDING:MISC', VER] + ARCH_OPTS
     TargetAdd('mayaeggimport'+VNUM+'_mayaeggimport.obj', opts=OPTS, input='mayaEggImport.cxx')
     TargetAdd('mayaeggimport'+VNUM+'_mayaeggimport.obj', opts=OPTS, input='mayaEggImport.cxx')
     TargetAdd('mayaeggimport'+VNUM+'.mll', input='mayaegg'+VNUM+'_loader.obj')
     TargetAdd('mayaeggimport'+VNUM+'.mll', input='mayaegg'+VNUM+'_loader.obj')
     TargetAdd('mayaeggimport'+VNUM+'.mll', input='mayaeggimport'+VNUM+'_mayaeggimport.obj')
     TargetAdd('mayaeggimport'+VNUM+'.mll', input='mayaeggimport'+VNUM+'_mayaeggimport.obj')
@@ -5863,7 +5899,7 @@ for VER in MAYAVERSIONS:
     TargetAdd('mayaeggimport'+VNUM+'.mll', input=COMMON_PANDA_LIBS)
     TargetAdd('mayaeggimport'+VNUM+'.mll', input=COMMON_PANDA_LIBS)
     if GetTarget() == 'windows':
     if GetTarget() == 'windows':
       TargetAdd('mayaeggimport'+VNUM+'.mll', input='libp3pystub.lib')
       TargetAdd('mayaeggimport'+VNUM+'.mll', input='libp3pystub.lib')
-    TargetAdd('mayaeggimport'+VNUM+'.mll', opts=['ADVAPI', VER])
+    TargetAdd('mayaeggimport'+VNUM+'.mll', opts=['ADVAPI', VER]+ARCH_OPTS)
 
 
     TargetAdd('mayaloader'+VNUM+'_config_mayaloader.obj', opts=OPTS, input='config_mayaloader.cxx')
     TargetAdd('mayaloader'+VNUM+'_config_mayaloader.obj', opts=OPTS, input='config_mayaloader.cxx')
     TargetAdd('libp3mayaloader'+VNUM+'.dll', input='mayaloader'+VNUM+'_config_mayaloader.obj')
     TargetAdd('libp3mayaloader'+VNUM+'.dll', input='mayaloader'+VNUM+'_config_mayaloader.obj')
@@ -5887,7 +5923,7 @@ for VER in MAYAVERSIONS:
     TargetAdd('libp3mayaloader'+VNUM+'.dll', input='libp3pandatoolbase.lib')
     TargetAdd('libp3mayaloader'+VNUM+'.dll', input='libp3pandatoolbase.lib')
     TargetAdd('libp3mayaloader'+VNUM+'.dll', input='libpandaegg.dll')
     TargetAdd('libp3mayaloader'+VNUM+'.dll', input='libpandaegg.dll')
     TargetAdd('libp3mayaloader'+VNUM+'.dll', input=COMMON_PANDA_LIBS)
     TargetAdd('libp3mayaloader'+VNUM+'.dll', input=COMMON_PANDA_LIBS)
-    TargetAdd('libp3mayaloader'+VNUM+'.dll', opts=['ADVAPI', VER])
+    TargetAdd('libp3mayaloader'+VNUM+'.dll', opts=['ADVAPI', VER]+ARCH_OPTS)
 
 
     TargetAdd('mayapview'+VNUM+'_mayaPview.obj', opts=OPTS, input='mayaPview.cxx')
     TargetAdd('mayapview'+VNUM+'_mayaPview.obj', opts=OPTS, input='mayaPview.cxx')
     TargetAdd('libmayapview'+VNUM+'.mll', input='mayapview'+VNUM+'_mayaPview.obj')
     TargetAdd('libmayapview'+VNUM+'.mll', input='mayapview'+VNUM+'_mayaPview.obj')
@@ -5898,7 +5934,7 @@ for VER in MAYAVERSIONS:
       TargetAdd('libmayapview'+VNUM+'.mll', input=COMMON_EGG2X_LIBS_PYSTUB)
       TargetAdd('libmayapview'+VNUM+'.mll', input=COMMON_EGG2X_LIBS_PYSTUB)
     else:
     else:
       TargetAdd('libmayapview'+VNUM+'.mll', input=COMMON_EGG2X_LIBS)
       TargetAdd('libmayapview'+VNUM+'.mll', input=COMMON_EGG2X_LIBS)
-    TargetAdd('libmayapview'+VNUM+'.mll', opts=['ADVAPI', VER])
+    TargetAdd('libmayapview'+VNUM+'.mll', opts=['ADVAPI', VER]+ARCH_OPTS)
 
 
     TargetAdd('maya2egg'+VNUM+'_mayaToEgg.obj', opts=OPTS, input='mayaToEgg.cxx')
     TargetAdd('maya2egg'+VNUM+'_mayaToEgg.obj', opts=OPTS, input='mayaToEgg.cxx')
     TargetAdd('maya2egg'+VNUM+'_bin.exe', input='maya2egg'+VNUM+'_mayaToEgg.obj')
     TargetAdd('maya2egg'+VNUM+'_bin.exe', input='maya2egg'+VNUM+'_mayaToEgg.obj')
@@ -5908,10 +5944,7 @@ for VER in MAYAVERSIONS:
       TargetAdd('maya2egg'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS_PYSTUB)
       TargetAdd('maya2egg'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS_PYSTUB)
     else:
     else:
       TargetAdd('maya2egg'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS)
       TargetAdd('maya2egg'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS)
-    if GetTarget() == "darwin" and int(VNUM) >= 2009:
-      TargetAdd('maya2egg'+VNUM+'_bin.exe', opts=['ADVAPI', 'NOPPC', VER])
-    else:
-      TargetAdd('maya2egg'+VNUM+'_bin.exe', opts=['ADVAPI', VER])
+    TargetAdd('maya2egg'+VNUM+'_bin.exe', opts=['ADVAPI', VER]+ARCH_OPTS)
 
 
     TargetAdd('egg2maya'+VNUM+'_eggToMaya.obj', opts=OPTS, input='eggToMaya.cxx')
     TargetAdd('egg2maya'+VNUM+'_eggToMaya.obj', opts=OPTS, input='eggToMaya.cxx')
     TargetAdd('egg2maya'+VNUM+'_bin.exe', input='egg2maya'+VNUM+'_eggToMaya.obj')
     TargetAdd('egg2maya'+VNUM+'_bin.exe', input='egg2maya'+VNUM+'_eggToMaya.obj')
@@ -5921,10 +5954,7 @@ for VER in MAYAVERSIONS:
       TargetAdd('egg2maya'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS_PYSTUB)
       TargetAdd('egg2maya'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS_PYSTUB)
     else:
     else:
       TargetAdd('egg2maya'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS)
       TargetAdd('egg2maya'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS)
-    if GetTarget() == 'darwin' and int(VNUM) >= 2009:
-      TargetAdd('egg2maya'+VNUM+'_bin.exe', opts=['ADVAPI', 'NOPPC', VER])
-    else:
-      TargetAdd('egg2maya'+VNUM+'_bin.exe', opts=['ADVAPI', VER])
+    TargetAdd('egg2maya'+VNUM+'_bin.exe', opts=['ADVAPI', VER]+ARCH_OPTS)
 
 
     TargetAdd('mayacopy'+VNUM+'_mayaCopy.obj', opts=OPTS, input='mayaCopy.cxx')
     TargetAdd('mayacopy'+VNUM+'_mayaCopy.obj', opts=OPTS, input='mayaCopy.cxx')
     TargetAdd('mayacopy'+VNUM+'_bin.exe', input='mayacopy'+VNUM+'_mayaCopy.obj')
     TargetAdd('mayacopy'+VNUM+'_bin.exe', input='mayacopy'+VNUM+'_mayaCopy.obj')
@@ -5934,31 +5964,28 @@ for VER in MAYAVERSIONS:
       TargetAdd('mayacopy'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS_PYSTUB)
       TargetAdd('mayacopy'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS_PYSTUB)
     else:
     else:
       TargetAdd('mayacopy'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS)
       TargetAdd('mayacopy'+VNUM+'_bin.exe', input=COMMON_EGG2X_LIBS)
-    if GetTarget() == 'darwin' and int(VNUM) >= 2009:
-      TargetAdd('mayacopy'+VNUM+'_bin.exe', opts=['ADVAPI', 'NOPPC', VER])
-    else:
-      TargetAdd('mayacopy'+VNUM+'_bin.exe', opts=['ADVAPI', VER])
+    TargetAdd('mayacopy'+VNUM+'_bin.exe', opts=['ADVAPI', VER]+ARCH_OPTS)
 
 
     TargetAdd('mayasavepview'+VNUM+'_mayaSavePview.obj', opts=OPTS, input='mayaSavePview.cxx')
     TargetAdd('mayasavepview'+VNUM+'_mayaSavePview.obj', opts=OPTS, input='mayaSavePview.cxx')
     TargetAdd('libmayasavepview'+VNUM+'.mll', input='mayasavepview'+VNUM+'_mayaSavePview.obj')
     TargetAdd('libmayasavepview'+VNUM+'.mll', input='mayasavepview'+VNUM+'_mayaSavePview.obj')
-    TargetAdd('libmayasavepview'+VNUM+'.mll', opts=['ADVAPI',  VER])
+    TargetAdd('libmayasavepview'+VNUM+'.mll', opts=['ADVAPI', VER]+ARCH_OPTS)
 
 
     TargetAdd('mayapath'+VNUM+'.obj', opts=OPTS, input='mayapath.cxx')
     TargetAdd('mayapath'+VNUM+'.obj', opts=OPTS, input='mayapath.cxx')
 
 
     TargetAdd('maya2egg'+VNUM+'.exe', input='mayapath'+VNUM+'.obj')
     TargetAdd('maya2egg'+VNUM+'.exe', input='mayapath'+VNUM+'.obj')
-    TargetAdd('maya2egg'+VNUM+'.exe', opts=['ADVAPI'])
-    TargetAdd('maya2egg'+VNUM+'.exe', input=COMMON_DTOOL_LIBS)
     TargetAdd('maya2egg'+VNUM+'.exe', input='libpandaexpress.dll')
     TargetAdd('maya2egg'+VNUM+'.exe', input='libpandaexpress.dll')
+    TargetAdd('maya2egg'+VNUM+'.exe', input=COMMON_DTOOL_LIBS_PYSTUB)
+    TargetAdd('maya2egg'+VNUM+'.exe', opts=['ADVAPI']+ARCH_OPTS)
 
 
     TargetAdd('egg2maya'+VNUM+'.exe', input='mayapath'+VNUM+'.obj')
     TargetAdd('egg2maya'+VNUM+'.exe', input='mayapath'+VNUM+'.obj')
-    TargetAdd('egg2maya'+VNUM+'.exe', opts=['ADVAPI'])
-    TargetAdd('egg2maya'+VNUM+'.exe', input=COMMON_DTOOL_LIBS)
     TargetAdd('egg2maya'+VNUM+'.exe', input='libpandaexpress.dll')
     TargetAdd('egg2maya'+VNUM+'.exe', input='libpandaexpress.dll')
+    TargetAdd('egg2maya'+VNUM+'.exe', input=COMMON_DTOOL_LIBS_PYSTUB)
+    TargetAdd('egg2maya'+VNUM+'.exe', opts=['ADVAPI']+ARCH_OPTS)
 
 
     TargetAdd('mayacopy'+VNUM+'.exe', input='mayapath'+VNUM+'.obj')
     TargetAdd('mayacopy'+VNUM+'.exe', input='mayapath'+VNUM+'.obj')
-    TargetAdd('mayacopy'+VNUM+'.exe', opts=['ADVAPI'])
-    TargetAdd('mayacopy'+VNUM+'.exe', input=COMMON_DTOOL_LIBS)
     TargetAdd('mayacopy'+VNUM+'.exe', input='libpandaexpress.dll')
     TargetAdd('mayacopy'+VNUM+'.exe', input='libpandaexpress.dll')
+    TargetAdd('mayacopy'+VNUM+'.exe', input=COMMON_DTOOL_LIBS_PYSTUB)
+    TargetAdd('mayacopy'+VNUM+'.exe', opts=['ADVAPI']+ARCH_OPTS)
 
 
 #
 #
 # DIRECTORY: contrib/src/ai/
 # DIRECTORY: contrib/src/ai/
@@ -6597,6 +6624,7 @@ def MakeInstallerOSX():
     oscmd("cp -R %s/models                dstroot/base/Developer/Panda3D/models" % GetOutputDir())
     oscmd("cp -R %s/models                dstroot/base/Developer/Panda3D/models" % GetOutputDir())
     oscmd("cp -R doc/LICENSE              dstroot/base/Developer/Panda3D/LICENSE")
     oscmd("cp -R doc/LICENSE              dstroot/base/Developer/Panda3D/LICENSE")
     oscmd("cp -R doc/ReleaseNotes         dstroot/base/Developer/Panda3D/ReleaseNotes")
     oscmd("cp -R doc/ReleaseNotes         dstroot/base/Developer/Panda3D/ReleaseNotes")
+    oscmd("cp -R %s/Frameworks            dstroot/base/Developer/Panda3D/Frameworks" % GetOutputDir())
     if os.path.isdir(GetOutputDir()+"/plugins"):
     if os.path.isdir(GetOutputDir()+"/plugins"):
         oscmd("cp -R %s/plugins           dstroot/base/Developer/Panda3D/plugins" % GetOutputDir())
         oscmd("cp -R %s/plugins           dstroot/base/Developer/Panda3D/plugins" % GetOutputDir())
 
 
@@ -6650,11 +6678,11 @@ def MakeInstallerOSX():
     if PkgSkip("PYTHON")==0:
     if PkgSkip("PYTHON")==0:
         PV = SDK["PYTHONVERSION"].replace("python", "")
         PV = SDK["PYTHONVERSION"].replace("python", "")
         oscmd("mkdir -p dstroot/pythoncode/usr/bin")
         oscmd("mkdir -p dstroot/pythoncode/usr/bin")
-        oscmd("mkdir -p dstroot/pythoncode/Developer/Panda3D/direct")
+        oscmd("mkdir -p dstroot/pythoncode/Developer/Panda3D")
         oscmd("mkdir -p dstroot/pythoncode/Library/Python/%s/site-packages" % PV)
         oscmd("mkdir -p dstroot/pythoncode/Library/Python/%s/site-packages" % PV)
         WriteFile("dstroot/pythoncode/Library/Python/%s/site-packages/Panda3D.pth" % PV, "/Developer/Panda3D")
         WriteFile("dstroot/pythoncode/Library/Python/%s/site-packages/Panda3D.pth" % PV, "/Developer/Panda3D")
         oscmd("cp -R %s/pandac                dstroot/pythoncode/Developer/Panda3D/pandac" % GetOutputDir())
         oscmd("cp -R %s/pandac                dstroot/pythoncode/Developer/Panda3D/pandac" % GetOutputDir())
-        oscmd("cp -R direct/src/*             dstroot/pythoncode/Developer/Panda3D/direct")
+        oscmd("cp -R %s/direct                dstroot/pythoncode/Developer/Panda3D/direct" % GetOutputDir())
         oscmd("ln -s %s                       dstroot/pythoncode/usr/bin/ppython" % SDK["PYTHONEXEC"])
         oscmd("ln -s %s                       dstroot/pythoncode/usr/bin/ppython" % SDK["PYTHONEXEC"])
         if os.path.isdir(GetOutputDir()+"/Pmw"):
         if os.path.isdir(GetOutputDir()+"/Pmw"):
             oscmd("cp -R %s/Pmw               dstroot/pythoncode/Developer/Panda3D/Pmw" % GetOutputDir())
             oscmd("cp -R %s/Pmw               dstroot/pythoncode/Developer/Panda3D/Pmw" % GetOutputDir())
@@ -6691,15 +6719,15 @@ def MakeInstallerOSX():
         if not os.path.isdir("dstroot/" + pkg):
         if not os.path.isdir("dstroot/" + pkg):
             os.makedirs("dstroot/" + pkg)
             os.makedirs("dstroot/" + pkg)
 
 
-        if OSXTARGET:
-            target = '--target %s' % (OSXTARGET)
+        if OSXTARGET and OSXTARGET <= (10, 5):
+            target = '--target %d.%d' % (OSXTARGET)
         else:
         else:
             target = ''
             target = ''
 
 
         if os.path.exists("/Developer/usr/bin/packagemaker"):
         if os.path.exists("/Developer/usr/bin/packagemaker"):
             cmd = '/Developer/usr/bin/packagemaker --info /tmp/Info_plist --version ' + VERSION + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate'
             cmd = '/Developer/usr/bin/packagemaker --info /tmp/Info_plist --version ' + VERSION + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate'
         elif os.path.exists("/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker"):
         elif os.path.exists("/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker"):
-            cmd = '/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker --info /tmp/Info_plist --version ' + VERSION + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg --target ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate'
+            cmd = '/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker --info /tmp/Info_plist --version ' + VERSION + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate'
         elif os.path.exists("/Developer/Tools/packagemaker"):
         elif os.path.exists("/Developer/Tools/packagemaker"):
             cmd = '/Developer/Tools/packagemaker -build -f dstroot/' + pkg + '/ -p dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg -i /tmp/Info_plist'
             cmd = '/Developer/Tools/packagemaker -build -f dstroot/' + pkg + '/ -p dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg -i /tmp/Info_plist'
         else:
         else:
@@ -6713,7 +6741,7 @@ def MakeInstallerOSX():
     dist = open("dstroot/Panda3D/Panda3D.mpkg/Contents/distribution.dist", "w")
     dist = open("dstroot/Panda3D/Panda3D.mpkg/Contents/distribution.dist", "w")
     dist.write('<?xml version="1.0" encoding="utf-8"?>\n')
     dist.write('<?xml version="1.0" encoding="utf-8"?>\n')
     dist.write('<installer-script minSpecVersion="1.000000" authoringTool="com.apple.PackageMaker" authoringToolVersion="3.0.3" authoringToolBuild="174">\n')
     dist.write('<installer-script minSpecVersion="1.000000" authoringTool="com.apple.PackageMaker" authoringToolVersion="3.0.3" authoringToolBuild="174">\n')
-    dist.write('    <title>Panda3D</title>\n')
+    dist.write('    <title>Panda3D SDK %s</title>\n' % (VERSION))
     dist.write('    <options customize="always" allow-external-scripts="no" rootVolumeOnly="false"/>\n')
     dist.write('    <options customize="always" allow-external-scripts="no" rootVolumeOnly="false"/>\n')
     dist.write('    <license language="en" mime-type="text/plain">%s</license>\n' % ReadFile("doc/LICENSE"))
     dist.write('    <license language="en" mime-type="text/plain">%s</license>\n' % ReadFile("doc/LICENSE"))
     dist.write('    <choices-outline>\n')
     dist.write('    <choices-outline>\n')
@@ -6752,8 +6780,8 @@ def MakeInstallerOSX():
     dist.write('</installer-script>\n')
     dist.write('</installer-script>\n')
     dist.close()
     dist.close()
 
 
-    oscmd('hdiutil create Panda3D-rw.dmg -srcfolder dstroot/Panda3D')
-    oscmd('hdiutil convert Panda3D-rw.dmg -format UDBZ -o Panda3D-%s.dmg' % VERSION)
+    oscmd('hdiutil create Panda3D-rw.dmg -volname "Panda3D SDK %s" -srcfolder dstroot/Panda3D' % (VERSION))
+    oscmd('hdiutil convert Panda3D-rw.dmg -format UDBZ -o Panda3D-%s.dmg' % (VERSION))
     oscmd('rm -f Panda3D-rw.dmg')
     oscmd('rm -f Panda3D-rw.dmg')
 
 
 def MakeInstallerFreeBSD():
 def MakeInstallerFreeBSD():

+ 87 - 39
makepanda/makepandacore.py

@@ -1062,7 +1062,10 @@ def MakeBuildTree():
     MakeDirectory(OUTPUTDIR + "/panda3d")
     MakeDirectory(OUTPUTDIR + "/panda3d")
     CreateFile(OUTPUTDIR + "/panda3d/__init__.py")
     CreateFile(OUTPUTDIR + "/panda3d/__init__.py")
 
 
-    if GetTarget() == 'android':
+    if GetTarget() == 'darwin':
+        MakeDirectory(OUTPUTDIR + "/Frameworks")
+
+    elif GetTarget() == 'android':
         MakeDirectory(OUTPUTDIR + "/libs")
         MakeDirectory(OUTPUTDIR + "/libs")
         MakeDirectory(OUTPUTDIR + "/libs/" + ANDROID_ABI)
         MakeDirectory(OUTPUTDIR + "/libs/" + ANDROID_ABI)
         MakeDirectory(OUTPUTDIR + "/src")
         MakeDirectory(OUTPUTDIR + "/src")
@@ -1214,8 +1217,9 @@ def UnsetLinkAllStatic():
 ##
 ##
 ########################################################################
 ########################################################################
 
 
-PKG_LIST_ALL=[]
-PKG_LIST_OMIT={}
+PKG_LIST_ALL = []
+PKG_LIST_OMIT = {}
+PKG_LIST_CUSTOM = set()
 
 
 def PkgListSet(pkgs):
 def PkgListSet(pkgs):
     global PKG_LIST_ALL
     global PKG_LIST_ALL
@@ -1241,6 +1245,12 @@ def PkgEnable(pkg):
 def PkgDisable(pkg):
 def PkgDisable(pkg):
     PKG_LIST_OMIT[pkg] = 1
     PKG_LIST_OMIT[pkg] = 1
 
 
+def PkgSetCustomLocation(pkg):
+    PKG_LIST_CUSTOM.add(pkg)
+
+def PkgHasCustomLocation(pkg):
+    return pkg in PKG_LIST_CUSTOM
+
 def PkgSkip(pkg):
 def PkgSkip(pkg):
     return PKG_LIST_OMIT[pkg]
     return PKG_LIST_OMIT[pkg]
 
 
@@ -1398,22 +1408,22 @@ def PkgConfigEnable(opt, pkgname, tool = "pkg-config"):
     for i, j in PkgConfigGetDefSymbols(pkgname, tool).items():
     for i, j in PkgConfigGetDefSymbols(pkgname, tool).items():
         DefSymbol(opt, i, j)
         DefSymbol(opt, i, j)
 
 
-def LibraryExists(lib, lpath=[]):
+def LocateLibrary(lib, lpath=[]):
     """ Returns True if this library was found in the given search path, False otherwise. """
     """ Returns True if this library was found in the given search path, False otherwise. """
     target = GetTarget()
     target = GetTarget()
 
 
     for dir in lpath:
     for dir in lpath:
         if target == 'darwin' and os.path.isfile(os.path.join(dir, 'lib%s.dylib' % lib)):
         if target == 'darwin' and os.path.isfile(os.path.join(dir, 'lib%s.dylib' % lib)):
-            return True
+            return os.path.join(dir, 'lib%s.dylib' % lib)
         elif target != 'darwin' and os.path.isfile(os.path.join(dir, 'lib%s.so' % lib)):
         elif target != 'darwin' and os.path.isfile(os.path.join(dir, 'lib%s.so' % lib)):
-            return True
+            return os.path.join(dir, 'lib%s.so' % lib)
         elif os.path.isfile(os.path.join(dir, 'lib%s.a' % lib)):
         elif os.path.isfile(os.path.join(dir, 'lib%s.a' % lib)):
-            return True
+            return os.path.join(dir, 'lib%s.a' % lib)
 
 
-    return False
+    return None
 
 
 def SystemLibraryExists(lib):
 def SystemLibraryExists(lib):
-    return LibraryExists(lib, SYS_LIB_DIRS)
+    return LocateLibrary(lib, SYS_LIB_DIRS) is not None
 
 
 def ChooseLib(libs, thirdparty=None):
 def ChooseLib(libs, thirdparty=None):
     """ Chooses a library from the parameters, in order of preference. Returns the first if none of them were found. """
     """ Chooses a library from the parameters, in order of preference. Returns the first if none of them were found. """
@@ -1427,7 +1437,7 @@ def ChooseLib(libs, thirdparty=None):
         libname = l
         libname = l
         if l.startswith("lib"):
         if l.startswith("lib"):
             libname = l[3:]
             libname = l[3:]
-        if LibraryExists(libname, lpath):
+        if LocateLibrary(libname, lpath):
             return libname
             return libname
 
 
     if len(libs) > 0:
     if len(libs) > 0:
@@ -1463,16 +1473,18 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
         for d in olddefs:
         for d in olddefs:
             defs[d] = ""
             defs[d] = ""
 
 
-    if (pkg.lower() == "swscale" and os.path.isfile(GetThirdpartyDir() + "ffmpeg/include/libswscale/swscale.h")):
+    custom_loc = PkgHasCustomLocation(pkg)
+
+    if pkg.lower() == "swscale" and os.path.isfile(GetThirdpartyDir() + "ffmpeg/include/libswscale/swscale.h"):
         # Let it be handled by the ffmpeg package
         # Let it be handled by the ffmpeg package
         LibName(target_pkg, "-lswscale")
         LibName(target_pkg, "-lswscale")
         return
         return
-    if (pkg.lower() == "swresample" and os.path.isfile(GetThirdpartyDir() + "ffmpeg/include/libswresample/swresample.h")):
+    if pkg.lower() == "swresample" and os.path.isfile(GetThirdpartyDir() + "ffmpeg/include/libswresample/swresample.h"):
         LibName(target_pkg, "-lswresample")
         LibName(target_pkg, "-lswresample")
         return
         return
 
 
     pkg_dir = os.path.join(GetThirdpartyDir(), pkg.lower())
     pkg_dir = os.path.join(GetThirdpartyDir(), pkg.lower())
-    if (os.path.isdir(pkg_dir)):
+    if not custom_loc and os.path.isdir(pkg_dir):
         if framework and os.path.isdir(os.path.join(pkg_dir, framework + ".framework")):
         if framework and os.path.isdir(os.path.join(pkg_dir, framework + ".framework")):
             FrameworkDirectory(target_pkg, pkg_dir)
             FrameworkDirectory(target_pkg, pkg_dir)
             LibName(target_pkg, "-framework " + framework)
             LibName(target_pkg, "-framework " + framework)
@@ -1512,7 +1524,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
             DefSymbol(target_pkg, d, v)
             DefSymbol(target_pkg, d, v)
         return
         return
 
 
-    elif (GetHost() == "darwin" and framework != None):
+    elif not custom_loc and GetHost() == "darwin" and framework != None:
         prefix = SDK["MACOSX"]
         prefix = SDK["MACOSX"]
         if (os.path.isdir(prefix + "/Library/Frameworks/%s.framework" % framework) or
         if (os.path.isdir(prefix + "/Library/Frameworks/%s.framework" % framework) or
             os.path.isdir(prefix + "/System/Library/Frameworks/%s.framework" % framework) or
             os.path.isdir(prefix + "/System/Library/Frameworks/%s.framework" % framework) or
@@ -1526,7 +1538,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
         elif VERBOSE:
         elif VERBOSE:
             print(ColorText("cyan", "Couldn't find the framework %s" % (framework)))
             print(ColorText("cyan", "Couldn't find the framework %s" % (framework)))
 
 
-    elif (LocateBinary(tool) != None and (tool != "pkg-config" or pkgconfig != None)):
+    elif not custom_loc and LocateBinary(tool) != None and (tool != "pkg-config" or pkgconfig != None):
         if (isinstance(pkgconfig, str) or tool != "pkg-config"):
         if (isinstance(pkgconfig, str) or tool != "pkg-config"):
             if (PkgConfigHavePkg(pkgconfig, tool)):
             if (PkgConfigHavePkg(pkgconfig, tool)):
                 return PkgConfigEnable(target_pkg, pkgconfig, tool)
                 return PkgConfigEnable(target_pkg, pkgconfig, tool)
@@ -1556,22 +1568,38 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
             libname = l
             libname = l
             if l.startswith("lib"):
             if l.startswith("lib"):
                 libname = l[3:]
                 libname = l[3:]
-            if SystemLibraryExists(libname):
+
+            if custom_loc:
+                # Try searching in the package's LibDirectories.
+                lpath = [dir for ppkg, dir in LIBDIRECTORIES if pkg == ppkg]
+                location = LocateLibrary(libname, lpath)
+                if location is not None:
+                    LibName(target_pkg, location)
+                else:
+                    have_pkg = False
+                    print(GetColor("cyan") + "Couldn't find library lib" + libname + GetColor())
+
+            elif SystemLibraryExists(libname):
+                # It exists in a system library directory.
                 LibName(target_pkg, "-l" + libname)
                 LibName(target_pkg, "-l" + libname)
             else:
             else:
                 # Try searching in the package's LibDirectories.
                 # Try searching in the package's LibDirectories.
                 lpath = [dir for ppkg, dir in LIBDIRECTORIES if pkg == ppkg or ppkg == "ALWAYS"]
                 lpath = [dir for ppkg, dir in LIBDIRECTORIES if pkg == ppkg or ppkg == "ALWAYS"]
-                if LibraryExists(libname, lpath):
+                location = LocateLibrary(libname, lpath)
+                if location is not None:
                     LibName(target_pkg, "-l" + libname)
                     LibName(target_pkg, "-l" + libname)
                 else:
                 else:
                     have_pkg = False
                     have_pkg = False
-                    if VERBOSE:
+                    if VERBOSE or custom_loc:
                         print(GetColor("cyan") + "Couldn't find library lib" + libname + GetColor())
                         print(GetColor("cyan") + "Couldn't find library lib" + libname + GetColor())
 
 
         # Determine which include directories to look in.
         # Determine which include directories to look in.
-        incdirs = list(SYS_INC_DIRS)
+        incdirs = []
+        if not custom_loc:
+            incdirs += list(SYS_INC_DIRS)
+
         for ppkg, pdir in INCDIRECTORIES:
         for ppkg, pdir in INCDIRECTORIES:
-            if pkg == ppkg or ppkg == "ALWAYS":
+            if pkg == ppkg or (ppkg == "ALWAYS" and not custom_loc):
                 incdirs.append(pdir)
                 incdirs.append(pdir)
 
 
         # The incs list contains both subdirectories to explicitly add to
         # The incs list contains both subdirectories to explicitly add to
@@ -1585,14 +1613,17 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
             # Note: It's possible to specify a file instead of a dir, for the sake of checking if it exists.
             # Note: It's possible to specify a file instead of a dir, for the sake of checking if it exists.
             if incdir is None and i.endswith(".h"):
             if incdir is None and i.endswith(".h"):
                 have_pkg = False
                 have_pkg = False
-                if VERBOSE:
+                if VERBOSE or custom_loc:
                     print(GetColor("cyan") + "Couldn't find header file " + i + GetColor())
                     print(GetColor("cyan") + "Couldn't find header file " + i + GetColor())
 
 
             if incdir is not None and os.path.isdir(incdir):
             if incdir is not None and os.path.isdir(incdir):
                 IncDirectory(target_pkg, incdir)
                 IncDirectory(target_pkg, incdir)
 
 
-        if (not have_pkg):
-            if (pkg in PkgListGet()):
+        if not have_pkg:
+            if custom_loc:
+                print("%sERROR:%s Could not locate thirdparty package %s in specified directory, aborting build" % (GetColor("red"), GetColor(), pkg.lower()))
+                exit()
+            elif pkg in PkgListGet():
                 print("%sWARNING:%s Could not locate thirdparty package %s, excluding from build" % (GetColor("red"), GetColor(), pkg.lower()))
                 print("%sWARNING:%s Could not locate thirdparty package %s, excluding from build" % (GetColor("red"), GetColor(), pkg.lower()))
                 PkgDisable(pkg)
                 PkgDisable(pkg)
             else:
             else:
@@ -1847,7 +1878,6 @@ def SdkLocatePython(prefer_thirdparty_python=False):
 
 
     elif CrossCompiling() or (prefer_thirdparty_python and os.path.isdir(os.path.join(GetThirdpartyDir(), "python"))):
     elif CrossCompiling() or (prefer_thirdparty_python and os.path.isdir(os.path.join(GetThirdpartyDir(), "python"))):
         tp_python = os.path.join(GetThirdpartyDir(), "python")
         tp_python = os.path.join(GetThirdpartyDir(), "python")
-        SDK["PYTHON"] = tp_python + "/include"
 
 
         if GetTarget() == 'darwin':
         if GetTarget() == 'darwin':
             py_libs = glob.glob(tp_python + "/lib/libpython[0-9].[0-9].dylib")
             py_libs = glob.glob(tp_python + "/lib/libpython[0-9].[0-9].dylib")
@@ -1865,6 +1895,24 @@ def SdkLocatePython(prefer_thirdparty_python=False):
         py_lib = os.path.basename(py_libs[0])
         py_lib = os.path.basename(py_libs[0])
         SDK["PYTHONVERSION"] = "python" + py_lib[9] + "." + py_lib[11]
         SDK["PYTHONVERSION"] = "python" + py_lib[9] + "." + py_lib[11]
         SDK["PYTHONEXEC"] = tp_python + "/bin/" + SDK["PYTHONVERSION"]
         SDK["PYTHONEXEC"] = tp_python + "/bin/" + SDK["PYTHONVERSION"]
+        SDK["PYTHON"] = tp_python + "/include/" + SDK["PYTHONVERSION"]
+
+    elif GetTarget() == 'darwin':
+         # On Mac OS X, use the system Python framework.
+         py_fwx = SDK.get("MACOSX", "") + "/System/Library/Frameworks/Python.framework/Versions/Current"
+
+         if not os.path.islink(py_fwx):
+             exit("Could not locate Python installation at %s" % (py_fwx))
+
+         ver = os.path.basename(os.readlink(py_fwx))
+         py_fwx = SDK.get("MACOSX", "") + "/System/Library/Frameworks/Python.framework/Versions/%s" % ver
+
+         SDK["PYTHON"] = py_fwx + "/Headers"
+         SDK["PYTHONVERSION"] = "python" + ver
+         SDK["PYTHONEXEC"] = "/System/Library/Frameworks/Python.framework/Versions/" + ver + "/bin/python" + ver
+
+         if sys.version[:3] != ver:
+             print("Warning: building with Python %s instead of %s since you targeted a specific Mac OS X version." % (ver, sys.version[:3]))
 
 
     #elif GetTarget() == 'windows':
     #elif GetTarget() == 'windows':
     #    SDK["PYTHON"] = os.path.dirname(sysconfig.get_python_inc())
     #    SDK["PYTHON"] = os.path.dirname(sysconfig.get_python_inc())
@@ -1932,22 +1980,23 @@ def SdkLocateMSPlatform(strMode = 'default'):
 def SdkLocateMacOSX(osxtarget = None):
 def SdkLocateMacOSX(osxtarget = None):
     if (GetHost() != "darwin"): return
     if (GetHost() != "darwin"): return
     if (osxtarget != None):
     if (osxtarget != None):
-        if (os.path.exists("/Developer/SDKs/MacOSX%su.sdk" % osxtarget)):
-            SDK["MACOSX"] = "/Developer/SDKs/MacOSX%su.sdk" % osxtarget
-        elif (os.path.exists("/Developer/SDKs/MacOSX%s.sdk" % osxtarget)):
-            SDK["MACOSX"] = "/Developer/SDKs/MacOSX%s.sdk" % osxtarget
-        elif (os.path.exists("/Developer/SDKs/MacOSX%s.0.sdk" % osxtarget)):
-            SDK["MACOSX"] = "/Developer/SDKs/MacOSX%s.0.sdk" % osxtarget
-        elif (os.path.exists("/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX%s.sdk" % osxtarget)):
-            SDK["MACOSX"] = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX%s.sdk" % osxtarget
+        sdkname = "MacOSX%d.%d" % osxtarget
+        if (os.path.exists("/Developer/SDKs/%su.sdk" % sdkname)):
+            SDK["MACOSX"] = "/Developer/SDKs/%su.sdk" % sdkname
+        elif (os.path.exists("/Developer/SDKs/%s.sdk" % sdkname)):
+            SDK["MACOSX"] = "/Developer/SDKs/%s.sdk" % sdkname
+        elif (os.path.exists("/Developer/SDKs/%s.0.sdk" % sdkname)):
+            SDK["MACOSX"] = "/Developer/SDKs/%s.0.sdk" % sdkname
+        elif (os.path.exists("/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/%s.sdk" % sdkname)):
+            SDK["MACOSX"] = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/%s.sdk" % sdkname
         else:
         else:
             handle = os.popen("xcode-select -print-path")
             handle = os.popen("xcode-select -print-path")
             result = handle.read().strip().rstrip('/')
             result = handle.read().strip().rstrip('/')
             handle.close()
             handle.close()
-            if (os.path.exists("%s/Platforms/MacOSX.platform/Developer/SDKs/MacOSX%s.sdk" % (result, osxtarget))):
-                SDK["MACOSX"] = "%s/Platforms/MacOSX.platform/Developer/SDKs/MacOSX%s.sdk" % (result, osxtarget)
+            if (os.path.exists("%s/Platforms/MacOSX.platform/Developer/SDKs/%s.sdk" % (result, sdkname))):
+                SDK["MACOSX"] = "%s/Platforms/MacOSX.platform/Developer/SDKs/%s.sdk" % (result, sdkname)
             else:
             else:
-                exit("Couldn't find any MacOSX SDK for OSX version %s!" % osxtarget)
+                exit("Couldn't find any MacOSX SDK for OSX version %s!" % sdkname)
     else:
     else:
         SDK["MACOSX"] = ""
         SDK["MACOSX"] = ""
 
 
@@ -2370,11 +2419,10 @@ def SetupBuildEnvironment(compiler):
     AddToPathEnv("PYTHONPATH", builtdir)
     AddToPathEnv("PYTHONPATH", builtdir)
     AddToPathEnv("PANDA_PRC_DIR", os.path.join(builtdir, "etc"))
     AddToPathEnv("PANDA_PRC_DIR", os.path.join(builtdir, "etc"))
     AddToPathEnv("PATH", os.path.join(builtdir, "bin"))
     AddToPathEnv("PATH", os.path.join(builtdir, "bin"))
-    if (GetHost() == 'windows'):
-        AddToPathEnv("PATH", os.path.join(builtdir, "plugins"))
+    if GetHost() == 'windows':
+        # extension_native_helpers.py currently expects to find libpandaexpress on sys.path.
         AddToPathEnv("PYTHONPATH", os.path.join(builtdir, "bin"))
         AddToPathEnv("PYTHONPATH", os.path.join(builtdir, "bin"))
-    else:
-        AddToPathEnv("PYTHONPATH", os.path.join(builtdir, "lib"))
+        AddToPathEnv("PATH", os.path.join(builtdir, "plugins"))
 
 
     # Now for the special (DY)LD_LIBRARY_PATH on Unix-esque systems.
     # Now for the special (DY)LD_LIBRARY_PATH on Unix-esque systems.
     if GetHost() != 'windows':
     if GetHost() != 'windows':

+ 12 - 8
panda/metalibs/pandadx9/Sources.pp

@@ -125,7 +125,7 @@ OpenALAudioManager() {
       alcGetError(_device); // clear errors
       alcGetError(_device); // clear errors
       _context = alcCreateContext(_device, NULL);
       _context = alcCreateContext(_device, NULL);
       alc_audio_errcheck("alcCreateContext(_device, NULL)",_device);
       alc_audio_errcheck("alcCreateContext(_device, NULL)",_device);
-      if (_context!=NULL) {
+      if (_context != NULL) {
         _openal_active = true;
         _openal_active = true;
       }
       }
     }
     }
@@ -142,20 +142,24 @@ OpenALAudioManager() {
   } else {
   } else {
     alcGetError(_device); // clear errors
     alcGetError(_device); // clear errors
     alcMakeContextCurrent(_context);
     alcMakeContextCurrent(_context);
-    alc_audio_errcheck("alcMakeContextCurrent(_context)",_device);
-
+    alc_audio_errcheck("alcMakeContextCurrent(_context)", _device);
 
 
     // set 3D sound characteristics as they are given in the configrc
     // set 3D sound characteristics as they are given in the configrc
     audio_3d_set_doppler_factor(audio_doppler_factor);
     audio_3d_set_doppler_factor(audio_doppler_factor);
     audio_3d_set_distance_factor(audio_distance_factor);
     audio_3d_set_distance_factor(audio_distance_factor);
     audio_3d_set_drop_off_factor(audio_drop_off_factor);
     audio_3d_set_drop_off_factor(audio_drop_off_factor);
-  }
 
 
-  audio_cat->debug() << "ALC_DEVICE_SPECIFIER:" << alcGetString(_device, ALC_DEVICE_SPECIFIER) << endl;    
-  audio_cat->debug() << "AL_RENDERER:" << alGetString(AL_RENDERER) << endl;
-  audio_cat->debug() << "AL_VENDOR:" << alGetString(AL_VENDOR) << endl;
-  audio_cat->debug() << "AL_VERSION:" << alGetString(AL_VERSION) << endl;
+    if (audio_cat.is_debug()) {
+      audio_cat->debug()
+        << "ALC_DEVICE_SPECIFIER:" << alcGetString(_device, ALC_DEVICE_SPECIFIER) << endl;
+    }
+  }
 
 
+  if (audio_cat.is_debug()) {
+    audio_cat->debug() << "AL_RENDERER:" << alGetString(AL_RENDERER) << endl;
+    audio_cat->debug() << "AL_VENDOR:" << alGetString(AL_VENDOR) << endl;
+    audio_cat->debug() << "AL_VERSION:" << alGetString(AL_VERSION) << endl;
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 170 - 21
panda/src/bullet/bulletBodyNode.cxx

@@ -155,6 +155,8 @@ output(ostream &out) const {
 
 
   out << " (" << get_num_shapes() << " shapes)";
   out << " (" << get_num_shapes() << " shapes)";
 
 
+  out << (is_active() ? " active" : " inactive");
+
   if (is_static()) out << " static";
   if (is_static()) out << " static";
   if (is_kinematic()) out << " kinematic";
   if (is_kinematic()) out << " kinematic";
 }
 }
@@ -165,13 +167,16 @@ output(ostream &out) const {
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void BulletBodyNode::
 void BulletBodyNode::
-add_shape(BulletShape *shape, const TransformState *ts) {
+add_shape(BulletShape *bullet_shape, const TransformState *ts) {
 
 
   nassertv(get_object());
   nassertv(get_object());
   nassertv(ts);
   nassertv(ts);
 
 
-  nassertv(!(shape->ptr()->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE 
-    && ((btConvexHullShape *)shape->ptr())->getNumVertices() == 0));
+  btCollisionShape *shape = bullet_shape->ptr();
+  nassertv(shape != NULL);
+
+  nassertv(!(shape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE &&
+            ((btConvexHullShape *)shape)->getNumVertices() == 0));
 
 
   // Transform
   // Transform
   btTransform trans = TransformState_to_btTrans(ts);
   btTransform trans = TransformState_to_btTrans(ts);
@@ -193,13 +198,13 @@ add_shape(BulletShape *shape, const TransformState *ts) {
       // After adding the shape we will have one shape, but with transform.
       // After adding the shape we will have one shape, but with transform.
       // We need to wrap the shape within a compound shape, in oder to
       // We need to wrap the shape within a compound shape, in oder to
       // be able to set the local transform.
       // be able to set the local transform.
-      next = shape->ptr();
+      next = shape;
     }
     }
     else {
     else {
       // After adding the shape we will have a total of one shape, without 
       // After adding the shape we will have a total of one shape, without 
       // local transform. We can set the shape directly.
       // local transform. We can set the shape directly.
       next = new btCompoundShape();
       next = new btCompoundShape();
-      ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
+      ((btCompoundShape *)next)->addChildShape(trans, shape);
     }
     }
 
 
     get_object()->setCollisionShape(next);
     get_object()->setCollisionShape(next);
@@ -214,7 +219,7 @@ add_shape(BulletShape *shape, const TransformState *ts) {
       // to the compound shape.
       // to the compound shape.
       next = previous;
       next = previous;
 
 
-      ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
+      ((btCompoundShape *)next)->addChildShape(trans, shape);
     }
     }
     else {
     else {
       // We have one shape which is NOT a compound shape, and want to add
       // We have one shape which is NOT a compound shape, and want to add
@@ -223,7 +228,7 @@ add_shape(BulletShape *shape, const TransformState *ts) {
 
 
       btTransform previous_trans = btTransform::getIdentity();
       btTransform previous_trans = btTransform::getIdentity();
       ((btCompoundShape *)next)->addChildShape(previous_trans, previous);
       ((btCompoundShape *)next)->addChildShape(previous_trans, previous);
-      ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
+      ((btCompoundShape *)next)->addChildShape(trans, shape);
 
 
       get_object()->setCollisionShape(next);
       get_object()->setCollisionShape(next);
       _shape = next;
       _shape = next;
@@ -236,10 +241,10 @@ add_shape(BulletShape *shape, const TransformState *ts) {
     nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
     nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
 
 
     next = previous;
     next = previous;
-    ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
+    ((btCompoundShape *)next)->addChildShape(trans, shape);
   }
   }
 
 
-  _shapes.push_back(shape);
+  _shapes.push_back(bullet_shape);
 
 
   // Restore the local scaling again
   // Restore the local scaling again
   np.set_scale(scale);
   np.set_scale(scale);
@@ -340,7 +345,16 @@ LPoint3 BulletBodyNode::
 get_shape_pos(int idx) const {
 get_shape_pos(int idx) const {
 
 
   nassertr(idx >= 0 && idx < (int)_shapes.size(), LPoint3::zero());
   nassertr(idx >= 0 && idx < (int)_shapes.size(), LPoint3::zero());
-  return get_shape_mat(idx).get_row3(3);
+
+  btCollisionShape *root = get_object()->getCollisionShape();
+  if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
+    btCompoundShape *compound = (btCompoundShape *)root;
+
+    btTransform trans = compound->getChildTransform(idx);
+    return btVector3_to_LVector3(trans.getOrigin());
+  }
+
+  return LPoint3::zero();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -350,15 +364,24 @@ get_shape_pos(int idx) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 LMatrix4 BulletBodyNode::
 LMatrix4 BulletBodyNode::
 get_shape_mat(int idx) const {
 get_shape_mat(int idx) const {
+  return get_shape_transform(idx)->get_mat();
+}
 
 
-  nassertr(idx >= 0 && idx < (int)_shapes.size(), LMatrix4::ident_mat());
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_shape_transform
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPT(TransformState) BulletBodyNode::
+get_shape_transform(int idx) const {
+  nassertr(idx >= 0 && idx < (int)_shapes.size(), TransformState::make_identity());
 
 
   btCollisionShape *root = get_object()->getCollisionShape();
   btCollisionShape *root = get_object()->getCollisionShape();
   if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
   if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
     btCompoundShape *compound = (btCompoundShape *)root;
     btCompoundShape *compound = (btCompoundShape *)root;
 
 
     btTransform trans = compound->getChildTransform(idx);
     btTransform trans = compound->getChildTransform(idx);
-    return btTrans_to_LMatrix4(trans);
+    return btTrans_to_TransformState(trans);
 
 
     // The above code assumes that shape's index in _shapes member
     // The above code assumes that shape's index in _shapes member
     // is the same as the shapes index within the compound. If it
     // is the same as the shapes index within the compound. If it
@@ -375,7 +398,7 @@ get_shape_mat(int idx) const {
     */
     */
   }
   }
 
 
-  return LMatrix4::ident_mat();
+  return TransformState::make_identity();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -448,19 +471,22 @@ set_active(bool active, bool force) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletBodyNode::set_deactivation_enabled
 //     Function: BulletBodyNode::set_deactivation_enabled
 //       Access: Published
 //       Access: Published
-//  Description:
+//  Description: If true, this object will be deactivated after a
+//               certain amount of time has passed without movement.
+//               If false, the object will always remain active.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void BulletBodyNode::
 void BulletBodyNode::
-set_deactivation_enabled(const bool enabled, const bool force) {
+set_deactivation_enabled(bool enabled) {
 
 
-  int state = (enabled) ? WANTS_DEACTIVATION : DISABLE_DEACTIVATION;
+  // Don't change the state if it's currently active and we enable
+  // deactivation.
+  if (enabled != is_deactivation_enabled()) {
 
 
-  if (force) {
+    // It's OK to set to ACTIVE_TAG even if we don't mean to activate it; it
+    // will be disabled right away if the deactivation timer has run out.
+    int state = (enabled) ? ACTIVE_TAG : DISABLE_DEACTIVATION;
     get_object()->forceActivationState(state);
     get_object()->forceActivationState(state);
   }
   }
-  else {
-    get_object()->setActivationState(state);
-  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -471,7 +497,7 @@ set_deactivation_enabled(const bool enabled, const bool force) {
 bool BulletBodyNode::
 bool BulletBodyNode::
 is_deactivation_enabled() const {
 is_deactivation_enabled() const {
 
 
-  return (get_object()->getActivationState() & DISABLE_DEACTIVATION) == 0;
+  return (get_object()->getActivationState() != DISABLE_DEACTIVATION);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -700,3 +726,126 @@ cout << "origin " << aabbMin.x() << " " << aabbMin.y() << " " << aabbMin.z() <<
   return bounds;
   return bounds;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  PandaNode::write_datagram(manager, dg);
+
+  dg.add_bool(is_static());
+  dg.add_bool(is_kinematic());
+  dg.add_bool(notifies_collisions());
+  dg.add_bool(get_collision_response());
+  dg.add_stdfloat(get_contact_processing_threshold());
+  //dg.add_bool(is_active());
+  dg.add_stdfloat(get_deactivation_time());
+  dg.add_bool(is_deactivation_enabled());
+  //dg.add_bool(is_debug_enabled());
+  dg.add_stdfloat(get_restitution());
+  dg.add_stdfloat(get_friction());
+#if BT_BULLET_VERSION >= 281
+  dg.add_stdfloat(get_rolling_friction());
+#else
+  dg.add_stdfloat(0);
+#endif
+  if (has_anisotropic_friction()) {
+    dg.add_bool(true);
+    get_anisotropic_friction().write_datagram(dg);
+  } else {
+    dg.add_bool(false);
+  }
+  dg.add_stdfloat(get_ccd_swept_sphere_radius());
+  dg.add_stdfloat(get_ccd_motion_threshold());
+
+  for (int i = 0; i < _shapes.size(); ++i) {
+    manager->write_pointer(dg, get_shape(i));
+    manager->write_pointer(dg, get_shape_transform(i));
+  }
+
+  // Write NULL pointer to indicate the end of the list.
+  manager->write_pointer(dg, NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::complete_pointers
+//       Access: Public, Virtual
+//  Description: Receives an array of pointers, one for each time
+//               manager->read_pointer() was called in fillin().
+//               Returns the number of pointers processed.
+////////////////////////////////////////////////////////////////////
+int BulletBodyNode::
+complete_pointers(TypedWritable **p_list, BamReader *manager) {
+  int pi = PandaNode::complete_pointers(p_list, manager);
+
+  PT(BulletShape) shape = DCAST(BulletShape, p_list[pi++]);
+
+  while (shape != (BulletShape *)NULL) {
+    const TransformState *trans = DCAST(TransformState, p_list[pi++]);
+    add_shape(shape, trans);
+
+    shape = DCAST(BulletShape, p_list[pi++]);
+  }
+
+  return pi;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::require_fully_complete
+//       Access: Public, Virtual
+//  Description: Some objects require all of their nested pointers to
+//               have been completed before the objects themselves can
+//               be completed.  If this is the case, override this
+//               method to return true, and be careful with circular
+//               references (which would make the object unreadable
+//               from a bam file).
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+require_fully_complete() const {
+  // We require the shape pointers to be complete before we add them.
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new BulletBodyNode.
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  PandaNode::fillin(scan, manager);
+
+  set_static(scan.get_bool());
+  set_kinematic(scan.get_bool());
+  notify_collisions(scan.get_bool());
+  set_collision_response(scan.get_bool());
+  set_contact_processing_threshold(scan.get_stdfloat());
+  //set_active(scan.get_bool(), true);
+  set_deactivation_time(scan.get_stdfloat());
+  set_deactivation_enabled(scan.get_bool());
+  set_restitution(scan.get_stdfloat());
+  set_friction(scan.get_stdfloat());
+#if BT_BULLET_VERSION >= 281
+  set_rolling_friction(scan.get_stdfloat());
+#else
+  scan.get_stdfloat();
+#endif
+  if (scan.get_bool()) {
+    LVector3 friction;
+    friction.read_datagram(scan);
+    set_anisotropic_friction(friction);
+  }
+  set_ccd_swept_sphere_radius(scan.get_stdfloat());
+  set_ccd_motion_threshold(scan.get_stdfloat());
+
+  // Read shapes.  The list is bounded by a NULL pointer.
+  while (manager->read_pointer(scan)) {
+    // Each shape comes with a TransformState.
+    manager->read_pointer(scan);
+  }
+}

+ 13 - 3
panda/src/bullet/bulletBodyNode.h

@@ -33,9 +33,10 @@ class BulletShape;
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletBodyNode : public PandaNode {
 class EXPCL_PANDABULLET BulletBodyNode : public PandaNode {
+protected:
+  BulletBodyNode(const char *name);
 
 
 PUBLISHED:
 PUBLISHED:
-  BulletBodyNode(const char *name);
   INLINE ~BulletBodyNode();
   INLINE ~BulletBodyNode();
 
 
   // Shapes
   // Shapes
@@ -48,6 +49,7 @@ PUBLISHED:
 
 
   LPoint3 get_shape_pos(int idx) const;
   LPoint3 get_shape_pos(int idx) const;
   LMatrix4 get_shape_mat(int idx) const;
   LMatrix4 get_shape_mat(int idx) const;
+  CPT(TransformState) get_shape_transform(int idx) const;
   BoundingSphere get_shape_bounds() const;
   BoundingSphere get_shape_bounds() const;
 
 
   void add_shapes_from_collision_solids(CollisionNode *cnode);
   void add_shapes_from_collision_solids(CollisionNode *cnode);
@@ -82,7 +84,7 @@ PUBLISHED:
   void set_deactivation_time(PN_stdfloat dt);
   void set_deactivation_time(PN_stdfloat dt);
   PN_stdfloat get_deactivation_time() const;
   PN_stdfloat get_deactivation_time() const;
 
 
-  void set_deactivation_enabled(const bool enabled, const bool force=false);
+  void set_deactivation_enabled(bool enabled);
   bool is_deactivation_enabled() const;
   bool is_deactivation_enabled() const;
 
 
   // Debug Visualistion
   // Debug Visualistion
@@ -142,7 +144,15 @@ private:
 
 
   static bool is_identity(btTransform &trans);
   static bool is_identity(btTransform &trans);
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+  virtual int complete_pointers(TypedWritable **plist,
+                                BamReader *manager);
+  virtual bool require_fully_complete() const;
+
+protected:
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 64 - 1
panda/src/bullet/bulletBoxShape.cxx

@@ -66,7 +66,7 @@ get_half_extents_with_margin() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletBoxShape::make_from_solid
 //     Function: BulletBoxShape::make_from_solid
-//       Access: Public
+//       Access: Public, Static
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 BulletBoxShape *BulletBoxShape::
 BulletBoxShape *BulletBoxShape::
@@ -82,3 +82,66 @@ make_from_solid(const CollisionBox *solid) {
   return new BulletBoxShape(extents);
   return new BulletBoxShape(extents);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletBoxShape::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletBoxShape::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_margin());
+  get_half_extents_with_margin().write_datagram(dg);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type BulletShape is encountered
+//               in the Bam file.  It should create the BulletShape
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletBoxShape::
+make_from_bam(const FactoryParams &params) {
+  BulletBoxShape *param = new BulletBoxShape;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletBoxShape::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  nassertv(_shape == NULL);
+
+  PN_stdfloat margin = scan.get_stdfloat();
+
+  LVector3 half_extents;
+  half_extents.read_datagram(scan);
+
+  _shape = new btBoxShape(LVecBase3_to_btVector3(half_extents));
+  _shape->setUserPointer(this);
+  _shape->setMargin(margin);
+}

+ 11 - 1
panda/src/bullet/bulletBoxShape.h

@@ -29,6 +29,9 @@
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletBoxShape : public BulletShape {
 class EXPCL_PANDABULLET BulletBoxShape : public BulletShape {
+private:
+  // Only used by make_from_bam
+  INLINE BulletBoxShape() : _shape(NULL) {};
 
 
 PUBLISHED:
 PUBLISHED:
   BulletBoxShape(const LVecBase3 &halfExtents);
   BulletBoxShape(const LVecBase3 &halfExtents);
@@ -47,7 +50,14 @@ public:
 private:
 private:
   btBoxShape *_shape;
   btBoxShape *_shape;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 100 - 4
panda/src/bullet/bulletConvexHullShape.cxx

@@ -66,10 +66,17 @@ add_array(const PTA_LVecBase3 &points) {
   _shape->setUserPointer(this);
   _shape->setUserPointer(this);
 
 
   PTA_LVecBase3::const_iterator it;
   PTA_LVecBase3::const_iterator it;
-  for (it=points.begin(); it!=points.end(); it++) {
-    LVecBase3 v = *it;
-    _shape->addPoint(LVecBase3_to_btVector3(v));
+
+#if BT_BULLET_VERSION >= 282
+  for (it = points.begin(); it != points.end(); ++it) {
+    _shape->addPoint(LVecBase3_to_btVector3(*it), false);
   }
   }
+  _shape->recalcLocalAabb();
+#else
+  for (it = points.begin(); it != points.end(); ++it) {
+    _shape->addPoint(LVecBase3_to_btVector3(*it));
+  }
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -100,8 +107,97 @@ add_geom(const Geom *geom, const TransformState *ts) {
   _shape->setUserPointer(this);
   _shape->setUserPointer(this);
 
 
   pvector<LPoint3>::const_iterator it;
   pvector<LPoint3>::const_iterator it;
-  for (it=points.begin(); it!=points.end(); it++) {
+
+#if BT_BULLET_VERSION >= 282
+  for (it = points.begin(); it != points.end(); ++it) {
+    LVecBase3 v = *it;
+    _shape->addPoint(LVecBase3_to_btVector3(*it), false);
+  }
+  _shape->recalcLocalAabb();
+#else
+  for (it = points.begin(); it != points.end(); ++it) {
+    LVecBase3 v = *it;
     _shape->addPoint(LVecBase3_to_btVector3(*it));
     _shape->addPoint(LVecBase3_to_btVector3(*it));
   }
   }
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletConvexHullShape::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletConvexHullShape::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_margin());
+
+  unsigned int num_points = _shape->getNumPoints();
+  dg.add_uint32(num_points);
+
+  const btVector3 *points = _shape->getUnscaledPoints();
+
+  for (unsigned int i = 0; i < num_points; ++i) {
+    LVecBase3 point = btVector3_to_LVecBase3(points[i]);
+    point.write_datagram(dg);
+  }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type BulletShape is encountered
+//               in the Bam file.  It should create the BulletShape
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletConvexHullShape::
+make_from_bam(const FactoryParams &params) {
+  BulletConvexHullShape *param = new BulletConvexHullShape;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletConvexHullShape::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  PN_stdfloat margin = scan.get_stdfloat();
+  unsigned int num_points = scan.get_uint32();
+
+#if BT_BULLET_VERSION >= 282
+  for (unsigned int i = 0; i < num_points; ++i) {
+    LVecBase3 point;
+    point.read_datagram(scan);
+    _shape->addPoint(LVecBase3_to_btVector3(point), false);
+  }
+  _shape->recalcLocalAabb();
+#else
+  for (unsigned int i = 0; i < num_points; ++i) {
+    LVecBase3 point;
+    point.read_datagram(scan);
+    _shape->addPoint(LVecBase3_to_btVector3(point));
+  }
+#endif
+}

+ 8 - 2
panda/src/bullet/bulletConvexHullShape.h

@@ -29,7 +29,6 @@
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletConvexHullShape : public BulletShape {
 class EXPCL_PANDABULLET BulletConvexHullShape : public BulletShape {
-
 PUBLISHED:
 PUBLISHED:
   BulletConvexHullShape();
   BulletConvexHullShape();
   INLINE BulletConvexHullShape(const BulletConvexHullShape &copy);
   INLINE BulletConvexHullShape(const BulletConvexHullShape &copy);
@@ -47,7 +46,14 @@ public:
 private:
 private:
   btConvexHullShape *_shape;
   btConvexHullShape *_shape;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 67 - 0
panda/src/bullet/bulletDebugNode.cxx

@@ -463,3 +463,70 @@ drawSphere(btScalar radius, const btTransform &transform, const btVector3 &color
   drawArc(center, zoffs, xoffs, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
   drawArc(center, zoffs, xoffs, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletDebugNode.
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  // Don't upcall to GeomNode since we're not interested in storing
+  // the actual debug Geoms in the .bam file.
+  PandaNode::write_datagram(manager, dg);
+
+  dg.add_bool(_wireframe);
+  dg.add_bool(_constraints);
+  dg.add_bool(_bounds);
+  dg.add_bool(_drawer._normals);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of this type is encountered
+//               in the Bam file.  It should create the rigid body
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletDebugNode::
+make_from_bam(const FactoryParams &params) {
+  BulletDebugNode *param = new BulletDebugNode;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new BulletDebugNode.
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  // Don't upcall to GeomNode since we're not interested in storing
+  // the actual debug Geoms in the .bam file.
+  PandaNode::fillin(scan, manager);
+
+  _wireframe = scan.get_bool();
+  _constraints = scan.get_bool();
+  _bounds = scan.get_bool();
+  _drawer._normals = scan.get_bool();
+}

+ 8 - 1
panda/src/bullet/bulletDebugNode.h

@@ -101,7 +101,14 @@ private:
 
 
   friend class BulletWorld;
   friend class BulletWorld;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 68 - 1
panda/src/bullet/bulletPlaneShape.cxx

@@ -43,7 +43,7 @@ ptr() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletPlaneShape::make_from_solid
 //     Function: BulletPlaneShape::make_from_solid
-//       Access: Public
+//       Access: Public, Static
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 BulletPlaneShape *BulletPlaneShape::
 BulletPlaneShape *BulletPlaneShape::
@@ -55,3 +55,70 @@ make_from_solid(const CollisionPlane *solid) {
   return new BulletPlaneShape(normal, constant);
   return new BulletPlaneShape(normal, constant);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletPlaneShape::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletPlaneShape::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_margin());
+  get_plane_normal().write_datagram(dg);
+  dg.add_stdfloat(get_plane_constant());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type BulletShape is encountered
+//               in the Bam file.  It should create the BulletShape
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletPlaneShape::
+make_from_bam(const FactoryParams &params) {
+  BulletPlaneShape *param = new BulletPlaneShape;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletPlaneShape::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  nassertv(_shape == NULL);
+
+  PN_stdfloat margin = scan.get_stdfloat();
+
+  LVector3 normal;
+  normal.read_datagram(scan);
+
+  PN_stdfloat constant = scan.get_stdfloat();
+
+  _shape = new btStaticPlaneShape(LVecBase3_to_btVector3(normal), constant);
+  _shape->setUserPointer(this);
+  _shape->setMargin(margin);
+}
+

+ 11 - 1
panda/src/bullet/bulletPlaneShape.h

@@ -29,6 +29,9 @@
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletPlaneShape : public BulletShape {
 class EXPCL_PANDABULLET BulletPlaneShape : public BulletShape {
+private:
+  // Only used by make_from_bam
+  INLINE BulletPlaneShape() : _shape(NULL) {};
 
 
 PUBLISHED:
 PUBLISHED:
   BulletPlaneShape(const LVector3 &normal, PN_stdfloat constant);
   BulletPlaneShape(const LVector3 &normal, PN_stdfloat constant);
@@ -47,7 +50,14 @@ public:
 private:
 private:
   btStaticPlaneShape *_shape;
   btStaticPlaneShape *_shape;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 99 - 0
panda/src/bullet/bulletRigidBodyNode.cxx

@@ -490,6 +490,28 @@ get_gravity() const {
   return btVector3_to_LVector3(_rigid->getGravity());
   return btVector3_to_LVector3(_rigid->getGravity());
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_linear_factor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVector3 BulletRigidBodyNode::
+get_linear_factor() const {
+
+  return btVector3_to_LVector3(_rigid->getLinearFactor());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_angular_factor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVector3 BulletRigidBodyNode::
+get_angular_factor() const {
+
+  return btVector3_to_LVector3(_rigid->getAngularFactor());
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletRigidBodyNode::set_linear_factor
 //     Function: BulletRigidBodyNode::set_linear_factor
 //       Access: Published
 //       Access: Published
@@ -650,3 +672,80 @@ pick_dirty_flag() {
   return _motion->pick_dirty_flag();
   return _motion->pick_dirty_flag();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletRigidBodyNode.
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  BulletBodyNode::write_datagram(manager, dg);
+
+  dg.add_stdfloat(get_mass());
+  dg.add_stdfloat(get_linear_damping());
+  dg.add_stdfloat(get_angular_damping());
+  dg.add_stdfloat(get_linear_sleep_threshold());
+  dg.add_stdfloat(get_angular_sleep_threshold());
+  get_gravity().write_datagram(dg);
+  get_linear_factor().write_datagram(dg);
+  get_angular_factor().write_datagram(dg);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of this type is encountered
+//               in the Bam file.  It should create the rigid body
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletRigidBodyNode::
+make_from_bam(const FactoryParams &params) {
+  BulletRigidBodyNode *param = new BulletRigidBodyNode;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new BulletRigidBodyNode.
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  BulletBodyNode::fillin(scan, manager);
+
+  set_mass(scan.get_stdfloat());
+  set_linear_damping(scan.get_stdfloat());
+  set_angular_damping(scan.get_stdfloat());
+  set_linear_sleep_threshold(scan.get_stdfloat());
+  set_angular_sleep_threshold(scan.get_stdfloat());
+
+  LVector3 gravity, linear_factor, angular_factor;
+  gravity.read_datagram(scan);
+  linear_factor.read_datagram(scan);
+  angular_factor.read_datagram(scan);
+
+  set_gravity(gravity);
+  set_linear_factor(linear_factor);
+  set_angular_factor(angular_factor);
+}

+ 11 - 2
panda/src/bullet/bulletRigidBodyNode.h

@@ -80,6 +80,8 @@ PUBLISHED:
   LVector3 get_gravity() const;
   LVector3 get_gravity() const;
 
 
   // Restrict movement
   // Restrict movement
+  LVector3 get_linear_factor() const;
+  LVector3 get_angular_factor() const;
   void set_linear_factor(const LVector3 &factor);
   void set_linear_factor(const LVector3 &factor);
   void set_angular_factor(const LVector3 &factor);
   void set_angular_factor(const LVector3 &factor);
 
 
@@ -100,7 +102,7 @@ protected:
 private:
 private:
   virtual void shape_changed();
   virtual void shape_changed();
 
 
-  // The motion state is used for syncronisation between Bullet
+  // The motion state is used for synchronisation between Bullet
   // and the Panda3D scene graph.
   // and the Panda3D scene graph.
   class MotionState : public btMotionState {
   class MotionState : public btMotionState {
 
 
@@ -127,7 +129,14 @@ private:
   MotionState *_motion;
   MotionState *_motion;
   btRigidBody *_rigid;
   btRigidBody *_rigid;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 5 - 3
panda/src/bullet/bulletShape.h

@@ -26,7 +26,9 @@
 //       Class : BulletShape
 //       Class : BulletShape
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDABULLET BulletShape : public TypedReferenceCount {
+class EXPCL_PANDABULLET BulletShape : public TypedWritableReferenceCount {
+protected:
+  INLINE BulletShape() {};
 
 
 PUBLISHED:
 PUBLISHED:
   INLINE virtual ~BulletShape();
   INLINE virtual ~BulletShape();
@@ -58,9 +60,9 @@ public:
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedReferenceCount::init_type();
+    TypedWritableReferenceCount::init_type();
     register_type(_type_handle, "BulletShape", 
     register_type(_type_handle, "BulletShape", 
-                  TypedReferenceCount::get_class_type());
+                  TypedWritableReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 61 - 1
panda/src/bullet/bulletSphereShape.cxx

@@ -41,7 +41,7 @@ ptr() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletSphereShape::make_from_solid
 //     Function: BulletSphereShape::make_from_solid
-//       Access: Public
+//       Access: Public, Static
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 BulletSphereShape *BulletSphereShape::
 BulletSphereShape *BulletSphereShape::
@@ -50,3 +50,63 @@ make_from_solid(const CollisionSphere *solid) {
   return new BulletSphereShape(solid->get_radius());
   return new BulletSphereShape(solid->get_radius());
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSphereShape::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletSphereShape::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSphereShape::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletSphereShape::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_margin());
+  dg.add_stdfloat(get_radius());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSphereShape::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type BulletShape is encountered
+//               in the Bam file.  It should create the BulletShape
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletSphereShape::
+make_from_bam(const FactoryParams &params) {
+  BulletSphereShape *param = new BulletSphereShape;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSphereShape::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletSphereShape::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  nassertv(_shape == NULL);
+
+  PN_stdfloat margin = scan.get_stdfloat();
+
+  _shape = new btSphereShape(scan.get_stdfloat());
+  _shape->setUserPointer(this);
+  _shape->setMargin(margin);
+}

+ 11 - 1
panda/src/bullet/bulletSphereShape.h

@@ -28,6 +28,9 @@
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletSphereShape : public BulletShape {
 class EXPCL_PANDABULLET BulletSphereShape : public BulletShape {
+private:
+  // Only used by make_from_bam
+  INLINE BulletSphereShape() : _shape(NULL) {};
 
 
 PUBLISHED:
 PUBLISHED:
   BulletSphereShape(PN_stdfloat radius);
   BulletSphereShape(PN_stdfloat radius);
@@ -45,7 +48,14 @@ public:
 private:
 private:
   btSphereShape *_shape;
   btSphereShape *_shape;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 122 - 0
panda/src/bullet/bulletTriangleMesh.cxx

@@ -213,3 +213,125 @@ write(ostream &out, int indent_level) const {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMesh::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletTriangleMesh.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMesh::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMesh::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMesh::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_welding_distance());
+
+  // In case we ever want to represent more than 1 indexed mesh.
+  dg.add_int32(1);
+
+  btIndexedMesh &mesh = _mesh->getIndexedMeshArray()[0];
+  dg.add_int32(mesh.m_numVertices);
+  dg.add_int32(mesh.m_numTriangles);
+
+  // In case we want to use this to distinguish 16-bit vs 32-bit indices.
+  dg.add_bool(true);
+
+  // Add the vertices.
+  const unsigned char *vptr = mesh.m_vertexBase;
+  nassertv(vptr != NULL || mesh.m_numVertices == 0);
+
+  for (int i = 0; i < mesh.m_numVertices; ++i) {
+    const btVector3 &vertex = *((btVector3 *)vptr);
+    dg.add_stdfloat(vertex.getX());
+    dg.add_stdfloat(vertex.getY());
+    dg.add_stdfloat(vertex.getZ());
+    vptr += mesh.m_vertexStride;
+  }
+
+  // Now add the triangle indices.
+  const unsigned char *iptr = mesh.m_triangleIndexBase;
+  nassertv(iptr != NULL || mesh.m_numTriangles == 0);
+
+  if (_mesh->getUse32bitIndices()) {
+    for (int i = 0; i < mesh.m_numTriangles; ++i) {
+      int *triangle = (int *)iptr;
+      dg.add_int32(triangle[0]);
+      dg.add_int32(triangle[1]);
+      dg.add_int32(triangle[2]);
+      iptr += mesh.m_triangleIndexStride;
+    }
+  } else {
+    for (int i = 0; i < mesh.m_numTriangles; ++i) {
+      short int *triangle = (short int *)iptr;
+      dg.add_int32(triangle[0]);
+      dg.add_int32(triangle[1]);
+      dg.add_int32(triangle[2]);
+      iptr += mesh.m_triangleIndexStride;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMesh::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type BulletShape is encountered
+//               in the Bam file.  It should create the BulletShape
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletTriangleMesh::
+make_from_bam(const FactoryParams &params) {
+  BulletTriangleMesh *param = new BulletTriangleMesh;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMesh::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new BulletTriangleMesh.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMesh::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  set_welding_distance(scan.get_stdfloat());
+
+  nassertv(scan.get_int32() == 1);
+  int num_vertices = scan.get_int32();
+  int num_triangles = scan.get_int32();
+  nassertv(scan.get_bool() == true);
+
+  // Read and add the vertices.
+  _mesh->preallocateVertices(num_vertices);
+  for (int i = 0; i < num_vertices; ++i) {
+    PN_stdfloat x = scan.get_stdfloat();
+    PN_stdfloat y = scan.get_stdfloat();
+    PN_stdfloat z = scan.get_stdfloat();
+    _mesh->findOrAddVertex(btVector3(x, y, z), false);
+  }
+
+  // Now read and add the indices.
+  int num_indices = num_triangles * 3;
+  _mesh->preallocateIndices(num_indices);
+  for (int i = 0; i < num_indices; ++i) {
+    _mesh->addIndex(scan.get_int32());
+  }
+
+  // Since we manually added the vertices individually, we have to
+  // update the triangle count appropriately.
+  _mesh->getIndexedMeshArray()[0].m_numTriangles = num_triangles;
+}

+ 12 - 5
panda/src/bullet/bulletTriangleMesh.h

@@ -20,7 +20,7 @@
 #include "bullet_includes.h"
 #include "bullet_includes.h"
 #include "bullet_utils.h"
 #include "bullet_utils.h"
 
 
-#include "typedReferenceCount.h"
+#include "typedWritableReferenceCount.h"
 #include "nodePath.h"
 #include "nodePath.h"
 #include "luse.h"
 #include "luse.h"
 #include "geom.h"
 #include "geom.h"
@@ -31,7 +31,7 @@
 //       Class : BulletTriangleMesh
 //       Class : BulletTriangleMesh
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDABULLET BulletTriangleMesh : public TypedReferenceCount {
+class EXPCL_PANDABULLET BulletTriangleMesh : public TypedWritableReferenceCount {
 
 
 PUBLISHED:
 PUBLISHED:
   BulletTriangleMesh();
   BulletTriangleMesh();
@@ -63,15 +63,22 @@ public:
 private:
 private:
   btTriangleMesh *_mesh;
   btTriangleMesh *_mesh;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedReferenceCount::init_type();
+    TypedWritableReferenceCount::init_type();
     register_type(_type_handle, "BulletTriangleMesh", 
     register_type(_type_handle, "BulletTriangleMesh", 
-                  TypedReferenceCount::get_class_type());
+                  TypedWritableReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 116 - 1
panda/src/bullet/bulletTriangleMeshShape.cxx

@@ -21,6 +21,21 @@
 
 
 TypeHandle BulletTriangleMeshShape::_type_handle;
 TypeHandle BulletTriangleMeshShape::_type_handle;
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::Constructor
+//       Access: Private
+//  Description: Only used by make_from_bam.
+////////////////////////////////////////////////////////////////////
+BulletTriangleMeshShape::
+BulletTriangleMeshShape() :
+  _mesh(NULL),
+  _gimpact_shape(NULL),
+  _bvh_shape(NULL),
+  _dynamic(false),
+  _compress(false),
+  _bvh(false) {
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletTriangleMeshShape::Constructor
 //     Function: BulletTriangleMeshShape::Constructor
 //       Access: Published
 //       Access: Published
@@ -28,7 +43,10 @@ TypeHandle BulletTriangleMeshShape::_type_handle;
 //               if 'dynamic' is set to FALSE.
 //               if 'dynamic' is set to FALSE.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 BulletTriangleMeshShape::
 BulletTriangleMeshShape::
-BulletTriangleMeshShape(BulletTriangleMesh *mesh, bool dynamic, bool compress, bool bvh) {
+BulletTriangleMeshShape(BulletTriangleMesh *mesh, bool dynamic, bool compress, bool bvh) :
+  _dynamic(dynamic),
+  _compress(compress),
+  _bvh(bvh) {
 
 
   // Assert that mesh is not NULL
   // Assert that mesh is not NULL
   if (!mesh) {
   if (!mesh) {
@@ -101,3 +119,100 @@ refit_tree(const LPoint3 &aabb_min, const LPoint3 &aabb_max) {
                         LVecBase3_to_btVector3(aabb_max));
                         LVecBase3_to_btVector3(aabb_max));
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletTriangleMeshShape.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMeshShape::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMeshShape::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_margin());
+
+  manager->write_pointer(dg, _mesh);
+
+  dg.add_bool(_dynamic);
+  if (!_dynamic) {
+    dg.add_bool(_compress);
+    dg.add_bool(_bvh);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::complete_pointers
+//       Access: Public, Virtual
+//  Description: Receives an array of pointers, one for each time
+//               manager->read_pointer() was called in fillin().
+//               Returns the number of pointers processed.
+////////////////////////////////////////////////////////////////////
+int BulletTriangleMeshShape::
+complete_pointers(TypedWritable **p_list, BamReader *manager) {
+  int pi = BulletShape::complete_pointers(p_list, manager);
+
+  _mesh = DCAST(BulletTriangleMesh, p_list[pi++]);
+
+  btTriangleMesh *mesh_ptr = _mesh->ptr();
+  nassertr(mesh_ptr != NULL, pi);
+
+  if (_dynamic) {
+    _gimpact_shape = new btGImpactMeshShape(mesh_ptr);
+    _gimpact_shape->updateBound();
+    _gimpact_shape->setUserPointer(this);
+  } else {
+    _bvh_shape = new btBvhTriangleMeshShape(mesh_ptr, _compress, _bvh);
+    _bvh_shape->setUserPointer(this);
+  }
+
+  return pi;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type BulletShape is encountered
+//               in the Bam file.  It should create the BulletShape
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletTriangleMeshShape::
+make_from_bam(const FactoryParams &params) {
+  BulletTriangleMeshShape *param = new BulletTriangleMeshShape;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new BulletTriangleMeshShape.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMeshShape::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  PN_stdfloat margin = scan.get_stdfloat();
+
+  manager->read_pointer(scan);
+
+  _dynamic = scan.get_bool();
+  if (!_dynamic) {
+    _compress = scan.get_bool();
+    _bvh = scan.get_bool();
+  }
+}

+ 16 - 1
panda/src/bullet/bulletTriangleMeshShape.h

@@ -29,6 +29,8 @@ class BulletTriangleMesh;
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletTriangleMeshShape : public BulletShape {
 class EXPCL_PANDABULLET BulletTriangleMeshShape : public BulletShape {
+private:
+  INLINE BulletTriangleMeshShape();
 
 
 PUBLISHED:
 PUBLISHED:
   BulletTriangleMeshShape(BulletTriangleMesh *mesh, bool dynamic, bool compress=true, bool bvh=true);
   BulletTriangleMeshShape(BulletTriangleMesh *mesh, bool dynamic, bool compress=true, bool bvh=true);
@@ -50,7 +52,20 @@ private:
 
 
   PT(BulletTriangleMesh) _mesh;
   PT(BulletTriangleMesh) _mesh;
 
 
-////////////////////////////////////////////////////////////////////
+  bool _dynamic : 1;
+  bool _compress : 1;
+  bool _bvh : 1;
+
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+  virtual int complete_pointers(TypedWritable **plist,
+                              BamReader *manager);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 10 - 0
panda/src/bullet/config_bullet.cxx

@@ -182,6 +182,16 @@ init_libbullet() {
   BulletVehicle::init_type();
   BulletVehicle::init_type();
   BulletWorld::init_type();
   BulletWorld::init_type();
 
 
+  // Register factory functions for constructing objects from .bam files
+  BulletBoxShape::register_with_read_factory();
+  BulletConvexHullShape::register_with_read_factory();
+  BulletDebugNode::register_with_read_factory();
+  BulletPlaneShape::register_with_read_factory();
+  BulletRigidBodyNode::register_with_read_factory();
+  BulletSphereShape::register_with_read_factory();
+  BulletTriangleMesh::register_with_read_factory();
+  BulletTriangleMeshShape::register_with_read_factory();
+
   // Custom contact callbacks
   // Custom contact callbacks
   gContactAddedCallback = contact_added_callback;
   gContactAddedCallback = contact_added_callback;
   gContactProcessedCallback = contact_processed_callback;
   gContactProcessedCallback = contact_processed_callback;

+ 2 - 2
panda/src/cocoadisplay/cocoaGraphicsWindow.mm

@@ -159,7 +159,7 @@ begin_frame(FrameMode mode, Thread *current_thread) {
   // Set the drawable.
   // Set the drawable.
   if (_properties.get_fullscreen()) {
   if (_properties.get_fullscreen()) {
     // Fullscreen.
     // Fullscreen.
-    [cocoagsg->_context setFullScreen];
+    CGLSetFullScreenOnDisplay((CGLContextObj) [cocoagsg->_context CGLContextObj], CGDisplayIDToOpenGLDisplayMask(_display));
   } else {
   } else {
     // Although not recommended, it is technically possible to
     // Although not recommended, it is technically possible to
     // use the same context with multiple different-sized windows.
     // use the same context with multiple different-sized windows.
@@ -182,7 +182,7 @@ begin_frame(FrameMode mode, Thread *current_thread) {
 
 
   // Lock the view for drawing.
   // Lock the view for drawing.
   if (!_properties.get_fullscreen()) {
   if (!_properties.get_fullscreen()) {
-    nassertr([_view lockFocusIfCanDraw], false);
+    nassertr_always([_view lockFocusIfCanDraw], false);
   }
   }
 
 
   // Make the context current.
   // Make the context current.

+ 0 - 3
panda/src/collide/collisionFloorMesh.I

@@ -37,7 +37,6 @@
     graphicsWindowInputDevice.h \
     graphicsWindowInputDevice.h \
     graphicsWindowProc.h \
     graphicsWindowProc.h \
     graphicsWindowProcCallbackData.I graphicsWindowProcCallbackData.h \
     graphicsWindowProcCallbackData.I graphicsWindowProcCallbackData.h \
-    lru.h \
     nativeWindowHandle.I nativeWindowHandle.h \
     nativeWindowHandle.I nativeWindowHandle.h \
     parasiteBuffer.I parasiteBuffer.h \
     parasiteBuffer.I parasiteBuffer.h \
     pStatGPUTimer.I pStatGPUTimer.h \
     pStatGPUTimer.I pStatGPUTimer.h \
@@ -74,7 +73,6 @@
     graphicsWindowProc.cxx \
     graphicsWindowProc.cxx \
     graphicsWindowProcCallbackData.cxx \
     graphicsWindowProcCallbackData.cxx \
     graphicsDevice.cxx \
     graphicsDevice.cxx \
-    lru.cxx \
     nativeWindowHandle.cxx \
     nativeWindowHandle.cxx \
     parasiteBuffer.cxx \
     parasiteBuffer.cxx \
     windowHandle.cxx \
     windowHandle.cxx \
@@ -109,7 +107,6 @@
     graphicsThreadingModel.I graphicsThreadingModel.h \
     graphicsThreadingModel.I graphicsThreadingModel.h \
     graphicsWindowInputDevice.I graphicsWindowInputDevice.h \
     graphicsWindowInputDevice.I graphicsWindowInputDevice.h \
     graphicsDevice.I graphicsDevice.h \
     graphicsDevice.I graphicsDevice.h \
-    lru.h \
     nativeWindowHandle.I nativeWindowHandle.h \
     nativeWindowHandle.I nativeWindowHandle.h \
     parasiteBuffer.I parasiteBuffer.h \
     parasiteBuffer.I parasiteBuffer.h \
     pStatGPUTimer.I pStatGPUTimer.h \
     pStatGPUTimer.I pStatGPUTimer.h \

+ 1 - 1
panda/src/display/config_display.cxx

@@ -301,7 +301,7 @@ ConfigVariableBool allow_incomplete_render
           "the frame render if necessary."));
           "the frame render if necessary."));
 
 
 ConfigVariableInt win_size
 ConfigVariableInt win_size
-("win-size", "640 480",
+("win-size", "800 600",
  PRC_DESC("This is the default size at which to open a new window.  This "
  PRC_DESC("This is the default size at which to open a new window.  This "
           "replaces the deprecated win-width and win-height variables."));
           "replaces the deprecated win-width and win-height variables."));
 
 

+ 17 - 9
panda/src/display/get_x11.h

@@ -17,7 +17,7 @@
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 
 
-#ifdef HAVE_X11 
+#ifdef HAVE_X11
 // This header file is designed to help work around some of the
 // This header file is designed to help work around some of the
 // namespace spamming that X11 causes, by renaming the symbols that
 // namespace spamming that X11 causes, by renaming the symbols that
 // X11 declares that are known to conflict with other library names
 // X11 declares that are known to conflict with other library names
@@ -30,14 +30,21 @@
 #ifdef CPPPARSER
 #ifdef CPPPARSER
 // A simple hack so interrogate can get all of the necessary
 // A simple hack so interrogate can get all of the necessary
 // typenames.
 // typenames.
-typedef int X11_Display;
-typedef int X11_Window;
-typedef int X11_Cursor;
-typedef int XErrorEvent;
-typedef int XVisualInfo;
-typedef int Atom;
-typedef int XIM;
-typedef int XIC;
+typedef struct _XDisplay X11_Display;
+typedef unsigned int XID;
+typedef unsigned int Atom;
+typedef unsigned int Cardinal;
+typedef XID Colormap;
+typedef XID X11_Window;
+typedef XID X11_Cursor;
+typedef struct _XIM *XIM;
+typedef struct _XIC *XIC;
+struct XErrorEvent;
+struct XVisualInfo;
+#define Bool int
+#define Status int
+#define True 1
+#define False 0
 #else
 #else
 
 
 #include "pre_x11_include.h"
 #include "pre_x11_include.h"
@@ -45,6 +52,7 @@ typedef int XIC;
 #include <X11/Xutil.h>
 #include <X11/Xutil.h>
 #include <X11/keysym.h>
 #include <X11/keysym.h>
 #include <X11/Xatom.h>
 #include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
 
 
 #ifdef HAVE_XRANDR
 #ifdef HAVE_XRANDR
 #include <X11/extensions/Xrandr.h>
 #include <X11/extensions/Xrandr.h>

+ 2 - 0
panda/src/display/graphicsDevice.I

@@ -2001,9 +2001,11 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
   // to use.  We have to do this here because the ShaderGenerator
   // to use.  We have to do this here because the ShaderGenerator
   // needs a host window pointer.  Hopefully we'll be able to
   // needs a host window pointer.  Hopefully we'll be able to
   // eliminate that requirement in the future.
   // eliminate that requirement in the future.
+#ifdef HAVE_CG
   if (gsg->get_shader_generator() == NULL) {
   if (gsg->get_shader_generator() == NULL) {
     gsg->set_shader_generator(new ShaderGenerator(gsg, window));
     gsg->set_shader_generator(new ShaderGenerator(gsg, window));
   }
   }
+#endif
 
 
   return scene_setup;
   return scene_setup;
 }
 }

+ 48 - 0
panda/src/display/graphicsOutput.I

@@ -207,6 +207,20 @@ get_y_size() const {
   return _size.get_y();
   return _size.get_y();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::get_fb_size
+//       Access: Published
+//  Description: Returns the internal size of the window or buffer.
+//               This is almost always the same as get_size(),
+//               except when a pixel_zoom is in effect--see
+//               set_pixel_zoom().
+////////////////////////////////////////////////////////////////////
+INLINE LVecBase2i GraphicsOutput::
+get_fb_size() const {
+  return LVecBase2i(max(int(_size.get_x() * get_pixel_factor()), 1),
+                    max(int(_size.get_y() * get_pixel_factor()), 1));
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::get_fb_x_size
 //     Function: GraphicsOutput::get_fb_x_size
 //       Access: Published
 //       Access: Published
@@ -233,6 +247,23 @@ get_fb_y_size() const {
   return max(int(_size.get_y() * get_pixel_factor()), 1);
   return max(int(_size.get_y() * get_pixel_factor()), 1);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::get_sbs_left_size
+//       Access: Published
+//  Description: If side-by-side stereo is enabled, this returns the
+//               pixel size of the left eye, based on scaling
+//               get_size() by get_sbs_left_dimensions().  If
+//               side-by-side stereo is not enabled, this returns the
+//               same as get_size().
+////////////////////////////////////////////////////////////////////
+INLINE LVecBase2i GraphicsOutput::
+get_sbs_left_size() const {
+  PN_stdfloat left_w = _sbs_left_dimensions[1] - _sbs_left_dimensions[0];
+  PN_stdfloat left_h = _sbs_left_dimensions[3] - _sbs_left_dimensions[2];
+  return LVecBase2i(max(int(_size.get_x() * left_w), 1),
+                    max(int(_size.get_y() * left_h), 1));
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::get_sbs_left_x_size
 //     Function: GraphicsOutput::get_sbs_left_x_size
 //       Access: Published
 //       Access: Published
@@ -263,6 +294,23 @@ get_sbs_left_y_size() const {
   return max(int(_size.get_y() * left_h), 1);
   return max(int(_size.get_y() * left_h), 1);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsOutput::get_sbs_right_size
+//       Access: Published
+//  Description: If side-by-side stereo is enabled, this returns the
+//               pixel size of the right eye, based on scaling
+//               get_size() by get_sbs_right_dimensions().  If
+//               side-by-side stereo is not enabled, this returns the
+//               same as get_size().
+////////////////////////////////////////////////////////////////////
+INLINE LVecBase2i GraphicsOutput::
+get_sbs_right_size() const {
+  PN_stdfloat right_w = _sbs_right_dimensions[1] - _sbs_right_dimensions[0];
+  PN_stdfloat right_h = _sbs_right_dimensions[3] - _sbs_right_dimensions[2];
+  return LVecBase2i(max(int(_size.get_x() * right_w), 1),
+                    max(int(_size.get_y() * right_h), 1));
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::get_sbs_right_x_size
 //     Function: GraphicsOutput::get_sbs_right_x_size
 //       Access: Published
 //       Access: Published

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

@@ -135,10 +135,13 @@ PUBLISHED:
   INLINE const LVecBase2i &get_size() const;
   INLINE const LVecBase2i &get_size() const;
   INLINE int get_x_size() const;
   INLINE int get_x_size() const;
   INLINE int get_y_size() const;
   INLINE int get_y_size() const;
+  INLINE LVecBase2i get_fb_size() const;
   INLINE int get_fb_x_size() const;
   INLINE int get_fb_x_size() const;
   INLINE int get_fb_y_size() const;
   INLINE int get_fb_y_size() const;
+  INLINE LVecBase2i get_sbs_left_size() const;
   INLINE int get_sbs_left_x_size() const;
   INLINE int get_sbs_left_x_size() const;
   INLINE int get_sbs_left_y_size() const;
   INLINE int get_sbs_left_y_size() const;
+  INLINE LVecBase2i get_sbs_right_size() const;
   INLINE int get_sbs_right_x_size() const;
   INLINE int get_sbs_right_x_size() const;
   INLINE int get_sbs_right_y_size() const;
   INLINE int get_sbs_right_y_size() const;
   INLINE bool has_size() const;
   INLINE bool has_size() const;

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

@@ -397,6 +397,22 @@ get_max_cube_map_dimension() const {
   return _max_cube_map_dimension;
   return _max_cube_map_dimension;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_max_buffer_texture_size
+//       Access: Published
+//  Description: Returns the largest possible buffer texture size,
+//               or -1 if there is no particular limit.  Returns 0
+//               if cube map textures are not supported.
+//
+//               The value returned may not be meaningful until after
+//               the graphics context has been fully created (e.g. the
+//               window has been opened).
+////////////////////////////////////////////////////////////////////
+INLINE int GraphicsStateGuardian::
+get_max_buffer_texture_size() const {
+  return _max_buffer_texture_size;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_supports_texture_combine
 //     Function: GraphicsStateGuardian::get_supports_texture_combine
 //       Access: Published
 //       Access: Published
@@ -469,6 +485,16 @@ get_supports_cube_map() const {
   return _supports_cube_map;
   return _supports_cube_map;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_supports_buffer_texture
+//       Access: Published
+//  Description: Returns true if this GSG can render buffer textures.
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsStateGuardian::
+get_supports_buffer_texture() const {
+  return _supports_buffer_texture;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_supports_tex_non_pow2
 //     Function: GraphicsStateGuardian::get_supports_tex_non_pow2
 //       Access: Published
 //       Access: Published

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

@@ -185,6 +185,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
   _max_3d_texture_dimension = 0;
   _max_3d_texture_dimension = 0;
   _max_2d_texture_array_layers = 0;
   _max_2d_texture_array_layers = 0;
   _max_cube_map_dimension = 0;
   _max_cube_map_dimension = 0;
+  _max_buffer_texture_size = 0;
 
 
   // Assume we don't support these fairly advanced texture combiner
   // Assume we don't support these fairly advanced texture combiner
   // modes.
   // modes.
@@ -195,6 +196,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
   _supports_3d_texture = false;
   _supports_3d_texture = false;
   _supports_2d_texture_array = false;
   _supports_2d_texture_array = false;
   _supports_cube_map = false;
   _supports_cube_map = false;
+  _supports_buffer_texture = false;
   _supports_tex_non_pow2 = false;
   _supports_tex_non_pow2 = false;
   _supports_texture_srgb = false;
   _supports_texture_srgb = false;
   _supports_compressed_texture = false;
   _supports_compressed_texture = false;

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

@@ -121,6 +121,7 @@ PUBLISHED:
   INLINE int get_max_3d_texture_dimension() const;
   INLINE int get_max_3d_texture_dimension() const;
   INLINE int get_max_2d_texture_array_layers() const; //z axis
   INLINE int get_max_2d_texture_array_layers() const; //z axis
   INLINE int get_max_cube_map_dimension() const;
   INLINE int get_max_cube_map_dimension() const;
+  INLINE int get_max_buffer_texture_size() const;
 
 
   INLINE bool get_supports_texture_combine() const;
   INLINE bool get_supports_texture_combine() const;
   INLINE bool get_supports_texture_saved_result() const;
   INLINE bool get_supports_texture_saved_result() const;
@@ -129,6 +130,7 @@ PUBLISHED:
   INLINE bool get_supports_3d_texture() const;
   INLINE bool get_supports_3d_texture() const;
   INLINE bool get_supports_2d_texture_array() const;
   INLINE bool get_supports_2d_texture_array() const;
   INLINE bool get_supports_cube_map() const;
   INLINE bool get_supports_cube_map() const;
+  INLINE bool get_supports_buffer_texture() const;
   INLINE bool get_supports_tex_non_pow2() const;
   INLINE bool get_supports_tex_non_pow2() const;
   INLINE bool get_supports_texture_srgb() const;
   INLINE bool get_supports_texture_srgb() const;
 
 
@@ -476,6 +478,7 @@ protected:
   int _max_3d_texture_dimension;
   int _max_3d_texture_dimension;
   int _max_2d_texture_array_layers; //on the z axis
   int _max_2d_texture_array_layers; //on the z axis
   int _max_cube_map_dimension;
   int _max_cube_map_dimension;
+  int _max_buffer_texture_size;
 
 
   bool _supports_texture_combine;
   bool _supports_texture_combine;
   bool _supports_texture_saved_result;
   bool _supports_texture_saved_result;
@@ -484,6 +487,7 @@ protected:
   bool _supports_3d_texture;
   bool _supports_3d_texture;
   bool _supports_2d_texture_array;
   bool _supports_2d_texture_array;
   bool _supports_cube_map;
   bool _supports_cube_map;
+  bool _supports_buffer_texture;
   bool _supports_tex_non_pow2;
   bool _supports_tex_non_pow2;
   bool _supports_texture_srgb;
   bool _supports_texture_srgb;
 
 

+ 4 - 18
panda/src/display/graphicsWindow.cxx

@@ -736,24 +736,10 @@ set_properties_now(WindowProperties &properties) {
     // Fullscreen property specified, but unchanged.
     // Fullscreen property specified, but unchanged.
     properties.clear_fullscreen();
     properties.clear_fullscreen();
   }
   }
-  if (properties.has_mouse_mode() ) {
-    
-    if (properties.get_mouse_mode() == _properties.get_mouse_mode()) {  
-      properties.clear_mouse_mode();
-    }
-    else {
-      if(properties.get_mouse_mode() == WindowProperties::M_absolute) {
-        _properties.set_mouse_mode(WindowProperties::M_absolute);
-        mouse_mode_absolute();
-        properties.clear_mouse_mode();
-      }
-      else
-      {
-        _properties.set_mouse_mode(WindowProperties::M_relative);
-        mouse_mode_relative();
-        properties.clear_mouse_mode();        
-      }    
-    }
+  if (properties.has_mouse_mode() &&
+      properties.get_mouse_mode() == _properties.get_mouse_mode()) {
+    // Mouse mode specified, but unchanged.
+    properties.clear_mouse_mode();
   }
   }
 }
 }
 
 

+ 0 - 1229
panda/src/display/lru.cxx

@@ -1,1229 +0,0 @@
-// Filename: lru.cxx
-// Created by: aignacio (12Dec05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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."
-//
-////////////////////////////////////////////////////////////////////
-
-//#include "stdafx.h"
-
-#define LRU_UNIT_TEST 0
-
-#include <stdio.h>
-#include <stdlib.h>
-//#include <windows.h>
-
-#include "lru.h"
-#if ENABLE_MUTEX
-#include "mutexHolder.h"
-#endif
-
-
-static const int HIGH_PRIORITY_SCALE = 4;
-static const int LOW_PRIORITY_RANGE = 25;
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-Lru::Lru (int maximum_memory, int maximum_pages, int maximum_page_types)
-{
-  if(this) {
-    int  index;
-
-    memset(&this->_m, 0, sizeof (LruVariables));
-
-    this->_m.maximum_memory = maximum_memory;
-    this->_m.maximum_pages  = maximum_pages;
-    this->_m.maximum_page_types = maximum_page_types;
-    this->_m.available_memory = maximum_memory;
-    this->_m.current_frame_identifier = 1;
-    this->_m.weight = 0.20f;
-
-    this->set_maximum_frame_bandwidth_utilization(2000000.0f);
-
-    for(index = 0; index < MAXIMUM_LRU_PAGE_TYPES; index++) {
-      this->_m.page_in_function_array[index] = default_page_in_function;
-      this->_m.page_out_function_array[index] = default_page_out_function;
-    }
-
-    if(maximum_pages > 0) {
-      this -> _m.lru_page_pool = new LruPage * [maximum_pages];
-      this -> _m.lru_page_free_pool = new LruPage * [maximum_pages];
-      for(index = 0; index < maximum_pages; index++) {
-        LruPage  * lru_page;
-
-        lru_page = new LruPage ( );
-        if(lru_page) {
-          lru_page->_m.v.pre_allocated = true;
-          this->_m.lru_page_pool[index] = lru_page;
-        }
-        else {
-// ERROR
-        }
-      }
-    }
-
-    if(maximum_page_types > 0) {
-      this -> _m.page_type_statistics_array =
-        new PageTypeStatistics [maximum_page_types];
-    }
-
-#if ENABLE_MUTEX
-    this -> _m.mutex = new Mutex ("lru");
-#endif
-
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::Destructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-Lru::~Lru ( )
-{
-  int        index;
-  LruPage  * lru_page;
-
-  // free pre-allocated LruPages
-  if(this->_m.maximum_pages > 0) {
-    if(this->_m.lru_page_free_pool) {
-      for(index = 0; index < this->_m.maximum_pages; index++) {
-        lru_page = this->_m.lru_page_pool[index];
-        if(lru_page->_m.v.in_lru) {
-          this->remove_page(lru_page);
-        }
-
-        delete lru_page;
-      }
-
-      delete this -> _m.lru_page_free_pool;
-    }
-    if(this->_m.lru_page_pool) {
-      delete this -> _m.lru_page_pool;
-    }
-  }
-
-  // free dynamically allocated LruPages
-  for(index = 0; index < LPP_TotalPriorities; index++) {
-    LruPage  * next_lru_page;
-
-    lru_page = this->_m.lru_page_array[index];
-    while(lru_page) {
-      next_lru_page = lru_page->_m.next;
-
-      delete  lru_page;
-
-      lru_page = next_lru_page;
-    }
-  }
-
-  if(this->_m.page_type_statistics_array) {
-    delete this -> _m.page_type_statistics_array;
-  }
-
-#if ENABLE_MUTEX
-  if(this->_m.mutex) {
-    delete this -> _m.mutex;
-  }
-#endif
-
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LruPage::Constructor
-//       Access: Protected
-//  Description: Internal function only.
-//               Call  Lru::allocate_page instead.
-////////////////////////////////////////////////////////////////////
-LruPage::LruPage ( )
-{
-  if(this) {
-    memset(&this->_m, 0, sizeof (LruPageVariables));
-    _m.name = "";   
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LruPage::Destructor
-//       Access: Protected
-//  Description: Internal function only.
-//               Call  Lru::free_page instead.
-////////////////////////////////////////////////////////////////////
-LruPage::~LruPage ( )
-{
-
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: LruPage::change_priority
-//       Access: Protected
-//  Description:
-////////////////////////////////////////////////////////////////////
-void LruPage::change_priority (int delta)
-{
-  this->_m.priority_change += delta;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::register_lru_page_type
-//       Access: Public
-//  Description: Registers a specific type of page and its
-//               required page in and out functions.
-////////////////////////////////////////////////////////////////////
-bool Lru::register_lru_page_type (int index,
-  LruPageTypeFunction page_in_function,
-  LruPageTypeFunction page_out_function)
-{
-  bool  state;
-
-  state = false;
-  if(index >= 0 && index < MAXIMUM_LRU_PAGE_TYPES) {
-    this->_m.page_in_function_array[index] = page_in_function;
-    this->_m.page_out_function_array[index] = page_out_function;
-    state = true;
-  }
-
-  return state;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::allocate_page
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-LruPage *Lru::allocate_page (int size)
-{
-  LruPage  * lru_page;
-
-  lru_page = 0;
-  if(size <= this->_m.maximum_memory) {
-    if(this->_m.maximum_pages) {
-      if(this->_m.total_lru_pages_in_free_pool > 0) {
-        lru_page =
-          this->_m.lru_page_free_pool [this->_m.total_lru_pages_in_free_pool - 1];
-        this->_m.total_lru_pages_in_free_pool--;
-
-        memset (&lru_page -> _m, 0, sizeof (LruPage::LruPageVariables));
-        lru_page->_m.v.pre_allocated = true;
-      }
-      else {
-        if(this->_m.total_lru_pages_in_pool < this->_m.maximum_pages) {
-          lru_page = this->_m.lru_page_pool[this->_m.total_lru_pages_in_pool];
-          this->_m.total_lru_pages_in_pool++;
-        }
-        else {
-          // out of pre-allocated LruPages so dynamically allocate a page
-          lru_page = new LruPage ( );
-        }
-      }
-    }
-    else {
-      lru_page = new LruPage;
-    }
-    if(lru_page) {
-      lru_page->_m.lru = this;
-      lru_page->_m.size = size;
-      lru_page->_m.first_frame_identifier = this->_m.current_frame_identifier;
-      lru_page->_m.last_frame_identifier = this->_m.current_frame_identifier;
-
-      lru_page->_m.v.allocated = true;
-      lru_page->_m.identifier = this->_m.identifier;
-
-      lru_page->_m.average_frame_utilization = 1.0f;
-
-      this->_m.total_pages++;
-      this->_m.identifier++;
-    }
-    else {
-
-// ERROR: could not allocate LruPage
-
-    }
-  }
-  else {
-
-// ERROR: requested page size is larger than maximum memory size
-
-  }
-
-  return lru_page;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::update_start_update_lru_page
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-void Lru::update_start_update_lru_page (LruPage *lru_page)
-{
-  if(lru_page) {
-    if(this->_m.start_update_lru_page == lru_page) {
-      if(lru_page->_m.next) {
-        this->_m.start_update_lru_page = lru_page->_m.next;
-      }
-      else {
-        if((this->_m.start_priority_index + 1) >= LPP_TotalPriorities) {
-          this->_m.start_priority_index = 0;
-        }
-        else {
-          this->_m.start_priority_index = this->_m.start_priority_index + 1;
-        }
-
-        this->_m.start_update_lru_page = 0;
-      }
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::free_page
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-void Lru::free_page (LruPage *lru_page)
-{
-  if(this->_m.total_pages > 0) {
-    if(lru_page) {
-      LruMutexHolder(this->_m.mutex);
-
-      this->update_start_update_lru_page(lru_page);
-
-      if(lru_page->_m.v.in_cache) {
-        this->_m.available_memory += lru_page->_m.size;
-      }
-
-      if(lru_page->_m.v.pre_allocated) {
-        if(this->_m.maximum_pages) {
-          lru_page->_m.v.allocated = false;
-          this->_m.lru_page_free_pool [this->_m.total_lru_pages_in_free_pool] =
-            lru_page;
-          this->_m.total_lru_pages_in_free_pool++;
-        }
-        else {
-// ERROR: this case should not happen
-        }
-      }
-      else {
-        delete lru_page;
-      }
-
-      this->_m.total_pages--;
-    }
-  }
-  else {
-
-// ERROR: tried to free a page when 0 pages allocated
-
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::add_page
-//       Access: Public
-//  Description: Adds a page to the LRU based on the given priority.
-////////////////////////////////////////////////////////////////////
-void Lru::add_page (LruPagePriority priority, LruPage *lru_page)
-{
-  if(lru_page) {
-    LruMutexHolder(this->_m.mutex);
-
-    LruPage * first_lru_page;
-
-    lru_page->_m.priority = priority;
-
-    first_lru_page = this->_m.lru_page_array[lru_page->_m.priority];
-    if(first_lru_page) {
-      first_lru_page->_m.previous = lru_page;
-      lru_page->_m.next = first_lru_page;
-    }
-
-    this->_m.lru_page_array[lru_page->_m.priority] = lru_page;
-
-    lru_page->_m.v.in_lru = true;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::add_cached_page
-//       Access: Public
-//  Description: Adds a page that is already paged in to the LRU
-//               based on the given priority.
-////////////////////////////////////////////////////////////////////
-void Lru::add_cached_page (LruPagePriority priority, LruPage *lru_page)
-{
-  if(lru_page) {
-    LruMutexHolder(this->_m.mutex);
-
-    lru_page->_m.v.in_cache = true;
-
-    if(lru_page->_m.size > this->_m.available_memory) {
-      int  memory_required;
-
-      memory_required = lru_page->_m.size - this->_m.available_memory;
-
-      // unload page(s)
-      this->page_out_lru(memory_required);
-    }
-
-    this->_m.available_memory -= lru_page->_m.size;
-
-    this->add_page(priority, lru_page);
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::remove_page
-//       Access: Public
-//  Description: Removes a page from the LRU.
-////////////////////////////////////////////////////////////////////
-void Lru::remove_page (LruPage *lru_page)
-{
-  if(this) {
-    if(this->_m.total_pages > 0) {
-      if(lru_page) {
-        LruMutexHolder(this->_m.mutex);
-
-        this->update_start_update_lru_page(lru_page);
-
-        if(lru_page->_m.previous) {
-          lru_page->_m.previous->_m.next = lru_page->_m.next;
-          if(lru_page->_m.next) {
-            lru_page->_m.next->_m.previous = lru_page->_m.previous;
-          }
-        }
-        else {
-          this->_m.lru_page_array[lru_page->_m.priority] =
-            lru_page->_m.next;
-          if(lru_page->_m.next) {
-            lru_page->_m.next->_m.previous = 0;
-          }
-        }
-
-        lru_page->_m.next = 0;
-        lru_page->_m.previous = 0;
-
-        lru_page->_m.v.in_lru = false;
-      }
-    }
-    else {
-
-// ERROR: tried to remove a page when 0 pages are allocated
-
-    }
-  }
-  else {
-
-// ERROR: Lru == 0, this should not happen
-
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::lock_page
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-void Lru::lock_page (LruPage *lru_page)
-{
-  lru_page->_m.v.lock = true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::unlock_page
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-void Lru::unlock_page (LruPage *lru_page)
-{
-  lru_page->_m.v.lock = false;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::access_page
-//       Access: Public
-//  Description: This must always be called before accessing or
-//               using a page's memory since it pages in the page
-//               if it is currently paged out.
-////////////////////////////////////////////////////////////////////
-void Lru::access_page (LruPage *lru_page)
-{
-  if(lru_page) {
-    if(lru_page->_m.current_frame_identifier
-       == this->_m.current_frame_identifier) {
-      lru_page->_m.current_frame_usage++;
-      this->_m.total_page_all_access_size += lru_page->_m.size;
-    }
-    else {
-      // first update this frame
-      lru_page->_m.last_frame_identifier = lru_page->_m.current_frame_identifier;
-      lru_page->_m.current_frame_identifier = this->_m.current_frame_identifier;
-      lru_page->_m.last_frame_usage = lru_page->_m.current_frame_usage;
-      lru_page->_m.current_frame_usage = 1;
-      lru_page->_m.total_frame_page_faults = 0;
-
-      this->_m.total_page_access_size += lru_page->_m.size;
-    }
-
-    // check if the page is out
-    if(lru_page->_m.v.in_cache == false) {
-      bool  state;
-
-      state = true;
-
-      LruMutexHolder(this->_m.mutex);
-
-      // check memory usage
-      if(lru_page->_m.size > this->_m.available_memory) {
-        int  memory_required;
-
-        memory_required = lru_page->_m.size - this->_m.available_memory;
-
-        // unload page(s)
-        state = this->page_out_lru(memory_required);
-      }
-
-      // load the page in
-      if(state) {
-        // PAGE IN CALLBACK
-        if(this->_m.page_in_function_array[lru_page->_m.v.type](lru_page)) {
-          this->_m.available_memory -= lru_page->_m.size;
-          lru_page->_m.v.in_cache = true;
-
-          // CHANGE THE PAGE PRIORITY FROM LPP_PageOut TO LPP_New
-          this->remove_page(lru_page);
-          this->add_page(LPP_New, lru_page);
-
-          this->_m.total_lifetime_page_ins++;
-        }
-      }
-
-      lru_page->_m.total_frame_page_faults++;
-      lru_page->_m.total_page_faults++;
-    }
-
-    lru_page->_m.total_usage++;
-    lru_page->_m.update_total_usage++;
-
-    this->_m.total_page_access++;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::set_maximum_frame_bandwidth_utilization
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-void Lru::set_maximum_frame_bandwidth_utilization
-  (PN_stdfloat maximum_frame_bandwidth_utilization)
-{
-  this->_m.maximum_frame_bandwidth_utilization =
-    maximum_frame_bandwidth_utilization;
-
-  this->_m.frame_bandwidth_factor = (PN_stdfloat) LPP_TotalPriorities
-    / this->_m.maximum_frame_bandwidth_utilization;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::begin_frame
-//       Access: Public
-//  Description: This must be called before each frame.
-////////////////////////////////////////////////////////////////////
-void Lru::begin_frame ( )
-{
-  this->_m.current_frame_identifier++;
-
-  this->_m.total_page_ins_last_frame = this->_m.total_page_ins;
-  this->_m.total_page_outs = this->_m.total_page_outs;
-
-  this->_m.total_page_ins = 0;
-  this->_m.total_page_outs = 0;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::update_page_priorities
-//       Access: Public
-//  Description: This updates the priority of a page that has a
-//               change in priority.
-////////////////////////////////////////////////////////////////////
-void Lru::update_page_priorities (void)
-{
-  int index;
-  LruPage *lru_page;
-
-  for(index = 0; index < this->_m.total_lru_page_priority_changes; index++) {
-    int priority;
-
-    lru_page = this->_m.lru_page_priority_change_array[index];
-
-    this->remove_page(lru_page);
-
-    priority = (( int ) lru_page->_m.priority + lru_page->_m.priority_change);
-    if(priority < 0) {
-      priority = 0;
-    }
-    if(priority >= LPP_TotalPriorities) {
-      priority = LPP_TotalPriorities - 1;
-    }
-
-    this->add_page((LruPagePriority) priority, lru_page);
-    lru_page->_m.priority_change = 0;
-  }
-  this->_m.total_lru_page_priority_changes = 0;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::update_lru_page
-//       Access: Public
-//  Description: This updates the page's average utilization.
-//               Priority LPP_New is considered to be average usage
-//               of 1.0 (which means the page is used once per frame
-//               on average).  Priorities < LPP_New are for pages
-//               used more than once per frame and Priorities >
-//               LPP_New are for pages used less than once per frame.
-//               If there was a change in priority, then adds it to
-//               the array of lru pages with changed priorities
-//               which will be updated later.
-////////////////////////////////////////////////////////////////////
-void Lru::update_lru_page (LruPage *lru_page)
-{
-
-#if LRU_UNIT_TEST
-  if(false) {
-    char  string[256];
-
-    sprintf(string, "  UPDATE %d\n", lru_page->_m.identifier);
-    OutputDebugString(string);
-  }
-#endif
-
-  if(lru_page->_m.v.lock == false && lru_page->_m.v.in_cache) {
-    int delta_priority;
-    int lifetime_frames;
-
-    delta_priority = 0;
-
-    lifetime_frames = this->_m.current_frame_identifier -
-      lru_page->_m.first_frame_identifier;
-    if(lifetime_frames >= 1) {
-      if(lru_page->_m.update_frame_identifier) {
-        int target_priority;
-        int integer_update_frames;
-        PN_stdfloat update_frames;
-        PN_stdfloat one_over_update_frames;
-        PN_stdfloat update_average_frame_utilization;
-
-        integer_update_frames = (this->_m.current_frame_identifier -
-          lru_page->_m.update_frame_identifier);
-        if(integer_update_frames > 0) {
-          update_frames = ( PN_stdfloat ) integer_update_frames;
-          one_over_update_frames = 1.0f / update_frames;
-
-          update_average_frame_utilization =
-            (PN_stdfloat) (lru_page->_m.update_total_usage)* one_over_update_frames;
-
-          lru_page->_m.average_frame_utilization =
-            calculate_exponential_moving_average(
-               update_average_frame_utilization, this->_m.weight,
-               lru_page->_m.average_frame_utilization);
-
-          target_priority = lru_page->_m.priority;
-          if(lru_page->_m.average_frame_utilization >= 1.0f) {
-            int integer_average_frame_utilization;
-
-            integer_average_frame_utilization =
-              (int) ((lru_page->_m.average_frame_utilization - 1.0f) *
-              (PN_stdfloat) HIGH_PRIORITY_SCALE);
-            if(integer_average_frame_utilization >= LPP_New) {
-              integer_average_frame_utilization = LPP_New;
-            }
-            integer_average_frame_utilization = LPP_New -
-              integer_average_frame_utilization;
-            target_priority = integer_average_frame_utilization;
-          }
-          else {
-            int integer_average_frame_utilization;
-
-            integer_average_frame_utilization = (int)
-               (lru_page->_m.average_frame_utilization *
-               (PN_stdfloat) LOW_PRIORITY_RANGE);
-            integer_average_frame_utilization = LOW_PRIORITY_RANGE -
-              integer_average_frame_utilization;
-            target_priority = LPP_New + integer_average_frame_utilization;
-          }
-
-          delta_priority = target_priority - lru_page->_m.priority;
-          lru_page->change_priority(delta_priority);
-        }
-      }
-
-      lru_page->_m.update_frame_identifier = this->_m.current_frame_identifier;
-      lru_page->_m.update_total_usage = 0;
-    }
-
-    if(lru_page->_m.priority_change) {
-      if(this->_m.total_lru_page_priority_changes
-         < FRAME_MAXIMUM_PRIORITY_CHANGES)
-      {
-        this->_m.lru_page_priority_change_array
-          [this->_m.total_lru_page_priority_changes] = lru_page;
-        this->_m.total_lru_page_priority_changes++;
-      }
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::update_lru_page_old
-//       Access: Public
-//  Description: This updates the page's average utilization and
-//               adds it to the array of pages with changed
-//               priorities if there was a change in priority.
-//               Old method.
-////////////////////////////////////////////////////////////////////
-void Lru::update_lru_page_old (LruPage *lru_page)
-{
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::update_entire_lru
-//       Access: Public
-//  Description: This updates all the pages in the Lru.
-//               Lru::partial_lru_update should be called instead
-//               due to performance reasons.
-////////////////////////////////////////////////////////////////////
-void Lru::update_entire_lru ( )
-{
-  if(this->_m.total_pages > 0) {
-    int index;
-    LruPage *lru_page;
-
-    LruMutexHolder(this->_m.mutex);
-
-    for(index = 0; index < LPP_TotalPriorities; index++) {
-
-      LruPage  * next_lru_page;
-
-      lru_page = this->_m.lru_page_array[index];
-      while(lru_page) {
-        next_lru_page = lru_page->_m.next;
-
-        this->update_lru_page(lru_page);
-
-        lru_page = next_lru_page;
-      }
-    }
-
-    this->update_page_priorities( );
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::partial_lru_update
-//       Access: Public
-//  Description: This only updates a number of pages up to the
-//               specified maximum_updates.
-////////////////////////////////////////////////////////////////////
-void Lru::partial_lru_update (int maximum_updates)
-{
-  int total_page_updates;
-
-  if (maximum_updates <= 0) {
-    // enforce a minimum number of updates
-    maximum_updates = 1;
-  }
-
-  total_page_updates = 0;
-  if(this->_m.total_pages > 0) {
-    int index;
-    int start_priority;
-    LruPage *lru_page;
-
-    LruMutexHolder(this->_m.mutex);
-
-    start_priority = this->_m.start_priority_index;
-
-    {
-      for(index = start_priority;  index < LPP_TotalPriorities; index++) {
-
-        LruPage *next_lru_page;
-
-        if(index == start_priority) {
-          if(this->_m.start_update_lru_page) {
-            lru_page = this->_m.start_update_lru_page;
-          }
-          else {
-            lru_page = this->_m.lru_page_array[index];
-          }
-        }
-        else {
-          lru_page = this->_m.lru_page_array[index];
-        }
-        while(lru_page) {
-          next_lru_page = lru_page->_m.next;
-
-          this->update_lru_page(lru_page);
-
-          total_page_updates++;
-          if(total_page_updates >= maximum_updates) {
-            if(next_lru_page) {
-              this->_m.start_priority_index = index;
-              this->_m.start_update_lru_page = next_lru_page;
-            }
-            else {
-              if((index + 1) >= LPP_TotalPriorities) {
-                this->_m.start_priority_index = 0;
-              }
-              else {
-                this->_m.start_priority_index = index + 1;
-              }
-
-              this->_m.start_update_lru_page = 0;
-            }
-
-            break;
-          }
-
-          lru_page = next_lru_page;
-        }
-
-        if(total_page_updates >= maximum_updates) {
-          break;
-        }
-      }
-    }
-
-    if(total_page_updates < maximum_updates) {
-      for(index = 0;  index <= start_priority;  index++) {
-        LruPage *next_lru_page;
-
-        lru_page = this->_m.lru_page_array[index];
-        while(lru_page) {
-          next_lru_page = lru_page->_m.next;
-
-          this->update_lru_page(lru_page);
-
-          total_page_updates++;
-          if(total_page_updates >= maximum_updates) {
-            if(next_lru_page) {
-              this->_m.start_priority_index = index;
-              this->_m.start_update_lru_page = next_lru_page;
-            }
-            else {
-              if((index + 1) >= LPP_TotalPriorities) {
-                this->_m.start_priority_index = 0;
-              }
-              else {
-                this->_m.start_priority_index = index + 1;
-              }
-
-              this->_m.start_update_lru_page = 0;
-            }
-
-            break;
-          }
-
-          lru_page = next_lru_page;
-        }
-
-        if(total_page_updates >= maximum_updates) {
-          break;
-        }
-      }
-    }
-
-    if(total_page_updates < maximum_updates) {
-      this->_m.start_priority_index  = 0;
-      this->_m.start_update_lru_page = 0;
-    }
-
-    this->update_page_priorities( );
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::unlock_all_pages
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-void Lru::unlock_all_pages (void)
-{
-  if(this->_m.total_pages > 0) {
-    int  index;
-
-    for(index = 0;  index < LPP_TotalPriorities; index++) {
-      LruPage *lru_page;
-      LruPage *next_lru_page;
-
-      lru_page = this->_m.lru_page_array[index];
-      while(lru_page) {
-        next_lru_page = lru_page->_m.next;
-
-        lru_page->_m.v.lock = false;
-
-        lru_page = next_lru_page;
-      }
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::page_out_lru
-//       Access: Public
-//  Description: Pages out the lowest priority pages until the
-//               memory_required is satisfied.  This will unlock
-//               all pages if needed.
-////////////////////////////////////////////////////////////////////
-bool Lru::page_out_lru (int memory_required)
-{
-  bool state;
-  int attempts;
-
-  state = false;
-  attempts = 0;
-  if(this->_m.total_pages > 0) {
-    LruMutexHolder(this->_m.mutex);
-
-    do {
-      int index;
-      int minimum_frame_identifier;
-      
-      minimum_frame_identifier = this->_m.current_frame_identifier - 1;
-
-      // page out lower priority pages first
-      for(index = LPP_PageOut - 1; index >= 0; index--) {
-        LruPage *lru_page;
-        LruPage *next_lru_page;
-
-        lru_page = this->_m.lru_page_array[index];
-        while(lru_page) {
-          next_lru_page = lru_page->_m.next;
-
-          if(attempts == 0 && (lru_page->_m.current_frame_identifier >= minimum_frame_identifier)) {
-            // avoid swapping out pages used in the current and last frame on the first attempt
-          }
-          else {
-            if(lru_page->_m.v.lock == false && lru_page->_m.v.in_cache) {
-              memory_required -= lru_page->_m.size;
-              this->_m.available_memory += lru_page->_m.size;
-              lru_page->_m.v.in_cache = false;
-
-              // PAGE OUT CALLBACK
-              this->_m.page_out_function_array[lru_page->_m.v.type](lru_page);
-              this->_m.total_lifetime_page_outs++;
-
-              // MOVE THE PAGE TO THE LPP_PageOut PRIORITY
-              this->remove_page(lru_page);
-              this->add_page(LPP_PageOut, lru_page);
-
-              if(memory_required <= 0) {
-                break;
-              }
-            }
-          }
-          
-          lru_page = next_lru_page;
-        }
-
-        if(memory_required <= 0) {
-          break;
-        }
-      }
-
-      if(memory_required > 0) {
-        state = false;
-      }
-      else {
-        state = true;
-      }
-
-      attempts++;
-    } while(state == false && attempts < 2);
-  }
-
-  return state;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::count_priority_level_pages
-//       Access: Public
-//  Description: Debug function. Counts the number of pages for each
-//               priority level.
-////////////////////////////////////////////////////////////////////
-void Lru::count_priority_level_pages (void)
-{
-  int  index;
-
-  LruMutexHolder(this->_m.mutex);
-
-  for(index = 0; index < LPP_TotalPriorities; index++) {
-    int total_pages;
-    LruPage *lru_page;
-    LruPage *next_lru_page;
-
-    total_pages = 0;
-    lru_page = this->_m.lru_page_array[index];
-    while(lru_page) {
-      next_lru_page = lru_page->_m.next;
-
-      total_pages++;
-
-      lru_page = next_lru_page;
-    }
-
-    this->_m.lru_page_count_array[index] = total_pages;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: Lru::calculate_lru_statistics
-//       Access: Public
-//  Description: Debug function.
-////////////////////////////////////////////////////////////////////
-void Lru::calculate_lru_statistics (void)
-{
-  LruMutexHolder(this->_m.mutex);
-
-  if(this->_m.maximum_page_types > 0) {
-    int  index;
-
-    memset(this->_m.page_type_statistics_array, 0,
-           sizeof (PageTypeStatistics) * this->_m.maximum_page_types);
-    for(index = 0;  index < LPP_TotalPriorities;  index++) {
-      LruPage *lru_page;
-      LruPage *next_lru_page;
-      PageTypeStatistics *page_type_statistics;
-
-      lru_page = this->_m.lru_page_array[index];
-      while(lru_page) {
-        int  type;
-
-        next_lru_page = lru_page->_m.next;
-
-        type = lru_page->_m.v.type;
-        page_type_statistics = &this->_m.page_type_statistics_array[type];
-        page_type_statistics->total_pages++;
-
-        if(lru_page->_m.v.in_cache) {
-          page_type_statistics->total_pages_in++;
-          page_type_statistics->total_memory_in += lru_page->_m.size;
-        }
-        else {
-          page_type_statistics->total_pages_out++;
-          page_type_statistics->total_memory_out += lru_page->_m.size;
-        }
-
-        lru_page = next_lru_page;
-      }
-    }
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: calculate_exponential_moving_average
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-PN_stdfloat calculate_exponential_moving_average(PN_stdfloat value,
-  PN_stdfloat weight, PN_stdfloat average)
-{
-  return ((value - average) * weight) + average;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: default_page_in_function
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-bool default_page_in_function(LruPage *lru_page)
-{
-
-#if LRU_UNIT_TEST
-  char  string[256];
-
-  sprintf(string, "  PAGE IN %d\n", lru_page->_m.identifier);
-  OutputDebugString(string);
-#endif
-
-  return true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: default_page_out_function
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-bool default_page_out_function(LruPage *lru_page)
-{
-
-#if LRU_UNIT_TEST
-  char  string[256];
-
-  sprintf(string, "  PAGE OUT %d\n", lru_page->_m.identifier);
-  OutputDebugString(string);
-#endif
-
-  return true;
-}
-
-#if LRU_UNIT_TEST
-
-////////////////////////////////////////////////////////////////////
-//     Function: test_ema
-//       Access:
-//  Description: Unit test function for ema.
-////////////////////////////////////////////////////////////////////
-void test_ema(void)
-{
-  int    index;
-  PN_stdfloat  usage;
-  PN_stdfloat  weight;
-  PN_stdfloat  average;
-
-  weight  = 0.2;
-  average = 1.0f;
-  for(index = 0; index < 50; index++) {
-    if(index < 25) {
-      usage = (PN_stdfloat) (index & 0x01);
-    }
-    else {
-      usage = 0.0f;
-    }
-    average =
-      calculate_exponential_moving_average(usage, weight, average);
-
-    char  string[256];
-    sprintf(string, "%d  %f\n", index, average);
-    OutputDebugString(string);
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: test_lru
-//       Access:
-//  Description: Unit test function for Lru.
-////////////////////////////////////////////////////////////////////
-void test_lru(void)
-{
-  int maximum_memory;
-  int maximum_pages;
-  int maximum_page_types;
-  Lru *lru;
-
-  test_ema( );
-
-  maximum_memory = 3000000;
-  maximum_pages = 3;
-  maximum_page_types = 4;
-  lru = new Lru (maximum_memory, maximum_pages, maximum_page_types);
-  if(lru) {
-    lru->_m.minimum_memory = 1000000;
-
-    LruPage *lru_page_0;
-    LruPage *lru_page_1;
-    LruPage *lru_page_2;
-    LruPage *lru_page_3;
-    LruPage *lru_page_4;
-    LruPage *lru_page_5;
-
-    lru_page_0 = lru->allocate_page(1000000);
-    if(lru_page_0) {
-      lru->add_page(LPP_PageOut, lru_page_0);
-    }
-
-    lru_page_1 = lru->allocate_page(1000000);
-    if(lru_page_1) {
-      lru->add_page(LPP_PageOut, lru_page_1);
-    }
-
-    lru_page_2 = lru->allocate_page(1000000);
-    if(lru_page_2) {
-      lru->add_page(LPP_PageOut, lru_page_2);
-    }
-
-    lru_page_3 = lru->allocate_page(1000000);
-    if(lru_page_3) {
-      lru->add_page(LPP_PageOut, lru_page_3);
-    }
-
-    lru_page_4 = lru->allocate_page(1000000);
-    if(lru_page_4) {
-      lru->add_page(LPP_PageOut, lru_page_4);
-    }
-
-    lru_page_5 = lru->allocate_page(1000000);
-    if(lru_page_5) {
-      lru->add_page(LPP_PageOut, lru_page_5);
-    }
-
-    int index;
-    int total_frames;
-
-    total_frames = 300;
-    for(index = 0;  index < total_frames;  index++) {
-      char  string[256];
-
-      sprintf(string, "FRAME %d\n", index);
-      OutputDebugString(string);
-
-      lru->begin_frame( );
-
-      if(index <= 5) {
-        lru->access_page(lru_page_0);
-      }
-
-      lru->access_page(lru_page_1);
-      lru->access_page(lru_page_1);
-
-      if(index & 0x01) {
-        lru->access_page(lru_page_2);
-      }
-
-      if((index % 10) == 0) {
-        lru->access_page(lru_page_3);
-      }
-
-      if(index >= 100) {
-        lru->access_page(lru_page_4);
-      }
-
-      if(index >= 200) {
-        lru->access_page(lru_page_5);
-      }
-
-      if(false) {
-        lru->update_entire_lru( );
-      }
-      else {
-        int  maximum_updates;
-
-        maximum_updates = 3;
-        lru->partial_lru_update(maximum_updates);
-      }
-    }
-
-    if(!true) {
-      lru->remove_page(lru_page_2);
-      lru->free_page(lru_page_2);
-
-      lru->remove_page(lru_page_3);
-      lru->free_page(lru_page_3);
-
-      lru->remove_page(lru_page_1);
-      lru->free_page(lru_page_1);
-    }
-
-    delete lru;
-  }
-}
-
-#endif

+ 0 - 269
panda/src/display/lru.h

@@ -1,269 +0,0 @@
-// Filename: lru.h
-// Created by: aignacio (12Dec05)
-//
-////////////////////////////////////////////////////////////////////
-//
-// 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."
-//
-////////////////////////////////////////////////////////////////////
-
-#ifndef LRU_H
-#define LRU_H
-
-#define ENABLE_MUTEX 1
-
-#if ENABLE_MUTEX
-#include "lightMutex.h"
-#include "lightMutexHolder.h"
-#define LruMutexHolder(mutex) MutexHolder(mutex)
-#else
-#define LruMutexHolder(mutex)
-#endif
-
-
-static const int MAXIMUM_LRU_PAGE_TYPES = 8;
-static const int FRAME_MAXIMUM_PRIORITY_CHANGES = 256;
-
-
-class Lru;
-class LruPage;
-
-enum LruPagePriority
-{
-  LPP_Highest = 0,
-  LPP_High = 10,
-  LPP_New = 20,
-  LPP_Normal = 25,
-  LPP_Intermediate = 30,
-  LPP_Low = 40,
-  LPP_TotalPriorities = 50,
-
-  LPP_PageOut = LPP_TotalPriorities - 1
-};
-
-typedef union _LruPageType
-{
-  void *pointer;
-
-}
-LruPageType;
-
-typedef struct
-{
-  int total_pages;
-  int total_pages_in;
-  int total_pages_out;
-  int total_memory_in;
-  int total_memory_out;
-}
-PageTypeStatistics;
-
-typedef bool (*LruPageTypeFunction) (LruPage *lru_page);
-
-class EXPCL_PANDA_DISPLAY LruPage
-{
-
-protected:
-
-  LruPage ( );
-  ~LruPage ( );
-  void change_priority (int delta);
-
-public:
-
-  typedef struct _LruPageVariables
-  {
-    LruPageType lru_page_type;  // pointer to memory type
-
-    int size;
-    LruPagePriority priority;
-    int priority_change;
-
-    struct
-    {
-      unsigned int type : 8;
-      unsigned int lock : 1;
-      unsigned int in_cache : 1;
-      unsigned int in_memory : 1;
-      unsigned int on_disk : 1;
-      unsigned int pre_allocated : 1;
-      unsigned int allocated : 1;
-      unsigned int in_lru : 1;
-    } v;
-
-    int first_frame_identifier;   // creation time
-    int last_frame_identifier;    // previous time page was used
-    int current_frame_identifier;
-    int update_frame_identifier;
-
-    int current_frame_usage;
-    int last_frame_usage;
-
-    int total_frame_page_faults;
-    int total_page_faults;
-
-    int total_usage;
-    int update_total_usage;
-
-    int identifier;
-
-    PN_stdfloat average_frame_utilization;
-
-    LruPage *previous;
-    LruPage *next;
-    Lru *lru;
-    
-    string name;
-  }
-  LruPageVariables;
-
-  LruPageVariables _m;
-
-  friend class Lru;
-};
-
-////////////////////////////////////////////////////////////////////
-//       Class : Lru
-// Description : Least Recently Used algorithm implementation:
-// In the Lru, each "memory page" has an associated class LruPage.
-// The Lru has a range of priorities from LPP_Highest to
-// LPP_PagedOut. Each priority has a doubly linked list of LruPages.
-// The algorithim uses an adaptive method based on the average
-// utilization of each page per frame (or time slice). The
-// average utilization is calculated with an exponetial moving
-// average. This is superior to a standard average since a standard
-// average becomes less and less adaptive the longer a page exists.
-// The average utilization is used to set the priority of each page.
-// A higher average utilization automatically raises the priority
-// of a page and a lower average utilization automatically lowers
-// the priority of a page. Therefore, pages with a higher average
-// utilization have a higher chance of being kept in memory or
-// cached and pages with a lower average utilization have a higher
-// chance of being paged out.  When a page is paged in and there
-// is not enough memory available, then the lowest priority pages
-// will be paged out first until there is enough memory available.
-////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_DISPLAY Lru
-{
-public:
-
-  Lru (int maximum_memory, int maximum_pages, int maximum_page_types);
-  ~Lru ( );
-
-  bool register_lru_page_type (int index, LruPageTypeFunction page_in_function, LruPageTypeFunction page_out_function);
-
-  LruPage *allocate_page (int size);
-  void update_start_update_lru_page (LruPage *lru_page);
-
-  void free_page (LruPage *lru_page);
-
-  void add_page (LruPagePriority priority, LruPage *lru_page);
-  void add_cached_page (LruPagePriority priority, LruPage *lru_page);
-  void remove_page (LruPage *lru_page);
-
-  void lock_page (LruPage *lru_page);
-  void unlock_page (LruPage *lru_page);
-
-  void access_page (LruPage *lru_page);
-
-  void set_maximum_frame_bandwidth_utilization (PN_stdfloat maximum_frame_bandwidth_utilization);
-
-  void begin_frame ( );
-
-  void update_entire_lru ( );
-  void partial_lru_update (int maximum_updates);
-
-  // set maximum number of page updates per frame
-  // pause/resume updates/current_frame_identifier
-
-  void unlock_all_pages (void);
-
-  void count_priority_level_pages (void);
-
-  void calculate_lru_statistics (void);
-
-  bool page_out_lru (int memory_required);
-
-private:
-  void update_page_priorities (void);
-  void update_lru_page (LruPage *lru_page);
-  void update_lru_page_old (LruPage *lru_page);
-
-public:
-  typedef struct _LruVariables
-  {
-    // LruPagePriority lists
-    LruPage *lru_page_array [LPP_TotalPriorities];
-
-    int total_pages;
-    int available_memory;
-    int current_frame_identifier;
-
-    int maximum_memory;
-    int minimum_memory; // target amount of memory to keep free if possible
-    int maximum_page_types;
-
-    int total_lifetime_page_ins;
-    int total_lifetime_page_outs;
-
-    int total_page_ins_last_frame;
-    int total_page_outs_last_frame;
-
-    int total_page_ins;
-    int total_page_outs;
-
-    int total_page_access;
-    double total_page_access_size;
-    double total_page_all_access_size;
-
-    int start_priority_index;
-    LruPage *start_update_lru_page;
-
-    int identifier; // the number of pages created during the lifetime of the LRU
-
-    PN_stdfloat weight; // used for exponential moving average
-    PN_stdfloat maximum_frame_bandwidth_utilization;
-
-    PN_stdfloat frame_bandwidth_factor;
-
-    LruPageTypeFunction page_in_function_array [MAXIMUM_LRU_PAGE_TYPES];
-    LruPageTypeFunction page_out_function_array [MAXIMUM_LRU_PAGE_TYPES];
-
-    int total_lru_page_priority_changes;
-    LruPage *lru_page_priority_change_array [FRAME_MAXIMUM_PRIORITY_CHANGES];
-
-    int maximum_pages;
-    int total_lru_pages_in_pool;
-    int total_lru_pages_in_free_pool;
-    LruPage **lru_page_pool;
-    LruPage **lru_page_free_pool;
-
-    int lru_page_count_array [LPP_TotalPriorities];
-    PageTypeStatistics *page_type_statistics_array;
-
-    void *context;  // user specified data
-
-#if ENABLE_MUTEX
-    Mutex *mutex;
-#endif
-  }
-  LruVariables;
-
-  LruVariables _m;
-
-  friend class LruPage;
-};
-
-PN_stdfloat calculate_exponential_moving_average (PN_stdfloat value, PN_stdfloat weight, PN_stdfloat average);
-bool default_page_in_function (LruPage *lru_page);
-bool default_page_out_function (LruPage *lru_page);
-
-void test_ema (void);
-void test_lru (void);
-
-#endif

+ 0 - 1
panda/src/display/p3display_composite2.cxx

@@ -5,7 +5,6 @@
 #include "graphicsWindowProc.cxx"
 #include "graphicsWindowProc.cxx"
 #include "graphicsWindowProcCallbackData.cxx"
 #include "graphicsWindowProcCallbackData.cxx"
 #include "graphicsWindowInputDevice.cxx"
 #include "graphicsWindowInputDevice.cxx"
-#include "lru.cxx"
 #include "nativeWindowHandle.cxx"
 #include "nativeWindowHandle.cxx"
 #include "parasiteBuffer.cxx"
 #include "parasiteBuffer.cxx"
 #include "standardMunger.cxx"
 #include "standardMunger.cxx"

+ 13 - 0
panda/src/display/standardMunger.I

@@ -23,3 +23,16 @@ INLINE GraphicsStateGuardian *StandardMunger::
 get_gsg() const {
 get_gsg() const {
   return (GraphicsStateGuardian *)GeomMunger::get_gsg();
   return (GraphicsStateGuardian *)GeomMunger::get_gsg();
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: StandardMunger::get_render_mode
+//       Access: Protected
+//  Description: Returns the render mode active on this munger.
+//               Intended for derived classes that may have to munge
+//               differently depending on render mode.
+////////////////////////////////////////////////////////////////////
+INLINE RenderModeAttrib::Mode StandardMunger::
+get_render_mode() const {
+  return (_render_mode != NULL) ? _render_mode->get_mode()
+                                : RenderModeAttrib::M_filled;
+}

+ 2 - 0
panda/src/display/standardMunger.cxx

@@ -365,6 +365,7 @@ munge_state_impl(const RenderState *state) {
     munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot());
     munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot());
   }
   }
 
 
+#ifdef HAVE_CG
   if (_auto_shader) {
   if (_auto_shader) {
     CPT(RenderState) shader_state = munged_state->get_auto_shader_state();
     CPT(RenderState) shader_state = munged_state->get_auto_shader_state();
     ShaderGenerator *shader_generator = get_gsg()->get_shader_generator();
     ShaderGenerator *shader_generator = get_gsg()->get_shader_generator();
@@ -379,6 +380,7 @@ munge_state_impl(const RenderState *state) {
     }
     }
     munged_state = munged_state->set_attrib(shader_state->_generated_shader);
     munged_state = munged_state->set_attrib(shader_state->_generated_shader);
   }
   }
+#endif
 
 
   return munged_state;
   return munged_state;
 }
 }

+ 2 - 0
panda/src/display/standardMunger.h

@@ -49,6 +49,8 @@ protected:
   virtual int geom_compare_to_impl(const GeomMunger *other) const;
   virtual int geom_compare_to_impl(const GeomMunger *other) const;
   virtual CPT(RenderState) munge_state_impl(const RenderState *state);
   virtual CPT(RenderState) munge_state_impl(const RenderState *state);
 
 
+  INLINE RenderModeAttrib::Mode get_render_mode() const;
+
 private:
 private:
   int _num_components;
   int _num_components;
   NumericType _numeric_type;
   NumericType _numeric_type;

+ 1 - 0
panda/src/display/subprocessWindowBuffer.cxx

@@ -16,6 +16,7 @@
 #include <sys/mman.h>
 #include <sys/mman.h>
 #include <fcntl.h>
 #include <fcntl.h>
 #include <string.h>
 #include <string.h>
+#include <unistd.h>
 
 
 #include <iostream>
 #include <iostream>
 using namespace std;
 using namespace std;

+ 23 - 12
panda/src/display/windowProperties.I

@@ -798,19 +798,30 @@ clear_z_order() {
 //     Function: WindowProperties::set_mouse_mode
 //     Function: WindowProperties::set_mouse_mode
 //       Access: Published
 //       Access: Published
 //  Description: Specifies the mode in which the window is to operate
 //  Description: Specifies the mode in which the window is to operate
-//               its mouse pointer.  The default is M_absolute, which
-//               is the normal mode in which a mouse pointer operates;
-//               but you can also set M_relative, which is
-//               particularly useful for FPS-style mouse movements
-//               where you have hidden the mouse pointer and are are
-//               more interested in how fast the mouse is moving,
-//               rather than precisely where the pointer is hovering.
+//               its mouse pointer.
+//
+//               M_absolute: the normal mode in which a mouse pointer
+//               operates, where the mouse can move outside the window
+//               and the mouse coordinates are relative to its
+//               position in the window.
+//
+//               M_relative (OSX or Unix/X11 only): a mode where only
+//               relative movements are reported; particularly useful
+//               for FPS-style mouse movements where you have hidden
+//               the mouse pointer and are are more interested in how
+//               fast the mouse is moving, rather than precisely where
+//               the pointer is hovering.
+//
+//               This has no effect on Windows.  On Unix/X11, this
+//               requires the Xxf86dga extension to be available.
+//
+//               M_confined: this mode reports absolute mouse
+//               positions, but confines the mouse pointer to
+//               the window boundary.  It can portably replace
+//               M_relative for an FPS, but you need to periodically
+//               move the pointer to the center of the window
+//               and track movement deltas.
 //
 //
-//               This has no effect on Windows, which does not
-//               have this concept; but is important to do on OSX
-//               and Unix/X11 to properly enable a smooth FPS-style
-//               mouselook mode.  On Unix/X11, this requires the
-//               Xxf86dga extension to be available.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void WindowProperties::
 INLINE void WindowProperties::
 set_mouse_mode(MouseMode mode) {
 set_mouse_mode(MouseMode mode) {

+ 4 - 0
panda/src/display/windowProperties.cxx

@@ -400,6 +400,8 @@ operator << (ostream &out, WindowProperties::MouseMode mode) {
     return out << "absolute";
     return out << "absolute";
   case WindowProperties::M_relative:
   case WindowProperties::M_relative:
     return out << "relative";
     return out << "relative";
+  case WindowProperties::M_confined:
+    return out << "confined";
   }
   }
   return out << "**invalid WindowProperties::MouseMode(" << (int)mode << ")**";
   return out << "**invalid WindowProperties::MouseMode(" << (int)mode << ")**";
 }
 }
@@ -413,6 +415,8 @@ operator >> (istream &in, WindowProperties::MouseMode &mode) {
     mode = WindowProperties::M_absolute;
     mode = WindowProperties::M_absolute;
   } else if (word == "relative") {
   } else if (word == "relative") {
     mode = WindowProperties::M_relative;
     mode = WindowProperties::M_relative;
+  } else if (word == "confined") {
+    mode = WindowProperties::M_confined;
   } else {
   } else {
     display_cat.warning()
     display_cat.warning()
       << "Unknown mouse mode: " << word << "\n";
       << "Unknown mouse mode: " << word << "\n";

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

@@ -40,6 +40,7 @@ PUBLISHED:
   enum MouseMode {
   enum MouseMode {
     M_absolute,
     M_absolute,
     M_relative,
     M_relative,
+    M_confined,
   };
   };
 
 
   WindowProperties();
   WindowProperties();

+ 0 - 2
panda/src/distort/oSphereLens.I

@@ -32,8 +32,6 @@
 #include "fog.h"
 #include "fog.h"
 #include "pointerToArray.h"
 #include "pointerToArray.h"
 
 
-#include "lru.h"
-
 #include "vertexElementArray.h"
 #include "vertexElementArray.h"
 #include "dxShaderContext9.h"
 #include "dxShaderContext9.h"
 
 

+ 0 - 2
panda/src/dxgsg9/dxIndexBufferContext9.I

@@ -19,8 +19,6 @@
 #include "texture.h"
 #include "texture.h"
 #include "textureContext.h"
 #include "textureContext.h"
 
 
-#include "lru.h"
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : DXTextureContext9
 //       Class : DXTextureContext9
 // Description :
 // Description :

+ 11 - 5
panda/src/dxgsg9/dxVertexBufferContext9.I

@@ -2216,7 +2216,7 @@ check_for_polysets(EggGroup *egg_group, bool &all_polysets, bool &any_hidden) {
 //               transform, just returns it.
 //               transform, just returns it.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(GeomVertexData) EggLoader::
 PT(GeomVertexData) EggLoader::
-make_vertex_data(const EggRenderState *render_state, 
+make_vertex_data(const EggRenderState *render_state,
                  EggVertexPool *vertex_pool, EggNode *primitive_home,
                  EggVertexPool *vertex_pool, EggNode *primitive_home,
                  const LMatrix4d &transform, TransformBlendTable *blend_table,
                  const LMatrix4d &transform, TransformBlendTable *blend_table,
                  bool is_dynamic, CharacterMaker *character_maker,
                  bool is_dynamic, CharacterMaker *character_maker,
@@ -2231,7 +2231,7 @@ make_vertex_data(const EggRenderState *render_state,
   if (di != _vertex_pool_data.end()) {
   if (di != _vertex_pool_data.end()) {
     return (*di).second;
     return (*di).second;
   }
   }
-  
+
   PT(GeomVertexArrayFormat) array_format = new GeomVertexArrayFormat;
   PT(GeomVertexArrayFormat) array_format = new GeomVertexArrayFormat;
   array_format->add_column
   array_format->add_column
     (InternalName::get_vertex(), vertex_pool->get_num_dimensions(),
     (InternalName::get_vertex(), vertex_pool->get_num_dimensions(),
@@ -2244,9 +2244,15 @@ make_vertex_data(const EggRenderState *render_state,
   }
   }
 
 
   if (!ignore_color) {
   if (!ignore_color) {
-    array_format->add_column
-      (InternalName::get_color(), 1, 
-       Geom::NT_packed_dabc, Geom::C_color);
+    // Let's not use Direct3D-style colors on platforms where we only
+    // have OpenGL anyway.
+#ifdef _WIN32
+    array_format->add_column(InternalName::get_color(), 1,
+                             Geom::NT_packed_dabc, Geom::C_color);
+#else
+    array_format->add_column(InternalName::get_color(), 4,
+                             Geom::NT_uint8, Geom::C_color);
+#endif
   }
   }
 
 
   vector_string uv_names, uvw_names, tbn_names;
   vector_string uv_names, uvw_names, tbn_names;

+ 1 - 0
panda/src/egg2pg/eggSaver.I

@@ -21,6 +21,7 @@ forcetype OFileStream
 forcetype FileStream
 forcetype FileStream
 forcetype IDecryptStream
 forcetype IDecryptStream
 forcetype OEncryptStream
 forcetype OEncryptStream
+forcetype LineStream
 
 
 forcetype ofstream
 forcetype ofstream
 forcetype ifstream
 forcetype ifstream

+ 2 - 1
panda/src/express/config_express.h

@@ -25,8 +25,9 @@
 #include "configVariableList.h"
 #include "configVariableList.h"
 #include "configVariableFilename.h"
 #include "configVariableFilename.h"
 
 
-// Include this so interrogate can find it.
+// Include these so interrogate can find them.
 #include "executionEnvironment.h"
 #include "executionEnvironment.h"
+#include "lineStream.h"
 
 
 #ifdef ANDROID
 #ifdef ANDROID
 #include <jni.h>
 #include <jni.h>

+ 1 - 1
panda/src/express/copy_stream.cxx

@@ -565,7 +565,7 @@ make_directory_full(const Filename &filename) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(VirtualFile) VirtualFileSystem::
 PT(VirtualFile) VirtualFileSystem::
 get_file(const Filename &filename, bool status_only) const {
 get_file(const Filename &filename, bool status_only) const {
-  int open_flags = status_only ? 0 : OF_status_only;
+  int open_flags = status_only ? OF_status_only : 0;
   ((VirtualFileSystem *)this)->_lock.acquire();
   ((VirtualFileSystem *)this)->_lock.acquire();
   PT(VirtualFile) result = do_get_file(filename, open_flags);
   PT(VirtualFile) result = do_get_file(filename, open_flags);
   ((VirtualFileSystem *)this)->_lock.release();
   ((VirtualFileSystem *)this)->_lock.release();

+ 7 - 0
panda/src/express/windowsRegistry.cxx

@@ -113,6 +113,13 @@ typedef char GLchar;
 #define GL_R32F GL_R32F_EXT
 #define GL_R32F GL_R32F_EXT
 #define GL_RG32F GL_RG32F_EXT
 #define GL_RG32F GL_RG32F_EXT
 #define GL_RGB8 GL_RGB8_OES
 #define GL_RGB8 GL_RGB8_OES
+#define GL_TEXTURE_COMPARE_FUNC_ARB GL_TEXTURE_COMPARE_FUNC_EXT
+#define GL_TEXTURE_COMPARE_MODE_ARB GL_TEXTURE_COMPARE_MODE_EXT
+#define GL_COMPARE_R_TO_TEXTURE_ARB GL_COMPARE_REF_TO_TEXTURE_EXT
+#define GL_SAMPLER_2D_SHADOW GL_SAMPLER_2D_SHADOW_EXT
+#define GL_MAX_DRAW_BUFFERS GL_MAX_DRAW_BUFFERS_NV
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE
 
 
 #undef SUPPORT_IMMEDIATE_MODE
 #undef SUPPORT_IMMEDIATE_MODE
 #define APIENTRY
 #define APIENTRY

+ 1 - 0
panda/src/glesgsg/glesgsg.h

@@ -118,6 +118,7 @@
 #define GL_ALPHA8 GL_ALPHA8_EXT
 #define GL_ALPHA8 GL_ALPHA8_EXT
 #define GL_LUMINANCE8 GL_LUMINANCE8_EXT
 #define GL_LUMINANCE8 GL_LUMINANCE8_EXT
 #define GL_LUMINANCE8_ALPHA8 GL_LUMINANCE8_ALPHA8_EXT
 #define GL_LUMINANCE8_ALPHA8 GL_LUMINANCE8_ALPHA8_EXT
+#define GL_MAX_VERTEX_UNITS_ARB GL_MAX_VERTEX_UNITS_OES
 
 
 #undef SUPPORT_IMMEDIATE_MODE
 #undef SUPPORT_IMMEDIATE_MODE
 #define APIENTRY
 #define APIENTRY

+ 4 - 3
panda/src/glesgsg/panda_esglext.h

@@ -1,7 +1,7 @@
 #ifndef __panda_esglext_h_
 #ifndef __panda_esglext_h_
 #define __panda_esglext_h_
 #define __panda_esglext_h_
 
 
-/* $Revision$ on $Date$ */
+/* $Revision: 20798 $ on $Date:: 2013-03-07 01:19:34 -0800 #$ */
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
@@ -1055,10 +1055,10 @@ typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum
 #ifndef GL_EXT_multi_draw_arrays
 #ifndef GL_EXT_multi_draw_arrays
 #define GL_EXT_multi_draw_arrays 1
 #define GL_EXT_multi_draw_arrays 1
 #ifdef GL_GLEXT_PROTOTYPES
 #ifdef GL_GLEXT_PROTOTYPES
-GL_API void GL_APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei);
+GL_API void GL_APIENTRY glMultiDrawArraysEXT (GLenum, const GLint *, const GLsizei *, GLsizei);
 GL_API void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
 GL_API void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei);
 #endif /* GL_GLEXT_PROTOTYPES */
 #endif /* GL_GLEXT_PROTOTYPES */
-typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
 typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
 typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
 #endif
 #endif
 
 
@@ -1275,3 +1275,4 @@ typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
 #endif
 #endif
 
 
 #endif /* __glext_h_ */
 #endif /* __glext_h_ */
+

+ 121 - 13
panda/src/glstuff/glCgShaderContext_src.I

@@ -87,6 +87,46 @@ munge_format_impl(const GeomVertexFormat *orig,
   CLP(GraphicsStateGuardian) *glgsg;
   CLP(GraphicsStateGuardian) *glgsg;
   DCAST_INTO_R(glgsg, get_gsg(), NULL);
   DCAST_INTO_R(glgsg, get_gsg(), NULL);
 
 
+#ifndef OPENGLES
+  // OpenGL ES 1 does, but regular OpenGL doesn't support GL_BYTE vertices
+  // and texture coordinates.
+  const GeomVertexColumn *vertex_type = orig->get_vertex_column();
+  if (vertex_type != (GeomVertexColumn *)NULL &&
+      (vertex_type->get_numeric_type() == NT_int8 ||
+       vertex_type->get_numeric_type() == NT_uint8)) {
+    int vertex_array = orig->get_array_with(InternalName::get_vertex());
+
+    PT(GeomVertexArrayFormat) new_array_format = new_format->modify_array(vertex_array);
+
+    // Replace the existing vertex format with the new format.
+    new_array_format->add_column
+      (InternalName::get_vertex(), 3, NT_int16,
+       C_point, vertex_type->get_start(), vertex_type->get_column_alignment());
+  }
+
+  // Convert packed formats that OpenGL may not understand.
+  for (int i = 0; i < orig->get_num_columns(); ++i) {
+    const GeomVertexColumn *column = orig->get_column(i);
+    int array = orig->get_array_with(column->get_name());
+
+    if (column->get_numeric_type() == NT_packed_dabc &&
+        !glgsg->_supports_packed_dabc) {
+      // Unpack the packed ARGB color into its four byte components.
+      PT(GeomVertexArrayFormat) array_format = new_format->modify_array(array);
+      array_format->add_column(column->get_name(), 4, NT_uint8, C_color,
+                               column->get_start(), column->get_column_alignment());
+
+    } else if (column->get_numeric_type() == NT_packed_ufloat &&
+               !glgsg->_supports_packed_ufloat) {
+      // Unpack to three 32-bit floats.  (In future, should try 16-bit float)
+      PT(GeomVertexArrayFormat) array_format = new_format->modify_array(array);
+      array_format->add_column(column->get_name(), 3, NT_float32,
+                               column->get_contents(), column->get_start(),
+                               column->get_column_alignment());
+    }
+  }
+#endif  // !OPENGLES
+
   const GeomVertexColumn *color_type = orig->get_color_column();
   const GeomVertexColumn *color_type = orig->get_color_column();
   if (color_type != (GeomVertexColumn *)NULL &&
   if (color_type != (GeomVertexColumn *)NULL &&
       color_type->get_numeric_type() == NT_packed_dabc &&
       color_type->get_numeric_type() == NT_packed_dabc &&
@@ -99,8 +139,8 @@ munge_format_impl(const GeomVertexFormat *orig,
 
 
     // Replace the existing color format with the new format.
     // Replace the existing color format with the new format.
     new_array_format->add_column
     new_array_format->add_column
-      (InternalName::get_color(), 4, NT_uint8,
-       C_color, color_type->get_start(), color_type->get_column_alignment());
+      (InternalName::get_color(), 4, NT_uint8, C_color,
+       color_type->get_start(), color_type->get_column_alignment());
   }
   }
 
 
   if (animation.get_animation_type() == AT_hardware) {
   if (animation.get_animation_type() == AT_hardware) {
@@ -237,22 +277,46 @@ premunge_format_impl(const GeomVertexFormat *orig) {
   CLP(GraphicsStateGuardian) *glgsg;
   CLP(GraphicsStateGuardian) *glgsg;
   DCAST_INTO_R(glgsg, get_gsg(), NULL);
   DCAST_INTO_R(glgsg, get_gsg(), NULL);
 
 
-  const GeomVertexColumn *color_type = orig->get_color_column();
-  if (color_type != (GeomVertexColumn *)NULL &&
-      color_type->get_numeric_type() == NT_packed_dabc &&
-      !glgsg->_supports_packed_dabc) {
-    // We need to convert the color format; OpenGL doesn't support the
-    // byte order of DirectX's packed ARGB format.
-    int color_array = orig->get_array_with(InternalName::get_color());
+#ifndef OPENGLES
+  // OpenGL ES 1 does, but regular OpenGL doesn't support GL_BYTE vertices
+  // and texture coordinates.
+  const GeomVertexColumn *vertex_type = orig->get_vertex_column();
+  if (vertex_type != (GeomVertexColumn *)NULL &&
+      (vertex_type->get_numeric_type() == NT_int8 ||
+       vertex_type->get_numeric_type() == NT_uint8)) {
+    int vertex_array = orig->get_array_with(InternalName::get_vertex());
 
 
-    PT(GeomVertexArrayFormat) new_array_format = new_format->modify_array(color_array);
+    PT(GeomVertexArrayFormat) new_array_format = new_format->modify_array(vertex_array);
 
 
-    // Replace the existing color format with the new format.
+    // Replace the existing vertex format with the new format.
     new_array_format->add_column
     new_array_format->add_column
-      (InternalName::get_color(), 4, NT_uint8,
-       C_color, color_type->get_start(), color_type->get_column_alignment());
+      (InternalName::get_vertex(), 3, NT_int16,
+       C_point, vertex_type->get_start(), vertex_type->get_column_alignment());
   }
   }
 
 
+  // Convert packed formats that OpenGL may not understand.
+  for (int i = 0; i < orig->get_num_columns(); ++i) {
+    const GeomVertexColumn *column = orig->get_column(i);
+    int array = orig->get_array_with(column->get_name());
+
+    if (column->get_numeric_type() == NT_packed_dabc &&
+        !glgsg->_supports_packed_dabc) {
+      // Unpack the packed ARGB color into its four byte components.
+      PT(GeomVertexArrayFormat) array_format = new_format->modify_array(array);
+      array_format->add_column(column->get_name(), 4, NT_uint8, C_color,
+                               column->get_start(), column->get_column_alignment());
+
+    } else if (column->get_numeric_type() == NT_packed_ufloat &&
+               !glgsg->_supports_packed_ufloat) {
+      // Unpack to three 32-bit floats.  (In future, should try 16-bit float)
+      PT(GeomVertexArrayFormat) array_format = new_format->modify_array(array);
+      array_format->add_column(column->get_name(), 3, NT_float32,
+                               column->get_contents(), column->get_start(),
+                               column->get_column_alignment());
+    }
+  }
+#endif  // !OPENGLES
+
   CPT(GeomVertexFormat) format = GeomVertexFormat::register_format(new_format);
   CPT(GeomVertexFormat) format = GeomVertexFormat::register_format(new_format);
 
 
   if ((_flags & F_parallel_arrays) != 0) {
   if ((_flags & F_parallel_arrays) != 0) {
@@ -362,6 +426,45 @@ premunge_format_impl(const GeomVertexFormat *orig) {
   return format;
   return format;
 }
 }
 
 
+#ifdef OPENGLES
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(GeomMunger)::munge_geom_impl
+//       Access: Protected, Virtual
+//  Description: Converts a Geom and/or its data as necessary.
+////////////////////////////////////////////////////////////////////
+void CLP(GeomMunger)::
+munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data,
+                Thread *current_thread) {
+  StandardMunger::munge_geom_impl(geom, vertex_data, current_thread);
+
+  // OpenGL ES has no polygon mode, so we have to emulate it.
+  RenderModeAttrib::Mode render_mode = get_render_mode();
+  if (render_mode == RenderModeAttrib::M_point) {
+    geom = geom->make_points();
+  } else if (render_mode == RenderModeAttrib::M_wireframe) {
+    geom = geom->make_lines();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(GeomMunger)::premunge_geom_impl
+//       Access: Protected, Virtual
+//  Description: Converts a Geom and/or its data as necessary.
+////////////////////////////////////////////////////////////////////
+void CLP(GeomMunger)::
+premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data) {
+  StandardMunger::premunge_geom_impl(geom, vertex_data);
+
+  // OpenGL ES has no polygon mode, so we have to emulate it.
+  RenderModeAttrib::Mode render_mode = get_render_mode();
+  if (render_mode == RenderModeAttrib::M_point) {
+    geom = geom->make_points();
+  } else if (render_mode == RenderModeAttrib::M_wireframe) {
+    geom = geom->make_lines();
+  }
+}
+#endif  // OPENGLES
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CLP(GeomMunger)::compare_to_impl
 //     Function: CLP(GeomMunger)::compare_to_impl
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
@@ -397,6 +500,11 @@ compare_to_impl(const GeomMunger *other) const {
 int CLP(GeomMunger)::
 int CLP(GeomMunger)::
 geom_compare_to_impl(const GeomMunger *other) const {
 geom_compare_to_impl(const GeomMunger *other) const {
   const CLP(GeomMunger) *om = DCAST(CLP(GeomMunger), other);
   const CLP(GeomMunger) *om = DCAST(CLP(GeomMunger), other);
+#ifdef OPENGLES
+  if (get_render_mode() != om->get_render_mode()) {
+    return get_render_mode() < om->get_render_mode() ? -1 : 1;
+  }
+#endif
   if (_texture != om->_texture) {
   if (_texture != om->_texture) {
     return _texture < om->_texture ? -1 : 1;
     return _texture < om->_texture ? -1 : 1;
   }
   }

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

@@ -42,6 +42,12 @@ protected:
                                                   const GeomVertexAnimationSpec &animation);
                                                   const GeomVertexAnimationSpec &animation);
   virtual CPT(GeomVertexFormat) premunge_format_impl(const GeomVertexFormat *orig);
   virtual CPT(GeomVertexFormat) premunge_format_impl(const GeomVertexFormat *orig);
 
 
+#ifdef OPENGLES
+  virtual void munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &data,
+                               Thread *current_thread);
+  virtual void premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &data);
+#endif
+
   virtual int compare_to_impl(const GeomMunger *other) const;
   virtual int compare_to_impl(const GeomMunger *other) const;
   virtual int geom_compare_to_impl(const GeomMunger *other) const;
   virtual int geom_compare_to_impl(const GeomMunger *other) const;
 
 

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

@@ -532,6 +532,7 @@ enable_depth_test(bool val) {
   }
   }
 }
 }
 
 
+#ifndef OPENGLES_2
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::enable_fog
 //     Function: GLGraphicsStateGuardian::enable_fog
 //       Access:
 //       Access:
@@ -539,7 +540,6 @@ enable_depth_test(bool val) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void CLP(GraphicsStateGuardian)::
 INLINE void CLP(GraphicsStateGuardian)::
 enable_fog(bool val) {
 enable_fog(bool val) {
-#ifndef OPENGLES_2
   if (_fog_enabled != val) {
   if (_fog_enabled != val) {
     _fog_enabled = val;
     _fog_enabled = val;
     if (val) {
     if (val) {
@@ -556,9 +556,10 @@ enable_fog(bool val) {
       glDisable(GL_FOG);
       glDisable(GL_FOG);
     }
     }
   }
   }
-#endif
 }
 }
+#endif
 
 
+#ifndef OPENGLES_2
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::enable_alpha_test
 //     Function: GLGraphicsStateGuardian::enable_alpha_test
 //       Access:
 //       Access:
@@ -566,7 +567,6 @@ enable_fog(bool val) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void CLP(GraphicsStateGuardian)::
 INLINE void CLP(GraphicsStateGuardian)::
 enable_alpha_test(bool val) {
 enable_alpha_test(bool val) {
-#ifndef OPENGLES_2
   if (_alpha_test_enabled != val) {
   if (_alpha_test_enabled != val) {
     _alpha_test_enabled = val;
     _alpha_test_enabled = val;
     if (val) {
     if (val) {
@@ -583,9 +583,8 @@ enable_alpha_test(bool val) {
       glDisable(GL_ALPHA_TEST);
       glDisable(GL_ALPHA_TEST);
     }
     }
   }
   }
-#endif // OPENGLES_2
 }
 }
-
+#endif
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::enable_polygon_offset
 //     Function: GLGraphicsStateGuardian::enable_polygon_offset
@@ -616,6 +615,36 @@ enable_polygon_offset(bool val) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::set_color_write_mask
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void CLP(GraphicsStateGuardian)::
+set_color_write_mask(int mask) {
+  if (gl_color_mask && _active_color_write_mask != mask) {
+    _active_color_write_mask = mask;
+    glColorMask((_color_write_mask & ColorWriteAttrib::C_red) != 0,
+                (_color_write_mask & ColorWriteAttrib::C_green) != 0,
+                (_color_write_mask & ColorWriteAttrib::C_blue) != 0,
+                (_color_write_mask & ColorWriteAttrib::C_alpha) != 0);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::clear_color_write_mask
+//       Access: Protected
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void CLP(GraphicsStateGuardian)::
+clear_color_write_mask() {
+  if (gl_color_mask && _active_color_write_mask != ColorWriteAttrib::C_all) {
+    _active_color_write_mask = ColorWriteAttrib::C_all;
+    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+  }
+}
+
+#ifndef OPENGLES_2
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::call_glFogfv
 //     Function: GLGraphicsStateGuardian::call_glFogfv
 //       Access: Public
 //       Access: Public
@@ -624,16 +653,16 @@ enable_polygon_offset(bool val) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void CLP(GraphicsStateGuardian)::
 INLINE void CLP(GraphicsStateGuardian)::
 call_glFogfv(GLenum pname, const LColor &color) {
 call_glFogfv(GLenum pname, const LColor &color) {
-#ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
 #ifndef STDFLOAT_DOUBLE
   glFogfv(pname, color.get_data());
   glFogfv(pname, color.get_data());
 #else  // STDFLOAT_DOUBLE
 #else  // STDFLOAT_DOUBLE
   LColorf fcolor = LCAST(float, color);
   LColorf fcolor = LCAST(float, color);
   glFogfv(pname, fcolor.get_data());
   glFogfv(pname, fcolor.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif  //  STDFLOAT_DOUBLE
-#endif
 }
 }
+#endif
 
 
+#ifndef OPENGLES_2
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::call_glMaterialfv
 //     Function: GLGraphicsStateGuardian::call_glMaterialfv
 //       Access: Public
 //       Access: Public
@@ -642,16 +671,16 @@ call_glFogfv(GLenum pname, const LColor &color) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void CLP(GraphicsStateGuardian)::
 INLINE void CLP(GraphicsStateGuardian)::
 call_glMaterialfv(GLenum face, GLenum pname, const LColor &color) {
 call_glMaterialfv(GLenum face, GLenum pname, const LColor &color) {
-#ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
 #ifndef STDFLOAT_DOUBLE
   glMaterialfv(face, pname, color.get_data());
   glMaterialfv(face, pname, color.get_data());
 #else  // STDFLOAT_DOUBLE
 #else  // STDFLOAT_DOUBLE
   LColorf fcolor = LCAST(float, color);
   LColorf fcolor = LCAST(float, color);
   glMaterialfv(face, pname, fcolor.get_data());
   glMaterialfv(face, pname, fcolor.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif  //  STDFLOAT_DOUBLE
-#endif
 }
 }
+#endif
 
 
+#ifndef OPENGLES_2
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::call_glLightfv
 //     Function: GLGraphicsStateGuardian::call_glLightfv
 //       Access: Public
 //       Access: Public
@@ -660,16 +689,16 @@ call_glMaterialfv(GLenum face, GLenum pname, const LColor &color) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void CLP(GraphicsStateGuardian)::
 INLINE void CLP(GraphicsStateGuardian)::
 call_glLightfv(GLenum light, GLenum pname, const LVecBase4 &value) {
 call_glLightfv(GLenum light, GLenum pname, const LVecBase4 &value) {
-#ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
 #ifndef STDFLOAT_DOUBLE
   glLightfv(light, pname, value.get_data());
   glLightfv(light, pname, value.get_data());
 #else  // STDFLOAT_DOUBLE
 #else  // STDFLOAT_DOUBLE
   LVecBase4f fvalue = LCAST(float, value);
   LVecBase4f fvalue = LCAST(float, value);
   glLightfv(light, pname, fvalue.get_data());
   glLightfv(light, pname, fvalue.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif  //  STDFLOAT_DOUBLE
-#endif
 }
 }
+#endif
 
 
+#ifndef OPENGLES_2
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::call_glLightfv
 //     Function: GLGraphicsStateGuardian::call_glLightfv
 //       Access: Public
 //       Access: Public
@@ -678,16 +707,16 @@ call_glLightfv(GLenum light, GLenum pname, const LVecBase4 &value) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void CLP(GraphicsStateGuardian)::
 INLINE void CLP(GraphicsStateGuardian)::
 call_glLightfv(GLenum light, GLenum pname, const LVecBase3 &value) {
 call_glLightfv(GLenum light, GLenum pname, const LVecBase3 &value) {
-#ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
 #ifndef STDFLOAT_DOUBLE
   glLightfv(light, pname, value.get_data());
   glLightfv(light, pname, value.get_data());
 #else  // STDFLOAT_DOUBLE
 #else  // STDFLOAT_DOUBLE
   LVecBase3f fvalue = LCAST(float, value);
   LVecBase3f fvalue = LCAST(float, value);
   glLightfv(light, pname, fvalue.get_data());
   glLightfv(light, pname, fvalue.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif  //  STDFLOAT_DOUBLE
-#endif
 }
 }
+#endif
 
 
+#ifndef OPENGLES_2
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::call_glLightModelfv
 //     Function: GLGraphicsStateGuardian::call_glLightModelfv
 //       Access: Public
 //       Access: Public
@@ -696,16 +725,16 @@ call_glLightfv(GLenum light, GLenum pname, const LVecBase3 &value) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void CLP(GraphicsStateGuardian)::
 INLINE void CLP(GraphicsStateGuardian)::
 call_glLightModelfv(GLenum pname, const LVecBase4 &value) {
 call_glLightModelfv(GLenum pname, const LVecBase4 &value) {
-#ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
 #ifndef STDFLOAT_DOUBLE
   glLightModelfv(pname, value.get_data());
   glLightModelfv(pname, value.get_data());
 #else  // STDFLOAT_DOUBLE
 #else  // STDFLOAT_DOUBLE
   LVecBase4f fvalue = LCAST(float, value);
   LVecBase4f fvalue = LCAST(float, value);
   glLightModelfv(pname, fvalue.get_data());
   glLightModelfv(pname, fvalue.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif  //  STDFLOAT_DOUBLE
-#endif  // OPENGLES_2
 }
 }
+#endif
 
 
+#ifndef OPENGLES_2
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::call_glTexEnvfv
 //     Function: GLGraphicsStateGuardian::call_glTexEnvfv
 //       Access: Public
 //       Access: Public
@@ -714,15 +743,14 @@ call_glLightModelfv(GLenum pname, const LVecBase4 &value) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void CLP(GraphicsStateGuardian)::
 INLINE void CLP(GraphicsStateGuardian)::
 call_glTexEnvfv(GLenum target, GLenum pname, const LVecBase4 &value) {
 call_glTexEnvfv(GLenum target, GLenum pname, const LVecBase4 &value) {
-#ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
 #ifndef STDFLOAT_DOUBLE
   glTexEnvfv(target, pname, value.get_data());
   glTexEnvfv(target, pname, value.get_data());
 #else  // STDFLOAT_DOUBLE
 #else  // STDFLOAT_DOUBLE
   LVecBase4f fvalue = LCAST(float, value);
   LVecBase4f fvalue = LCAST(float, value);
   glTexEnvfv(target, pname, fvalue.get_data());
   glTexEnvfv(target, pname, fvalue.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif  //  STDFLOAT_DOUBLE
-#endif
 }
 }
+#endif
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::call_glTexParameterfv
 //     Function: GLGraphicsStateGuardian::call_glTexParameterfv
@@ -740,6 +768,7 @@ call_glTexParameterfv(GLenum target, GLenum pname, const LVecBase4 &value) {
 #endif  //  STDFLOAT_DOUBLE
 #endif  //  STDFLOAT_DOUBLE
 }
 }
 
 
+#ifndef OPENGLES_2
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::get_light_id
 //     Function: GLGraphicsStateGuardian::get_light_id
 //       Access: Public
 //       Access: Public
@@ -747,13 +776,11 @@ call_glTexParameterfv(GLenum target, GLenum pname, const LVecBase4 &value) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GLenum CLP(GraphicsStateGuardian)::
 INLINE GLenum CLP(GraphicsStateGuardian)::
 get_light_id(int index) const {
 get_light_id(int index) const {
-#ifndef OPENGLES_2
   return GL_LIGHT0 + index;
   return GL_LIGHT0 + index;
-#else
-  return 0;
-#endif
 }
 }
+#endif
 
 
+#ifndef OPENGLES_2
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::get_clip_plane_id
 //     Function: GLGraphicsStateGuardian::get_clip_plane_id
 //       Access: Public
 //       Access: Public
@@ -761,12 +788,9 @@ get_light_id(int index) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GLenum CLP(GraphicsStateGuardian)::
 INLINE GLenum CLP(GraphicsStateGuardian)::
 get_clip_plane_id(int index) const {
 get_clip_plane_id(int index) const {
-#ifndef OPENGLES_2
   return GL_CLIP_PLANE0 + index;
   return GL_CLIP_PLANE0 + index;
-#else
-  return 0;
-#endif
 }
 }
+#endif
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CLP(GraphicsStateGuardian)::get_supports_framebuffer_multisample
 //     Function: CLP(GraphicsStateGuardian)::get_supports_framebuffer_multisample
@@ -776,7 +800,7 @@ get_clip_plane_id(int index) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool CLP(GraphicsStateGuardian)::
 INLINE bool CLP(GraphicsStateGuardian)::
 get_supports_framebuffer_multisample() {
 get_supports_framebuffer_multisample() {
-    return _supports_framebuffer_multisample;
+  return _supports_framebuffer_multisample;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -787,7 +811,7 @@ get_supports_framebuffer_multisample() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool CLP(GraphicsStateGuardian)::
 INLINE bool CLP(GraphicsStateGuardian)::
 get_supports_framebuffer_multisample_coverage_nv() {
 get_supports_framebuffer_multisample_coverage_nv() {
-    return _supports_framebuffer_multisample_coverage_nv;
+  return _supports_framebuffer_multisample_coverage_nv;
 }
 }
 
 
 
 
@@ -799,7 +823,7 @@ get_supports_framebuffer_multisample_coverage_nv() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool CLP(GraphicsStateGuardian)::
 INLINE bool CLP(GraphicsStateGuardian)::
 get_supports_framebuffer_blit() {
 get_supports_framebuffer_blit() {
-    return _supports_framebuffer_blit;
+  return _supports_framebuffer_blit;
 }
 }
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG

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


+ 60 - 12
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -21,6 +21,7 @@
 #include "texture.h"
 #include "texture.h"
 #include "displayRegion.h"
 #include "displayRegion.h"
 #include "material.h"
 #include "material.h"
+#include "colorWriteAttrib.h"
 #include "depthTestAttrib.h"
 #include "depthTestAttrib.h"
 #include "textureAttrib.h"
 #include "textureAttrib.h"
 #include "texMatrixAttrib.h"
 #include "texMatrixAttrib.h"
@@ -179,10 +180,14 @@ typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, con
 typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
 typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
 #endif  // OPENGLES_1
 #endif  // OPENGLES_1
 #ifndef OPENGLES
 #ifndef OPENGLES
 typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
 typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
@@ -193,8 +198,6 @@ typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pna
 typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
 typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
 typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
 typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
 typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
 typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
-typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
 typedef void (APIENTRYP PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
 typedef void (APIENTRYP PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
 typedef void (APIENTRYP PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
 typedef void (APIENTRYP PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
 typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
 typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
@@ -280,15 +283,19 @@ public:
                            bool force);
                            bool force);
   virtual void end_draw_primitives();
   virtual void end_draw_primitives();
 
 
+#ifndef OPENGLES
   void issue_memory_barrier(GLbitfield barrier);
   void issue_memory_barrier(GLbitfield barrier);
+#endif
 
 
   virtual TextureContext *prepare_texture(Texture *tex, int view);
   virtual TextureContext *prepare_texture(Texture *tex, int view);
   virtual bool update_texture(TextureContext *tc, bool force);
   virtual bool update_texture(TextureContext *tc, bool force);
   virtual void release_texture(TextureContext *tc);
   virtual void release_texture(TextureContext *tc);
   virtual bool extract_texture_data(Texture *tex);
   virtual bool extract_texture_data(Texture *tex);
 
 
+#ifndef OPENGLES
   virtual SamplerContext *prepare_sampler(const SamplerState &sampler);
   virtual SamplerContext *prepare_sampler(const SamplerState &sampler);
   virtual void release_sampler(SamplerContext *sc);
   virtual void release_sampler(SamplerContext *sc);
+#endif
 
 
   virtual GeomContext *prepare_geom(Geom *geom);
   virtual GeomContext *prepare_geom(Geom *geom);
   virtual void release_geom(GeomContext *gc);
   virtual void release_geom(GeomContext *gc);
@@ -317,12 +324,16 @@ public:
                        const GeomPrimitivePipelineReader *reader,
                        const GeomPrimitivePipelineReader *reader,
                        bool force);
                        bool force);
 
 
+#ifndef OPENGLES
   virtual void begin_occlusion_query();
   virtual void begin_occlusion_query();
   virtual PT(OcclusionQueryContext) end_occlusion_query();
   virtual PT(OcclusionQueryContext) end_occlusion_query();
+#endif
 
 
   virtual PT(TimerQueryContext) issue_timer_query(int pstats_index);
   virtual PT(TimerQueryContext) issue_timer_query(int pstats_index);
 
 
+#ifndef OPENGLES
   virtual void dispatch_compute(int size_x, int size_y, int size_z);
   virtual void dispatch_compute(int size_x, int size_y, int size_z);
+#endif
 
 
   virtual PT(GeomMunger) make_geom_munger(const RenderState *state,
   virtual PT(GeomMunger) make_geom_munger(const RenderState *state,
                                           Thread *current_thread);
                                           Thread *current_thread);
@@ -336,6 +347,7 @@ public:
   virtual bool framebuffer_copy_to_ram
   virtual bool framebuffer_copy_to_ram
     (Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb);
     (Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb);
 
 
+#ifndef OPENGLES_2
   void apply_fog(Fog *fog);
   void apply_fog(Fog *fog);
 
 
   virtual void bind_light(PointLight *light_obj, const NodePath &light,
   virtual void bind_light(PointLight *light_obj, const NodePath &light,
@@ -344,6 +356,7 @@ public:
                           int light_id);
                           int light_id);
   virtual void bind_light(Spotlight *light_obj, const NodePath &light,
   virtual void bind_light(Spotlight *light_obj, const NodePath &light,
                           int light_id);
                           int light_id);
+#endif
 
 
   void print_gfx_visual();
   void print_gfx_visual();
 
 
@@ -379,18 +392,26 @@ protected:
   void do_issue_rescale_normal();
   void do_issue_rescale_normal();
   void do_issue_color_write();
   void do_issue_color_write();
   void do_issue_depth_test();
   void do_issue_depth_test();
+#ifndef OPENGLES_2
   void do_issue_alpha_test();
   void do_issue_alpha_test();
+#endif
   void do_issue_depth_write();
   void do_issue_depth_write();
   void do_issue_cull_face();
   void do_issue_cull_face();
+#ifndef OPENGLES_2
   void do_issue_fog();
   void do_issue_fog();
+#endif
   void do_issue_depth_offset();
   void do_issue_depth_offset();
   void do_issue_shade_model();
   void do_issue_shade_model();
   void do_issue_shader(bool state_has_changed = false);
   void do_issue_shader(bool state_has_changed = false);
+#ifndef OPENGLES_2
   void do_issue_material();
   void do_issue_material();
+#endif
   void do_issue_texture();
   void do_issue_texture();
   void do_issue_blending();
   void do_issue_blending();
+#ifndef OPENGLES_2
   void do_issue_tex_gen();
   void do_issue_tex_gen();
   void do_issue_tex_matrix();
   void do_issue_tex_matrix();
+#endif
   void do_issue_stencil();
   void do_issue_stencil();
   void do_issue_scissor();
   void do_issue_scissor();
 
 
@@ -413,6 +434,8 @@ protected:
   virtual void *do_get_extension_func(const char *name);
   virtual void *do_get_extension_func(const char *name);
 
 
   virtual void reissue_transforms();
   virtual void reissue_transforms();
+
+#ifndef OPENGLES_2
   virtual void enable_lighting(bool enable);
   virtual void enable_lighting(bool enable);
   virtual void set_ambient_light(const LColor &color);
   virtual void set_ambient_light(const LColor &color);
   virtual void enable_light(int light_id, bool enable);
   virtual void enable_light(int light_id, bool enable);
@@ -423,6 +446,7 @@ protected:
   virtual void begin_bind_clip_planes();
   virtual void begin_bind_clip_planes();
   virtual void bind_clip_plane(const NodePath &plane, int plane_id);
   virtual void bind_clip_plane(const NodePath &plane, int plane_id);
   virtual void end_bind_clip_planes();
   virtual void end_bind_clip_planes();
+#endif
 
 
   virtual void free_pointers();
   virtual void free_pointers();
 
 
@@ -443,16 +467,24 @@ protected:
   INLINE void enable_alpha_test(bool val);
   INLINE void enable_alpha_test(bool val);
   INLINE void enable_polygon_offset(bool val);
   INLINE void enable_polygon_offset(bool val);
 
 
+  INLINE void set_color_write_mask(int mask);
+  INLINE void clear_color_write_mask();
+
+#ifndef OPENGLES_2
   INLINE void call_glFogfv(GLenum pname, const LColor &color);
   INLINE void call_glFogfv(GLenum pname, const LColor &color);
   INLINE void call_glMaterialfv(GLenum face, GLenum pname, const LColor &color);
   INLINE void call_glMaterialfv(GLenum face, GLenum pname, const LColor &color);
   INLINE void call_glLightfv(GLenum light, GLenum pname, const LVecBase4 &value);
   INLINE void call_glLightfv(GLenum light, GLenum pname, const LVecBase4 &value);
   INLINE void call_glLightfv(GLenum light, GLenum pname, const LVecBase3 &value);
   INLINE void call_glLightfv(GLenum light, GLenum pname, const LVecBase3 &value);
   INLINE void call_glLightModelfv(GLenum pname, const LVecBase4 &value);
   INLINE void call_glLightModelfv(GLenum pname, const LVecBase4 &value);
   INLINE void call_glTexEnvfv(GLenum target, GLenum pname, const LVecBase4 &value);
   INLINE void call_glTexEnvfv(GLenum target, GLenum pname, const LVecBase4 &value);
+#endif
+
   INLINE void call_glTexParameterfv(GLenum target, GLenum pname, const LVecBase4 &value);
   INLINE void call_glTexParameterfv(GLenum target, GLenum pname, const LVecBase4 &value);
 
 
+#ifndef OPENGLES_2
   INLINE GLenum get_light_id(int index) const;
   INLINE GLenum get_light_id(int index) const;
   INLINE GLenum get_clip_plane_id(int index) const;
   INLINE GLenum get_clip_plane_id(int index) const;
+#endif
 
 
   void set_draw_buffer(int rbtype);
   void set_draw_buffer(int rbtype);
   void set_read_buffer(int rbtype);
   void set_read_buffer(int rbtype);
@@ -481,10 +513,12 @@ protected:
   static GLenum get_usage(Geom::UsageHint usage_hint);
   static GLenum get_usage(Geom::UsageHint usage_hint);
 
 
   void unbind_buffers();
   void unbind_buffers();
+#ifndef OPENGLES_2
   void disable_standard_vertex_arrays();
   void disable_standard_vertex_arrays();
   bool update_standard_vertex_arrays(bool force);
   bool update_standard_vertex_arrays(bool force);
   void disable_standard_texture_bindings();
   void disable_standard_texture_bindings();
   void update_standard_texture_bindings();
   void update_standard_texture_bindings();
+#endif
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
   void update_show_usage_texture_bindings(int show_stage_index);
   void update_show_usage_texture_bindings(int show_stage_index);
@@ -539,6 +573,7 @@ protected:
   bool _polygon_offset_enabled;
   bool _polygon_offset_enabled;
   bool _flat_shade_model;
   bool _flat_shade_model;
   int  _decal_level;
   int  _decal_level;
+  int _active_color_write_mask;
 
 
   bool _dithering_enabled;
   bool _dithering_enabled;
 
 
@@ -565,7 +600,7 @@ protected:
   ShaderContext *_texture_binding_shader_context;
   ShaderContext *_texture_binding_shader_context;
 #endif
 #endif
 #ifdef OPENGLES_2
 #ifdef OPENGLES_2
-  static PT(Shader)  _default_shader;
+  static PT(Shader) _default_shader;
 #endif
 #endif
 
 
 #ifdef HAVE_CG
 #ifdef HAVE_CG
@@ -635,27 +670,35 @@ public:
   PFNGLWEIGHTDVARBPROC _glWeightdv;
   PFNGLWEIGHTDVARBPROC _glWeightdv;
 
 
   bool _supports_matrix_palette;
   bool _supports_matrix_palette;
-#ifdef OPENGLES
+#ifdef OPENGLES_1
   PFNGLCURRENTPALETTEMATRIXOESPROC _glCurrentPaletteMatrix;
   PFNGLCURRENTPALETTEMATRIXOESPROC _glCurrentPaletteMatrix;
   PFNGLMATRIXINDEXPOINTEROESPROC _glMatrixIndexPointer;
   PFNGLMATRIXINDEXPOINTEROESPROC _glMatrixIndexPointer;
-#else
+#endif
+#ifndef OPENGLES
   PFNGLCURRENTPALETTEMATRIXARBPROC _glCurrentPaletteMatrix;
   PFNGLCURRENTPALETTEMATRIXARBPROC _glCurrentPaletteMatrix;
   PFNGLMATRIXINDEXPOINTERARBPROC _glMatrixIndexPointer;
   PFNGLMATRIXINDEXPOINTERARBPROC _glMatrixIndexPointer;
   PFNGLMATRIXINDEXUIVARBPROC _glMatrixIndexuiv;
   PFNGLMATRIXINDEXUIVARBPROC _glMatrixIndexuiv;
 #endif
 #endif
 
 
-  bool _supports_draw_range_elements;
+#ifndef OPENGLES
   PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements;
   PFNGLDRAWRANGEELEMENTSPROC _glDrawRangeElements;
+#endif
 
 
+#ifndef OPENGLES_1
   PFNGLTEXIMAGE3DPROC_P _glTexImage3D;
   PFNGLTEXIMAGE3DPROC_P _glTexImage3D;
   PFNGLTEXSUBIMAGE3DPROC _glTexSubImage3D;
   PFNGLTEXSUBIMAGE3DPROC _glTexSubImage3D;
   PFNGLCOPYTEXSUBIMAGE3DPROC _glCopyTexSubImage3D;
   PFNGLCOPYTEXSUBIMAGE3DPROC _glCopyTexSubImage3D;
+#endif
 
 
   bool _supports_tex_storage;
   bool _supports_tex_storage;
   PFNGLTEXSTORAGE1DPROC _glTexStorage1D;
   PFNGLTEXSTORAGE1DPROC _glTexStorage1D;
   PFNGLTEXSTORAGE2DPROC _glTexStorage2D;
   PFNGLTEXSTORAGE2DPROC _glTexStorage2D;
   PFNGLTEXSTORAGE3DPROC _glTexStorage3D;
   PFNGLTEXSTORAGE3DPROC _glTexStorage3D;
 
 
+#ifndef OPENGLES
+  PFNGLTEXBUFFERPROC _glTexBuffer;
+#endif
+
   bool _supports_clear_texture;
   bool _supports_clear_texture;
 #ifndef OPENGLES
 #ifndef OPENGLES
   PFNGLCLEARTEXIMAGEPROC _glClearTexImage;
   PFNGLCLEARTEXIMAGEPROC _glClearTexImage;
@@ -672,9 +715,11 @@ public:
   bool _supports_bgr;
   bool _supports_bgr;
   bool _supports_rescale_normal;
   bool _supports_rescale_normal;
   bool _supports_packed_dabc;
   bool _supports_packed_dabc;
+  bool _supports_packed_ufloat;
 
 
-  bool _supports_multitexture;
   PFNGLACTIVETEXTUREPROC _glActiveTexture;
   PFNGLACTIVETEXTUREPROC _glActiveTexture;
+#ifndef OPENGLES_2
+  bool _supports_multitexture;
   PFNGLCLIENTACTIVETEXTUREPROC _glClientActiveTexture;
   PFNGLCLIENTACTIVETEXTUREPROC _glClientActiveTexture;
   PFNGLMULTITEXCOORD1FPROC _glMultiTexCoord1f;
   PFNGLMULTITEXCOORD1FPROC _glMultiTexCoord1f;
   PFNGLMULTITEXCOORD2FPROC _glMultiTexCoord2f;
   PFNGLMULTITEXCOORD2FPROC _glMultiTexCoord2f;
@@ -684,6 +729,7 @@ public:
   PFNGLMULTITEXCOORD2DPROC _glMultiTexCoord2d;
   PFNGLMULTITEXCOORD2DPROC _glMultiTexCoord2d;
   PFNGLMULTITEXCOORD3DPROC _glMultiTexCoord3d;
   PFNGLMULTITEXCOORD3DPROC _glMultiTexCoord3d;
   PFNGLMULTITEXCOORD4DPROC _glMultiTexCoord4d;
   PFNGLMULTITEXCOORD4DPROC _glMultiTexCoord4d;
+#endif
 
 
   bool _supports_buffers;
   bool _supports_buffers;
   PFNGLGENBUFFERSPROC _glGenBuffers;
   PFNGLGENBUFFERSPROC _glGenBuffers;
@@ -789,11 +835,15 @@ public:
   PFNGLUNIFORMMATRIX3FVPROC _glUniformMatrix3fv;
   PFNGLUNIFORMMATRIX3FVPROC _glUniformMatrix3fv;
   PFNGLUNIFORMMATRIX4FVPROC _glUniformMatrix4fv;
   PFNGLUNIFORMMATRIX4FVPROC _glUniformMatrix4fv;
   PFNGLVALIDATEPROGRAMPROC _glValidateProgram;
   PFNGLVALIDATEPROGRAMPROC _glValidateProgram;
+  PFNGLVERTEXATTRIB4FVPROC _glVertexAttrib4fv;
+  PFNGLVERTEXATTRIB4DVPROC _glVertexAttrib4dv;
   PFNGLVERTEXATTRIBPOINTERPROC _glVertexAttribPointer;
   PFNGLVERTEXATTRIBPOINTERPROC _glVertexAttribPointer;
   PFNGLVERTEXATTRIBIPOINTERPROC _glVertexAttribIPointer;
   PFNGLVERTEXATTRIBIPOINTERPROC _glVertexAttribIPointer;
   PFNGLVERTEXATTRIBLPOINTERPROC _glVertexAttribLPointer;
   PFNGLVERTEXATTRIBLPOINTERPROC _glVertexAttribLPointer;
   PFNGLVERTEXATTRIBDIVISORPROC _glVertexAttribDivisor;
   PFNGLVERTEXATTRIBDIVISORPROC _glVertexAttribDivisor;
-#endif  // OPENGLES_1
+  PFNGLDRAWARRAYSINSTANCEDPROC _glDrawArraysInstanced;
+  PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced;
+#endif  // !OPENGLES_1
 #ifndef OPENGLES
 #ifndef OPENGLES
   PFNGLGENSAMPLERSPROC _glGenSamplers;
   PFNGLGENSAMPLERSPROC _glGenSamplers;
   PFNGLDELETESAMPLERSPROC _glDeleteSamplers;
   PFNGLDELETESAMPLERSPROC _glDeleteSamplers;
@@ -804,8 +854,6 @@ public:
   PFNGLSAMPLERPARAMETERFVPROC _glSamplerParameterfv;
   PFNGLSAMPLERPARAMETERFVPROC _glSamplerParameterfv;
   PFNGLPROGRAMPARAMETERIPROC _glProgramParameteri;
   PFNGLPROGRAMPARAMETERIPROC _glProgramParameteri;
   PFNGLPATCHPARAMETERIPROC _glPatchParameteri;
   PFNGLPATCHPARAMETERIPROC _glPatchParameteri;
-  PFNGLDRAWARRAYSINSTANCEDPROC _glDrawArraysInstanced;
-  PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced;
   PFNGLBINDTEXTURESPROC _glBindTextures;
   PFNGLBINDTEXTURESPROC _glBindTextures;
   PFNGLBINDSAMPLERSPROC _glBindSamplers;
   PFNGLBINDSAMPLERSPROC _glBindSamplers;
   PFNGLBINDIMAGETEXTUREPROC _glBindImageTexture;
   PFNGLBINDIMAGETEXTUREPROC _glBindImageTexture;
@@ -823,7 +871,7 @@ public:
   PFNGLMAKETEXTUREHANDLENONRESIDENTPROC _glMakeTextureHandleNonResident;
   PFNGLMAKETEXTUREHANDLENONRESIDENTPROC _glMakeTextureHandleNonResident;
   PFNGLUNIFORMHANDLEUI64PROC _glUniformHandleui64;
   PFNGLUNIFORMHANDLEUI64PROC _glUniformHandleui64;
   PFNGLUNIFORMHANDLEUI64VPROC _glUniformHandleui64v;
   PFNGLUNIFORMHANDLEUI64VPROC _glUniformHandleui64v;
-#endif  // OPENGLES
+#endif  // !OPENGLES
 
 
   GLenum _edge_clamp;
   GLenum _edge_clamp;
   GLenum _border_clamp;
   GLenum _border_clamp;
@@ -831,7 +879,7 @@ public:
   GLenum _mirror_clamp;
   GLenum _mirror_clamp;
   GLenum _mirror_edge_clamp;
   GLenum _mirror_edge_clamp;
   GLenum _mirror_border_clamp;
   GLenum _mirror_border_clamp;
-#ifndef OPENGLES
+#ifndef OPENGLES_1
   GLsizei _instance_count;
   GLsizei _instance_count;
 #endif
 #endif
 
 

+ 319 - 102
panda/src/glstuff/glShaderContext_src.I

@@ -196,6 +196,8 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
   _glgsg = glgsg;
   _glgsg = glgsg;
   _glsl_program = 0;
   _glsl_program = 0;
   _uses_standard_vertex_arrays = false;
   _uses_standard_vertex_arrays = false;
+  _has_divisor = false;
+  _color_attrib_index = -1;
 
 
   nassertv(s->get_language() == Shader::SL_GLSL);
   nassertv(s->get_language() == Shader::SL_GLSL);
 
 
@@ -315,10 +317,14 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
                 bind._part[1] = Shader::SMO_view_to_model;
                 bind._part[1] = Shader::SMO_view_to_model;
               }
               }
 
 
-              if (transpose) {
-                bind._piece = Shader::SMP_upper3x3;
+              if (param_type != GL_FLOAT_MAT3) {
+                GLCAT.error() << "p3d_NormalMatrix input should be mat3, not mat4!\n";
               } else {
               } else {
-                bind._piece = Shader::SMP_transpose3x3;
+                if (transpose) {
+                  bind._piece = Shader::SMP_upper3x3;
+                } else {
+                  bind._piece = Shader::SMP_transpose3x3;
+                }
               }
               }
 
 
             } else if (matrix_name == "ModelMatrix") {
             } else if (matrix_name == "ModelMatrix") {
@@ -356,13 +362,26 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             continue;
             continue;
           }
           }
           if (size > 7 && noprefix.substr(0, 7) == "Texture") {
           if (size > 7 && noprefix.substr(0, 7) == "Texture") {
-            _glgsg->_glUniform1i(p, s->_tex_spec.size());
             Shader::ShaderTexSpec bind;
             Shader::ShaderTexSpec bind;
             bind._id = arg_id;
             bind._id = arg_id;
             bind._name = 0;
             bind._name = 0;
-            bind._desired_type = Texture::TT_2d_texture;
-            bind._stage = atoi(noprefix.substr(7).c_str());
-            s->_tex_spec.push_back(bind);
+
+            string tail;
+            bind._stage = string_to_int(noprefix.substr(7), tail);
+            if (!tail.empty()) {
+              GLCAT.error()
+                << "Error parsing shader input name: unexpected '"
+                << tail << "' in '" << param_name << "'\n";
+              continue;
+            }
+
+            if (get_sampler_texture_type(bind._desired_type, param_type)) {
+              _glgsg->_glUniform1i(p, s->_tex_spec.size());
+              s->_tex_spec.push_back(bind);
+            } else {
+              GLCAT.error()
+                << "Could not bind texture input " << param_name << "\n";
+            }
             continue;
             continue;
           }
           }
           if (size > 9 && noprefix.substr(0, 9) == "Material.") {
           if (size > 9 && noprefix.substr(0, 9) == "Material.") {
@@ -377,22 +396,46 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             bind._dep[1] = Shader::SSD_NONE;
             bind._dep[1] = Shader::SSD_NONE;
 
 
             if (noprefix == "Material.ambient") {
             if (noprefix == "Material.ambient") {
+              if (param_type != GL_FLOAT_VEC4) {
+                GLCAT.error()
+                  << "p3d_Material.ambient should be vec4\n";
+              }
               bind._piece = Shader::SMP_row0;
               bind._piece = Shader::SMP_row0;
               s->_mat_spec.push_back(bind);
               s->_mat_spec.push_back(bind);
               continue;
               continue;
+
             } else if (noprefix == "Material.diffuse") {
             } else if (noprefix == "Material.diffuse") {
+              if (param_type != GL_FLOAT_VEC4) {
+                GLCAT.error()
+                  << "p3d_Material.diffuse should be vec4\n";
+              }
               bind._piece = Shader::SMP_row1;
               bind._piece = Shader::SMP_row1;
               s->_mat_spec.push_back(bind);
               s->_mat_spec.push_back(bind);
               continue;
               continue;
+
             } else if (noprefix == "Material.emission") {
             } else if (noprefix == "Material.emission") {
+              if (param_type != GL_FLOAT_VEC4) {
+                GLCAT.error()
+                  << "p3d_Material.emission should be vec4\n";
+              }
               bind._piece = Shader::SMP_row2;
               bind._piece = Shader::SMP_row2;
               s->_mat_spec.push_back(bind);
               s->_mat_spec.push_back(bind);
               continue;
               continue;
+
             } else if (noprefix == "Material.specular") {
             } else if (noprefix == "Material.specular") {
+              if (param_type != GL_FLOAT_VEC3) {
+                GLCAT.error()
+                  << "p3d_Material.specular should be vec3\n";
+              }
               bind._piece = Shader::SMP_row3x3;
               bind._piece = Shader::SMP_row3x3;
               s->_mat_spec.push_back(bind);
               s->_mat_spec.push_back(bind);
               continue;
               continue;
+
             } else if (noprefix == "Material.shininess") {
             } else if (noprefix == "Material.shininess") {
+              if (param_type != GL_FLOAT) {
+                GLCAT.error()
+                  << "p3d_Material.shininess should be float\n";
+              }
               bind._piece = Shader::SMP_cell15;
               bind._piece = Shader::SMP_cell15;
               s->_mat_spec.push_back(bind);
               s->_mat_spec.push_back(bind);
               continue;
               continue;
@@ -401,7 +444,6 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
           if (noprefix == "ColorScale") {
           if (noprefix == "ColorScale") {
             Shader::ShaderMatSpec bind;
             Shader::ShaderMatSpec bind;
             bind._id = arg_id;
             bind._id = arg_id;
-            bind._piece = Shader::SMP_row3;
             bind._func = Shader::SMF_first;
             bind._func = Shader::SMF_first;
             bind._part[0] = Shader::SMO_attr_colorscale;
             bind._part[0] = Shader::SMO_attr_colorscale;
             bind._arg[0] = NULL;
             bind._arg[0] = NULL;
@@ -409,13 +451,22 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             bind._part[1] = Shader::SMO_identity;
             bind._part[1] = Shader::SMO_identity;
             bind._arg[1] = NULL;
             bind._arg[1] = NULL;
             bind._dep[1] = Shader::SSD_NONE;
             bind._dep[1] = Shader::SSD_NONE;
+
+            if (param_type == GL_FLOAT_VEC3) {
+              bind._piece = Shader::SMP_row3x3;
+            } else if (param_type == GL_FLOAT_VEC4) {
+              bind._piece = Shader::SMP_row3;
+            } else {
+              GLCAT.error()
+                << "p3d_ColorScale should be vec3 or vec4\n";
+              continue;
+            }
             s->_mat_spec.push_back(bind);
             s->_mat_spec.push_back(bind);
             continue;
             continue;
           }
           }
           if (noprefix == "Color") {
           if (noprefix == "Color") {
             Shader::ShaderMatSpec bind;
             Shader::ShaderMatSpec bind;
             bind._id = arg_id;
             bind._id = arg_id;
-            bind._piece = Shader::SMP_row3;
             bind._func = Shader::SMF_first;
             bind._func = Shader::SMF_first;
             bind._part[0] = Shader::SMO_attr_color;
             bind._part[0] = Shader::SMO_attr_color;
             bind._arg[0] = NULL;
             bind._arg[0] = NULL;
@@ -423,10 +474,25 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             bind._part[1] = Shader::SMO_identity;
             bind._part[1] = Shader::SMO_identity;
             bind._arg[1] = NULL;
             bind._arg[1] = NULL;
             bind._dep[1] = Shader::SSD_NONE;
             bind._dep[1] = Shader::SSD_NONE;
+
+            if (param_type == GL_FLOAT_VEC3) {
+              bind._piece = Shader::SMP_row3x3;
+            } else if (param_type == GL_FLOAT_VEC4) {
+              bind._piece = Shader::SMP_row3;
+            } else {
+              GLCAT.error()
+                << "p3d_Color should be vec3 or vec4\n";
+              continue;
+            }
             s->_mat_spec.push_back(bind);
             s->_mat_spec.push_back(bind);
             continue;
             continue;
           }
           }
           if (noprefix == "ClipPlane") {
           if (noprefix == "ClipPlane") {
+            if (param_type != GL_FLOAT_VEC4) {
+              GLCAT.error()
+                << "p3d_ClipPlane should be vec4 or vec4[]\n";
+              continue;
+            }
             for (int i = 0; i < param_size; ++i) {
             for (int i = 0; i < param_size; ++i) {
               Shader::ShaderMatSpec bind;
               Shader::ShaderMatSpec bind;
               bind._id = arg_id;
               bind._id = arg_id;
@@ -448,7 +514,6 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
           if (noprefix == "LightModel.ambient") {
           if (noprefix == "LightModel.ambient") {
             Shader::ShaderMatSpec bind;
             Shader::ShaderMatSpec bind;
             bind._id = arg_id;
             bind._id = arg_id;
-            bind._piece = Shader::SMP_row3;
             bind._func = Shader::SMF_first;
             bind._func = Shader::SMF_first;
             bind._part[0] = Shader::SMO_light_ambient;
             bind._part[0] = Shader::SMO_light_ambient;
             bind._arg[0] = NULL;
             bind._arg[0] = NULL;
@@ -456,6 +521,16 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             bind._part[1] = Shader::SMO_identity;
             bind._part[1] = Shader::SMO_identity;
             bind._arg[1] = NULL;
             bind._arg[1] = NULL;
             bind._dep[1] = Shader::SSD_NONE;
             bind._dep[1] = Shader::SSD_NONE;
+
+            if (param_type == GL_FLOAT_VEC3) {
+              bind._piece = Shader::SMP_row3x3;
+            } else if (param_type == GL_FLOAT_VEC4) {
+              bind._piece = Shader::SMP_row3;
+            } else {
+              GLCAT.error()
+                << "p3d_LightModel.ambient should be vec3 or vec4\n";
+              continue;
+            }
             s->_mat_spec.push_back(bind);
             s->_mat_spec.push_back(bind);
             continue;
             continue;
           }
           }
@@ -524,71 +599,39 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
           switch (param_type) {
           switch (param_type) {
 #ifndef OPENGLES
 #ifndef OPENGLES
             case GL_INT_SAMPLER_1D:
             case GL_INT_SAMPLER_1D:
-            case GL_UNSIGNED_INT_SAMPLER_1D:
-            case GL_SAMPLER_1D_SHADOW:
-            case GL_SAMPLER_1D: {
-              _glgsg->_glUniform1i(p, s->_tex_spec.size());
-              Shader::ShaderTexSpec bind;
-              bind._id = arg_id;
-              bind._name = InternalName::make(param_name);
-              bind._desired_type = Texture::TT_1d_texture;
-              bind._stage = texunitno++;
-              s->_tex_spec.push_back(bind);
-              continue; }
             case GL_INT_SAMPLER_2D:
             case GL_INT_SAMPLER_2D:
-            case GL_UNSIGNED_INT_SAMPLER_2D:
-            case GL_SAMPLER_2D_SHADOW:
-#endif
-            case GL_SAMPLER_2D: {
-              _glgsg->_glUniform1i(p, s->_tex_spec.size());
-              Shader::ShaderTexSpec bind;
-              bind._id = arg_id;
-              bind._name = InternalName::make(param_name);
-              bind._desired_type = Texture::TT_2d_texture;
-              bind._stage = texunitno++;
-              s->_tex_spec.push_back(bind);
-              continue; }
-#ifndef OPENGLES
             case GL_INT_SAMPLER_3D:
             case GL_INT_SAMPLER_3D:
-            case GL_UNSIGNED_INT_SAMPLER_3D:
-#endif
-            case GL_SAMPLER_3D: {
-              _glgsg->_glUniform1i(p, s->_tex_spec.size());
-              Shader::ShaderTexSpec bind;
-              bind._id = arg_id;
-              bind._name = InternalName::make(param_name);
-              bind._desired_type = Texture::TT_3d_texture;
-              bind._stage = texunitno++;
-              s->_tex_spec.push_back(bind);
-              continue; }
-#ifndef OPENGLES
+            case GL_INT_SAMPLER_2D_ARRAY:
             case GL_INT_SAMPLER_CUBE:
             case GL_INT_SAMPLER_CUBE:
+            case GL_INT_SAMPLER_BUFFER:
+            case GL_UNSIGNED_INT_SAMPLER_1D:
+            case GL_UNSIGNED_INT_SAMPLER_2D:
+            case GL_UNSIGNED_INT_SAMPLER_3D:
             case GL_UNSIGNED_INT_SAMPLER_CUBE:
             case GL_UNSIGNED_INT_SAMPLER_CUBE:
-            case GL_SAMPLER_CUBE_SHADOW:
-#endif
-            case GL_SAMPLER_CUBE: {
-              _glgsg->_glUniform1i(p, s->_tex_spec.size());
-              Shader::ShaderTexSpec bind;
-              bind._id = arg_id;
-              bind._name = InternalName::make(param_name);
-              bind._desired_type = Texture::TT_cube_map;
-              bind._stage = texunitno++;
-              s->_tex_spec.push_back(bind);
-              continue; }
-#ifndef OPENGLES
-            case GL_INT_SAMPLER_2D_ARRAY:
             case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
             case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+            case GL_UNSIGNED_INT_SAMPLER_BUFFER:
+            case GL_SAMPLER_1D_SHADOW:
+            case GL_SAMPLER_1D:
+            case GL_SAMPLER_CUBE_SHADOW:
+            case GL_SAMPLER_2D_ARRAY:
             case GL_SAMPLER_2D_ARRAY_SHADOW:
             case GL_SAMPLER_2D_ARRAY_SHADOW:
-            case GL_SAMPLER_2D_ARRAY: {
-              _glgsg->_glUniform1i(p, s->_tex_spec.size());
+            case GL_SAMPLER_BUFFER:
+#endif  // !OPENGLES
+            case GL_SAMPLER_2D:
+            case GL_SAMPLER_2D_SHADOW:
+            case GL_SAMPLER_3D:
+            case GL_SAMPLER_CUBE: {
               Shader::ShaderTexSpec bind;
               Shader::ShaderTexSpec bind;
               bind._id = arg_id;
               bind._id = arg_id;
               bind._name = InternalName::make(param_name);
               bind._name = InternalName::make(param_name);
-              bind._desired_type = Texture::TT_2d_texture_array;
+              bind._desired_type = Texture::TT_2d_texture;
               bind._stage = texunitno++;
               bind._stage = texunitno++;
-              s->_tex_spec.push_back(bind);
-              continue; }
-#endif
+              if (get_sampler_texture_type(bind._desired_type, param_type)) {
+                _glgsg->_glUniform1i(p, s->_tex_spec.size());
+                s->_tex_spec.push_back(bind);
+              }
+              continue;
+            }
             case GL_FLOAT_MAT2:
             case GL_FLOAT_MAT2:
 #ifndef OPENGLES
 #ifndef OPENGLES
             case GL_FLOAT_MAT2x3:
             case GL_FLOAT_MAT2x3:
@@ -598,7 +641,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             case GL_FLOAT_MAT4x2:
             case GL_FLOAT_MAT4x2:
             case GL_FLOAT_MAT4x3:
             case GL_FLOAT_MAT4x3:
 #endif
 #endif
-              GLCAT.warning() << "GLSL shader requested an unrecognized matrix type\n";
+              GLCAT.warning() << "GLSL shader requested an unsupported matrix type\n";
               continue;
               continue;
             case GL_FLOAT_MAT3: {
             case GL_FLOAT_MAT3: {
               Shader::ShaderMatSpec bind;
               Shader::ShaderMatSpec bind;
@@ -722,16 +765,19 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             case GL_IMAGE_3D_EXT:
             case GL_IMAGE_3D_EXT:
             case GL_IMAGE_CUBE_EXT:
             case GL_IMAGE_CUBE_EXT:
             case GL_IMAGE_2D_ARRAY_EXT:
             case GL_IMAGE_2D_ARRAY_EXT:
+            case GL_IMAGE_BUFFER_EXT:
             case GL_INT_IMAGE_1D_EXT:
             case GL_INT_IMAGE_1D_EXT:
             case GL_INT_IMAGE_2D_EXT:
             case GL_INT_IMAGE_2D_EXT:
             case GL_INT_IMAGE_3D_EXT:
             case GL_INT_IMAGE_3D_EXT:
             case GL_INT_IMAGE_CUBE_EXT:
             case GL_INT_IMAGE_CUBE_EXT:
             case GL_INT_IMAGE_2D_ARRAY_EXT:
             case GL_INT_IMAGE_2D_ARRAY_EXT:
+            case GL_INT_IMAGE_BUFFER_EXT:
             case GL_UNSIGNED_INT_IMAGE_1D_EXT:
             case GL_UNSIGNED_INT_IMAGE_1D_EXT:
             case GL_UNSIGNED_INT_IMAGE_2D_EXT:
             case GL_UNSIGNED_INT_IMAGE_2D_EXT:
             case GL_UNSIGNED_INT_IMAGE_3D_EXT:
             case GL_UNSIGNED_INT_IMAGE_3D_EXT:
             case GL_UNSIGNED_INT_IMAGE_CUBE_EXT:
             case GL_UNSIGNED_INT_IMAGE_CUBE_EXT:
             case GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT:
             case GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT:
+            case GL_UNSIGNED_INT_IMAGE_BUFFER_EXT:
               // This won't really change at runtime, so we might as well
               // This won't really change at runtime, so we might as well
               // bind once and then forget about it.
               // bind once and then forget about it.
               _glgsg->_glUniform1i(p, imgunitno++);
               _glgsg->_glUniform1i(p, imgunitno++);
@@ -880,7 +926,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
                        param_type == GL_UNSIGNED_INT_VEC3 ||
                        param_type == GL_UNSIGNED_INT_VEC3 ||
                        param_type == GL_UNSIGNED_INT_VEC4 ||
                        param_type == GL_UNSIGNED_INT_VEC4 ||
 #endif
 #endif
-                       param_type == GL_UNSIGNED_INT );
+                       param_type == GL_UNSIGNED_INT);
 
 
       if (noprefix.empty()) {
       if (noprefix.empty()) {
         // Arbitrarily named attribute.
         // Arbitrarily named attribute.
@@ -895,6 +941,9 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
       } else if (noprefix == "Color") {
       } else if (noprefix == "Color") {
         bind._name = InternalName::get_color();
         bind._name = InternalName::get_color();
 
 
+        // Save the index, so we can apply special handling to this attrib.
+        _color_attrib_index = p;
+
       } else if (noprefix.substr(0, 7) == "Tangent") {
       } else if (noprefix.substr(0, 7) == "Tangent") {
         bind._name = InternalName::get_tangent();
         bind._name = InternalName::get_tangent();
         if (noprefix.size() > 7) {
         if (noprefix.size() > 7) {
@@ -945,6 +994,119 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
   _glgsg->report_my_gl_errors();
   _glgsg->report_my_gl_errors();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLShaderContext::get_sampler_texture_type
+//       Access: Public
+//  Description: Returns the texture type required for the given
+//               GL sampler type.  Returns false if unsupported.
+////////////////////////////////////////////////////////////////////
+bool CLP(ShaderContext)::
+get_sampler_texture_type(int &out, GLenum param_type) {
+  switch (param_type) {
+#ifndef OPENGLES
+  case GL_SAMPLER_1D_SHADOW:
+    if (!_glgsg->_supports_shadow_filter) {
+      GLCAT.error()
+        << "GLSL shader uses shadow sampler, which is unsupported by the driver.\n";
+      return false;
+    }
+    // Fall through
+  case GL_INT_SAMPLER_1D:
+  case GL_UNSIGNED_INT_SAMPLER_1D:
+  case GL_SAMPLER_1D:
+    out = Texture::TT_1d_texture;
+    return true;
+
+  case GL_INT_SAMPLER_2D:
+  case GL_UNSIGNED_INT_SAMPLER_2D:
+#endif
+  case GL_SAMPLER_2D:
+    out = Texture::TT_2d_texture;
+    return true;
+
+  case GL_SAMPLER_2D_SHADOW:
+    out = Texture::TT_2d_texture;
+    if (!_glgsg->_supports_shadow_filter) {
+      GLCAT.error()
+        << "GLSL shader uses shadow sampler, which is unsupported by the driver.\n";
+      return false;
+    }
+    return true;
+
+#ifndef OPENGLES
+  case GL_INT_SAMPLER_3D:
+  case GL_UNSIGNED_INT_SAMPLER_3D:
+#endif
+  case GL_SAMPLER_3D:
+    out = Texture::TT_3d_texture;
+    if (_glgsg->_supports_3d_texture) {
+      return true;
+    } else {
+      GLCAT.error()
+        << "GLSL shader uses 3D texture, which is unsupported by the driver.\n";
+      return false;
+    }
+
+#ifndef OPENGLES
+  case GL_SAMPLER_CUBE_SHADOW:
+    if (!_glgsg->_supports_shadow_filter) {
+      GLCAT.error()
+        << "GLSL shader uses shadow sampler, which is unsupported by the driver.\n";
+      return false;
+    }
+    // Fall through
+  case GL_INT_SAMPLER_CUBE:
+  case GL_UNSIGNED_INT_SAMPLER_CUBE:
+#endif
+  case GL_SAMPLER_CUBE:
+    out = Texture::TT_cube_map;
+    if (!_glgsg->_supports_cube_map) {
+      GLCAT.error()
+        << "GLSL shader uses cube map, which is unsupported by the driver.\n";
+      return false;
+    }
+    return true;
+
+#ifndef OPENGLES
+  case GL_SAMPLER_2D_ARRAY_SHADOW:
+    if (!_glgsg->_supports_shadow_filter) {
+      GLCAT.error()
+        << "GLSL shader uses shadow sampler, which is unsupported by the driver.\n";
+      return false;
+    }
+    // Fall through
+  case GL_INT_SAMPLER_2D_ARRAY:
+  case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+  case GL_SAMPLER_2D_ARRAY:
+    out = Texture::TT_2d_texture_array;
+    if (_glgsg->_supports_2d_texture_array) {
+      return true;
+    } else {
+      GLCAT.error()
+        << "GLSL shader uses 2D texture array, which is unsupported by the driver.\n";
+      return false;
+    }
+
+  case GL_INT_SAMPLER_BUFFER:
+  case GL_UNSIGNED_INT_SAMPLER_BUFFER:
+  case GL_SAMPLER_BUFFER:
+    out = Texture::TT_buffer_texture;
+    if (_glgsg->_supports_buffer_texture) {
+      return true;
+    } else {
+      GLCAT.error()
+        << "GLSL shader uses buffer texture, which is unsupported by the driver.\n";
+      return false;
+    }
+#endif
+
+  default:
+    GLCAT.error()
+      << "GLSL shader uses unsupported sampler type for texture input.\n";
+    return false;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GLShaderContext::Destructor
 //     Function: GLShaderContext::Destructor
 //       Access: Public
 //       Access: Public
@@ -1063,7 +1225,7 @@ issue_parameters(int altered) {
             // Convert int data to float data.
             // Convert int data to float data.
             data = (float*) alloca(sizeof(float) * spec._dim[0] * spec._dim[1]);
             data = (float*) alloca(sizeof(float) * spec._dim[0] * spec._dim[1]);
             for (int i = 0; i < (spec._dim[0] * spec._dim[1]); ++i) {
             for (int i = 0; i < (spec._dim[0] * spec._dim[1]); ++i) {
-              data[i] = (int)(((float*)ptr_data->_ptr)[i]);
+              data[i] = (float)(((int*)ptr_data->_ptr)[i]);
             }
             }
             break;
             break;
 
 
@@ -1084,12 +1246,12 @@ issue_parameters(int altered) {
           }
           }
 
 
           switch (spec._dim[1]) {
           switch (spec._dim[1]) {
-          case 1: _glgsg->_glUniform1fv(p, spec._dim[0], (float*)ptr_data->_ptr); continue;
-          case 2: _glgsg->_glUniform2fv(p, spec._dim[0], (float*)ptr_data->_ptr); continue;
-          case 3: _glgsg->_glUniform3fv(p, spec._dim[0], (float*)ptr_data->_ptr); continue;
-          case 4: _glgsg->_glUniform4fv(p, spec._dim[0], (float*)ptr_data->_ptr); continue;
-          case 9: _glgsg->_glUniformMatrix3fv(p, spec._dim[0], GL_FALSE, (float*)ptr_data->_ptr); continue;
-          case 16: _glgsg->_glUniformMatrix4fv(p, spec._dim[0], GL_FALSE, (float*)ptr_data->_ptr); continue;
+          case 1: _glgsg->_glUniform1fv(p, spec._dim[0], (float*)data); continue;
+          case 2: _glgsg->_glUniform2fv(p, spec._dim[0], (float*)data); continue;
+          case 3: _glgsg->_glUniform3fv(p, spec._dim[0], (float*)data); continue;
+          case 4: _glgsg->_glUniform4fv(p, spec._dim[0], (float*)data); continue;
+          case 9: _glgsg->_glUniformMatrix3fv(p, spec._dim[0], GL_FALSE, (float*)data); continue;
+          case 16: _glgsg->_glUniformMatrix4fv(p, spec._dim[0], GL_FALSE, (float*)data); continue;
           }
           }
           nassertd(false) continue;
           nassertd(false) continue;
         }
         }
@@ -1202,7 +1364,7 @@ disable_shader_vertex_arrays() {
   for (int i=0; i<(int)_shader->_var_spec.size(); i++) {
   for (int i=0; i<(int)_shader->_var_spec.size(); i++) {
     const Shader::ShaderVarSpec &bind = _shader->_var_spec[i];
     const Shader::ShaderVarSpec &bind = _shader->_var_spec[i];
     const GLint p = _glsl_parameter_map[bind._id._seqno];
     const GLint p = _glsl_parameter_map[bind._id._seqno];
-    if (_glgsg->_supports_vertex_attrib_divisor) {
+    if (_has_divisor) {
       _glgsg->_glVertexAttribDivisor(p, 0);
       _glgsg->_glVertexAttribDivisor(p, 0);
     }
     }
     for (int i = 0; i < bind._elements; ++i) {
     for (int i = 0; i < bind._elements; ++i) {
@@ -1261,10 +1423,13 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
       }
       }
       GLint p = _glsl_parameter_map[bind._id._seqno];
       GLint p = _glsl_parameter_map[bind._id._seqno];
 
 
+      // Don't apply vertex colors if they are disabled with a ColorAttrib.
       int num_elements, element_stride, divisor;
       int num_elements, element_stride, divisor;
-      if (_glgsg->_data_reader->get_array_info(name, array_reader,
+      bool normalized;
+      if ((p != _color_attrib_index || _glgsg->_vertex_colors_enabled) &&
+          _glgsg->_data_reader->get_array_info(name, array_reader,
                                                num_values, numeric_type,
                                                num_values, numeric_type,
-                                               start, stride, divisor,
+                                               normalized, start, stride, divisor,
                                                num_elements, element_stride)) {
                                                num_elements, element_stride)) {
         const unsigned char *client_pointer;
         const unsigned char *client_pointer;
         if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) {
         if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) {
@@ -1282,15 +1447,19 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
           } else
           } else
 #endif
 #endif
           if (numeric_type == GeomEnums::NT_packed_dabc) {
           if (numeric_type == GeomEnums::NT_packed_dabc) {
+            // GL_BGRA is a special accepted value available since OpenGL 3.2.
+            // It requires us to pass GL_TRUE for normalized.
             _glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
             _glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
                                            GL_TRUE, stride, client_pointer);
                                            GL_TRUE, stride, client_pointer);
           } else {
           } else {
-            _glgsg->_glVertexAttribPointer(p, num_values, _glgsg->get_numeric_type(numeric_type),
-                                           GL_TRUE, stride, client_pointer);
+            _glgsg->_glVertexAttribPointer(p, num_values,
+                                           _glgsg->get_numeric_type(numeric_type),
+                                           normalized, stride, client_pointer);
           }
           }
 
 
           if (_glgsg->_supports_vertex_attrib_divisor) {
           if (_glgsg->_supports_vertex_attrib_divisor) {
             _glgsg->_glVertexAttribDivisor(p, divisor);
             _glgsg->_glVertexAttribDivisor(p, divisor);
+            _has_divisor = true;
           }
           }
 
 
           ++p;
           ++p;
@@ -1300,6 +1469,14 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
         for (int i = 0; i < bind._elements; ++i) {
         for (int i = 0; i < bind._elements; ++i) {
           _glgsg->_glDisableVertexAttribArray(p + i);
           _glgsg->_glDisableVertexAttribArray(p + i);
         }
         }
+        if (p == _color_attrib_index) {
+          // Vertex colors are disabled or not present.  Apply flat color.
+#if defined(STDFLOAT_DOUBLE) && !defined(OPENGLES)
+          _glgsg->_glVertexAttrib4dv(p, _glgsg->_scene_graph_color.get_data());
+#else
+          _glgsg->_glVertexAttrib4fv(p, _glgsg->_scene_graph_color.get_data());
+#endif
+        }
       }
       }
     }
     }
   }
   }
@@ -1342,22 +1519,38 @@ disable_shader_texture_bindings() {
 
 
     _glgsg->_glActiveTexture(GL_TEXTURE0 + i);
     _glgsg->_glActiveTexture(GL_TEXTURE0 + i);
 
 
+    switch (_shader->_tex_spec[i]._desired_type) {
+    case Texture::TT_1d_texture:
 #ifndef OPENGLES
 #ifndef OPENGLES
-    glBindTexture(GL_TEXTURE_1D, 0);
-#endif  // OPENGLES
-    glBindTexture(GL_TEXTURE_2D, 0);
+      glBindTexture(GL_TEXTURE_1D, 0);
+#endif
+      break;
+
+    case Texture::TT_2d_texture:
+      glBindTexture(GL_TEXTURE_2D, 0);
+      break;
+
+    case Texture::TT_3d_texture:
 #ifndef OPENGLES_1
 #ifndef OPENGLES_1
-    if (_glgsg->_supports_3d_texture) {
       glBindTexture(GL_TEXTURE_3D, 0);
       glBindTexture(GL_TEXTURE_3D, 0);
-    }
-#endif  // OPENGLES_1
+#endif
+      break;
+
+    case Texture::TT_2d_texture_array:
 #ifndef OPENGLES
 #ifndef OPENGLES
-    if (_glgsg->_supports_2d_texture_array) {
       glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 0);
       glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 0);
-    }
 #endif
 #endif
-    if (_glgsg->_supports_cube_map) {
+      break;
+
+    case Texture::TT_cube_map:
       glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
       glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+      break;
+
+    case Texture::TT_buffer_texture:
+#ifndef OPENGLES
+      glBindTexture(GL_TEXTURE_BUFFER, 0);
+#endif
+      break;
     }
     }
   }
   }
 
 
@@ -1491,7 +1684,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
   nassertv(texattrib != (TextureAttrib *)NULL);
   nassertv(texattrib != (TextureAttrib *)NULL);
 
 
   for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) {
   for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) {
-    const Shader::ShaderTexSpec &spec = _shader->_tex_spec[i];
+    Shader::ShaderTexSpec &spec = _shader->_tex_spec[i];
     const InternalName *id = spec._name;
     const InternalName *id = spec._name;
     int texunit = spec._stage;
     int texunit = spec._stage;
 
 
@@ -1519,9 +1712,15 @@ update_shader_texture_bindings(ShaderContext *prev) {
     }
     }
 
 
     if (tex->get_texture_type() != spec._desired_type) {
     if (tex->get_texture_type() != spec._desired_type) {
-      GLCAT.error()
-        << "Sampler type of GLSL shader input '" << *id << "' does not "
-           "match type of texture " << *tex << ".\n";
+      if (id != NULL) {
+        GLCAT.error()
+          << "Sampler type of GLSL shader input '" << *id << "' does not "
+             "match type of texture " << *tex << ".\n";
+      } else {
+        GLCAT.error()
+          << "Sampler type of GLSL shader input p3d_Texture" << texunit
+          << " does not match type of texture " << *tex << ".\n";
+      }
       //TODO: also check whether shadow sampler textures have shadow filter enabled.
       //TODO: also check whether shadow sampler textures have shadow filter enabled.
     }
     }
 
 
@@ -1593,7 +1792,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
 //  Description: This subroutine prints the infolog for a shader.
 //  Description: This subroutine prints the infolog for a shader.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 void CLP(ShaderContext)::
-glsl_report_shader_errors(GLuint shader, Shader::ShaderType type) {
+glsl_report_shader_errors(GLuint shader, Shader::ShaderType type, bool fatal) {
   char *info_log;
   char *info_log;
   GLint length = 0;
   GLint length = 0;
   GLint num_chars  = 0;
   GLint num_chars  = 0;
@@ -1642,6 +1841,9 @@ glsl_report_shader_errors(GLuint shader, Shader::ShaderType type) {
       GLCAT.error(false)
       GLCAT.error(false)
         << fn << "(" << lineno << ") : " << (line.c_str() + prefixlen) << "\n";
         << fn << "(" << lineno << ") : " << (line.c_str() + prefixlen) << "\n";
 
 
+    } else if (!fatal) {
+      GLCAT.warning(false) << line << "\n";
+
     } else {
     } else {
       GLCAT.error(false) << line << "\n";
       GLCAT.error(false) << line << "\n";
     }
     }
@@ -1654,7 +1856,7 @@ glsl_report_shader_errors(GLuint shader, Shader::ShaderType type) {
 //  Description: This subroutine prints the infolog for a program.
 //  Description: This subroutine prints the infolog for a program.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
 void CLP(ShaderContext)::
-glsl_report_program_errors(GLuint program) {
+glsl_report_program_errors(GLuint program, bool fatal) {
   char *info_log;
   char *info_log;
   GLint length = 0;
   GLint length = 0;
   GLint num_chars  = 0;
   GLint num_chars  = 0;
@@ -1664,8 +1866,13 @@ glsl_report_program_errors(GLuint program) {
   if (length > 1) {
   if (length > 1) {
     info_log = (char *) alloca(length);
     info_log = (char *) alloca(length);
     _glgsg->_glGetProgramInfoLog(program, length, &num_chars, info_log);
     _glgsg->_glGetProgramInfoLog(program, length, &num_chars, info_log);
+
     if (strcmp(info_log, "Success.\n") != 0 && strcmp(info_log, "No errors.\n") != 0) {
     if (strcmp(info_log, "Success.\n") != 0 && strcmp(info_log, "No errors.\n") != 0) {
-      GLCAT.error(false) << info_log << "\n";
+      if (!fatal) {
+        GLCAT.warning(false) << info_log << "\n";
+      } else {
+        GLCAT.error(false) << info_log << "\n";
+      }
     }
     }
   }
   }
 }
 }
@@ -1733,7 +1940,7 @@ glsl_compile_shader(Shader::ShaderType type) {
     GLCAT.error()
     GLCAT.error()
       << "An error occurred while compiling GLSL shader "
       << "An error occurred while compiling GLSL shader "
       << _shader->get_filename(type) << ":\n";
       << _shader->get_filename(type) << ":\n";
-    glsl_report_shader_errors(handle, type);
+    glsl_report_shader_errors(handle, type, true);
     _glgsg->_glDeleteShader(handle);
     _glgsg->_glDeleteShader(handle);
     _glgsg->report_my_gl_errors();
     _glgsg->report_my_gl_errors();
     return false;
     return false;
@@ -1743,7 +1950,7 @@ glsl_compile_shader(Shader::ShaderType type) {
   _glsl_shaders.push_back(handle);
   _glsl_shaders.push_back(handle);
 
 
   // There might be warnings, so report those.
   // There might be warnings, so report those.
-  glsl_report_shader_errors(handle, type);
+  glsl_report_shader_errors(handle, type, false);
 
 
   return true;
   return true;
 }
 }
@@ -1776,9 +1983,8 @@ glsl_compile_and_link() {
     valid &= glsl_compile_shader(Shader::ST_fragment);
     valid &= glsl_compile_shader(Shader::ST_fragment);
   }
   }
 
 
-#ifdef OPENGLES
-    nassertr(false, false); // OpenGL ES has no geometry shaders.
-#else
+  // OpenGL ES has no geometry shaders.
+#ifndef OPENGLES
   if (!_shader->get_text(Shader::ST_geometry).empty()) {
   if (!_shader->get_text(Shader::ST_geometry).empty()) {
     valid &= glsl_compile_shader(Shader::ST_geometry);
     valid &= glsl_compile_shader(Shader::ST_geometry);
 
 
@@ -1810,6 +2016,17 @@ glsl_compile_and_link() {
   //  glsl_report_shader_errors(*it);
   //  glsl_report_shader_errors(*it);
   //}
   //}
 
 
+  // Under OpenGL's compatibility profile, we have to make sure that we bind
+  // something to attribute 0.  Make sure that this is the position array.
+  _glgsg->_glBindAttribLocation(_glsl_program, 0, "p3d_Vertex");
+  _glgsg->_glBindAttribLocation(_glsl_program, 0, "vertex");
+
+  // While we're at it, let's also map these to fixed locations.  These
+  // attributes were historically fixed to these locations, so it might
+  // help a buggy driver.
+  _glgsg->_glBindAttribLocation(_glsl_program, 2, "p3d_Normal");
+  _glgsg->_glBindAttribLocation(_glsl_program, 3, "p3d_Color");
+
   // If we requested to retrieve the shader, we should indicate that before linking.
   // If we requested to retrieve the shader, we should indicate that before linking.
 #if !defined(NDEBUG) && !defined(OPENGLES)
 #if !defined(NDEBUG) && !defined(OPENGLES)
   if (gl_dump_compiled_shaders && _glgsg->_supports_get_program_binary) {
   if (gl_dump_compiled_shaders && _glgsg->_supports_get_program_binary) {
@@ -1823,12 +2040,12 @@ glsl_compile_and_link() {
   _glgsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status);
   _glgsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status);
   if (status != GL_TRUE) {
   if (status != GL_TRUE) {
     GLCAT.error() << "An error occurred while linking GLSL shader program!\n";
     GLCAT.error() << "An error occurred while linking GLSL shader program!\n";
-    glsl_report_program_errors(_glsl_program);
+    glsl_report_program_errors(_glsl_program, true);
     return false;
     return false;
   }
   }
 
 
   // Report any warnings.
   // Report any warnings.
-  glsl_report_program_errors(_glsl_program);
+  glsl_report_program_errors(_glsl_program, false);
 
 
   // Dump the binary if requested.
   // Dump the binary if requested.
 #if !defined(NDEBUG) && !defined(OPENGLES)
 #if !defined(NDEBUG) && !defined(OPENGLES)

+ 6 - 2
panda/src/glstuff/glShaderContext_src.h

@@ -35,6 +35,8 @@ public:
   ~CLP(ShaderContext)();
   ~CLP(ShaderContext)();
   ALLOC_DELETED_CHAIN(CLP(ShaderContext));
   ALLOC_DELETED_CHAIN(CLP(ShaderContext));
 
 
+  bool get_sampler_texture_type(int &out, GLenum param_type);
+
   INLINE bool valid(void);
   INLINE bool valid(void);
   void bind(bool reissue_parameters = true);
   void bind(bool reissue_parameters = true);
   void unbind();
   void unbind();
@@ -63,6 +65,7 @@ private:
   //typedef pvector<ParamContext> ParamContexts;
   //typedef pvector<ParamContext> ParamContexts;
   //ParamContexts _params;
   //ParamContexts _params;
 
 
+  GLint _color_attrib_index;
   pvector<GLint> _glsl_parameter_map;
   pvector<GLint> _glsl_parameter_map;
   pmap<GLint, GLuint64> _glsl_uniform_handles;
   pmap<GLint, GLuint64> _glsl_uniform_handles;
 
 
@@ -72,9 +75,10 @@ private:
   CLP(GraphicsStateGuardian) *_glgsg;
   CLP(GraphicsStateGuardian) *_glgsg;
 
 
   bool _uses_standard_vertex_arrays;
   bool _uses_standard_vertex_arrays;
+  bool _has_divisor;
 
 
-  void glsl_report_shader_errors(GLuint shader, Shader::ShaderType type);
-  void glsl_report_program_errors(GLuint program);
+  void glsl_report_shader_errors(GLuint shader, Shader::ShaderType type, bool fatal);
+  void glsl_report_program_errors(GLuint program, bool fatal);
   bool glsl_compile_shader(Shader::ShaderType type);
   bool glsl_compile_shader(Shader::ShaderType type);
   bool glsl_compile_and_link();
   bool glsl_compile_and_link();
   bool parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *s);
   bool parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *s);

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