Browse Source

Merge remote-tracking branch 'upstream/master' into cmake

Conflicts:
	panda/src/linmath/lvecBase4.h
Sam Edwards 11 years ago
parent
commit
3d0f587ca0
100 changed files with 5294 additions and 2446 deletions
  1. 3 2
      direct/src/showbase/extend_frozen.c
  2. 0 34
      dtool/Config.pp
  3. 0 13
      dtool/LocalSetup.pp
  4. 0 6
      dtool/Package.pp
  5. 0 7
      dtool/pptempl/Global.pp
  6. 10 1
      dtool/src/dtoolbase/atomicAdjust.h
  7. 148 0
      dtool/src/dtoolbase/atomicAdjustGccImpl.I
  8. 60 0
      dtool/src/dtoolbase/atomicAdjustGccImpl.h
  9. 23 1
      dtool/src/dtoolbase/cmath.I
  10. 3 1
      dtool/src/dtoolbase/cmath.h
  11. 11 0
      dtool/src/dtoolbase/dtoolbase_cc.h
  12. 8 1
      dtool/src/dtoolbase/nearly_zero.h
  13. 2 2
      dtool/src/dtoolbase/register_type.cxx
  14. 6 0
      dtool/src/dtoolbase/register_type.h
  15. 4 0
      dtool/src/dtoolbase/typeHandle.cxx
  16. 7 5
      dtool/src/dtoolbase/typeHandle.h
  17. 2 0
      dtool/src/dtoolbase/typeRegistry.h
  18. 59 43
      dtool/src/interrogate/functionRemap.cxx
  19. 1 0
      dtool/src/interrogate/functionRemap.h
  20. 8 6
      dtool/src/interrogate/interfaceMaker.cxx
  21. 23 0
      dtool/src/interrogate/interfaceMaker.h
  22. 2 7
      dtool/src/interrogate/interfaceMakerPython.cxx
  23. 398 214
      dtool/src/interrogate/interfaceMakerPythonNative.cxx
  24. 24 21
      dtool/src/interrogate/interfaceMakerPythonNative.h
  25. 49 36
      dtool/src/interrogate/interrogateBuilder.cxx
  26. 3 2
      dtool/src/interrogate/typeManager.cxx
  27. 1 1
      dtool/src/interrogatedb/dtool_super_base.cxx
  28. 21 5
      dtool/src/interrogatedb/py_panda.cxx
  29. 13 8
      dtool/src/interrogatedb/py_panda.h
  30. 3 1
      dtool/src/parser-inc/Python.h
  31. 4 0
      dtool/src/prc/configVariableCore.h
  32. 1 0
      dtool/src/prc/configVariableManager.h
  33. 2 2
      dtool/src/prc/notifyCategory.I
  34. 2 2
      dtool/src/prc/notifyCategory.h
  35. 12 4
      dtool/src/prc/notifyCategoryProxy.I
  36. 2 2
      dtool/src/prc/notifyCategoryProxy.h
  37. 20 0
      dtool/src/pystub/pystub.cxx
  38. 21 36
      makepanda/makepanda.py
  39. 8 3
      makepanda/makepandacore.py
  40. 2 4
      panda/src/androiddisplay/androidGraphicsStateGuardian.cxx
  41. 1 1
      panda/src/androiddisplay/androidGraphicsStateGuardian.h
  42. 1 1
      panda/src/cocoadisplay/Sources.pp
  43. 1 1
      panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h
  44. 4 5
      panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm
  45. 11 0
      panda/src/display/config_display.cxx
  46. 2 0
      panda/src/display/config_display.h
  47. 244 63
      panda/src/display/displayRegion.I
  48. 41 36
      panda/src/display/displayRegion.cxx
  49. 40 24
      panda/src/display/displayRegion.h
  50. 121 26
      panda/src/display/frameBufferProperties.I
  51. 121 58
      panda/src/display/frameBufferProperties.cxx
  52. 37 21
      panda/src/display/frameBufferProperties.h
  53. 52 1
      panda/src/display/graphicsEngine.cxx
  54. 3 0
      panda/src/display/graphicsEngine.h
  55. 11 0
      panda/src/display/graphicsStateGuardian.I
  56. 35 13
      panda/src/display/graphicsStateGuardian.cxx
  57. 5 1
      panda/src/display/graphicsStateGuardian.h
  58. 4 4
      panda/src/display/stereoDisplayRegion.cxx
  59. 1 1
      panda/src/display/stereoDisplayRegion.h
  60. 60 12
      panda/src/display/windowProperties.I
  61. 8 14
      panda/src/display/windowProperties.cxx
  62. 11 7
      panda/src/display/windowProperties.h
  63. 2 4
      panda/src/egldisplay/eglGraphicsStateGuardian.cxx
  64. 1 1
      panda/src/egldisplay/eglGraphicsStateGuardian.h
  65. 19 1
      panda/src/gles2gsg/gles2gsg.h
  66. 5 1
      panda/src/glesgsg/glesgsg.h
  67. 67 0
      panda/src/glstuff/glCgShaderContext_src.I
  68. 619 0
      panda/src/glstuff/glCgShaderContext_src.cxx
  69. 89 0
      panda/src/glstuff/glCgShaderContext_src.h
  70. 2 2
      panda/src/glstuff/glGeomContext_src.cxx
  71. 31 23
      panda/src/glstuff/glGeomMunger_src.cxx
  72. 198 66
      panda/src/glstuff/glGraphicsBuffer_src.cxx
  73. 6 4
      panda/src/glstuff/glGraphicsBuffer_src.h
  74. 55 55
      panda/src/glstuff/glGraphicsStateGuardian_src.I
  75. 374 178
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  76. 100 15
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  77. 6 6
      panda/src/glstuff/glImmediateModeSender_src.cxx
  78. 1 1
      panda/src/glstuff/glIndexBufferContext_src.cxx
  79. 1 1
      panda/src/glstuff/glOcclusionQueryContext_src.cxx
  80. 4 9
      panda/src/glstuff/glShaderContext_src.I
  81. 444 485
      panda/src/glstuff/glShaderContext_src.cxx
  82. 31 43
      panda/src/glstuff/glShaderContext_src.h
  83. 11 3
      panda/src/glstuff/glTextureContext_src.I
  84. 131 4
      panda/src/glstuff/glTextureContext_src.cxx
  85. 32 4
      panda/src/glstuff/glTextureContext_src.h
  86. 1 1
      panda/src/glstuff/glVertexBufferContext_src.cxx
  87. 104 33
      panda/src/glstuff/glmisc_src.cxx
  88. 30 22
      panda/src/glstuff/glmisc_src.h
  89. 1 2
      panda/src/glstuff/glstuff_src.cxx
  90. 1 2
      panda/src/glstuff/glstuff_src.h
  91. 109 0
      panda/src/glstuff/panda_glext.h
  92. 21 14
      panda/src/glxdisplay/glxGraphicsPipe.cxx
  93. 224 184
      panda/src/glxdisplay/glxGraphicsStateGuardian.cxx
  94. 4 4
      panda/src/glxdisplay/glxGraphicsStateGuardian.h
  95. 765 512
      panda/src/glxdisplay/panda_glxext.h
  96. 2 4
      panda/src/glxdisplay/posixGraphicsStateGuardian.cxx
  97. 1 1
      panda/src/glxdisplay/posixGraphicsStateGuardian.h
  98. 7 0
      panda/src/gobj/config_gobj.cxx
  99. 2 2
      panda/src/gobj/config_gobj.h
  100. 13 0
      panda/src/gobj/geom.I

+ 3 - 2
direct/src/showbase/extend_frozen.c

@@ -1,3 +1,4 @@
+#define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
 #ifdef _WIN32
@@ -105,7 +106,7 @@ py_extend_frozen_modules(PyObject *self, PyObject *args) {
     PyObject *tuple;
     const char *name;
     const char *code;
-    int size;
+    Py_ssize_t size;
 
     tuple = PySequence_GetItem(list, i);
     if (!PyArg_ParseTuple(tuple, "ss#", &name, &code, &size)) {
@@ -178,7 +179,7 @@ py_get_frozen_module_code(PyObject *self, PyObject *args) {
     if (strcmp(PyImport_FrozenModules[i].name, name) == 0) {
       int is_package = (PyImport_FrozenModules[i].size < 0);
       return Py_BuildValue("(s#i)", PyImport_FrozenModules[i].code,
-                           abs(PyImport_FrozenModules[i].size),
+                           (Py_ssize_t) abs(PyImport_FrozenModules[i].size),
                            is_package);
     }
     ++i;

+ 0 - 34
dtool/Config.pp

@@ -653,40 +653,6 @@
 // space (instead of a dot).  Thus, "1 1" means OpenGL version 1.1.
 #define MIN_GL_VERSION 1 1
 
-// Is Mesa installed separately from OpenGL?  Mesa is an open-source
-// software-only OpenGL renderer.  Panda can link with it
-// independently from OpenGL (and if Mesa is built statically, and/or
-// with -DUSE_MGL_NAMESPACE declared to rename gl* to mgl*, it can
-// switch between the system OpenGL implementation and the Mesa
-// implementation at runtime).
-
-// Also, Mesa includes some core libraries (in libOSMesa.so) that
-// allow totally headless rendering, handy if you want to run a
-// renderer as a batch service, and you don't want to insist that a
-// user be logged on to the desktop or otherwise deal with X11 or
-// Windows.
-
-// If you define HAVE_MESA here, and the appropriate paths to headers
-// and libraries, then Panda will build libmesadisplay, which can be
-// used in lieu of libpandagl or libpandadx to do rendering.  However,
-// for most applications, you don't need to do this, since (a) if you
-// have hardware rendering capability, you probably don't want to use
-// Mesa, since it's software-only, and (b) if you don't have hardware
-// rendering, you can install Mesa as the system's OpenGL
-// implementation, so you can just use the normal libpandagl.  You
-// only need to define HAVE_MESA if you want to run totally headless,
-// or if you want to be able to easily switch between Mesa and the
-// system OpenGL implementation at runtime.  If you compiled Mesa with
-// USE_MGL_NAMESPACE defined, define MESA_MGL here.
-#define MESA_IPATH
-#define MESA_LPATH
-#define MESA_LIBS
-#define MESA_MGL
-#defer HAVE_MESA $[libtest $[MESA_LPATH],$[MESA_LIBS]]
-
-// Similar to MIN_GL_VERSION, above.
-#define MIN_MESA_VERSION 1 1
-
 // Do you want to build tinydisplay, a light and fast software
 // renderer built into Panda, based on TinyGL?  This isn't as
 // full-featured as Mesa, but it is many times faster, and in fact

+ 0 - 13
dtool/LocalSetup.pp

@@ -176,11 +176,6 @@
 #else
 #print - Did not find X11
 #endif
-#if $[HAVE_MESA]
-#print + Mesa
-#else
-#print - Did not find Mesa
-#endif
 #if $[HAVE_OPENCV]
 #print + OpenCV
 #else
@@ -437,14 +432,6 @@ $[cdefine HAVE_ODE]
 /* Define if we have AWESOMIUM installed and want to build for AWESOMIUM.  */
 $[cdefine HAVE_AWESOMIUM]
 
-/* Define if we have Mesa installed and want to build mesadisplay.  */
-$[cdefine HAVE_MESA]
-$[cdefine MESA_MGL]
-#if HAVE_MESA
-# define MIN_MESA_VERSION_MAJOR $[word 1,$[MIN_MESA_VERSION]]
-# define MIN_MESA_VERSION_MINOR $[word 2,$[MIN_MESA_VERSION]]
-#endif
-
 /* Define if we have GLX installed and want to build for GLX.  */
 $[cdefine HAVE_GLX]
 

+ 0 - 6
dtool/Package.pp

@@ -236,12 +236,6 @@
 #set GLES2_LIBS $[GLES2_LIBS]
 #set HAVE_GLES2 $[HAVE_GLES2]
 
-#set MESA_IPATH $[unixfilename $[MESA_IPATH]]
-#set MESA_LPATH $[unixfilename $[MESA_LPATH]]
-#set MESA_LIBS $[MESA_LIBS]
-#set MESA_MGL $[MESA_MGL]
-#set HAVE_MESA $[HAVE_MESA]
-
 #set GLX_IPATH $[unixfilename $[GLX_IPATH]]
 #set GLX_LPATH $[unixfilename $[GLX_LPATH]]
 #set HAVE_GLX $[HAVE_GLX]

+ 0 - 7
dtool/pptempl/Global.pp

@@ -185,13 +185,6 @@
   #define xcursor_libs $[XCURSOR_LIBS]
 #endif
 
-#if $[HAVE_MESA]
-  #define mesa_ipath $[wildcard $[MESA_IPATH]]
-  #define mesa_lpath $[wildcard $[MESA_LPATH]]
-  #define mesa_cflags $[MESA_CFLAGS]
-  #define mesa_libs $[MESA_LIBS]
-#endif
-
 #if $[HAVE_GLX]
   #define glx_ipath $[wildcard $[GLX_IPATH]]
   #define glx_lpath $[wildcard $[GLX_LPATH]]

+ 10 - 1
dtool/src/dtoolbase/atomicAdjust.h

@@ -23,7 +23,7 @@
 #include "atomicAdjustDummyImpl.h"
 typedef AtomicAdjustDummyImpl AtomicAdjust;
 
-#elif  defined(__i386__) || defined(_M_IX86)
+#elif defined(__i386__) || defined(_M_IX86)
 // 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
 // any OS-provided calls.
@@ -39,6 +39,15 @@ typedef AtomicAdjustI386Impl AtomicAdjust;
 #define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
 #define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
 
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
+// GCC 4.7 and above has built-in __atomic functions for atomic operations.
+
+#include "atomicAdjustGccImpl.h"
+typedef AtomicAdjustGccImpl AtomicAdjust;
+
+#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
+#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
+
 #elif defined(THREAD_WIN32_IMPL)
 
 #include "atomicAdjustWin32Impl.h"

+ 148 - 0
dtool/src/dtoolbase/atomicAdjustGccImpl.I

@@ -0,0 +1,148 @@
+// Filename: atomicAdjustGccImpl.I
+// Created by:  rdb (04Jul14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustGccImpl::inc
+//       Access: Public, Static
+//  Description: Atomically increments the indicated variable.
+////////////////////////////////////////////////////////////////////
+INLINE void AtomicAdjustGccImpl::
+inc(TVOLATILE AtomicAdjustGccImpl::Integer &var) {
+  __atomic_fetch_add(&var, 1, __ATOMIC_SEQ_CST);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustGccImpl::dec
+//       Access: Public, Static
+//  Description: Atomically decrements the indicated variable and
+//               returns true if the new value is nonzero, false if it
+//               is zero.
+////////////////////////////////////////////////////////////////////
+INLINE bool AtomicAdjustGccImpl::
+dec(TVOLATILE AtomicAdjustGccImpl::Integer &var) {
+  return (__atomic_sub_fetch(&var, 1, __ATOMIC_SEQ_CST) != 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustGccImpl::add
+//       Access: Public, Static
+//  Description: Atomically computes var += delta.  It is legal for
+//               delta to be negative.
+////////////////////////////////////////////////////////////////////
+INLINE void AtomicAdjustGccImpl::
+add(TVOLATILE AtomicAdjustGccImpl::Integer &var,
+    AtomicAdjustGccImpl::Integer delta) {
+  __atomic_fetch_add(&var, delta, __ATOMIC_SEQ_CST);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustGccImpl::set
+//       Access: Public, Static
+//  Description: Atomically changes the indicated variable and
+//               returns the original value.
+////////////////////////////////////////////////////////////////////
+INLINE AtomicAdjustGccImpl::Integer AtomicAdjustGccImpl::
+set(TVOLATILE AtomicAdjustGccImpl::Integer &var,
+    AtomicAdjustGccImpl::Integer new_value) {
+
+  return __atomic_exchange_n(&var, new_value, __ATOMIC_SEQ_CST);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustGccImpl::get
+//       Access: Public, Static
+//  Description: Atomically retrieves the snapshot value of the
+//               indicated variable.  This is the only guaranteed safe
+//               way to retrieve the value that other threads might be
+//               asynchronously setting, incrementing, or decrementing
+//               (via other AtomicAjust methods).
+////////////////////////////////////////////////////////////////////
+INLINE AtomicAdjustGccImpl::Integer AtomicAdjustGccImpl::
+get(const TVOLATILE AtomicAdjustGccImpl::Integer &var) {
+  return __atomic_load_n(&var, __ATOMIC_SEQ_CST);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustGccImpl::set_ptr
+//       Access: Public, Static
+//  Description: Atomically changes the indicated variable and
+//               returns the original value.
+////////////////////////////////////////////////////////////////////
+INLINE AtomicAdjustGccImpl::Pointer AtomicAdjustGccImpl::
+set_ptr(TVOLATILE AtomicAdjustGccImpl::Pointer &var,
+        AtomicAdjustGccImpl::Pointer new_value) {
+
+  return __atomic_exchange_n(&var, new_value, __ATOMIC_SEQ_CST);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustGccImpl::get_ptr
+//       Access: Public, Static
+//  Description: Atomically retrieves the snapshot value of the
+//               indicated variable.  This is the only guaranteed safe
+//               way to retrieve the value that other threads might be
+//               asynchronously setting, incrementing, or decrementing
+//               (via other AtomicAjust methods).
+////////////////////////////////////////////////////////////////////
+INLINE AtomicAdjustGccImpl::Pointer AtomicAdjustGccImpl::
+get_ptr(const TVOLATILE AtomicAdjustGccImpl::Pointer &var) {
+  return __atomic_load_n(&var, __ATOMIC_SEQ_CST);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustGccImpl::compare_and_exchange
+//       Access: Public, Static
+//  Description: Atomic compare and exchange.
+//
+//               If mem is equal to old_value, store new_value in mem.
+//               In either case, return the original value of mem.
+//               The caller can test for success by comparing
+//               return_value == old_value.
+//
+//               The atomic function expressed in pseudo-code:
+//
+//                 orig_value = mem;
+//                 if (mem == old_value) {
+//                   mem = new_value;
+//                 }
+//                 return orig_value;
+//
+////////////////////////////////////////////////////////////////////
+INLINE AtomicAdjustGccImpl::Integer AtomicAdjustGccImpl::
+compare_and_exchange(TVOLATILE AtomicAdjustGccImpl::Integer &mem,
+                     AtomicAdjustGccImpl::Integer old_value,
+                     AtomicAdjustGccImpl::Integer new_value) {
+
+  __atomic_compare_exchange_n(&mem, &old_value, new_value, false,
+                              __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+  return old_value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustGccImpl::compare_and_exchange_ptr
+//       Access: Public, Static
+//  Description: Atomic compare and exchange.
+//
+//               As above, but works on pointers instead of integers.
+////////////////////////////////////////////////////////////////////
+INLINE AtomicAdjustGccImpl::Pointer AtomicAdjustGccImpl::
+compare_and_exchange_ptr(TVOLATILE AtomicAdjustGccImpl::Pointer &mem,
+                         AtomicAdjustGccImpl::Pointer old_value,
+                         AtomicAdjustGccImpl::Pointer new_value) {
+
+  __atomic_compare_exchange_n(&mem, &old_value, new_value, false,
+                              __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+  return old_value;
+}

+ 60 - 0
dtool/src/dtoolbase/atomicAdjustGccImpl.h

@@ -0,0 +1,60 @@
+// Filename: atomicAdjustGccImpl.h
+// Created by:  rdb (04Jul14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 ATOMICADJUSTGCCIMPL_H
+#define ATOMICADJUSTGCCIMPL_H
+
+#include "dtoolbase.h"
+#include "selectThreadImpl.h"
+
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
+
+////////////////////////////////////////////////////////////////////
+//       Class : AtomicAdjustGccImpl
+// Description : Uses GCC built-ins to implement atomic adjustments.
+////////////////////////////////////////////////////////////////////
+class EXPCL_DTOOL AtomicAdjustGccImpl {
+public:
+#if __GCC_ATOMIC_LONG_LOCK_FREE > __GCC_ATOMIC_INT_LOCK_FREE
+  // If the long can be more lock-free than int, use it instead.
+  typedef __attribute__ ((aligned (__SIZEOF_LONG__))) long Integer;
+#else
+  typedef __attribute__ ((aligned (__SIZEOF_INT__))) int Integer;
+#endif
+  typedef void *UnalignedPointer;
+  typedef __attribute__ ((aligned (__SIZEOF_POINTER__))) UnalignedPointer Pointer;
+
+  INLINE static void inc(TVOLATILE Integer &var);
+  INLINE static bool dec(TVOLATILE Integer &var);
+  INLINE static void add(TVOLATILE Integer &var, Integer delta);
+  INLINE static Integer set(TVOLATILE Integer &var, Integer new_value);
+  INLINE static Integer get(const TVOLATILE Integer &var);
+
+  INLINE static Pointer set_ptr(TVOLATILE Pointer &var, Pointer new_value);
+  INLINE static Pointer get_ptr(const TVOLATILE Pointer &var);
+
+  INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem,
+                                             Integer old_value,
+                                             Integer new_value);
+
+  INLINE static Pointer compare_and_exchange_ptr(TVOLATILE Pointer &mem,
+                                                 Pointer old_value,
+                                                 Pointer new_value);
+};
+
+#include "atomicAdjustGccImpl.I"
+
+#endif  // HAVE_POSIX_THREADS
+
+#endif

+ 23 - 1
dtool/src/dtoolbase/cmath.I

@@ -336,6 +336,28 @@ cpow(double x, double y) {
   return pow(x, y);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: cpow
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE int
+cpow(int x, int y) {
+  int result = 1;
+
+  if (y >= 0) {
+    for(; y > 0; --y) {
+      result *= x;
+    }
+    return result;
+
+  } else {
+    for(; y < 0; ++y) {
+      result *= x;
+    }
+    return 1 / result;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: cnan
 //  Description: 
@@ -343,7 +365,7 @@ cpow(double x, double y) {
 INLINE bool
 cnan(double v) {
 #ifndef _WIN32
-  return (isnan(v) != 0);
+  return (std::isnan(v) != 0);
 #else
   return (_isnan(v) != 0);
 #endif

+ 3 - 1
dtool/src/dtoolbase/cmath.h

@@ -23,7 +23,7 @@
 
 #include "dtoolbase.h"
 
-#include <math.h>
+#include <cmath>
 
 // Windows defines isnan() in a different place and with a different
 // name than everyone else.  Sheesh.
@@ -62,6 +62,8 @@ INLINE double cacos(double v);
 INLINE double cmod(double x, double y);
 INLINE double cpow(double x, double y);
 
+INLINE int cpow(int x, int y);
+
 // Returns true if the number is NaN, false if it's a genuine number
 // or infinity.
 INLINE bool cnan(double v);

+ 11 - 0
dtool/src/dtoolbase/dtoolbase_cc.h

@@ -33,6 +33,7 @@ using namespace std;
 
 #define INLINE inline
 #define TYPENAME typename
+#define CONSTEXPR
 
 #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname)
 
@@ -119,6 +120,16 @@ typedef ios::seekdir ios_seekdir;
 #define INLINE inline
 #endif
 
+#if defined(__has_extension) // Clang magic.
+#if __has_extension(cxx_constexpr)
+#define CONSTEXPR constexpr
+#endif
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && (__cplusplus >= 201103L)
+#define CONSTEXPR constexpr
+#else
+#define CONSTEXPR INLINE
+#endif
+
 #if defined(WIN32_VC) && !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES)
 // This macro must be used to export an instantiated template class
 // from a DLL.  If the template class name itself contains commas, it

+ 8 - 1
dtool/src/dtoolbase/nearly_zero.h

@@ -35,6 +35,13 @@ get_nearly_zero_value(float) {
   return 1.0e-6f;
 }
 
+INLINE int
+get_nearly_zero_value(int) {
+  // This is a bit silly, but we should nevertheless define it in
+  // case it is called for an integer type.
+  return 0;
+}
+
 
 // IS_THRESHOLD_ZERO(value, threshold) returns true if the value is
 // within threshold of zero.
@@ -73,7 +80,7 @@ get_nearly_zero_value(float) {
 // MAYBE_ZERO(value) returns 0 if the value is nearly zero, and the
 // value itself otherwise.
 #define MAYBE_ZERO(value) \
-  (IS_NEARLY_ZERO(value) ? 0.0 : (value))
+  (IS_NEARLY_ZERO(value) ? 0 : (value))
 
 
 #endif

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

@@ -26,6 +26,7 @@ TypeHandle bool_type_handle;
 TypeHandle double_type_handle;
 TypeHandle float_type_handle;
 TypeHandle string_type_handle;
+TypeHandle wstring_type_handle;
 
 TypeHandle long_p_type_handle;
 TypeHandle int_p_type_handle;
@@ -58,6 +59,7 @@ void init_system_type_handles() {
     register_type(double_type_handle, "double");
     register_type(float_type_handle, "float");
     register_type(string_type_handle, "string");
+    register_type(wstring_type_handle, "wstring");
 
     register_type(int_p_type_handle, "int*");
     register_type(short_p_type_handle, "short*");
@@ -75,5 +77,3 @@ void init_system_type_handles() {
     register_type(pset_type_handle, "pset");
   }
 }
-
-

+ 6 - 0
dtool/src/dtoolbase/register_type.h

@@ -92,6 +92,7 @@ extern TypeHandle EXPCL_DTOOL bool_type_handle;
 extern TypeHandle EXPCL_DTOOL double_type_handle;
 extern TypeHandle EXPCL_DTOOL float_type_handle;
 extern TypeHandle EXPCL_DTOOL string_type_handle;
+extern TypeHandle EXPCL_DTOOL wstring_type_handle;
 
 extern TypeHandle long_p_type_handle;
 extern TypeHandle int_p_type_handle;
@@ -175,6 +176,11 @@ INLINE TypeHandle _get_type_handle(const string *) {
   return string_type_handle;
 }
 
+template<>
+INLINE TypeHandle _get_type_handle(const wstring *) {
+  return wstring_type_handle;
+}
+
 template<>
 INLINE TypeHandle _get_type_handle(const long * const *) {
   return long_p_type_handle;

+ 4 - 0
dtool/src/dtoolbase/typeHandle.cxx

@@ -16,6 +16,10 @@
 #include "typeRegistryNode.h"
 #include "atomicAdjust.h"
 
+#ifdef HAVE_PYTHON
+#include "Python.h"
+#endif
+
 // This is initialized to zero by static initialization.
 TypeHandle TypeHandle::_none;
 

+ 7 - 5
dtool/src/dtoolbase/typeHandle.h

@@ -66,7 +66,10 @@
 class TypedObject;
 
 #ifdef HAVE_PYTHON
-#include "Python.h"
+#ifndef PyObject_HEAD
+struct _object;
+typedef _object PyObject;
+#endif
 #endif
 
 ////////////////////////////////////////////////////////////////////
@@ -127,15 +130,15 @@ PUBLISHED:
 
   INLINE TypeHandle get_parent_towards(TypeHandle ancestor,
                                        TypedObject *object = (TypedObject *)NULL) const;
-  
-  INLINE  int get_best_parent_from_Set(const std::set< int > &legal_vals) const;
+
+  INLINE int get_best_parent_from_Set(const std::set< int > &legal_vals) const;
 
 #ifdef DO_MEMORY_USAGE
   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);
 #else
-  INLINE int get_memory_usage(MemoryClass) const { return 0; }
+  CONSTEXPR int get_memory_usage(MemoryClass) const { return 0; }
   INLINE void inc_memory_usage(MemoryClass, int) { }
   INLINE void dec_memory_usage(MemoryClass, int) { }
 #endif  // DO_MEMORY_USAGE
@@ -170,4 +173,3 @@ EXPCL_DTOOL ostream &operator << (ostream &out, TypeHandle::MemoryClass mem_clas
 #include "typeHandle.I"
 
 #endif
-

+ 2 - 0
dtool/src/dtoolbase/typeRegistry.h

@@ -58,9 +58,11 @@ PUBLISHED:
 
   int get_num_typehandles();
   TypeHandle get_typehandle(int n);
+  MAKE_SEQ(get_typehandles, get_num_typehandles, get_typehandle);
 
   int get_num_root_classes();
   TypeHandle get_root_class(int n);
+  MAKE_SEQ(get_root_classes, get_num_root_classes, get_root_class);
 
   int get_num_parent_classes(TypeHandle child,
                              TypedObject *child_object) const;

+ 59 - 43
dtool/src/interrogate/functionRemap.cxx

@@ -50,6 +50,7 @@ FunctionRemap(const InterrogateType &itype, const InterrogateFunction &ifunc,
   _num_default_parameters = num_default_parameters;
   _type = T_normal;
   _flags = 0;
+  _args_type = 0;
   _wrapper_index = 0;
 
   _return_value_needs_management = false;
@@ -303,26 +304,6 @@ make_wrapper_entry(FunctionIndex function_index) {
     assert(!iwrapper._parameters.empty());
     iwrapper._parameters.front()._parameter_flags |=
       InterrogateFunctionWrapper::PF_is_this;
-
-    if (_parameters.size() >= 2 && _parameters[1]._name == "self" &&
-        TypeManager::is_pointer_to_PyObject(_parameters[1]._remap->get_orig_type())) {
-      // Here's a special case.  If the first parameter of a nonstatic
-      // method is a PyObject * called "self", then we will
-      // automatically fill it in from the this pointer, and remove it
-      // from the generated parameter list.
-      _parameters.erase(_parameters.begin() + 1);
-      _flags |= F_explicit_self;
-    }
-
-  } else if (_type == T_constructor) {
-    // We also allow "self" to be passed in to a constructor, even
-    // though the constructor doesn't normally accept a this pointer.
-    // But this makes sense to Python programmers.
-    if (_parameters.size() >= 1 && _parameters[0]._name == "self" &&
-        TypeManager::is_pointer_to_PyObject(_parameters[0]._remap->get_orig_type())) {
-      _parameters.erase(_parameters.begin() + 0);
-      _flags |= F_explicit_self;
-    }
   }
 
   if (!_void_return) {
@@ -650,12 +631,32 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
   }
 
   // Check for a special meaning by name and signature.
-  if (_type == T_normal) {
-    int first_param = 0;
-    if (_has_this) {
-      first_param = 1;
+  int first_param = 0;
+  if (_has_this) {
+    first_param = 1;
+  }
+
+  if (_has_this || _type == T_constructor) {
+    if (_parameters.size() > first_param && _parameters[first_param]._name == "self" &&
+        TypeManager::is_pointer_to_PyObject(_parameters[first_param]._remap->get_orig_type())) {
+      // Here's a special case.  If the first parameter of a nonstatic
+      // method is a PyObject * called "self", then we will
+      // automatically fill it in from the this pointer, and remove it
+      // from the generated parameter list.
+      _parameters.erase(_parameters.begin() + first_param);
+      _flags |= F_explicit_self;
     }
+  }
 
+  if (_parameters.size() == first_param) {
+    _args_type = InterfaceMaker::AT_no_args;
+  } else if (_parameters.size() == first_param + 1) {
+    _args_type = InterfaceMaker::AT_single_arg;
+  } else {
+    _args_type = InterfaceMaker::AT_varargs;
+  }
+
+  if (_type == T_normal) {
     if (fname == "operator []" || fname == "__getitem__") {
       _flags |= F_getitem;
       if (_has_this && _parameters.size() == 2) {
@@ -671,6 +672,7 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
         if (TypeManager::is_integer(_parameters[1]._remap->get_new_type())) {
           // Its first parameter is an int parameter, presumably an index.
           _flags |= F_setitem_int;
+          _args_type = InterfaceMaker::AT_varargs;
         }
       }
 
@@ -681,55 +683,69 @@ setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_mak
         _flags |= F_size;
       }
 
-    } else if (fname == "make_copy" ) {
+    } else if (fname == "make_copy") {
       if (_has_this && _parameters.size() == 1 &&
           TypeManager::is_pointer(_return_type->get_new_type())) {
         // It receives no parameters, and returns a pointer.
         _flags |= F_make_copy;
       }
 
-    } else if (fname == "__iter__" ) {
+    } else if (fname == "__iter__") {
       if (_has_this && _parameters.size() == 1 &&
           TypeManager::is_pointer(_return_type->get_new_type())) {
         // It receives no parameters, and returns a pointer.
         _flags |= F_iter;
       }
 
-    } else if (fname == "__getbuffer__" ) {
-      if (_has_this && _parameters.size() == 4 &&
+    } else if (fname == "__getbuffer__") {
+      if (_has_this && _parameters.size() == 3 &&
           TypeManager::is_integer(_return_type->get_new_type()) &&
-          TypeManager::is_pointer_to_PyObject(_parameters[1]._remap->get_orig_type()) &&
-          TypeManager::is_pointer_to_Py_buffer(_parameters[2]._remap->get_orig_type()) &&
-          TypeManager::is_integer(_parameters[3]._remap->get_orig_type())) {
+          TypeManager::is_pointer_to_Py_buffer(_parameters[1]._remap->get_orig_type()) &&
+          TypeManager::is_integer(_parameters[2]._remap->get_orig_type())) {
 
         _flags |= F_getbuffer;
       }
 
-    } else if (fname == "__releasebuffer__" ) {
-      if (_has_this && _parameters.size() == 3 &&
-          TypeManager::is_pointer_to_PyObject(_parameters[1]._remap->get_orig_type()) &&
-          TypeManager::is_pointer_to_Py_buffer(_parameters[2]._remap->get_orig_type())) {
+    } else if (fname == "__releasebuffer__") {
+      if (_has_this && _parameters.size() == 2 &&
+          TypeManager::is_pointer_to_Py_buffer(_parameters[1]._remap->get_orig_type())) {
 
         _flags |= F_releasebuffer;
       }
 
-    } else if (fname == "compare_to" ) {
+    } else if (fname == "compare_to") {
       if (_has_this && _parameters.size() == 2 &&
           TypeManager::is_integer(_return_type->get_new_type())) {
         // It receives one parameter, and returns an integer.
         _flags |= F_compare_to;
       }
+
+    } else if (fname == "operator ()" || fname == "__call__") {
+      // Call operators always take keyword arguments.
+      _args_type = InterfaceMaker::AT_keyword_args;
+
+    } else if (fname == "__setattr__" || fname == "__getattr__") {
+      // Just to prevent these from getting keyword arguments.
+
+    } else {
+      if (_args_type == InterfaceMaker::AT_varargs) {
+        // Every other method can take keyword arguments, if they
+        // take more than one argument.
+        _args_type = InterfaceMaker::AT_keyword_args;
+      }
     }
 
   } else if (_type == T_constructor) {
-    if (!_has_this && _parameters.size() == 1) {
-      if (TypeManager::unwrap(_parameters[0]._remap->get_orig_type()) ==
-          TypeManager::unwrap(_return_type->get_orig_type())) {
-        // If this is the only parameter, and it's the same as the
-        // "this" type, this is a copy constructor.
-        _flags |= F_copy_constructor;
-      }
+    if (!_has_this && _parameters.size() == 1 &&
+        TypeManager::unwrap(_parameters[0]._remap->get_orig_type()) ==
+        TypeManager::unwrap(_return_type->get_orig_type())) {
+      // If this is the only parameter, and it's the same as the
+      // "this" type, this is a copy constructor.
+      _flags |= F_copy_constructor;
+
     }
+    // Constructors always take varargs and keyword args.
+    _args_type = InterfaceMaker::AT_keyword_args;
   }
 
   return true;

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

@@ -107,6 +107,7 @@ public:
   int _num_default_parameters;
   Type _type;
   int _flags;
+  int _args_type;
   string _expression;
   string _function_signature;
   string _hash;

+ 8 - 6
dtool/src/interrogate/interfaceMaker.cxx

@@ -57,6 +57,7 @@ Function(const string &name,
 {
   _has_this = false;
   _flags = 0;
+  _args_type = AT_unknown;
 }
  
 ////////////////////////////////////////////////////////////////////
@@ -632,13 +633,13 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
       CPPInstance *cppfunc = (*ii).second;
       CPPFunctionType *ftype = cppfunc->_type->as_function_type();
       int max_default_parameters = 0;
-      
+
       if (separate_overloading()) {
         // Count up the number of default parameters this function might
         // take.
         CPPParameterList *parameters = ftype->_parameters;
         CPPParameterList::Parameters::reverse_iterator pi;
-        for (pi = parameters->_parameters.rbegin(); 
+        for (pi = parameters->_parameters.rbegin();
              pi != parameters->_parameters.rend();
              ++pi) {
           CPPInstance *param = (*pi);
@@ -651,7 +652,7 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
           }
         }
       }
-      
+
       // Now make a different wrapper for each combination of default
       // parameters.  This will happen only if separate_overloading(),
       // tested above, returned true; otherwise, max_default_parameters
@@ -663,7 +664,7 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
           make_function_remap(itype, ifunc, cppfunc, num_default_parameters);
         if (remap != (FunctionRemap *)NULL) {
           func->_remaps.push_back(remap);
-          
+
           // If *any* of the variants of this function has a "this"
           // pointer, the entire set of functions is deemed to have a
           // "this" pointer.
@@ -672,9 +673,10 @@ record_function(const InterrogateType &itype, FunctionIndex func_index) {
           }
 
           func->_flags |= remap->_flags;
-          
+          func->_args_type = (ArgsType)((int)func->_args_type | (int)remap->_args_type);
+
           // Make a wrapper for the function.
-          FunctionWrapperIndex wrapper_index = 
+          FunctionWrapperIndex wrapper_index =
             remap->make_wrapper_entry(func_index);
           if (wrapper_index != 0) {
             InterrogateFunction &mod_ifunc = idb->update_function(func_index);

+ 23 - 0
dtool/src/interrogate/interfaceMaker.h

@@ -71,6 +71,28 @@ public:
   static ostream &indent(ostream &out, int indent_level);
 
 public:
+  // This contains information about the number
+  // of arguments that the wrapping function should take.
+  enum ArgsType {
+    // This is deliberately engineered such that these
+    // values can be OR'ed together to produce another
+    // valid enum value.
+    AT_unknown      = 0x00,
+
+    // The method or function takes no arguments.
+    AT_no_args      = 0x01,
+
+    // There is only a single argument.
+    AT_single_arg   = 0x02,
+
+    // The method takes a variable number of arguments.
+    AT_varargs      = 0x03,
+
+    // The method may take keyword arguments, if appropriate
+    // in the scripting language.  Implies AT_varargs.
+    AT_keyword_args = 0x07,
+  };
+
   class Function {
   public:
     Function(const string &name,
@@ -85,6 +107,7 @@ public:
     Remaps _remaps;
     bool _has_this;
     int _flags;
+    ArgsType _args_type;
   };
   typedef vector<Function *> Functions;
   Functions _functions;

+ 2 - 7
dtool/src/interrogate/interfaceMakerPython.cxx

@@ -36,17 +36,12 @@ InterfaceMakerPython(InterrogateModuleDef *def) :
 void InterfaceMakerPython::
 write_includes(ostream &out) {
   InterfaceMaker::write_includes(out);
-  out << "#undef HAVE_LONG_LONG\n"
-      << "#undef _POSIX_C_SOURCE\n\n"
+  out << "#undef _POSIX_C_SOURCE\n\n"
       << "#if PYTHON_FRAMEWORK\n"
       << "  #include \"Python/Python.h\"\n"
       << "#else\n"
       << "  #include \"Python.h\"\n"
-      << "#endif\n"
-      << "#ifdef HAVE_LONG_LONG\n"
-      << "#undef HAVE_LONG_LONG\n"
-      << "#endif \n";
-
+      << "#endif\n";
 }
 
 ////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large
+ 398 - 214
dtool/src/interrogate/interfaceMakerPythonNative.cxx


+ 24 - 21
dtool/src/interrogate/interfaceMakerPythonNative.h

@@ -27,8 +27,7 @@ class FunctionRemap;
 // Description : An InterfaceMaker for generating complex Python
 //               function wrappers around C++ code.
 ////////////////////////////////////////////////////////////////////
-class InterfaceMakerPythonNative : public InterfaceMakerPython 
-{
+class InterfaceMakerPythonNative : public InterfaceMakerPython {
 public:
   InterfaceMakerPythonNative(InterrogateModuleDef *def);
   virtual ~InterfaceMakerPythonNative();
@@ -77,6 +76,8 @@ private:
     WT_getbuffer,
     WT_releasebuffer,
     WT_iter_next,
+    WT_one_or_two_params,
+    WT_ternary_operator,
   };
 
   class SlottedFunctionDef {
@@ -87,25 +88,28 @@ private:
   };
 
   static bool get_slotted_function_def(Object *obj, Function *func, SlottedFunctionDef &def);
-  
+
   void write_prototype_for_name(ostream &out, Function *func, const std::string &name);
   void write_prototype_for(ostream &out, Function *func);
-  void write_function_for_name(ostream &out, Object *obj, Function *func, const std::string &name, const std::string &PreProcess, const std::string &ClassName,
-                               bool coercion_allowed, bool &coercion_attempted);
-  void write_function_for_top(ostream &out, Object *obj, Function *func, const std::string &PreProcess);
-  void write_function_instance(ostream &out, Object *obj, Function *func,
-                               FunctionRemap *remap, string &expected_params, 
-                               int indent_level, bool errors_fatal, 
-                               ostream &forwarddecl, const std::string &functionnamestr,
-                               bool is_inplace, bool coercion_allowed,
-                               bool &coercion_attempted,
-                               const string &args_cleanup);
-  
+  void write_function_for_top(ostream &out, Object *obj, Function *func);
+  void write_function_for_name(ostream &out, Object *obj, Function *func,
+                               const std::string &name,
+                               bool coercion_allowed, bool &coercion_attempted,
+                               ArgsType args_type, bool return_int);
+
   void write_function_forset(ostream &out, Object *obj, Function *func,
                              std::set<FunctionRemap*> &remaps, string &expected_params,
-                             int indent_level, ostream &forwarddecl, bool inplace,
-                             bool coercion_allowed, bool &coercion_attempted, 
-                             const string &args_cleanup);
+                             int indent_level, bool inplace,
+                             bool coercion_allowed, bool &coercion_attempted,
+                             ArgsType args_type, bool return_int,
+                             const string &first_expr = string());
+
+  void write_function_instance(ostream &out, Object *obj, Function *func,
+                               FunctionRemap *remap, string &expected_params,
+                               int indent_level, bool is_inplace,
+                               bool coercion_allowed, bool &coercion_attempted,
+                               ArgsType args_type, bool return_int,
+                               const string &first_pexpr = string());
 
   void pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
                          const std::string &return_expr, bool in_place);
@@ -119,17 +123,16 @@ private:
   void write_class_prototypes(ostream &out) ;
   void write_class_declarations(ostream &out, ostream *out_h, Object *obj);
   void write_class_details(ostream &out, Object *obj);
-  
-  void do_assert_init(ostream &out, int &indent_level, bool constructor, const string &args_cleanup) const;
+
 public:
-  bool is_remap_legal(FunctionRemap &remap);
+  bool is_remap_legal(FunctionRemap *remap);
   bool is_function_legal( Function *func);
   bool is_cpp_type_legal(CPPType *ctype);
   bool isExportThisRun(CPPType *ctype);
   bool isExportThisRun(Function *func);
   bool isFunctionWithThis( Function *func);
   bool IsRunTimeTyped(const InterrogateType &itype);
-  
+
   // comunicates the cast capabilites among methods..
   struct CastDetails {
     CPPStructType   *_structType;

+ 49 - 36
dtool/src/interrogate/interrogateBuilder.cxx

@@ -1863,26 +1863,34 @@ get_type(CPPType *type, bool global) {
 
   // First, check to see if it's already there.
   string true_name = type->get_local_name(&parser);
-  TypesByName::const_iterator tni = _types_by_name.find(true_name);
-  if (tni != _types_by_name.end()) {
-    // It's already here, so update the global flag.
-    index = (*tni).second;
-    if (index == 0) {
-      // This is an invalid type; we don't know anything about it.
-      return 0;
-    }
 
-    InterrogateType &itype = InterrogateDatabase::get_ptr()->update_type(index);
-    if (global) {
-      itype._flags |= InterrogateType::F_global;
-    }
+  if (true_name.empty()) {
+    // Whoops, it's an anonymous type.  That's okay, because we'll
+    // usually only encounter them once anyway, so let's go ahead and
+    // define it without checking in _types_by_name.
 
-    if ((itype._flags & InterrogateType::F_fully_defined) != 0) {
-      return index;
-    }
+  } else {
+    TypesByName::const_iterator tni = _types_by_name.find(true_name);
+    if (tni != _types_by_name.end()) {
+      // It's already here, so update the global flag.
+      index = (*tni).second;
+      if (index == 0) {
+        // This is an invalid type; we don't know anything about it.
+        return 0;
+      }
+
+      InterrogateType &itype = InterrogateDatabase::get_ptr()->update_type(index);
+      if (global) {
+        itype._flags |= InterrogateType::F_global;
+      }
 
-    // But wait--it's not fully defined yet!  We'll go ahead and
-    // define it now.
+      if ((itype._flags & InterrogateType::F_fully_defined) != 0) {
+        return index;
+      }
+
+      // But wait--it's not fully defined yet!  We'll go ahead and
+      // define it now.
+    }
   }
 
   bool forced = in_forcetype(true_name);
@@ -1890,7 +1898,9 @@ get_type(CPPType *type, bool global) {
   if (index == 0) {
     // It isn't already there, so we have to define it.
     index = InterrogateDatabase::get_ptr()->get_next_index();
-    _types_by_name[true_name] = index;
+    if (!true_name.empty()) {
+      _types_by_name[true_name] = index;
+    }
 
     InterrogateType itype;
     if (global) {
@@ -1904,7 +1914,7 @@ get_type(CPPType *type, bool global) {
     InterrogateDatabase::get_ptr()->update_type(index);
 
   itype._name = get_preferred_name(type);
-  
+
   int num_alt_names = type->get_num_alt_names();
   if (num_alt_names != 0) {
     itype._alt_names.clear();
@@ -1954,23 +1964,19 @@ get_type(CPPType *type, bool global) {
     }
   }
 
-  if (forced || !in_ignoretype(true_name)) 
-  {
+  if (forced || !in_ignoretype(true_name)) {
     itype._flags |= InterrogateType::F_fully_defined;
 
-    if (type->as_simple_type() != (CPPSimpleType *)NULL) 
-    {
+    if (type->as_simple_type() != (CPPSimpleType *)NULL) {
       define_atomic_type(itype, type->as_simple_type());
 
-    } else if (type->as_pointer_type() != (CPPPointerType *)NULL)
-    {
+    } else if (type->as_pointer_type() != (CPPPointerType *)NULL) {
       define_wrapped_type(itype, type->as_pointer_type());
 
     } else if (type->as_const_type() != (CPPConstType *)NULL) {
       define_wrapped_type(itype, type->as_const_type());
 
-    } else if (type->as_struct_type() != (CPPStructType *)NULL) 
-    {
+    } else if (type->as_struct_type() != (CPPStructType *)NULL) {
       define_struct_type(itype, type->as_struct_type(), index, forced);
 
     } else if (type->as_enum_type() != (CPPEnumType *)NULL) {
@@ -1984,7 +1990,9 @@ get_type(CPPType *type, bool global) {
 
       // Remove the type from the database.
       InterrogateDatabase::get_ptr()->remove_type(index);
-      _types_by_name[true_name] = 0;
+      if (!true_name.empty()) {
+        _types_by_name[true_name] = 0;
+      }
       index = 0;
     }
   }
@@ -2229,6 +2237,7 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
   for (di = scope->_declarations.begin();
        di != scope->_declarations.end();
        ++di) {
+
     if ((*di)->get_subtype() == CPPDeclaration::ST_instance) {
       CPPInstance *inst = (*di)->as_instance();
       if (inst->_type->get_subtype() == CPPDeclaration::ST_function) {
@@ -2243,15 +2252,12 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
         }
       }
 
-    } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) 
-    {
+    } else if ((*di)->get_subtype() == CPPDeclaration::ST_type_declaration) {
       CPPType *type = (*di)->as_type_declaration()->_type;
 
-      if ((*di)->_vis <= min_vis || in_forcetype(type->get_local_name(&parser))) 
-      {
+      if ((*di)->_vis <= min_vis || in_forcetype(type->get_local_name(&parser))) {
         if (type->as_struct_type() != (CPPStructType *)NULL ||
-            type->as_enum_type() != (CPPEnumType *)NULL) 
-        {
+            type->as_enum_type() != (CPPEnumType *)NULL) {
           // Here's a nested class or enum definition.
           type->_vis = (*di)->_vis;
 
@@ -2259,13 +2265,20 @@ define_struct_type(InterrogateType &itype, CPPStructType *cpptype,
           assert(nested_type != (CPPExtensionType *)NULL);
 
           // Only try to export named types.
-          if (nested_type->_ident != (CPPIdentifier *)NULL) 
-          {
+          if (nested_type->_ident != (CPPIdentifier *)NULL) {
             TypeIndex nested_index = get_type(nested_type, false);
             itype._nested_types.push_back(nested_index);
           }
         }
       }
+    } else if ((*di)->get_subtype() == CPPDeclaration::ST_enum) {
+      CPPType *type = (*di)->as_enum_type();
+
+      // An anonymous enum type.
+      if ((*di)->_vis <= min_vis) {
+        TypeIndex nested_index = get_type(type, false);
+        itype._nested_types.push_back(nested_index);
+      }
     }
   }
 

+ 3 - 2
dtool/src/interrogate/typeManager.cxx

@@ -934,7 +934,7 @@ bool TypeManager::
 is_double(CPPType *type) {
   switch (type->get_subtype()) {
   case CPPDeclaration::ST_const:
-    return is_float(type->as_const_type()->_wrapped_around);
+    return is_double(type->as_const_type()->_wrapped_around);
 
   case CPPDeclaration::ST_simple:
     {
@@ -1199,7 +1199,8 @@ is_PyObject(CPPType *type) {
     return is_PyObject(type->as_const_type()->_wrapped_around);
 
   case CPPDeclaration::ST_extension:
-    return (type->get_local_name(&parser) == "PyObject");
+    return (type->get_local_name(&parser) == "PyObject" ||
+            type->get_local_name(&parser) == "_object");
 
   default:
     return false;

+ 1 - 1
dtool/src/interrogatedb/dtool_super_base.cxx

@@ -83,7 +83,7 @@ int Dtool_Init_DTOOL_SUPER_BASE(PyObject *self, PyObject *args, PyObject *kwds)
   return -1;
 }
 
-int Dtool_InitNoCoerce_DTOOL_SUPER_BASE(PyObject *self, PyObject *args, PyObject *kwds) {
+int Dtool_InitNoCoerce_DTOOL_SUPER_BASE(PyObject *self, PyObject *args) {
   PyErr_SetString(PyExc_TypeError, "cannot init super base");
   return -1;
 }

+ 21 - 5
dtool/src/interrogatedb/py_panda.cxx

@@ -79,9 +79,21 @@ attempt_coercion(PyObject *self, Dtool_PyTypedObject *classdef,
     if (classdef->_PyType.tp_new != NULL) {
       obj = classdef->_PyType.tp_new(&classdef->_PyType, self, NULL);
       assert(obj != NULL);
-      if (classdef->_Dtool_InitNoCoerce(obj, self, NULL) != 0) {
-        Py_DECREF(obj);
-        obj = NULL;
+
+      if (PyTuple_Check(self)) {
+        // A tuple was passed, which we assume are the constructor arguments.
+        if (classdef->_Dtool_InitNoCoerce(obj, self) != 0) {
+          Py_DECREF(obj);
+          obj = NULL;
+        }
+      } else {
+        // We need to pack the value into an args tuple.
+        PyObject *args = PyTuple_Pack(1, self);
+        if (classdef->_Dtool_InitNoCoerce(obj, args) != 0) {
+          Py_DECREF(obj);
+          obj = NULL;
+        }
+        Py_DECREF(args);
       }
     }
     if (obj == NULL) {
@@ -93,7 +105,11 @@ attempt_coercion(PyObject *self, Dtool_PyTypedObject *classdef,
       PyObject *make = PyObject_GetAttrString((PyObject *)classdef, "make");
       if (make != NULL) {
         PyErr_Clear();
-        obj = PyObject_Call(make, self, NULL);
+        if (PyTuple_Check(self)) {
+          obj = PyObject_CallObject(make, self);
+        } else {
+          obj = PyObject_CallFunctionObjArgs(make, self, NULL);
+        }
         Py_DECREF(make);
       }
     }
@@ -598,7 +614,7 @@ int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2) {
     PyErr_Clear();
   } else {
     PyObject *res = NULL;
-    PyObject *args = Py_BuildValue("(O)", v2);
+    PyObject *args = PyTuple_Pack(1, v2);
     if (args != NULL) {
       res = PyObject_Call(func, args, NULL);
       Py_DECREF(args);

+ 13 - 8
dtool/src/interrogatedb/py_panda.h

@@ -42,18 +42,23 @@
 
 #if defined(HAVE_PYTHON) && !defined(CPPPARSER)
 
-#ifdef HAVE_LONG_LONG
-#undef HAVE_LONG_LONG
-#endif 
 #ifdef _POSIX_C_SOURCE
 #undef _POSIX_C_SOURCE
 #endif
 
+#define PY_SSIZE_T_CLEAN 1
+
 #include "Python.h"
 #include "structmember.h"
-#ifdef HAVE_LONG_LONG
-#undef HAVE_LONG_LONG
-#endif 
+
+#ifndef HAVE_LONG_LONG
+#define PyLong_FromLongLong(x) PyLong_FromLong((long) (x))
+#define PyLong_FromUnsignedLongLong(x) PyLong_FromUnsignedLong((unsigned long) (x))
+#define PyLong_AsLongLong(x) PyLong_AsLong(x)
+#define PyLong_AsUnsignedLongLong(x) PyLong_AsUnsignedLong(x)
+#define PyLong_AsUnsignedLongLongMask(x) PyLong_AsUnsignedLongMask(x)
+#define PyLong_AsLongLongAndOverflow(x) PyLong_AsLongAndOverflow(x)
+#endif
 
 #if PY_VERSION_HEX < 0x02050000
 
@@ -139,7 +144,7 @@ typedef void * ( * ConvertFunctionType  )(PyObject *,Dtool_PyTypedObject * );
 typedef void * ( * ConvertFunctionType1  )(void *, Dtool_PyTypedObject *);
 typedef void   ( *FreeFunction  )(PyObject *);
 typedef void   ( *PyModuleClassInit)(PyObject *module);
-typedef int    ( *InitNoCoerce)(PyObject *self, PyObject *args, PyObject *kwds);
+typedef int    ( *InitNoCoerce)(PyObject *self, PyObject *args);
 
 //inline          Dtool_PyTypedObject *  Dtool_RuntimeTypeDtoolType(int type);
 inline void     Dtool_Deallocate_General(PyObject * self);
@@ -369,7 +374,7 @@ EXPCL_DTOOLCONFIG PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTyp
 extern EXPORT_THIS   Dtool_PyTypedObject Dtool_##CLASS_NAME;\
 extern struct        PyMethodDef Dtool_Methods_##CLASS_NAME[];\
 int         Dtool_Init_##CLASS_NAME(PyObject *self, PyObject *args, PyObject *kwds);\
-int         Dtool_InitNoCoerce_##CLASS_NAME(PyObject *self, PyObject *args, PyObject *kwds);\
+int         Dtool_InitNoCoerce_##CLASS_NAME(PyObject *self, PyObject *args);\
 PyObject *  Dtool_new_##CLASS_NAME(PyTypeObject *type, PyObject *args, PyObject *kwds);\
 void  *     Dtool_UpcastInterface_##CLASS_NAME(PyObject *self, Dtool_PyTypedObject *requested_type);\
 void  *     Dtool_DowncastInterface_##CLASS_NAME(void *self, Dtool_PyTypedObject *requested_type);\

+ 3 - 1
dtool/src/parser-inc/Python.h

@@ -20,7 +20,9 @@
 #ifndef PYTHON_H
 #define PYTHON_H
 
-class PyObject;
+struct _object;
+typedef _object PyObject;
+
 class PyThreadState;
 typedef int Py_ssize_t;
 struct Py_buffer;

+ 4 - 0
dtool/src/prc/configVariableCore.h

@@ -66,15 +66,19 @@ PUBLISHED:
   bool has_value() const;
   int get_num_declarations() const;
   const ConfigDeclaration *get_declaration(int n) const;
+  MAKE_SEQ(get_declarations, get_num_declarations, get_declaration);
 
   INLINE int get_num_references() const;
   INLINE const ConfigDeclaration *get_reference(int n) const;
+  MAKE_SEQ(get_references, get_num_references, get_reference);
 
   INLINE int get_num_trusted_references() const;
   INLINE const ConfigDeclaration *get_trusted_reference(int n) const;
+  MAKE_SEQ(get_trusted_references, get_num_trusted_references, get_trusted_reference);
 
   INLINE int get_num_unique_references() const;
   INLINE const ConfigDeclaration *get_unique_reference(int n) const;
+  MAKE_SEQ(get_unique_references, get_num_unique_references, get_unique_reference);
 
   void output(ostream &out) const;
   void write(ostream &out) const;

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

@@ -47,6 +47,7 @@ PUBLISHED:
 
   INLINE int get_num_variables() const;
   INLINE ConfigVariableCore *get_variable(int n) const;
+  MAKE_SEQ(get_variables, get_num_variables, get_variable);
   string get_variable_name(int n) const;
   bool is_variable_used(int n) const;
 

+ 2 - 2
dtool/src/prc/notifyCategory.I

@@ -106,7 +106,7 @@ is_debug() const {
 //               methods are redefined to be static to make it more
 //               obvious to the compiler.
 ////////////////////////////////////////////////////////////////////
-INLINE bool NotifyCategory::
+CONSTEXPR bool NotifyCategory::
 is_spam() {
   return false;
 }
@@ -119,7 +119,7 @@ is_spam() {
 //               methods are redefined to be static to make it more
 //               obvious to the compiler.
 ////////////////////////////////////////////////////////////////////
-INLINE bool NotifyCategory::
+CONSTEXPR bool NotifyCategory::
 is_debug() {
   return false;
 }

+ 2 - 2
dtool/src/prc/notifyCategory.h

@@ -56,8 +56,8 @@ PUBLISHED:
   INLINE bool is_spam() const;
   INLINE bool is_debug() const;
 #else
-  INLINE static bool is_spam();
-  INLINE static bool is_debug();
+  CONSTEXPR static bool is_spam();
+  CONSTEXPR static bool is_debug();
 #endif
   INLINE bool is_info() const;
   INLINE bool is_warning() const;

+ 12 - 4
dtool/src/prc/notifyCategoryProxy.I

@@ -80,30 +80,38 @@ is_on(NotifySeverity severity) {
 //       Access: Public
 //  Description:
 ////////////////////////////////////////////////////////////////////
+#ifdef NOTIFY_DEBUG
 template<class GetCategory>
 INLINE bool NotifyCategoryProxy<GetCategory>::
 is_spam() {
-#ifdef NOTIFY_DEBUG
   return get_unsafe_ptr()->is_spam();
+}
 #else
+template<class GetCategory>
+CONSTEXPR bool NotifyCategoryProxy<GetCategory>::
+is_spam() {
   return false;
-#endif
 }
+#endif
 
 ////////////////////////////////////////////////////////////////////
 //     Function: NotifyCategoryProxy::is_debug
 //       Access: Public
 //  Description:
 ////////////////////////////////////////////////////////////////////
+#ifdef NOTIFY_DEBUG
 template<class GetCategory>
 INLINE bool NotifyCategoryProxy<GetCategory>::
 is_debug() {
-#ifdef NOTIFY_DEBUG
   return get_unsafe_ptr()->is_debug();
+}
 #else
+template<class GetCategory>
+CONSTEXPR bool NotifyCategoryProxy<GetCategory>::
+is_debug() {
   return false;
-#endif
 }
+#endif
 
 ////////////////////////////////////////////////////////////////////
 //     Function: NotifyCategoryProxy::is_info

+ 2 - 2
dtool/src/prc/notifyCategoryProxy.h

@@ -85,8 +85,8 @@ public:
   INLINE bool is_spam();
   INLINE bool is_debug();
 #else
-  INLINE static bool is_spam();
-  INLINE static bool is_debug();
+  CONSTEXPR static bool is_spam();
+  CONSTEXPR static bool is_debug();
 #endif
   INLINE bool is_info();
   INLINE bool is_warning();

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

@@ -18,6 +18,7 @@ extern "C" {
   EXPCL_PYSTUB int PyArg_Parse(...);
   EXPCL_PYSTUB int PyArg_ParseTuple(...);
   EXPCL_PYSTUB int PyArg_ParseTupleAndKeywords(...);
+  EXPCL_PYSTUB int PyArg_UnpackTuple(...);
   EXPCL_PYSTUB int PyBool_FromLong(...);
   EXPCL_PYSTUB int PyBuffer_Release(...);
   EXPCL_PYSTUB int PyBytes_AsString(...);
@@ -84,11 +85,14 @@ extern "C" {
   EXPCL_PYSTUB int PyModule_AddObject(...);
   EXPCL_PYSTUB int PyModule_AddStringConstant(...);
   EXPCL_PYSTUB int PyModule_Create2(...);
+  EXPCL_PYSTUB int PyNumber_Check(...);
   EXPCL_PYSTUB int PyNumber_Float(...);
+  EXPCL_PYSTUB int PyNumber_Int(...);
   EXPCL_PYSTUB int PyNumber_Long(...);
   EXPCL_PYSTUB int PyObject_ASCII(...);
   EXPCL_PYSTUB int PyObject_Call(...);
   EXPCL_PYSTUB int PyObject_CallFunction(...);
+  EXPCL_PYSTUB int PyObject_CallFunctionObjArgs(...);
   EXPCL_PYSTUB int PyObject_CallMethod(...);
   EXPCL_PYSTUB int PyObject_CallMethodObjArgs(...);
   EXPCL_PYSTUB int PyObject_CallObject(...);
@@ -152,8 +156,14 @@ extern "C" {
   EXPCL_PYSTUB int Py_InitModule4(...);
   EXPCL_PYSTUB int Py_InitModule4_64(...);
   EXPCL_PYSTUB int Py_InitModule4TraceRefs(...);
+  EXPCL_PYSTUB int _PyArg_ParseTuple_SizeT(...);
+  EXPCL_PYSTUB int _PyArg_ParseTupleAndKeywords_SizeT(...);
+  EXPCL_PYSTUB int _PyArg_Parse_SizeT(...);
+  EXPCL_PYSTUB int _PyObject_CallFunction_SizeT(...);
+  EXPCL_PYSTUB int _PyObject_CallMethod_SizeT(...);
   EXPCL_PYSTUB int _PyObject_DebugFree(...);
   EXPCL_PYSTUB int _PyObject_Del(...);
+  EXPCL_PYSTUB int _Py_BuildValue_SizeT(...);
   EXPCL_PYSTUB int _Py_Dealloc(...);
   EXPCL_PYSTUB int _Py_NegativeRefcount(...);
   EXPCL_PYSTUB int _Py_RefTotal(...);
@@ -182,6 +192,7 @@ extern "C" {
 int PyArg_Parse(...) { return 0; };
 int PyArg_ParseTuple(...) { return 0; }
 int PyArg_ParseTupleAndKeywords(...) { return 0; }
+int PyArg_UnpackTuple(...) { return 0; };
 int PyBool_FromLong(...) { return 0; }
 int PyBuffer_Release(...) { return 0; }
 int PyBytes_AsString(...) { return 0; }
@@ -248,11 +259,14 @@ int PyModule_AddIntConstant(...) { return 0; };
 int PyModule_AddObject(...) { return 0; };
 int PyModule_AddStringConstant(...) { return 0; };
 int PyModule_Create2(...) { return 0; };
+int PyNumber_Check(...) { return 0; }
 int PyNumber_Float(...) { return 0; }
+int PyNumber_Int(...) { return 0; }
 int PyNumber_Long(...) { return 0; }
 int PyObject_ASCII(...) { return 0; }
 int PyObject_Call(...) { return 0; }
 int PyObject_CallFunction(...) { return 0; }
+int PyObject_CallFunctionObjArgs(...) { return 0; }
 int PyObject_CallMethod(...) { return 0; }
 int PyObject_CallMethodObjArgs(...) { return 0; }
 int PyObject_CallObject(...) { return 0; }
@@ -316,8 +330,14 @@ int Py_BuildValue(...) { return 0; }
 int Py_InitModule4(...) { return 0; }
 int Py_InitModule4_64(...) { return 0; }
 int Py_InitModule4TraceRefs(...) { return 0; };
+int _PyArg_ParseTuple_SizeT(...) { return 0; };
+int _PyArg_ParseTupleAndKeywords_SizeT(...) { return 0; };
+int _PyArg_Parse_SizeT(...) { return 0; };
+int _PyObject_CallFunction_SizeT(...) { return 0; };
+int _PyObject_CallMethod_SizeT(...) { return 0; };
 int _PyObject_DebugFree(...) { return 0; };
 int _PyObject_Del(...) { return 0; };
+int _Py_BuildValue_SizeT(...) { return 0; };
 int _Py_Dealloc(...) { return 0; };
 int _Py_NegativeRefcount(...) { return 0; };
 int _Py_RefTotal(...) { return 0; };

+ 21 - 36
makepanda/makepanda.py

@@ -92,7 +92,7 @@ PkgListSet(["PYTHON", "DIRECT",                        # Python support
   "GTK2", "WX", "FLTK",                                # Toolkit support
   "ROCKET",                                            # GUI libraries
   "CARBON", "COCOA",                                   # Mac OS X toolkits
-  "OSMESA", "X11", "XF86DGA", "XRANDR", "XCURSOR",     # Unix platform support
+  "X11", "XF86DGA", "XRANDR", "XCURSOR",               # Unix platform support
   "PANDATOOL", "PVIEW", "DEPLOYTOOLS",                 # Toolchain
   "SKEL",                                              # Example SKEL project
   "PANDAFX",                                           # Some distortion special lenses 
@@ -697,7 +697,6 @@ if (COMPILER=="GCC"):
         SmartPkgEnable("GLES",      "glesv1_cm", ("GLESv1_CM"), ("GLES/gl.h"), framework = "OpenGLES")
         SmartPkgEnable("GLES2",     "glesv2",    ("GLESv2"), ("GLES2/gl2.h")) #framework = "OpenGLES"?
         SmartPkgEnable("EGL",       "egl",       ("EGL"), ("EGL/egl.h"))
-        SmartPkgEnable("OSMESA",    "osmesa",    ("OSMesa"), ("GL/osmesa.h"))
         SmartPkgEnable("NVIDIACG",  "",          ("Cg"), "Cg/cg.h", framework = "Cg")
         SmartPkgEnable("ODE",       "",          ("ode"), "ode/ode.h", tool = "ode-config")
         SmartPkgEnable("OPENAL",    "openal",    ("openal"), "AL/al.h", framework = "OpenAL")
@@ -1901,9 +1900,6 @@ DTOOL_CONFIG=[
     ("HAVE_GL",                        '1',                      'UNDEF'),
     ("HAVE_GLES",                      'UNDEF',                  'UNDEF'),
     ("HAVE_GLES2",                     'UNDEF',                  'UNDEF'),
-    ("HAVE_MESA",                      'UNDEF',                  'UNDEF'),
-    ("MESA_MGL",                       'UNDEF',                  'UNDEF'),
-    ("HAVE_SGIGL",                     'UNDEF',                  'UNDEF'),
     ("HAVE_GLX",                       'UNDEF',                  '1'),
     ("HAVE_EGL",                       'UNDEF',                  'UNDEF'),
     ("HAVE_WGL",                       '1',                      'UNDEF'),
@@ -3828,15 +3824,16 @@ if (PkgSkip("OPENSSL")==0 and not RTDIST and not RUNTIME and PkgSkip("DEPLOYTOOL
   TargetAdd('build_patch.exe', input=COMMON_PANDA_LIBS_PYSTUB)
   TargetAdd('build_patch.exe', opts=OPTS)
 
-  TargetAdd('check_adler_check_adler.obj', opts=OPTS, input='check_adler.cxx')
-  TargetAdd('check_adler.exe', input=['check_adler_check_adler.obj'])
-  TargetAdd('check_adler.exe', input=COMMON_PANDA_LIBS_PYSTUB)
-  TargetAdd('check_adler.exe', opts=OPTS)
+  if not PkgSkip("ZLIB"):
+    TargetAdd('check_adler_check_adler.obj', opts=OPTS, input='check_adler.cxx')
+    TargetAdd('check_adler.exe', input=['check_adler_check_adler.obj'])
+    TargetAdd('check_adler.exe', input=COMMON_PANDA_LIBS_PYSTUB)
+    TargetAdd('check_adler.exe', opts=OPTS)
 
-  TargetAdd('check_crc_check_crc.obj', opts=OPTS, input='check_crc.cxx')
-  TargetAdd('check_crc.exe', input=['check_crc_check_crc.obj'])
-  TargetAdd('check_crc.exe', input=COMMON_PANDA_LIBS_PYSTUB)
-  TargetAdd('check_crc.exe', opts=OPTS)
+    TargetAdd('check_crc_check_crc.obj', opts=OPTS, input='check_crc.cxx')
+    TargetAdd('check_crc.exe', input=['check_crc_check_crc.obj'])
+    TargetAdd('check_crc.exe', input=COMMON_PANDA_LIBS_PYSTUB)
+    TargetAdd('check_crc.exe', opts=OPTS)
 
   TargetAdd('check_md5_check_md5.obj', opts=OPTS, input='check_md5.cxx')
   TargetAdd('check_md5.exe', input=['check_md5_check_md5.obj'])
@@ -4035,20 +4032,6 @@ if (not RUNTIME):
   TargetAdd('egg.pyd', input=COMMON_PANDA_LIBS)
   TargetAdd('egg.pyd', opts=['PYTHON'])
 
-#
-# DIRECTORY: panda/src/mesadisplay/
-#
-
-if (GetTarget() != 'windows' and PkgSkip("GL")==0 and PkgSkip("OSMESA")==0 and not RUNTIME):
-  OPTS=['DIR:panda/src/mesadisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAMESA', 'NVIDIACG', 'GL', 'OSMESA']
-  TargetAdd('p3mesadisplay_composite1.obj', opts=OPTS, input='p3mesadisplay_composite1.cxx')
-  OPTS=['DIR:panda/metalibs/pandagl', 'BUILDING:PANDAMESA', 'NVIDIACG', 'GL']
-  TargetAdd('libpandamesa.dll', input='p3mesadisplay_composite1.obj')
-  if (PkgSkip('PANDAFX')==0):
-    TargetAdd('libpandamesa.dll', input='libpandafx.dll')
-  TargetAdd('libpandamesa.dll', input=COMMON_PANDA_LIBS)
-  TargetAdd('libpandamesa.dll', opts=['MODULE', 'GL', 'OSMESA'])
-
 #
 # DIRECTORY: panda/src/x11display/
 #
@@ -5539,15 +5522,17 @@ if (PkgSkip("PANDATOOL")==0):
 # DIRECTORY: pandatool/src/miscprogs/
 #
 
-if (PkgSkip("PANDATOOL")==0):
-    OPTS=['DIR:pandatool/src/miscprogs']
-    TargetAdd('bin2c_binToC.obj', opts=OPTS, input='binToC.cxx')
-    TargetAdd('bin2c.exe', input='bin2c_binToC.obj')
-    TargetAdd('bin2c.exe', input='libp3progbase.lib')
-    TargetAdd('bin2c.exe', input='libp3pandatoolbase.lib')
-    TargetAdd('bin2c.exe', input=COMMON_PANDA_LIBS)
-    TargetAdd('bin2c.exe', input='libp3pystub.lib')
-    TargetAdd('bin2c.exe', opts=['ADVAPI'])
+# This is a bit of an esoteric tool, and it causes issues because
+# it conflicts with tools of the same name in different packages.
+#if (PkgSkip("PANDATOOL")==0):
+#    OPTS=['DIR:pandatool/src/miscprogs']
+#    TargetAdd('bin2c_binToC.obj', opts=OPTS, input='binToC.cxx')
+#    TargetAdd('bin2c.exe', input='bin2c_binToC.obj')
+#    TargetAdd('bin2c.exe', input='libp3progbase.lib')
+#    TargetAdd('bin2c.exe', input='libp3pandatoolbase.lib')
+#    TargetAdd('bin2c.exe', input=COMMON_PANDA_LIBS)
+#    TargetAdd('bin2c.exe', input='libp3pystub.lib')
+#    TargetAdd('bin2c.exe', opts=['ADVAPI'])
 
 #
 # DIRECTORY: pandatool/src/pstatserver/

+ 8 - 3
makepanda/makepandacore.py

@@ -2328,15 +2328,20 @@ def SetupBuildEnvironment(compiler):
 ########################################################################
 
 def CopyFile(dstfile, srcfile):
-    if (dstfile[-1]=='/'):
+    if dstfile[-1] == '/':
         dstdir = dstfile
         fnl = srcfile.rfind("/")
-        if (fnl < 0): fn = srcfile
-        else: fn = srcfile[fnl+1:]
+        if fnl < 0:
+            fn = srcfile
+        else:
+            fn = srcfile[fnl+1:]
         dstfile = dstdir + fn
+
     if NeedsBuild([dstfile], [srcfile]):
         if os.path.islink(srcfile):
             # Preserve symlinks
+            if os.path.exists(dstfile):
+                os.unlink(dstfile)
             os.symlink(os.readlink(srcfile), dstfile)
         else:
             WriteBinaryFile(dstfile, ReadBinaryFile(srcfile))

+ 2 - 4
panda/src/androiddisplay/androidGraphicsStateGuardian.cxx

@@ -405,8 +405,6 @@ get_extra_extensions() {
 //               not defined.
 ////////////////////////////////////////////////////////////////////
 void *AndroidGraphicsStateGuardian::
-do_get_extension_func(const char *prefix, const char *name) {
-  string fullname = string(prefix) + string(name);
-
-  return (void *)eglGetProcAddress(fullname.c_str());
+do_get_extension_func(const char *name) {
+  return (void *)eglGetProcAddress(name);
 }

+ 1 - 1
panda/src/androiddisplay/androidGraphicsStateGuardian.h

@@ -61,7 +61,7 @@ protected:
 
   virtual void query_gl_version();
   virtual void get_extra_extensions();
-  virtual void *do_get_extension_func(const char *prefix, const char *name);
+  virtual void *do_get_extension_func(const char *name);
 
 private:
   int _egl_version_major, _egl_version_minor;

+ 1 - 1
panda/src/cocoadisplay/Sources.pp

@@ -3,7 +3,7 @@
 #define OTHER_LIBS p3interrogatedb:c p3dconfig:c p3dtoolconfig:m \
                    p3dtoolutil:c p3dtoolbase:c p3dtool:m
 
-#define OSX_SYS_FRAMEWORKS ApplicationServices AppKit
+#define OSX_SYS_FRAMEWORKS ApplicationServices AppKit Carbon
 
 #begin lib_target
   #define TARGET p3cocoadisplay

+ 1 - 1
panda/src/cocoadisplay/cocoaGraphicsStateGuardian.h

@@ -46,7 +46,7 @@ public:
 
 protected:
   virtual void query_gl_version();
-  virtual void *do_get_extension_func(const char *prefix, const char *name);
+  virtual void *do_get_extension_func(const char *name);
 
 public:
   static TypeHandle get_class_type() {

+ 4 - 5
panda/src/cocoadisplay/cocoaGraphicsStateGuardian.mm

@@ -276,10 +276,9 @@ query_gl_version() {
 //               not defined.
 ////////////////////////////////////////////////////////////////////
 void *CocoaGraphicsStateGuardian::
-do_get_extension_func(const char *prefix, const char *name) {
-  char* fullname = (char*) malloc(strlen(prefix) + strlen(name) + 2);
-  strcpy(fullname + 1, prefix);
-  strcpy(fullname + 1 + strlen(prefix), name);
+do_get_extension_func(const char *name) {
+  char* fullname = (char*) malloc(strlen(name) + 2);
+  strcpy(fullname + 1, name);
   fullname[0] = '_';
 
   // Believe it or not, but this is actually the
@@ -292,7 +291,7 @@ do_get_extension_func(const char *prefix, const char *name) {
   }
 
   cocoadisplay_cat.warning() <<
-    "do_get_extension_func failed for " << prefix << name << "!\n";
+    "do_get_extension_func failed for " << fullname << "!\n";
 
   free(fullname);
   return NULL;

+ 11 - 0
panda/src/display/config_display.cxx

@@ -405,6 +405,17 @@ ConfigVariableBool framebuffer_stereo
  PRC_DESC("True if FM_stereo should be added to the default framebuffer "
           "properties, which requests a stereo-capable display, if "
           "supported by the graphics driver."));
+ConfigVariableBool framebuffer_srgb
+("framebuffer-srgb", false,
+ PRC_DESC("Set this to request an sRGB framebuffer, which will "
+          "convert all values to linear space before blending.  This "
+          "means that the output will be properly gamma-corrected, as "
+          "long as all the input textures are either converted from "
+          "original sRGB to linear or sRGB textures are used."));
+ConfigVariableBool framebuffer_float
+("framebuffer-float", false,
+ PRC_DESC("Set this to request a framebuffer that uses floating-point "
+          "storage for the color channel."));
 
 ConfigVariableInt depth_bits
 ("depth-bits", 0,

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

@@ -92,6 +92,8 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_alpha;
 extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_stencil;
 extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_accum;
 extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_stereo;
+extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_srgb;
+extern EXPCL_PANDA_DISPLAY ConfigVariableBool framebuffer_float;
 extern EXPCL_PANDA_DISPLAY ConfigVariableInt depth_bits;
 extern EXPCL_PANDA_DISPLAY ConfigVariableInt color_bits;
 extern EXPCL_PANDA_DISPLAY ConfigVariableInt alpha_bits;

+ 244 - 63
panda/src/display/displayRegion.I

@@ -38,6 +38,34 @@ get_lens_index() const {
   return cdata->_lens_index;
 }
 
+///////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_num_regions
+//       Access: Published
+//  Description: Returns the number of regions, see set_num_regions.
+////////////////////////////////////////////////////////////////////
+INLINE int DisplayRegion::
+get_num_regions() const {
+  CDReader cdata(_cycler);
+  return cdata->_regions.size();
+}
+
+///////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::set_num_regions
+//       Access: Published
+//  Description: Sets the number of regions that this DisplayRegion
+//               indicates.  Usually, this number is 1 (and it is
+//               always at least 1), and only the first is used for
+//               rendering.  However, if more than one is provided,
+//               you may select which one to render into using a
+//               geometry shader (gl_ViewportIndex in GLSL).
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+set_num_regions(int i) {
+  nassertv(i >= 1);
+  CDWriter cdata(_cycler);
+  cdata->_regions.resize(i);
+}
+
 ///////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::get_dimensions
 //       Access: Published
@@ -47,11 +75,24 @@ get_lens_index() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void DisplayRegion::
 get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const {
+  get_dimensions(0, l, r, b, t);
+}
+
+///////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_dimensions
+//       Access: Published
+//  Description: Retrieves the coordinates of the DisplayRegion's
+//               rectangle within its GraphicsOutput.  These numbers
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+get_dimensions(int i, PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const {
   CDReader cdata(_cycler);
-  l = cdata->_dimensions[0];
-  r = cdata->_dimensions[1];
-  b = cdata->_dimensions[2];
-  t = cdata->_dimensions[3];
+  const Region &region = cdata->_regions[i];
+  l = region._dimensions[0];
+  r = region._dimensions[1];
+  b = region._dimensions[2];
+  t = region._dimensions[3];
 }
 
 ///////////////////////////////////////////////////////////////////
@@ -62,9 +103,9 @@ get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) c
 //               will be in the range [0..1].
 ////////////////////////////////////////////////////////////////////
 INLINE LVecBase4 DisplayRegion::
-get_dimensions() const {
+get_dimensions(int i) const {
   CDReader cdata(_cycler);
-  return cdata->_dimensions;
+  return cdata->_regions[i]._dimensions;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -75,9 +116,9 @@ get_dimensions() const {
 //               will be in the range [0..1].
 ////////////////////////////////////////////////////////////////////
 INLINE PN_stdfloat DisplayRegion::
-get_left() const {
+get_left(int i) const {
   CDReader cdata(_cycler);
-  return cdata->_dimensions[0];
+  return cdata->_regions[i]._dimensions[0];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -88,9 +129,9 @@ get_left() const {
 //               will be in the range [0..1].
 ////////////////////////////////////////////////////////////////////
 INLINE PN_stdfloat DisplayRegion::
-get_right() const {
+get_right(int i) const {
   CDReader cdata(_cycler);
-  return cdata->_dimensions[1];
+  return cdata->_regions[i]._dimensions[1];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -101,9 +142,9 @@ get_right() const {
 //               number will be in the range [0..1].
 ////////////////////////////////////////////////////////////////////
 INLINE PN_stdfloat DisplayRegion::
-get_bottom() const {
+get_bottom(int i) const {
   CDReader cdata(_cycler);
-  return cdata->_dimensions[2];
+  return cdata->_regions[i]._dimensions[2];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -114,9 +155,9 @@ get_bottom() const {
 //               will be in the range [0..1].
 ////////////////////////////////////////////////////////////////////
 INLINE PN_stdfloat DisplayRegion::
-get_top() const {
+get_top(int i) const {
   CDReader cdata(_cycler);
-  return cdata->_dimensions[3];
+  return cdata->_regions[i]._dimensions[3];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -130,7 +171,35 @@ get_top() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void DisplayRegion::
 set_dimensions(PN_stdfloat l, PN_stdfloat r, PN_stdfloat b, PN_stdfloat t) {
-  set_dimensions(LVecBase4(l, r, b, t));
+  set_dimensions(0, LVecBase4(l, r, b, t));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::set_dimensions
+//       Access: Published, Virtual
+//  Description: Changes the portion of the framebuffer this
+//               DisplayRegion corresponds to.  The parameters range
+//               from 0 to 1, where 0,0 is the lower left corner and
+//               1,1 is the upper right; (0, 1, 0, 1) represents the
+//               whole screen.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+set_dimensions(int i, PN_stdfloat l, PN_stdfloat r, PN_stdfloat b, PN_stdfloat t) {
+  set_dimensions(i, LVecBase4(l, r, b, t));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::set_dimensions
+//       Access: Published, Virtual
+//  Description: Changes the portion of the framebuffer this
+//               DisplayRegion corresponds to.  The parameters range
+//               from 0 to 1, where 0,0 is the lower left corner and
+//               1,1 is the upper right; (0, 1, 0, 1) represents the
+//               whole screen.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+set_dimensions(const LVecBase4 &dimensions) {
+  set_dimensions(0, dimensions);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -387,9 +456,9 @@ get_draw_callback() const {
 //  Description: Returns the width of the DisplayRegion in pixels.
 ////////////////////////////////////////////////////////////////////
 INLINE int DisplayRegion::
-get_pixel_width() const {
+get_pixel_width(int i) const {
   CDReader cdata(_cycler);
-  return cdata->_pr - cdata->_pl;
+  return cdata->_regions[i]._pixels[1] - cdata->_regions[i]._pixels[0];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -398,9 +467,9 @@ get_pixel_width() const {
 //  Description: Returns the height of the DisplayRegion in pixels.
 ////////////////////////////////////////////////////////////////////
 INLINE int DisplayRegion::
-get_pixel_height() const {
+get_pixel_height(int i) const {
   CDReader cdata(_cycler);
-  return cdata->_pt - cdata->_pb;
+  return cdata->_regions[i]._pixels[3] - cdata->_regions[i]._pixels[2];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -411,11 +480,23 @@ get_pixel_height() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void DisplayRegion::
 get_pixels(int &pl, int &pr, int &pb, int &pt) const {
+  get_pixels(0, pl, pr, pb, pt);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_pixels
+//       Access: Public
+//  Description: Retrieves the coordinates of the DisplayRegion within
+//               its window, in pixels.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+get_pixels(int i, int &pl, int &pr, int &pb, int &pt) const {
   CDReader cdata(_cycler);
-  pl = cdata->_pl;
-  pr = cdata->_pr;
-  pb = cdata->_pb;
-  pt = cdata->_pt;
+  const Region &region = cdata->_regions[i];
+  pl = region._pixels[0];
+  pr = region._pixels[1];
+  pb = region._pixels[2];
+  pt = region._pixels[3];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -427,11 +508,24 @@ get_pixels(int &pl, int &pr, int &pb, int &pt) const {
 ////////////////////////////////////////////////////////////////////
 INLINE void DisplayRegion::
 get_region_pixels(int &xo, int &yo, int &w, int &h) const {
+  get_region_pixels(0, xo, yo, w, h);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_region_pixels
+//       Access: Public
+//  Description: Retrieves the coordinates of the DisplayRegion within
+//               its window, as the pixel location of its bottom-left
+//               corner, along with a pixel width and height.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+get_region_pixels(int i, int &xo, int &yo, int &w, int &h) const {
   CDReader cdata(_cycler);
-  xo = cdata->_pl;
-  yo = cdata->_pb;
-  w = cdata->_pr - cdata->_pl;
-  h = cdata->_pt - cdata->_pb;
+  const Region &region = cdata->_regions[i];
+  xo = region._pixels[0];
+  yo = region._pixels[2];
+  w = region._pixels[1] - xo;
+  h = region._pixels[3] - yo;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -444,11 +538,25 @@ get_region_pixels(int &xo, int &yo, int &w, int &h) const {
 ////////////////////////////////////////////////////////////////////
 INLINE void DisplayRegion::
 get_region_pixels_i(int &xo, int &yo, int &w, int &h) const {
+  get_region_pixels_i(0, xo, yo, w, h);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::get_region_pixels_i
+//       Access: Public
+//  Description: Similar to get_region_pixels(), but returns the upper
+//               left corner, and the pixel numbers are numbered from
+//               the top-left corner down, in the DirectX way of
+//               things.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegion::
+get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const {
   CDReader cdata(_cycler);
-  xo = cdata->_pl;
-  yo = cdata->_pti;
-  w = cdata->_pr - cdata->_pl;
-  h = cdata->_pbi - cdata->_pti;
+  const Region &region = cdata->_regions[i];
+  xo = region._pixels_i[0];
+  yo = region._pixels_i[2];
+  w = region._pixels_i[1] - xo;
+  h = region._pixels_i[3] - yo;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -522,6 +630,18 @@ get_draw_region_pcollector() {
   return _draw_region_pcollector;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegion::Region::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE DisplayRegion::Region::
+Region() :
+  _dimensions(0, 1, 0, 1),
+  _pixels(0),
+  _pixels_i(0) {
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegion::CDataCull::Constructor
 //       Access: Public
@@ -633,6 +753,16 @@ is_any_clear_active() const {
   return _object->is_any_clear_active();
 }
 
+///////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_num_regions
+//       Access: Published
+//  Description: Returns the number of regions, see set_num_regions.
+////////////////////////////////////////////////////////////////////
+INLINE int DisplayRegionPipelineReader::
+get_num_regions() const {
+  return _cdata->_regions.size();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DisplayRegionPipelineReader::get_dimensions
 //       Access: Public
@@ -642,10 +772,23 @@ is_any_clear_active() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void DisplayRegionPipelineReader::
 get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const {
-  l = _cdata->_dimensions[0];
-  r = _cdata->_dimensions[1];
-  b = _cdata->_dimensions[2];
-  t = _cdata->_dimensions[3];
+  return get_dimensions(0, l, r, b, t);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_dimensions
+//       Access: Public
+//  Description: Retrieves the coordinates of the DisplayRegion's
+//               rectangle within its GraphicsOutput.  These numbers
+//               will be in the range [0..1].
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegionPipelineReader::
+get_dimensions(int i, PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const {
+  const DisplayRegion::Region &region = _cdata->_regions[i];
+  l = region._dimensions[0];
+  r = region._dimensions[1];
+  b = region._dimensions[2];
+  t = region._dimensions[3];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -656,8 +799,8 @@ get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) c
 //               will be in the range [0..1].
 ////////////////////////////////////////////////////////////////////
 INLINE const LVecBase4 &DisplayRegionPipelineReader::
-get_dimensions() const {
-  return _cdata->_dimensions;
+get_dimensions(int i) const {
+  return _cdata->_regions[i]._dimensions;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -668,8 +811,8 @@ get_dimensions() const {
 //               will be in the range [0..1].
 ////////////////////////////////////////////////////////////////////
 INLINE PN_stdfloat DisplayRegionPipelineReader::
-get_left() const {
-  return _cdata->_dimensions[0];
+get_left(int i) const {
+  return _cdata->_regions[i]._dimensions[0];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -680,8 +823,8 @@ get_left() const {
 //               will be in the range [0..1].
 ////////////////////////////////////////////////////////////////////
 INLINE PN_stdfloat DisplayRegionPipelineReader::
-get_right() const {
-  return _cdata->_dimensions[1];
+get_right(int i) const {
+  return _cdata->_regions[i]._dimensions[1];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -692,8 +835,8 @@ get_right() const {
 //               number will be in the range [0..1].
 ////////////////////////////////////////////////////////////////////
 INLINE PN_stdfloat DisplayRegionPipelineReader::
-get_bottom() const {
-  return _cdata->_dimensions[2];
+get_bottom(int i) const {
+  return _cdata->_regions[i]._dimensions[2];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -704,8 +847,8 @@ get_bottom() const {
 //               will be in the range [0..1].
 ////////////////////////////////////////////////////////////////////
 INLINE PN_stdfloat DisplayRegionPipelineReader::
-get_top() const {
-  return _cdata->_dimensions[3];
+get_top(int i) const {
+  return _cdata->_regions[i]._dimensions[3];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -816,10 +959,22 @@ get_draw_callback() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void DisplayRegionPipelineReader::
 get_pixels(int &pl, int &pr, int &pb, int &pt) const {
-  pl = _cdata->_pl;
-  pr = _cdata->_pr;
-  pb = _cdata->_pb;
-  pt = _cdata->_pt;
+  get_pixels(0, pl, pr, pb, pt);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_pixels
+//       Access: Public
+//  Description: Retrieves the coordinates of the DisplayRegion within
+//               its window, in pixels.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegionPipelineReader::
+get_pixels(int i, int &pl, int &pr, int &pb, int &pt) const {
+  const DisplayRegion::Region &region = _cdata->_regions[i];
+  pl = region._pixels[0];
+  pr = region._pixels[1];
+  pb = region._pixels[2];
+  pt = region._pixels[3];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -831,10 +986,23 @@ get_pixels(int &pl, int &pr, int &pb, int &pt) const {
 ////////////////////////////////////////////////////////////////////
 INLINE void DisplayRegionPipelineReader::
 get_region_pixels(int &xo, int &yo, int &w, int &h) const {
-  xo = _cdata->_pl;
-  yo = _cdata->_pb;
-  w = _cdata->_pr - _cdata->_pl;
-  h = _cdata->_pt - _cdata->_pb;
+  get_region_pixels(0, xo, yo, w, h);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_region_pixels
+//       Access: Public
+//  Description: Retrieves the coordinates of the DisplayRegion within
+//               its window, as the pixel location of its bottom-left
+//               corner, along with a pixel width and height.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegionPipelineReader::
+get_region_pixels(int i, int &xo, int &yo, int &w, int &h) const {
+  const DisplayRegion::Region &region = _cdata->_regions[i];
+  xo = region._pixels[0];
+  yo = region._pixels[2];
+  w = region._pixels[1] - xo;
+  h = region._pixels[3] - yo;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -847,10 +1015,24 @@ get_region_pixels(int &xo, int &yo, int &w, int &h) const {
 ////////////////////////////////////////////////////////////////////
 INLINE void DisplayRegionPipelineReader::
 get_region_pixels_i(int &xo, int &yo, int &w, int &h) const {
-  xo = _cdata->_pl;
-  yo = _cdata->_pti;
-  w = _cdata->_pr - _cdata->_pl;
-  h = _cdata->_pbi - _cdata->_pti;
+  get_region_pixels_i(0, xo, yo, w, h);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DisplayRegionPipelineReader::get_region_pixels_i
+//       Access: Public
+//  Description: Similar to get_region_pixels(), but returns the upper
+//               left corner, and the pixel numbers are numbered from
+//               the top-left corner down, in the DirectX way of
+//               things.
+////////////////////////////////////////////////////////////////////
+INLINE void DisplayRegionPipelineReader::
+get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const {
+  const DisplayRegion::Region &region = _cdata->_regions[i];
+  xo = region._pixels_i[0];
+  yo = region._pixels_i[2];
+  w = region._pixels_i[1] - xo;
+  h = region._pixels_i[3] - yo;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -859,8 +1041,8 @@ get_region_pixels_i(int &xo, int &yo, int &w, int &h) const {
 //  Description: Returns the width of the DisplayRegion in pixels.
 ////////////////////////////////////////////////////////////////////
 INLINE int DisplayRegionPipelineReader::
-get_pixel_width() const {
-  return _cdata->_pr - _cdata->_pl;
+get_pixel_width(int i) const {
+  return _cdata->_regions[i]._pixels[1] - _cdata->_regions[i]._pixels[0];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -869,8 +1051,7 @@ get_pixel_width() const {
 //  Description: Gets the index into a lens_node lens array. 0 default
 ////////////////////////////////////////////////////////////////////
 INLINE int DisplayRegionPipelineReader::
-get_lens_index() const
-{
+get_lens_index() const {
   return _cdata->_lens_index;
 }
 
@@ -880,6 +1061,6 @@ get_lens_index() const
 //  Description: Returns the height of the DisplayRegion in pixels.
 ////////////////////////////////////////////////////////////////////
 INLINE int DisplayRegionPipelineReader::
-get_pixel_height() const {
-  return _cdata->_pt - _cdata->_pb;
+get_pixel_height(int i) const {
+  return _cdata->_regions[i]._pixels[3] - _cdata->_regions[i]._pixels[2];
 }

+ 41 - 36
panda/src/display/displayRegion.cxx

@@ -42,7 +42,8 @@ DisplayRegion(GraphicsOutput *window, const LVecBase4 &dimensions) :
 {
   _screenshot_buffer_type = window->get_draw_buffer_type();
   _draw_buffer_type = window->get_draw_buffer_type();
-  set_dimensions(dimensions);
+  set_num_regions(1);
+  set_dimensions(0, dimensions);
   compute_pixels_all_stages();
 
   _window->add_display_region(this);
@@ -127,15 +128,15 @@ set_lens_index(int index) {
 //               whole screen.
 ////////////////////////////////////////////////////////////////////
 void DisplayRegion::
-set_dimensions(const LVecBase4 &dimensions) {
+set_dimensions(int i, const LVecBase4 &dimensions) {
   int pipeline_stage = Thread::get_current_pipeline_stage();
   nassertv(pipeline_stage == 0);
   CDWriter cdata(_cycler);
 
-  cdata->_dimensions = dimensions;
+  cdata->_regions[i]._dimensions = dimensions;
 
   if (_window != (GraphicsOutput *)NULL && _window->has_size()) {
-    do_compute_pixels(_window->get_fb_x_size(), _window->get_fb_y_size(), cdata);
+    do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(), cdata);
   }
 }
 
@@ -419,9 +420,8 @@ set_target_tex_page(int page) {
 void DisplayRegion::
 output(ostream &out) const {
   CDReader cdata(_cycler);
-  out << "DisplayRegion(" << cdata->_dimensions << ")=pixels(" << cdata->_pl
-      << " " << cdata->_pr << " " << cdata->_pb << " " << cdata->_pt
-      << ")";
+  out << "DisplayRegion(" << cdata->_regions[0]._dimensions
+      << ")=pixels(" << cdata->_regions[0]._pixels << ")";
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -636,8 +636,10 @@ void DisplayRegion::
 compute_pixels() {
   if (_window != (GraphicsOutput *)NULL) {
     CDWriter cdata(_cycler, false);
-    do_compute_pixels(_window->get_fb_x_size(), _window->get_fb_y_size(), 
-                      cdata);
+    for (int i = 0; i < cdata->_regions.size(); ++i) {
+      do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(), 
+                        cdata);
+    }
   }
 }
 
@@ -656,8 +658,10 @@ compute_pixels_all_stages() {
   if (_window != (GraphicsOutput *)NULL) {
     OPEN_ITERATE_ALL_STAGES(_cycler) {
       CDStageWriter cdata(_cycler, pipeline_stage);
-      do_compute_pixels(_window->get_fb_x_size(), _window->get_fb_y_size(), 
-                        cdata);
+      for (int i = 0; i < cdata->_regions.size(); ++i) {
+        do_compute_pixels(i, _window->get_fb_x_size(), _window->get_fb_y_size(), 
+                          cdata);
+      }
     }
     CLOSE_ITERATE_ALL_STAGES(_cycler);
   }
@@ -673,7 +677,9 @@ compute_pixels_all_stages() {
 void DisplayRegion::
 compute_pixels(int x_size, int y_size) {
   CDWriter cdata(_cycler, false);
-  do_compute_pixels(x_size, y_size, cdata);
+  for (int i = 0; i < cdata->_regions.size(); ++i) {
+    do_compute_pixels(i, x_size, y_size, cdata);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -689,7 +695,9 @@ void DisplayRegion::
 compute_pixels_all_stages(int x_size, int y_size) {
   OPEN_ITERATE_ALL_STAGES(_cycler) {
     CDStageWriter cdata(_cycler, pipeline_stage);
-    do_compute_pixels(x_size, y_size, cdata);
+    for (int i = 0; i < cdata->_regions.size(); ++i) {
+      do_compute_pixels(i, x_size, y_size, cdata);
+    }
   } 
   CLOSE_ITERATE_ALL_STAGES(_cycler);
 }
@@ -741,32 +749,36 @@ win_display_regions_changed() {
 //               assumes that we already have the lock.
 ////////////////////////////////////////////////////////////////////
 void DisplayRegion::
-do_compute_pixels(int x_size, int y_size, CData *cdata) {
+do_compute_pixels(int i, int x_size, int y_size, CData *cdata) {
   if (display_cat.is_debug()) {
     display_cat.debug()
       << "DisplayRegion::do_compute_pixels(" << x_size << ", " << y_size << ")\n";
   }
 
-  int old_w = cdata->_pr - cdata->_pl;
-  int old_h = cdata->_pt - cdata->_pb;
+  Region &region = cdata->_regions[i];
+
+  int old_w = region._pixels[1] - region._pixels[0];
+  int old_h = region._pixels[3] - region._pixels[2];
 
-  cdata->_pl = int((cdata->_dimensions[0] * x_size) + 0.5);
-  cdata->_pr = int((cdata->_dimensions[1] * x_size) + 0.5);
+  region._pixels[0] = int((region._dimensions[0] * x_size) + 0.5);
+  region._pixels[1] = int((region._dimensions[1] * x_size) + 0.5);
+  region._pixels_i[0] = region._pixels[0];
+  region._pixels_i[1] = region._pixels[1];
 
   nassertv(_window != (GraphicsOutput *)NULL);
   if (_window->get_inverted()) {
     // The window is inverted; compute the DisplayRegion accordingly.
-    cdata->_pb = int(((1.0f - cdata->_dimensions[3]) * y_size) + 0.5);
-    cdata->_pt = int(((1.0f - cdata->_dimensions[2]) * y_size) + 0.5);
-    cdata->_pbi = int((cdata->_dimensions[3] * y_size) + 0.5);
-    cdata->_pti = int((cdata->_dimensions[2] * y_size) + 0.5);
+    region._pixels[2] = int(((1.0f - region._dimensions[3]) * y_size) + 0.5);
+    region._pixels[3] = int(((1.0f - region._dimensions[2]) * y_size) + 0.5);
+    region._pixels_i[2] = int((region._dimensions[3] * y_size) + 0.5);
+    region._pixels_i[3] = int((region._dimensions[2] * y_size) + 0.5);
 
   } else {
     // The window is normal.
-    cdata->_pb = int((cdata->_dimensions[2] * y_size) + 0.5);
-    cdata->_pt = int((cdata->_dimensions[3] * y_size) + 0.5);
-    cdata->_pbi = int(((1.0f - cdata->_dimensions[2]) * y_size) + 0.5);
-    cdata->_pti = int(((1.0f - cdata->_dimensions[3]) * y_size) + 0.5);
+    region._pixels[2] = int((region._dimensions[2] * y_size) + 0.5);
+    region._pixels[3] = int((region._dimensions[3] * y_size) + 0.5);
+    region._pixels_i[2] = int(((1.0f - region._dimensions[2]) * y_size) + 0.5);
+    region._pixels_i[3] = int(((1.0f - region._dimensions[3]) * y_size) + 0.5);
   }
 }
 
@@ -814,9 +826,7 @@ do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
 ////////////////////////////////////////////////////////////////////
 DisplayRegion::CData::
 CData() :
-  _dimensions(0.0f, 1.0f, 0.0f, 1.0f),
-  _pl(0), _pr(0), _pb(0), _pt(0),
-  _pbi(0), _pti(0), _lens_index(0),
+  _lens_index(0),
   _camera_node((Camera *)NULL),
   _active(true),
   _sort(0),
@@ -824,6 +834,7 @@ CData() :
   _tex_view_offset(0),
   _target_tex_page(-1)
 {
+  _regions.push_back(Region());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -833,13 +844,7 @@ CData() :
 ////////////////////////////////////////////////////////////////////
 DisplayRegion::CData::
 CData(const DisplayRegion::CData &copy) :
-  _dimensions(copy._dimensions),
-  _pl(copy._pl),
-  _pr(copy._pr),
-  _pb(copy._pb),
-  _pt(copy._pt),
-  _pbi(copy._pbi),
-  _pti(copy._pti),
+  _regions(copy._regions),
   _lens_index(copy._lens_index),
   _camera(copy._camera),
   _camera_node(copy._camera_node),

+ 40 - 24
panda/src/display/displayRegion.h

@@ -72,14 +72,19 @@ public:
   INLINE bool operator < (const DisplayRegion &other) const;
 
 PUBLISHED:
+  INLINE int get_num_regions() const;
+  INLINE void set_num_regions(int i);
   INLINE void get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const;
-  INLINE LVecBase4 get_dimensions() const;
-  INLINE PN_stdfloat get_left() const;
-  INLINE PN_stdfloat get_right() const;
-  INLINE PN_stdfloat get_bottom() const;
-  INLINE PN_stdfloat get_top() const;
+  INLINE void get_dimensions(int i, PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const;
+  INLINE LVecBase4 get_dimensions(int i = 0) const;
+  INLINE PN_stdfloat get_left(int i = 0) const;
+  INLINE PN_stdfloat get_right(int i = 0) const;
+  INLINE PN_stdfloat get_bottom(int i = 0) const;
+  INLINE PN_stdfloat get_top(int i = 0) const;
   INLINE void set_dimensions(PN_stdfloat l, PN_stdfloat r, PN_stdfloat b, PN_stdfloat t);
-  virtual void set_dimensions(const LVecBase4 &dimensions);
+  INLINE void set_dimensions(int i, PN_stdfloat l, PN_stdfloat r, PN_stdfloat b, PN_stdfloat t);
+  INLINE void set_dimensions(const LVecBase4 &dimensions);
+  virtual void set_dimensions(int i, const LVecBase4 &dimensions);
 
   INLINE GraphicsOutput *get_window() const;
   GraphicsPipe *get_pipe() const;
@@ -123,8 +128,8 @@ PUBLISHED:
   INLINE void clear_draw_callback();
   INLINE CallbackObject *get_draw_callback() const;
 
-  INLINE int get_pixel_width() const;
-  INLINE int get_pixel_height() const;
+  INLINE int get_pixel_width(int i = 0) const;
+  INLINE int get_pixel_height(int i = 0) const;
 
   virtual void output(ostream &out) const;
 
@@ -144,8 +149,11 @@ public:
   void compute_pixels(int x_size, int y_size);
   void compute_pixels_all_stages(int x_size, int y_size);
   INLINE void get_pixels(int &pl, int &pr, int &pb, int &pt) const;
+  INLINE void get_pixels(int i, int &pl, int &pr, int &pb, int &pt) const;
   INLINE void get_region_pixels(int &xo, int &yo, int &w, int &h) const;
+  INLINE void get_region_pixels(int i, int &xo, int &yo, int &w, int &h) const;
   INLINE void get_region_pixels_i(int &xo, int &yo, int &w, int &h) const;
+  INLINE void get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const;
 
   virtual bool supports_pixel_zoom() const;
 
@@ -157,11 +165,20 @@ public:
   INLINE PStatCollector &get_cull_region_pcollector();
   INLINE PStatCollector &get_draw_region_pcollector();
 
+  struct Region {
+    INLINE Region();
+
+    LVecBase4 _dimensions;  // left, right, bottom, top
+    LVecBase4i _pixels;
+    LVecBase4i _pixels_i;
+  };
+  typedef pvector<Region> Regions;
+
 private:
   class CData;
 
   void win_display_regions_changed();
-  void do_compute_pixels(int x_size, int y_size, CData *cdata);
+  void do_compute_pixels(int i, int x_size, int y_size, CData *cdata);
   void set_active_index(int index);
 
 protected:
@@ -194,14 +211,8 @@ private:
       return DisplayRegion::get_class_type();
     }
 
-    LVecBase4 _dimensions;  // left, right, bottom, top
-    
-    int _pl;
-    int _pr;
-    int _pb;
-    int _pt;
-    int _pbi;
-    int _pti;
+    Regions _regions;
+
     int _lens_index; // index into which lens of a camera is associated with this display region.  0 is default
     
     NodePath _camera;
@@ -293,12 +304,14 @@ public:
 
   INLINE bool is_any_clear_active() const;
 
+  INLINE int get_num_regions() const;
   INLINE void get_dimensions(PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const;
-  INLINE const LVecBase4 &get_dimensions() const;
-  INLINE PN_stdfloat get_left() const;
-  INLINE PN_stdfloat get_right() const;
-  INLINE PN_stdfloat get_bottom() const;
-  INLINE PN_stdfloat get_top() const;
+  INLINE void get_dimensions(int i, PN_stdfloat &l, PN_stdfloat &r, PN_stdfloat &b, PN_stdfloat &t) const;
+  INLINE const LVecBase4 &get_dimensions(int i = 0) const;
+  INLINE PN_stdfloat get_left(int i = 0) const;
+  INLINE PN_stdfloat get_right(int i = 0) const;
+  INLINE PN_stdfloat get_bottom(int i = 0) const;
+  INLINE PN_stdfloat get_top(int i = 0) const;
 
   INLINE GraphicsOutput *get_window() const;
   GraphicsPipe *get_pipe() const;
@@ -313,11 +326,14 @@ public:
   INLINE CallbackObject *get_draw_callback() const;
 
   INLINE void get_pixels(int &pl, int &pr, int &pb, int &pt) const;
+  INLINE void get_pixels(int i, int &pl, int &pr, int &pb, int &pt) const;
   INLINE void get_region_pixels(int &xo, int &yo, int &w, int &h) const;
+  INLINE void get_region_pixels(int i, int &xo, int &yo, int &w, int &h) const;
   INLINE void get_region_pixels_i(int &xo, int &yo, int &w, int &h) const;
+  INLINE void get_region_pixels_i(int i, int &xo, int &yo, int &w, int &h) const;
 
-  INLINE int get_pixel_width() const;
-  INLINE int get_pixel_height() const;
+  INLINE int get_pixel_width(int i = 0) const;
+  INLINE int get_pixel_height(int i = 0) const;
 
   INLINE int get_lens_index() const;
 

+ 121 - 26
panda/src/display/frameBufferProperties.I

@@ -59,7 +59,7 @@ is_single_buffered() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool FrameBufferProperties::
 is_stereo() const {
-  return (_property[FBP_stereo] != 0);
+  return (_flags & FBF_stereo) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -189,9 +189,9 @@ get_back_buffers() const {
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
+INLINE bool FrameBufferProperties::
 get_indexed_color() const {
-  return _property[FBP_indexed_color];
+  return (_flags & FBF_indexed_color) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -199,9 +199,9 @@ get_indexed_color() const {
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
+INLINE bool FrameBufferProperties::
 get_rgb_color() const {
-  return _property[FBP_rgb_color];
+  return (_flags & FBF_rgb_color) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -209,9 +209,9 @@ get_rgb_color() const {
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
+INLINE bool FrameBufferProperties::
 get_stereo() const {
-  return _property[FBP_stereo];
+  return (_flags & FBF_stereo) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -219,9 +219,9 @@ get_stereo() const {
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
+INLINE bool FrameBufferProperties::
 get_force_hardware() const {
-  return _property[FBP_force_hardware];
+  return (_flags & FBF_force_hardware) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -229,9 +229,39 @@ get_force_hardware() const {
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-INLINE int FrameBufferProperties::
+INLINE bool FrameBufferProperties::
 get_force_software() const {
-  return _property[FBP_force_software];
+  return (_flags & FBF_force_software) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::get_srgb_color
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FrameBufferProperties::
+get_srgb_color() const {
+  return (_flags & FBF_srgb_color) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::get_float_color
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FrameBufferProperties::
+get_float_color() const {
+  return (_flags & FBF_float_color) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::get_float_depth
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool FrameBufferProperties::
+get_float_depth() const {
+  return (_flags & FBF_float_depth) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -365,9 +395,13 @@ set_back_buffers(int n) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_indexed_color(int n) {
-  _property[FBP_indexed_color] = n;
-  _specified[FBP_indexed_color] = true;
+set_indexed_color(bool n) {
+  if (n) {
+    _flags |= FBF_indexed_color;
+  } else {
+    _flags &= ~FBF_indexed_color;
+  }
+  _flags_specified |= FBF_indexed_color;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -376,9 +410,13 @@ set_indexed_color(int n) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_rgb_color(int n) {
-  _property[FBP_rgb_color] = n;
-  _specified[FBP_rgb_color] = true;
+set_rgb_color(bool n) {
+  if (n) {
+    _flags |= FBF_rgb_color;
+  } else {
+    _flags &= ~FBF_rgb_color;
+  }
+  _flags_specified |= FBF_rgb_color;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -387,9 +425,13 @@ set_rgb_color(int n) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_stereo(int n) {
-  _property[FBP_stereo] = n;
-  _specified[FBP_stereo] = true;
+set_stereo(bool n) {
+  if (n) {
+    _flags |= FBF_stereo;
+  } else {
+    _flags &= ~FBF_stereo;
+  }
+  _flags_specified |= FBF_stereo;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -398,9 +440,13 @@ set_stereo(int n) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_force_hardware(int n) {
-  _property[FBP_force_hardware] = n;
-  _specified[FBP_force_hardware] = true;
+set_force_hardware(bool n) {
+  if (n) {
+    _flags |= FBF_force_hardware;
+  } else {
+    _flags &= ~FBF_force_hardware;
+  }
+  _flags_specified |= FBF_force_hardware;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -409,7 +455,56 @@ set_force_hardware(int n) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void FrameBufferProperties::
-set_force_software(int n) {
-  _property[FBP_force_software] = n;
-  _specified[FBP_force_software] = true;
+set_force_software(bool n) {
+  if (n) {
+    _flags |= FBF_force_software;
+  } else {
+    _flags &= ~FBF_force_software;
+  }
+  _flags_specified |= FBF_force_software;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::set_srgb_color
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FrameBufferProperties::
+set_srgb_color(bool n) {
+  if (n) {
+    _flags |= FBF_srgb_color;
+  } else {
+    _flags &= ~FBF_srgb_color;
+  }
+  _flags_specified |= FBF_srgb_color;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::set_float_color
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FrameBufferProperties::
+set_float_color(bool n) {
+  if (n) {
+    _flags |= FBF_float_color;
+  } else {
+    _flags &= ~FBF_float_color;
+  }
+  _flags_specified |= FBF_float_color;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FrameBufferProperties::set_float_depth
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FrameBufferProperties::
+set_float_depth(bool n) {
+  if (n) {
+    _flags |= FBF_float_depth;
+  } else {
+    _flags &= ~FBF_float_depth;
+  }
+  _flags_specified |= FBF_float_depth;
 }

+ 121 - 58
panda/src/display/frameBufferProperties.cxx

@@ -34,7 +34,10 @@ FrameBufferProperties() {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 operator = (const FrameBufferProperties &copy) {
-  for (int i=0; i<FBP_COUNT; i++) {
+  _flags_specified = copy._flags_specified;
+  _flags = copy._flags;
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     _specified[i] = copy._specified[i];
     _property[i]  = copy._property[i];
   }
@@ -49,11 +52,17 @@ operator = (const FrameBufferProperties &copy) {
 ////////////////////////////////////////////////////////////////////
 bool FrameBufferProperties::
 subsumes(const FrameBufferProperties &other) const {
-  for (int i=0; i<FBP_COUNT; i++) {
+  if (((other._flags & other._flags_specified) & ~(_flags & _flags_specified)) != 0) {
+    // The other has bits enabled that we don't have enabled.
+    return false;
+  }
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     if (other._property[i] > _property[i]) {
       return false;
     }
   }
+
   return true;
 }
 
@@ -73,9 +82,9 @@ get_default() {
     return default_props;
   }
 
-  default_props.set_rgb_color(1);
+  default_props.set_rgb_color(true);
   default_props.set_back_buffers(back_buffers);
-  
+
   int num_words = framebuffer_mode.get_num_words();
   if (num_words > 0) {
     display_cat.error()
@@ -99,10 +108,10 @@ get_default() {
   }
 
   if (framebuffer_hardware) {
-    default_props.set_force_hardware(1);
+    default_props.set_force_hardware(true);
   }
   if (framebuffer_software) {
-    default_props.set_force_software(1);
+    default_props.set_force_software(true);
   }
   if (framebuffer_depth) {
     default_props.set_depth_bits(1);
@@ -120,7 +129,13 @@ get_default() {
     default_props.set_multisamples(1);
   }
   if (framebuffer_stereo) {
-    default_props.set_stereo(1);
+    default_props.set_stereo(true);
+  }
+  if (framebuffer_srgb) {
+    default_props.set_srgb_color(true);
+  }
+  if (framebuffer_float) {
+    default_props.set_float_color(true);
   }
   if (depth_bits > 0) {
     default_props.set_depth_bits(depth_bits);
@@ -141,10 +156,9 @@ get_default() {
     default_props.set_multisamples(multisamples);
   }
 
-  if ((default_props._property[FBP_force_software])&&
-      (default_props._property[FBP_force_hardware])) {
-    default_props._property[FBP_force_software] = 0;
-    default_props._property[FBP_force_hardware] = 0;
+  if ((default_props._flags & FBF_force_software) != 0 &&
+      (default_props._flags & FBF_force_hardware) != 0){
+    default_props._flags &= ~(FBF_force_software | FBF_force_hardware);
   }
 
   default_ready = true;
@@ -158,7 +172,11 @@ get_default() {
 ////////////////////////////////////////////////////////////////////
 bool FrameBufferProperties::
 operator == (const FrameBufferProperties &other) const {
-  for (int i=0; i<FBP_COUNT; i++) {
+  if ((_flags & _flags_specified) != (other._flags & other._flags_specified)) {
+    return false;
+  }
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     if (_specified[i] != other._specified[i]) {
       return false;
     }
@@ -166,6 +184,7 @@ operator == (const FrameBufferProperties &other) const {
       return false;
     }
   }
+
   return true;
 }
 
@@ -178,7 +197,10 @@ operator == (const FrameBufferProperties &other) const {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 clear() {
-  for (int i=0; i<FBP_COUNT; i++) {
+  _flags = 0;
+  _flags_specified = 0;
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     _specified[i] = 0;
     _property[i] = 0;
   }
@@ -193,7 +215,10 @@ clear() {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 add_properties(const FrameBufferProperties &other) {
-  for (int i=0; i<FBP_COUNT; i++) {
+  _flags &= ~other._flags_specified;
+  _flags |= other._flags & other._flags_specified;
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     if (other._specified[i]) {
       _property[i] = other._property[i];
       _specified[i] = true;
@@ -204,15 +229,25 @@ add_properties(const FrameBufferProperties &other) {
 ////////////////////////////////////////////////////////////////////
 //     Function: FrameBufferProperties::output
 //       Access: Published
-//  Description: Sets any properties that are explicitly specified in
-//               other on this object.  Leaves other properties
-//               unchanged.
+//  Description: Generates a string representation.
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 output(ostream &out) const {
+  if ((_flags & FBF_float_depth) != 0) {
+    out << "float_depth ";
+  }
   if (_property[FBP_depth_bits] > 0) {
     out << "depth_bits=" << _property[FBP_depth_bits] << " ";
   }
+  if ((_flags & FBF_float_color) != 0) {
+    out << "float_color ";
+  }
+  if ((_flags & FBF_srgb_color) != 0) {
+    out << "srgb_color ";
+  }
+  if ((_flags & FBF_indexed_color) != 0) {
+    out << "indexed_color ";
+  }
   if (_property[FBP_color_bits] > 0) {
     out << "color_bits=" << _property[FBP_color_bits] << " ";
   }
@@ -243,17 +278,14 @@ output(ostream &out) const {
   if (_property[FBP_back_buffers] > 0) {
     out << "back_buffers=" << _property[FBP_back_buffers] << " ";
   }
-  if (_property[FBP_indexed_color] > 0) {
-    out << "indexed_color=" << _property[FBP_indexed_color] << " ";
+  if ((_flags & FBF_stereo) != 0) {
+    out << "stereo ";
   }
-  if (_property[FBP_stereo] > 0) {
-    out << "stereo=" << _property[FBP_stereo] << " ";
+  if ((_flags & FBF_force_hardware) != 0) {
+    out << "force_hardware ";
   }
-  if (_property[FBP_force_hardware] > 0) {
-    out << "force_hardware=" << _property[FBP_force_hardware] << " ";
-  }
-  if (_property[FBP_force_software] > 0) {
-    out << "force_software=" << _property[FBP_force_software] << " ";
+  if ((_flags & FBF_force_software) != 0) {
+    out << "force_software ";
   }
 }
 
@@ -287,7 +319,7 @@ get_aux_mask() const {
 int FrameBufferProperties::
 get_buffer_mask() const {
   int mask = 0;
-  
+
   if (_property[FBP_back_buffers] > 0) {
     mask = RenderBuffer::T_front | RenderBuffer::T_back;
   } else {
@@ -310,7 +342,11 @@ get_buffer_mask() const {
 ////////////////////////////////////////////////////////////////////
 bool FrameBufferProperties::
 is_any_specified() const {
-  for (int i=0; i<FBP_COUNT; i++) {
+  if (_flags_specified != 0) {
+    return true;
+  }
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     if (_specified[i]) {
       return true;
     }
@@ -325,7 +361,9 @@ is_any_specified() const {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 set_all_specified() {
-  for (int i=0; i<FBP_COUNT; i++) {
+  _flags_specified = FBF_all;
+
+  for (int i = 0; i < FBP_COUNT; ++i) {
     _specified[i] = true;
   }
 }
@@ -370,13 +408,22 @@ is_basic() const {
   if (_property[FBP_back_buffers] > 0) {
     return false;
   }
-  if (_property[FBP_indexed_color] > 0) {
+  if ((_flags & FBF_indexed_color) != 0) {
+    return false;
+  }
+  if ((_flags & FBF_force_hardware) != 0) {
     return false;
   }
-  if (_property[FBP_force_hardware] > 0) {
+  if ((_flags & FBF_force_software) != 0) {
     return false;
   }
-  if (_property[FBP_force_software] > 0) {
+  if ((_flags & FBF_srgb_color) != 0) {
+    return false;
+  }
+  if ((_flags & FBF_float_color) != 0) {
+    return false;
+  }
+  if ((_flags & FBF_float_depth) != 0) {
     return false;
   }
   return true;
@@ -391,7 +438,7 @@ is_basic() const {
 ////////////////////////////////////////////////////////////////////
 void FrameBufferProperties::
 set_one_bit_per_channel() {
-  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; ++prop) {
+  for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) {
     if (_property[prop] > 1) {
       _property[prop] = 1;
     }
@@ -426,13 +473,13 @@ set_one_bit_per_channel() {
 int FrameBufferProperties::
 get_quality(const FrameBufferProperties &reqs) const {
 
-  if ((_property[FBP_indexed_color]==0) && (_property[FBP_rgb_color]==0)) {
+  if (!get_indexed_color() && !get_rgb_color()) {
     // Nonfunctioning window.
     return 0;
   }
-  
-  if ((reqs._property[FBP_rgb_color]      > _property[FBP_rgb_color])||
-      (reqs._property[FBP_indexed_color]  > _property[FBP_indexed_color])) {
+
+  if ((reqs.get_rgb_color() && !get_rgb_color()) ||
+      (reqs.get_indexed_color() && !get_indexed_color())) {
     // These properties are nonnegotiable.
     return 0;
   }
@@ -441,17 +488,17 @@ get_quality(const FrameBufferProperties &reqs) const {
 
   // Deduct for using the wrong kind of renderer (hardware or software).
   // Cost: 10,000,000
-  
-  if ((reqs._property[FBP_force_hardware] > _property[FBP_force_hardware])||
-      (reqs._property[FBP_force_software] > _property[FBP_force_software])) {
+
+  if ((reqs._flags & FBF_force_hardware) > (_flags & FBF_force_hardware) ||
+      (reqs._flags & FBF_force_software) > (_flags & FBF_force_software)) {
     quality -= 10000000;
   }
 
   // Deduct for missing depth, color, alpha, stencil, or accum.
   // Cost: 1,000,000
 
-  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) {
-    if ((reqs._property[prop]) && (_property[prop]==0)) {
+  for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) {
+    if (reqs._property[prop] && _property[prop] == 0) {
       quality -= 1000000;
     }
   }
@@ -459,7 +506,7 @@ get_quality(const FrameBufferProperties &reqs) const {
   // Deduct for missing aux bitplanes.
   // Cost: 100,000
 
-  for (int prop=FBP_aux_rgba; prop<=FBP_aux_float; prop++) {
+  for (int prop = FBP_aux_rgba; prop <= FBP_aux_float; ++prop) {
     if (reqs._property[prop] > _property[prop]) {
       quality -= 100000;
     }
@@ -468,13 +515,31 @@ get_quality(const FrameBufferProperties &reqs) const {
   // Deduct for stereo not enabled.
   // Cost: 100,000
 
-  if (reqs._property[FBP_stereo] > _property[FBP_stereo]) {
+  if (reqs.get_stereo() && !get_stereo()) {
+    quality -= 100000;
+  }
+
+  // Deduct for not being sRGB-capable.
+  // Cost: 100,000
+
+  if (reqs.get_srgb_color() && !get_srgb_color()) {
+    quality -= 100000;
+  }
+
+  // Deduct for not having a floating-point format if we requested it.
+  // Cost: 100,000
+
+  if (reqs.get_float_color() && !get_float_color()) {
+    quality -= 100000;
+  }
+
+  if (reqs.get_float_depth() && !get_float_depth()) {
     quality -= 100000;
   }
 
   // Deduct for insufficient back-buffers.
   // Cost: 100,000
-  
+
   if (reqs._property[FBP_back_buffers] > _property[FBP_back_buffers]) {
     quality -= 100000;
   }
@@ -488,7 +553,7 @@ get_quality(const FrameBufferProperties &reqs) const {
   // Deduct for not enough bits in depth, color, alpha, stencil, or accum.
   // Cost: 10,000
 
-  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) {
+  for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) {
     if (_property[prop] != 0 && reqs._property[prop] > _property[prop]) {
       quality -= 10000;
     }
@@ -497,33 +562,33 @@ get_quality(const FrameBufferProperties &reqs) const {
   // deduct for insufficient multisamples.
   // Cost: 1,000
 
-  if (_property[FBP_multisamples] != 0 && 
+  if (_property[FBP_multisamples] != 0 &&
       reqs._property[FBP_multisamples] > _property[FBP_multisamples]) {
     quality -= 1000;
   }
 
   // Deduct for unrequested bitplanes.
   // Cost: 50
-  
-  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) {
+
+  for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) {
     if ((_property[prop]) && (reqs._property[prop] == 0)) {
       quality -= 50;
     }
   }
-  for (int prop=FBP_aux_rgba; prop<=FBP_aux_float; prop++) {
+  for (int prop = FBP_aux_rgba; prop <= FBP_aux_float; ++prop) {
     int extra = _property[prop] > reqs._property[prop];
     if (extra > 0) {
       extra = min(extra, 3);
       quality -= extra*50;
     }
   }
-  
+
   // Deduct for excessive resolution in any bitplane (unless we asked
   // for only 1 bit, which is the convention for any amount).
 
   // Cost: 50
-  
-  for (int prop=FBP_depth_bits; prop<=FBP_accum_bits; prop++) {
+
+  for (int prop = FBP_depth_bits; prop <= FBP_accum_bits; ++prop) {
     if (reqs._property[prop] > 1 &&
         _property[prop] > reqs._property[prop]) {
       quality -= 50;
@@ -555,9 +620,9 @@ get_quality(const FrameBufferProperties &reqs) const {
       quality += _property[prop];
     }
   }
-  
+
   return quality;
-};
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: FrameBufferProperties::verify_hardware_software
@@ -594,8 +659,6 @@ verify_hardware_software(const FrameBufferProperties &props, const string &rende
       << "hardware/software configuration in your Config.prc file.\n";
     return false;
   }
-  
+
   return true;
 }
-
-

+ 37 - 21
panda/src/display/frameBufferProperties.h

@@ -44,18 +44,28 @@ private:
     FBP_multisamples,
     FBP_coverage_samples,
     FBP_back_buffers,
-    FBP_indexed_color,
-    FBP_rgb_color,
-    FBP_stereo,
-    FBP_force_hardware,
-    FBP_force_software,
-    
+
     // This is a sentinel value.
     FBP_COUNT
   };
-  
+
+  enum FrameBufferFlag {
+    FBF_indexed_color  = 0x001,
+    FBF_rgb_color      = 0x002,
+    FBF_stereo         = 0x004,
+    FBF_force_hardware = 0x008,
+    FBF_force_software = 0x010,
+    FBF_srgb_color     = 0x020,
+    FBF_float_color    = 0x040,
+    FBF_float_depth    = 0x080,
+    FBF_all            = 0x100-1,
+  };
+
   int _property[FBP_COUNT];
-  int _specified[FBP_COUNT];
+  bool _specified[FBP_COUNT];
+
+  int _flags;
+  int _flags_specified;
 
 PUBLISHED:
 
@@ -71,11 +81,14 @@ PUBLISHED:
   INLINE int get_multisamples() const;
   INLINE int get_coverage_samples() const;
   INLINE int get_back_buffers() const;
-  INLINE int get_indexed_color() const;
-  INLINE int get_rgb_color() const;
-  INLINE int get_stereo() const;
-  INLINE int get_force_hardware() const;
-  INLINE int get_force_software() const;
+  INLINE bool get_indexed_color() const;
+  INLINE bool get_rgb_color() const;
+  INLINE bool get_stereo() const;
+  INLINE bool get_force_hardware() const;
+  INLINE bool get_force_software() const;
+  INLINE bool get_srgb_color() const;
+  INLINE bool get_float_color() const;
+  INLINE bool get_float_depth() const;
 
   // Individual assigners.
   INLINE void set_depth_bits(int n);
@@ -89,11 +102,14 @@ PUBLISHED:
   INLINE void set_multisamples(int n);
   INLINE void set_coverage_samples(int n);
   INLINE void set_back_buffers(int n);
-  INLINE void set_indexed_color(int n);
-  INLINE void set_rgb_color(int n);
-  INLINE void set_stereo(int n);
-  INLINE void set_force_hardware(int n);
-  INLINE void set_force_software(int n);
+  INLINE void set_indexed_color(bool n);
+  INLINE void set_rgb_color(bool n);
+  INLINE void set_stereo(bool n);
+  INLINE void set_force_hardware(bool n);
+  INLINE void set_force_software(bool n);
+  INLINE void set_srgb_color(bool n);
+  INLINE void set_float_color(bool n);
+  INLINE void set_float_depth(bool n);
 
   // Other.
 
@@ -111,9 +127,9 @@ PUBLISHED:
   void add_properties(const FrameBufferProperties &other);
   void output(ostream &out) const;
   void set_one_bit_per_channel();
-  
-  bool is_stereo() const;
-  bool is_single_buffered() const;
+
+  INLINE bool is_stereo() const;
+  INLINE bool is_single_buffered() const;
   int get_quality(const FrameBufferProperties &reqs) const;
   bool is_any_specified() const;
   bool is_basic() const;

+ 52 - 1
panda/src/display/graphicsEngine.cxx

@@ -1094,7 +1094,58 @@ extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg) {
     return gsg->extract_texture_data(tex);
   }
 }
- 
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::dispatch_compute
+//       Access: Published
+//  Description: Asks the indicated GraphicsStateGuardian to dispatch
+//               the compute shader in the given ShaderAttrib using
+//               the given work group counts.  This can act as an
+//               interface for running a one-off compute shader,
+//               without having to store it in the scene graph using
+//               a ComputeNode.
+//
+//               Since this requires a round-trip to the draw thread,
+//               it may require waiting for the current thread to
+//               finish rendering if it is called in a multithreaded
+//               environment.  However, you can call this several
+//               consecutive times on different textures for little
+//               additional cost.
+//
+//               The return value is true if the operation is
+//               successful, false otherwise.
+////////////////////////////////////////////////////////////////////
+void GraphicsEngine::
+dispatch_compute(const LVecBase3i &work_groups, const ShaderAttrib *sattr, GraphicsStateGuardian *gsg) {
+  ReMutexHolder holder(_lock);
+
+  CPT(RenderState) state = RenderState::make(sattr);
+
+  string draw_name = gsg->get_threading_model().get_draw_name();
+  if (draw_name.empty()) {
+    // A single-threaded environment.  No problem.
+
+  } else {
+    // A multi-threaded environment.  We have to wait until the draw
+    // thread has finished its current task.
+    WindowRenderer *wr = get_window_renderer(draw_name, 0);
+    RenderThread *thread = (RenderThread *)wr;
+    MutexHolder holder2(thread->_cv_mutex);
+      
+    while (thread->_thread_state != TS_wait) {
+      thread->_cv_done.wait();
+    }
+
+    // OK, now the draw thread is idle.  That's really good enough for
+    // our purposes; we don't *actually* need to make the draw thread
+    // do the work--it's sufficient that it's not doing anything else
+    // while we access the GSG.
+  }
+
+  gsg->set_state_and_transform(state, TransformState::make_identity());
+  gsg->dispatch_compute(work_groups[0], work_groups[1], work_groups[2]);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::get_global_ptr
 //       Access: Published, Static

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

@@ -108,6 +108,9 @@ PUBLISHED:
   BLOCKING void flip_frame();
 
   bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg);
+  void dispatch_compute(const LVecBase3i &work_groups,
+                        const ShaderAttrib *sattr,
+                        GraphicsStateGuardian *gsg);
 
   static GraphicsEngine *get_global_ptr();
 

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

@@ -655,6 +655,17 @@ get_supports_tessellation_shaders() const {
   return _supports_tessellation_shaders;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_supports_compute_shaders
+//       Access: Published
+//  Description: Returns true if this particular GSG supports
+//               compute shaders.
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsStateGuardian::
+get_supports_compute_shaders() const {
+  return _supports_compute_shaders;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_supports_glsl
 //       Access: Published

+ 35 - 13
panda/src/display/graphicsStateGuardian.cxx

@@ -754,6 +754,17 @@ end_occlusion_query() {
   return result;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::dispatch_compute
+//       Access: Public, Virtual
+//  Description: Dispatches a currently bound compute shader using
+//               the given work group counts.
+////////////////////////////////////////////////////////////////////
+void GraphicsStateGuardian::
+dispatch_compute(int num_groups_x, int num_groups_y, int num_groups_z) {
+  nassertv(false /* Compute shaders not supported by GSG */);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_geom_munger
 //       Access: Public, Virtual
@@ -1145,9 +1156,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 &
     return &t;
   }
   case Shader::SMO_mat_constant_x: {
-    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
-    nassertr(!np.is_empty(), &LMatrix4::ident_mat());
-    return &(np.node()->get_transform()->get_mat());
+    return &_target_shader->get_shader_input_matrix(name, t);
   }
   case Shader::SMO_vec_constant_x: {
     const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
@@ -1169,8 +1178,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 &
     return &(get_external_transform()->get_mat());
   }
   case Shader::SMO_view_to_model: {
-    // DANGER: SLOW AND NOT CACHEABLE!
-    t.invert_from(get_external_transform()->get_mat());
+    t = get_external_transform()->get_inverse()->get_mat();
     return &t;
   }
   case Shader::SMO_apiview_to_view: {
@@ -1216,7 +1224,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 &
     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4::ident_mat());
     t = get_scene()->get_camera_transform()->get_mat() *
-      invert(np.get_net_transform()->get_mat());
+      np.get_net_transform()->get_inverse()->get_mat();
     return &t;
   }
   case Shader::SMO_apiview_x_to_view: {
@@ -1231,7 +1239,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 &
     const NodePath &np = _target_shader->get_shader_input_nodepath(name);
     nassertr(!np.is_empty(), &LMatrix4::ident_mat());
     t = (get_scene()->get_camera_transform()->get_mat() *
-         invert(np.get_net_transform()->get_mat()) *
+         np.get_net_transform()->get_inverse()->get_mat() *
          LMatrix4::convert_mat(_coordinate_system, _internal_coordinate_system));
     return &t;
   }
@@ -1252,21 +1260,35 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 &
     nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
     Lens *lens = DCAST(LensNode, np.node())->get_lens();
     t = get_scene()->get_camera_transform()->get_mat() *
-      invert(np.get_net_transform()->get_mat()) *
+      np.get_net_transform()->get_inverse()->get_mat() *
       LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) *
       lens->get_projection_mat(_current_stereo_channel);
     return &t;
   }
   case Shader::SMO_apiclip_x_to_view: {
-    // NOT IMPLEMENTED
-    return &LMatrix4::ident_mat();
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
+    nassertr(!np.is_empty(), &LMatrix4::ident_mat());
+    nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
+    Lens *lens = DCAST(LensNode, np.node())->get_lens();
+    t = calc_projection_mat(lens)->get_inverse()->get_mat() *
+      get_cs_transform_for(lens->get_coordinate_system())->get_inverse()->get_mat() *
+      np.get_net_transform()->get_mat() *
+      get_scene()->get_world_transform()->get_mat();
+    return &t;
   }
   case Shader::SMO_view_to_apiclip_x: {
-    // NOT IMPLEMENTED
-    return &LMatrix4::ident_mat();
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name);
+    nassertr(!np.is_empty(), &LMatrix4::ident_mat());
+    nassertr(np.node()->is_of_type(LensNode::get_class_type()), &LMatrix4::ident_mat());
+    Lens *lens = DCAST(LensNode, np.node())->get_lens();
+    t = get_scene()->get_camera_transform()->get_mat() *
+      np.get_net_transform()->get_inverse()->get_mat() *
+      get_cs_transform_for(lens->get_coordinate_system())->get_mat() *
+      calc_projection_mat(lens)->get_mat();
+    return &t;
   }
   default:
-    // should never get here
+    nassertr(false /*should never get here*/, &LMatrix4::ident_mat());
     return &LMatrix4::ident_mat();
   }
 }

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

@@ -145,6 +145,7 @@ PUBLISHED:
   INLINE bool get_supports_basic_shaders() const;
   INLINE bool get_supports_geometry_shaders() const;
   INLINE bool get_supports_tessellation_shaders() const;
+  INLINE bool get_supports_compute_shaders() const;
   INLINE bool get_supports_glsl() const;
   INLINE bool get_supports_stencil() const;
   INLINE bool get_supports_two_sided_stencil() const;
@@ -225,6 +226,8 @@ public:
   virtual void begin_occlusion_query();
   virtual PT(OcclusionQueryContext) end_occlusion_query();
 
+  virtual void dispatch_compute(int size_x, int size_y, int size_z);
+
   virtual PT(GeomMunger) get_geom_munger(const RenderState *state,
                                          Thread *current_thread);
   virtual PT(GeomMunger) make_geom_munger(const RenderState *state,
@@ -487,10 +490,11 @@ protected:
   bool _supports_basic_shaders;
   bool _supports_geometry_shaders;
   bool _supports_tessellation_shaders;
+  bool _supports_compute_shaders;
   bool _supports_glsl;
   bool _supports_framebuffer_multisample;
   bool _supports_framebuffer_blit;
-  
+
   bool _supports_stencil;
   bool _supports_stencil_wrap;
   bool _supports_two_sided_stencil;

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

@@ -109,10 +109,10 @@ set_pixel_zoom(PN_stdfloat pixel_zoom) {
 //               indicated dimensions.
 ////////////////////////////////////////////////////////////////////
 void StereoDisplayRegion::
-set_dimensions(const LVecBase4 &dimensions) {
-  DisplayRegion::set_dimensions(dimensions);
-  _left_eye->set_dimensions(dimensions);
-  _right_eye->set_dimensions(dimensions);
+set_dimensions(int i, const LVecBase4 &dimensions) {
+  DisplayRegion::set_dimensions(i, dimensions);
+  _left_eye->set_dimensions(i, dimensions);
+  _right_eye->set_dimensions(i, dimensions);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/display/stereoDisplayRegion.h

@@ -51,7 +51,7 @@ PUBLISHED:
   virtual void set_pixel_zoom(PN_stdfloat pixel_zoom);
 
   // Inherited from DisplayRegion
-  virtual void set_dimensions(const LVecBase4 &dimensions);
+  virtual void set_dimensions(int i, const LVecBase4 &dimensions);
   virtual bool is_stereo() const;
   virtual void set_camera(const NodePath &camera);
   virtual void set_active(bool active);

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

@@ -53,6 +53,21 @@ is_any_specified() const {
   return (_specified != 0);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::set_origin
+//       Access: Published
+//  Description: Specifies the origin on the screen (in pixels,
+//               relative to the top-left corner) at which the window
+//               should appear.  This is the origin of the top-left
+//               corner of the useful part of the window, not
+//               including decorations.
+////////////////////////////////////////////////////////////////////
+INLINE void WindowProperties::
+set_origin(const LPoint2i &origin) {
+  _origin = origin;
+  _specified |= S_origin;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: WindowProperties::set_origin
 //       Access: Published
@@ -64,11 +79,22 @@ is_any_specified() const {
 ////////////////////////////////////////////////////////////////////
 INLINE void WindowProperties::
 set_origin(int x_origin, int y_origin) {
-  _x_origin = x_origin;
-  _y_origin = y_origin;
+  _origin.set(x_origin, y_origin);
   _specified |= S_origin;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::get_origin
+//       Access: Published
+//  Description: Returns the coordinates of the window's top-left
+//               corner, not including decorations.
+////////////////////////////////////////////////////////////////////
+INLINE const LPoint2i &WindowProperties::
+get_origin() const {
+  nassertr(has_origin(), LPoint2i::zero());
+  return _origin;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: WindowProperties::get_x_origin
 //       Access: Published
@@ -78,7 +104,7 @@ set_origin(int x_origin, int y_origin) {
 INLINE int WindowProperties::
 get_x_origin() const {
   nassertr(has_origin(), 0);
-  return _x_origin;
+  return _origin.get_x();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -90,7 +116,7 @@ get_x_origin() const {
 INLINE int WindowProperties::
 get_y_origin() const {
   nassertr(has_origin(), 0);
-  return _y_origin;
+  return _origin.get_y();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -112,8 +138,20 @@ has_origin() const {
 INLINE void WindowProperties::
 clear_origin() {
   _specified &= ~S_origin;
-  _x_origin = 0;
-  _y_origin = 0;
+  _origin = LPoint2i::zero();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::set_size
+//       Access: Published
+//  Description: Specifies the requested size of the window, in
+//               pixels.  This is the size of the useful part of the
+//               window, not including decorations.
+////////////////////////////////////////////////////////////////////
+INLINE void WindowProperties::
+set_size(const LVector2i &size) {
+  _size = size;
+  _specified |= S_size;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -125,11 +163,22 @@ clear_origin() {
 ////////////////////////////////////////////////////////////////////
 INLINE void WindowProperties::
 set_size(int x_size, int y_size) {
-  _x_size = x_size;
-  _y_size = y_size;
+  _size.set(x_size, y_size);
   _specified |= S_size;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: WindowProperties::get_origin
+//       Access: Published
+//  Description: Returns size in pixels of the useful part of the
+//               window, not including decorations.
+////////////////////////////////////////////////////////////////////
+INLINE const LVector2i &WindowProperties::
+get_size() const {
+  nassertr(has_size(), LVector2i::zero());
+  return _size;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: WindowProperties::get_x_size
 //       Access: Published
@@ -140,7 +189,7 @@ set_size(int x_size, int y_size) {
 INLINE int WindowProperties::
 get_x_size() const {
   nassertr(has_size(), 0);
-  return _x_size;
+  return _size.get_x();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -153,7 +202,7 @@ get_x_size() const {
 INLINE int WindowProperties::
 get_y_size() const {
   nassertr(has_size(), 0);
-  return _y_size;
+  return _size.get_y();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -175,8 +224,7 @@ has_size() const {
 INLINE void WindowProperties::
 clear_size() {
   _specified &= ~S_size;
-  _x_size = 0;
-  _y_size = 0;
+  _size = LVector2i::zero();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 8 - 14
panda/src/display/windowProperties.cxx

@@ -36,10 +36,8 @@ WindowProperties() {
 void WindowProperties::
 operator = (const WindowProperties &copy) {
   _specified = copy._specified;
-  _x_origin = copy._x_origin;
-  _y_origin = copy._y_origin;
-  _x_size = copy._x_size;
-  _y_size = copy._y_size;
+  _origin = copy._origin;
+  _size = copy._size;
   _title = copy._title;
   _icon_filename = copy._icon_filename;
   _cursor_filename = copy._cursor_filename;
@@ -169,10 +167,8 @@ bool WindowProperties::
 operator == (const WindowProperties &other) const {
   return (_specified == other._specified &&
           _flags == other._flags &&
-          _x_origin == other._x_origin &&
-          _y_origin == other._y_origin &&
-          _x_size == other._x_size &&
-          _y_size == other._y_size &&
+          _origin == other._origin &&
+          _size == other._size &&
           _z_order == other._z_order &&
           _title == other._title &&
           _icon_filename == other._icon_filename &&
@@ -191,10 +187,8 @@ operator == (const WindowProperties &other) const {
 void WindowProperties::
 clear() {
   _specified = 0;
-  _x_origin = 0;
-  _y_origin = 0;
-  _x_size = 0;
-  _y_size = 0;
+  _origin = LPoint2i::zero();
+  _size = LVector2i::zero();
   _title = string();
   _icon_filename = Filename();
   _cursor_filename = Filename();
@@ -244,10 +238,10 @@ set_parent_window(size_t parent) {
 void WindowProperties::
 add_properties(const WindowProperties &other) {
   if (other.has_origin()) {
-    set_origin(other.get_x_origin(), other.get_y_origin());
+    set_origin(other.get_origin());
   }
   if (other.has_size()) {
-    set_size(other.get_x_size(), other.get_y_size());
+    set_size(other.get_size());
   }
   if (other.has_title()) {
     set_title(other.get_title());

+ 11 - 7
panda/src/display/windowProperties.h

@@ -19,7 +19,9 @@
 #include "filename.h"
 #include "pnotify.h"
 #include "windowHandle.h"
-   
+#include "lpoint2.h"
+#include "lvector2.h"
+
 ////////////////////////////////////////////////////////////////////
 //       Class : WindowProperties
 // Description : A container for the various kinds of properties we
@@ -57,14 +59,18 @@ PUBLISHED:
 
   void clear();
   INLINE bool is_any_specified() const;
-  
+
+  INLINE void set_origin(const LPoint2i &origin);
   INLINE void set_origin(int x_origin, int y_origin);
+  INLINE const LPoint2i &get_origin() const;
   INLINE int get_x_origin() const;
   INLINE int get_y_origin() const;
   INLINE bool has_origin() const;
   INLINE void clear_origin();
 
+  INLINE void set_size(const LVector2i &size);
   INLINE void set_size(int x_size, int y_size);
+  INLINE const LVector2i &get_size() const;
   INLINE int get_x_size() const;
   INLINE int get_y_size() const;
   INLINE bool has_size() const;
@@ -73,7 +79,7 @@ PUBLISHED:
   INLINE bool has_mouse_mode() const;
   INLINE void set_mouse_mode(MouseMode mode);
   INLINE MouseMode get_mouse_mode() const;
-  INLINE void clear_mouse_mode();  
+  INLINE void clear_mouse_mode();
 
   INLINE void set_title(const string &title);
   INLINE const string &get_title() const;
@@ -183,10 +189,8 @@ private:
   };
 
   int _specified;
-  int _x_origin;
-  int _y_origin;
-  int _x_size;
-  int _y_size;
+  LPoint2i _origin;
+  LVector2i _size;
   MouseMode _mouse_mode;
   string _title;
   Filename _cursor_filename;

+ 2 - 4
panda/src/egldisplay/eglGraphicsStateGuardian.cxx

@@ -390,8 +390,6 @@ get_extra_extensions() {
 //               not defined.
 ////////////////////////////////////////////////////////////////////
 void *eglGraphicsStateGuardian::
-do_get_extension_func(const char *prefix, const char *name) {
-  string fullname = string(prefix) + string(name);
-
-  return (void *)eglGetProcAddress(fullname.c_str());
+do_get_extension_func(const char *name) {
+  return (void *)eglGetProcAddress(name);
 }

+ 1 - 1
panda/src/egldisplay/eglGraphicsStateGuardian.h

@@ -64,7 +64,7 @@ protected:
 
   virtual void query_gl_version();
   virtual void get_extra_extensions();
-  virtual void *do_get_extension_func(const char *prefix, const char *name);
+  virtual void *do_get_extension_func(const char *name);
 
 private:
   int _egl_version_major, _egl_version_minor;

+ 19 - 1
panda/src/gles2gsg/gles2gsg.h

@@ -96,11 +96,29 @@ typedef char GLchar;
 #define GL_RG16F GL_RG16F_EXT
 #define GL_RGB16F GL_RGB16F_EXT
 #define GL_RGBA16F GL_RGBA16F_EXT
+#define GL_RGB16F GL_RGB16F_EXT
+#define GL_RGBA16F GL_RGBA16F_EXT
+#define GL_RGB32F GL_RGB32F_EXT
+#define GL_RGBA32F GL_RGBA32F_EXT
+#define GL_DEBUG_SEVERITY_HIGH GL_DEBUG_SEVERITY_HIGH_KHR
+#define GL_DEBUG_SEVERITY_MEDIUM GL_DEBUG_SEVERITY_MEDIUM_KHR
+#define GL_DEBUG_SEVERITY_LOW GL_DEBUG_SEVERITY_LOW_KHR
+#define GL_DEBUG_SEVERITY_NOTIFICATION GL_DEBUG_SEVERITY_NOTIFICATION_KHR
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR
+#define GL_FRAMEBUFFER_SRGB GL_FRAMEBUFFER_SRGB_EXT
+#define GL_SRGB GL_SRGB_EXT
+#define GL_SRGB_ALPHA GL_SRGB_ALPHA_EXT
+#define GL_SRGB8 GL_SRGB8_EXT
+#define GL_SRGB8_ALPHA GL_SRGB8_ALPHA_EXT
+#define GL_SLUMINANCE GL_SLUMINANCE_NV
+#define GL_SLUMINANCE_ALPHA GL_SLUMINANCE_ALPHA_NV
+#define GL_SLUMINANCE8 GL_SLUMINANCE8_NV
+#define GL_SLUMINANCE8_ALPHA GL_SLUMINANCE8_ALPHA_NV
 
 #undef SUPPORT_IMMEDIATE_MODE
 #define APIENTRY
 #define APIENTRYP *
 
 #include "glstuff_src.h"
- 
+
 #endif  // GLES2GSG_H

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

@@ -110,11 +110,15 @@
 #define GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT_OES
 #define GL_FUNC_REVERSE_SUBTRACT GL_FUNC_REVERSE_SUBTRACT_OES
 #define GL_BGRA GL_BGRA_EXT
+#define GL_RGB16F GL_RGB16F_EXT
+#define GL_RGBA16F GL_RGBA16F_EXT
+#define GL_RGB32F GL_RGB32F_EXT
+#define GL_RGBA32F GL_RGBA32F_EXT
 
 #undef SUPPORT_IMMEDIATE_MODE
 #define APIENTRY
 #define APIENTRYP *
 
 #include "glstuff_src.h"
- 
+
 #endif  // GLESGSG_H

+ 67 - 0
panda/src/glstuff/glCgShaderContext_src.I

@@ -0,0 +1,67 @@
+// Filename: glCgShaderContext_src.h
+// Created by: rdb (27Jun14)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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 OPENGLES_1
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::valid
+//       Access: Public
+//  Description: Returns true if the shader is "valid", ie, if the
+//               compilation was successful.  The compilation could
+//               fail if there is a syntax error in the shader, or
+//               if the current video card isn't shader-capable,
+//               or if no shader languages are compiled into panda.
+////////////////////////////////////////////////////////////////////
+INLINE bool CLP(CgShaderContext)::
+valid() {
+  if (_shader->get_error_flag()) return false;
+  if (_shader->get_language() != Shader::SL_Cg) return false;
+  if (_cg_context) return true;
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::uses_standard_vertex_arrays
+//       Access: Public
+//  Description: Returns true if the shader may need to access
+//               standard vertex attributes as passed by
+//               glVertexPointer and the like.
+////////////////////////////////////////////////////////////////////
+INLINE bool CLP(CgShaderContext)::
+uses_standard_vertex_arrays() {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::uses_custom_vertex_arrays
+//       Access: Public
+//  Description: Always true, for now.
+////////////////////////////////////////////////////////////////////
+INLINE bool CLP(CgShaderContext)::
+uses_custom_vertex_arrays() {
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::uses_custom_texture_bindings
+//       Access: Public
+//  Description: Always true, for now.
+////////////////////////////////////////////////////////////////////
+INLINE bool CLP(CgShaderContext)::
+uses_custom_texture_bindings() {
+  return true;
+}
+
+#endif  // OPENGLES_1
+

+ 619 - 0
panda/src/glstuff/glCgShaderContext_src.cxx

@@ -0,0 +1,619 @@
+// Filename: glCgShaderContext_src.cxx
+// Created by: jyelon (01Sep05)
+// Updated by: fperazzi, PandaSE (29Apr10) (updated CLP with note that some
+//   parameter types only supported under Cg)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+#if defined(HAVE_CG) && !defined(OPENGLES)
+
+#include "Cg/cgGL.h"
+
+#include "pStatTimer.h"
+
+TypeHandle CLP(CgShaderContext)::_type_handle;
+
+#ifndef NDEBUG
+#define cg_report_errors() { \
+  CGerror err = cgGetError(); \
+  if (err != CG_NO_ERROR) { \
+    GLCAT.error() << __FILE__ ", line " << __LINE__ << ": " << cgGetErrorString(err) << "\n"; \
+  } }
+#else
+#define cg_report_errors()
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::Constructor
+//       Access: Public
+//  Description: xyz
+////////////////////////////////////////////////////////////////////
+CLP(CgShaderContext)::
+CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext(s) {
+  _glgsg = glgsg;
+  _cg_context = 0;
+  _cg_vprogram = 0;
+  _cg_fprogram = 0;
+  _cg_gprogram = 0;
+  _cg_vprofile = CG_PROFILE_UNKNOWN;
+  _cg_fprofile = CG_PROFILE_UNKNOWN;
+  _cg_gprofile = CG_PROFILE_UNKNOWN;
+
+  nassertv(s->get_language() == Shader::SL_Cg);
+
+  // Ask the shader to compile itself for us and 
+  // to give us the resulting Cg program objects.
+  if (!s->cg_compile_for(_glgsg->_shader_caps,
+                         _cg_context,
+                         _cg_vprogram,
+                         _cg_fprogram,
+                         _cg_gprogram,
+                         _cg_parameter_map)) {
+    return;
+  }
+
+  // Load the program.
+  if (_cg_vprogram != 0) {
+    _cg_vprofile = cgGetProgramProfile(_cg_vprogram);
+    cgGLLoadProgram(_cg_vprogram);
+    CGerror verror = cgGetError();
+    if (verror != CG_NO_ERROR) {
+      const char *str = cgGetErrorString(verror);
+      GLCAT.error()
+        << "Could not load Cg vertex program: " << s->get_filename(Shader::ST_vertex)
+        << " (" << cgGetProfileString(_cg_vprofile) << " " << str << ")\n";
+      release_resources();
+    }
+  }
+
+  if (_cg_fprogram != 0) {
+    _cg_fprofile = cgGetProgramProfile(_cg_fprogram);
+    cgGLLoadProgram(_cg_fprogram);
+    CGerror ferror = cgGetError();
+    if (ferror != CG_NO_ERROR) {
+      const char *str = cgGetErrorString(ferror);
+      GLCAT.error()
+        << "Could not load Cg fragment program: " << s->get_filename(Shader::ST_fragment)
+        << " (" << cgGetProfileString(_cg_fprofile) << " " << str << ")\n";
+      release_resources();
+    }
+  }
+
+  if (_cg_gprogram != 0) {
+    _cg_gprofile = cgGetProgramProfile(_cg_gprogram);
+    cgGLLoadProgram(_cg_gprogram);
+    CGerror gerror = cgGetError();
+    if (gerror != CG_NO_ERROR) {
+      const char *str = cgGetErrorString(gerror);
+      GLCAT.error()
+        << "Could not load Cg geometry program: " << s->get_filename(Shader::ST_geometry)
+        << " (" << cgGetProfileString(_cg_gprofile) << " " << str << ")\n";
+      release_resources();
+    }
+  }
+
+  _glgsg->report_my_gl_errors();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::Destructor
+//       Access: Public
+//  Description: xyz
+////////////////////////////////////////////////////////////////////
+CLP(CgShaderContext)::
+~CLP(CgShaderContext)() {
+  release_resources();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::release_resources
+//       Access: Public
+//  Description: Should deallocate all system resources (such as
+//               vertex program handles or Cg contexts).
+////////////////////////////////////////////////////////////////////
+void CLP(CgShaderContext)::
+release_resources() {
+  if (_cg_context) {
+    cgDestroyContext(_cg_context);
+    _cg_context  = 0;
+    // Do *NOT* destroy the programs here! It causes problems.
+//  if (_cg_vprogram != 0) cgDestroyProgram(_cg_vprogram);
+//  if (_cg_fprogram != 0) cgDestroyProgram(_cg_fprogram);
+//  if (_cg_gprogram != 0) cgDestroyProgram(_cg_gprogram);
+    _cg_vprogram = 0;
+    _cg_fprogram = 0;
+    _cg_gprogram = 0;
+    _cg_parameter_map.clear();
+  }
+  if (_glgsg) {
+    _glgsg->report_my_gl_errors();
+  } else if (glGetError() != GL_NO_ERROR) {
+    GLCAT.error() << "GL error in ShaderContext destructor\n";
+  }
+
+  if (!_glgsg) {
+    return;
+  }
+  _glgsg->report_my_gl_errors();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::bind
+//       Access: Public
+//  Description: This function is to be called to enable a new
+//               shader.  It also initializes all of the shader's
+//               input parameters.
+////////////////////////////////////////////////////////////////////
+void CLP(CgShaderContext)::
+bind(bool reissue_parameters) {
+  if (reissue_parameters) {
+    // Pass in k-parameters and transform-parameters
+    issue_parameters(Shader::SSD_general);
+  }
+
+  if (_cg_context != 0) {
+    // Bind the shaders.
+    if (_cg_vprogram != 0) {
+      cgGLEnableProfile(_cg_vprofile);
+      cgGLBindProgram(_cg_vprogram);
+    }
+    if (_cg_fprogram != 0) {
+      cgGLEnableProfile(_cg_fprofile);
+      cgGLBindProgram(_cg_fprogram);
+    }
+    if (_cg_gprogram != 0) {
+      cgGLEnableProfile(_cg_gprofile);
+      cgGLBindProgram(_cg_gprogram);
+    }
+
+    cg_report_errors();
+    _glgsg->report_my_gl_errors();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::unbind
+//       Access: Public
+//  Description: This function disables a currently-bound shader.
+////////////////////////////////////////////////////////////////////
+void CLP(CgShaderContext)::
+unbind() {
+  if (_cg_context != 0) {
+    if (_cg_vprogram != 0) {
+      cgGLUnbindProgram(_cg_vprofile);
+      cgGLDisableProfile(_cg_vprofile);
+    }
+    if (_cg_fprogram != 0) {
+      cgGLUnbindProgram(_cg_fprofile);
+      cgGLDisableProfile(_cg_fprofile);
+    }
+    if (_cg_gprogram != 0) {
+      cgGLUnbindProgram(_cg_gprofile);
+      cgGLDisableProfile(_cg_gprofile);
+    }
+
+    cg_report_errors();
+    _glgsg->report_my_gl_errors();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::issue_parameters
+//       Access: Public
+//  Description: This function gets called whenever the RenderState
+//               or TransformState has changed, but the Shader
+//               itself has not changed.  It loads new values into the
+//               shader's parameters.
+//
+//               If "altered" is false, that means you promise that
+//               the parameters for this shader context have already
+//               been issued once, and that since the last time the
+//               parameters were issued, no part of the render
+//               state has changed except the external and internal
+//               transforms.
+////////////////////////////////////////////////////////////////////
+void CLP(CgShaderContext)::
+issue_parameters(int altered) {
+  PStatTimer timer(_glgsg->_draw_set_state_shader_parameters_pcollector);
+
+  if (!valid()) {
+    return;
+  }
+
+  // Iterate through _ptr parameters
+  for (int i=0; i<(int)_shader->_ptr_spec.size(); i++) {
+    if (altered & (_shader->_ptr_spec[i]._dep[0] | _shader->_ptr_spec[i]._dep[1])) {
+      const Shader::ShaderPtrSpec& _ptr = _shader->_ptr_spec[i];
+      Shader::ShaderPtrData* ptr_data = 
+        const_cast< Shader::ShaderPtrData*>(_glgsg->fetch_ptr_parameter(_ptr));
+      
+      if (ptr_data == NULL){ //the input is not contained in ShaderPtrData
+        release_resources();
+        return;
+      }
+      //check if the data must be shipped to the GPU
+      /*if (!ptr_data->_updated)
+        continue;
+        ptr_data->_updated = false;*/
+
+      //Check if the size of the shader input and ptr_data match
+      int input_size = _ptr._dim[0] * _ptr._dim[1] * _ptr._dim[2];
+
+      // dimension is negative only if the parameter had the (deprecated)k_ prefix.
+      if ((input_size > ptr_data->_size) && (_ptr._dim[0] > 0)) { 
+        GLCAT.error() << _ptr._id._name << ": incorrect number of elements, expected " 
+                      <<  input_size <<" got " <<  ptr_data->_size << "\n";
+        release_resources();
+        return;
+      }
+      CGparameter p = _cg_parameter_map[_ptr._id._seqno];
+      
+      switch (ptr_data->_type) {
+      case Shader::SPT_float:
+        switch(_ptr._info._class) {
+        case Shader::SAC_scalar: cgSetParameter1fv(p,(float*)ptr_data->_ptr); continue;
+        case Shader::SAC_vector:
+          switch(_ptr._info._type) {
+          case Shader::SAT_vec1: cgSetParameter1fv(p,(float*)ptr_data->_ptr); continue;
+          case Shader::SAT_vec2: cgSetParameter2fv(p,(float*)ptr_data->_ptr); continue;
+          case Shader::SAT_vec3: cgSetParameter3fv(p,(float*)ptr_data->_ptr); continue;
+          case Shader::SAT_vec4: cgSetParameter4fv(p,(float*)ptr_data->_ptr); continue;
+          }
+        case Shader::SAC_matrix: cgGLSetMatrixParameterfc(p,(float*)ptr_data->_ptr); continue;
+        case Shader::SAC_array: {
+          switch(_ptr._info._subclass) {
+          case Shader::SAC_scalar: 
+            cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue;
+          case Shader::SAC_vector:
+            switch(_ptr._dim[2]) {
+            case 1: cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue;
+            case 2: cgGLSetParameterArray2f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue;
+            case 3: cgGLSetParameterArray3f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue;
+            case 4: cgGLSetParameterArray4f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue;
+            }
+          case Shader::SAC_matrix:
+            cgGLSetMatrixParameterArrayfc(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue;
+          }
+        }
+        }
+      case Shader::SPT_double:
+        switch(_ptr._info._class) {
+        case Shader::SAC_scalar: cgSetParameter1dv(p,(double*)ptr_data->_ptr); continue;
+        case Shader::SAC_vector:
+          switch(_ptr._info._type) {
+          case Shader::SAT_vec1: cgSetParameter1dv(p,(double*)ptr_data->_ptr); continue;
+          case Shader::SAT_vec2: cgSetParameter2dv(p,(double*)ptr_data->_ptr); continue;
+          case Shader::SAT_vec3: cgSetParameter3dv(p,(double*)ptr_data->_ptr); continue;
+          case Shader::SAT_vec4: cgSetParameter4dv(p,(double*)ptr_data->_ptr); continue;
+          }
+        case Shader::SAC_matrix: cgGLSetMatrixParameterdc(p,(double*)ptr_data->_ptr); continue;
+        case Shader::SAC_array: {
+          switch(_ptr._info._subclass) {
+          case Shader::SAC_scalar: 
+            cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue;
+          case Shader::SAC_vector:
+            switch(_ptr._dim[2]) {
+            case 1: cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue;
+            case 2: cgGLSetParameterArray2d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue;
+            case 3: cgGLSetParameterArray3d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue;
+            case 4: cgGLSetParameterArray4d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue;
+            }
+          case Shader::SAC_matrix:
+            cgGLSetMatrixParameterArraydc(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue;
+          }
+        }
+        }
+      case Shader::SPT_int:
+        switch(_ptr._info._class) {
+        case Shader::SAC_scalar: cgSetParameter1iv(p,(int*)ptr_data->_ptr); continue;
+        case Shader::SAC_vector:
+          switch(_ptr._info._type) {
+          case Shader::SAT_vec1: cgSetParameter1iv(p,(int*)ptr_data->_ptr); continue;
+          case Shader::SAT_vec2: cgSetParameter2iv(p,(int*)ptr_data->_ptr); continue;
+          case Shader::SAT_vec3: cgSetParameter3iv(p,(int*)ptr_data->_ptr); continue;
+          case Shader::SAT_vec4: cgSetParameter4iv(p,(int*)ptr_data->_ptr); continue;
+          }
+        }
+      default: GLCAT.error() << _ptr._id._name << ":" << "unrecognized parameter type\n"; 
+        release_resources(); 
+        return;
+      }
+    }
+  }
+
+  for (int i=0; i<(int)_shader->_mat_spec.size(); i++) {
+    if (altered & (_shader->_mat_spec[i]._dep[0] | _shader->_mat_spec[i]._dep[1])) {
+      const LMatrix4 *val = _glgsg->fetch_specified_value(_shader->_mat_spec[i], altered);
+      if (!val) continue;
+#ifndef STDFLOAT_DOUBLE
+      // In this case, the data is already single-precision.
+      const PN_float32 *data = val->get_data();
+#else
+      // In this case, we have to convert it.
+      LMatrix4f valf = LCAST(PN_float32, *val);
+      const PN_float32 *data = valf.get_data();
+#endif
+
+      CGparameter p = _cg_parameter_map[_shader->_mat_spec[i]._id._seqno];
+      switch (_shader->_mat_spec[i]._piece) {
+      case Shader::SMP_whole: GLfc(cgGLSetMatrixParameter)(p, data); continue;
+      case Shader::SMP_transpose: GLfr(cgGLSetMatrixParameter)(p, data); continue;
+      case Shader::SMP_col0: GLf(cgGLSetParameter4)(p, data[0], data[4], data[ 8], data[12]); continue;
+      case Shader::SMP_col1: GLf(cgGLSetParameter4)(p, data[1], data[5], data[ 9], data[13]); continue;
+      case Shader::SMP_col2: GLf(cgGLSetParameter4)(p, data[2], data[6], data[10], data[14]); continue;
+      case Shader::SMP_col3: GLf(cgGLSetParameter4)(p, data[3], data[7], data[11], data[15]); continue;
+      case Shader::SMP_row0: GLfv(cgGLSetParameter4)(p, data+ 0); continue;
+      case Shader::SMP_row1: GLfv(cgGLSetParameter4)(p, data+ 4); continue;
+      case Shader::SMP_row2: GLfv(cgGLSetParameter4)(p, data+ 8); continue;
+      case Shader::SMP_row3: GLfv(cgGLSetParameter4)(p, data+12); continue;
+      case Shader::SMP_row3x1: GLfv(cgGLSetParameter1)(p, data+12); continue;
+      case Shader::SMP_row3x2: GLfv(cgGLSetParameter2)(p, data+12); continue;
+      case Shader::SMP_row3x3: GLfv(cgGLSetParameter3)(p, data+12); continue;
+      case Shader::SMP_upper3x3:
+        {
+          LMatrix3f upper3 = val->get_upper_3();
+          GLfc(cgGLSetMatrixParameter)(p, upper3.get_data());
+          continue;
+        }
+      case Shader::SMP_transpose3x3:
+        {
+          LMatrix3f upper3 = val->get_upper_3();
+          GLfr(cgGLSetMatrixParameter)(p, upper3.get_data());
+          continue;
+        }
+      case Shader::SMP_cell15:
+        GLf(cgGLSetParameter1)(p, data[15]);
+        continue;
+      }
+    }
+  }
+
+  _glgsg->report_my_gl_errors();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::disable_shader_vertex_arrays
+//       Access: Public
+//  Description: Disable all the vertex arrays used by this shader.
+////////////////////////////////////////////////////////////////////
+void CLP(CgShaderContext)::
+disable_shader_vertex_arrays() {
+  if (!valid()) {
+    return;
+  }
+
+  for (int i=0; i<(int)_shader->_var_spec.size(); i++) {
+    CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno];
+    if (p == 0) continue;
+    cgGLDisableClientState(p);
+  }
+
+  cg_report_errors();
+  _glgsg->report_my_gl_errors();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::update_shader_vertex_arrays
+//       Access: Public
+//  Description: Disables all vertex arrays used by the previous
+//               shader, then enables all the vertex arrays needed
+//               by this shader.  Extracts the relevant vertex array
+//               data from the gsg.
+//               The current implementation is inefficient, because
+//               it may unnecessarily disable arrays then immediately
+//               reenable them.  We may optimize this someday.
+////////////////////////////////////////////////////////////////////
+bool CLP(CgShaderContext)::
+update_shader_vertex_arrays(ShaderContext *prev, bool force) {
+  if (prev) {
+    prev->disable_shader_vertex_arrays();
+  }
+
+  if (!valid()) {
+    return true;
+  }
+
+  cg_report_errors();
+
+#ifdef SUPPORT_IMMEDIATE_MODE
+  if (_glgsg->_use_sender) {
+    GLCAT.error() << "immediate mode shaders not implemented yet\n";
+  } else
+#endif // SUPPORT_IMMEDIATE_MODE
+  {
+    const GeomVertexArrayDataHandle *array_reader;
+    Geom::NumericType numeric_type;
+    int start, stride, num_values;
+    int nvarying = _shader->_var_spec.size();
+    for (int i = 0; i < nvarying; ++i) {
+      if (_cg_parameter_map[_shader->_var_spec[i]._id._seqno] == 0) {
+        continue;
+      }
+
+      InternalName *name = _shader->_var_spec[i]._name;
+      int texslot = _shader->_var_spec[i]._append_uv;
+      if (texslot >= 0 && texslot < _glgsg->_state_texture->get_num_on_stages()) {
+        TextureStage *stage = _glgsg->_state_texture->get_on_stage(texslot);
+        InternalName *texname = stage->get_texcoord_name();
+
+        if (name == InternalName::get_texcoord()) {
+          name = texname;
+        } else if (texname != InternalName::get_texcoord()) {
+          name = name->append(texname->get_basename());
+        }
+      }
+      if (_glgsg->_data_reader->get_array_info(name,
+                                               array_reader, num_values, numeric_type,
+                                               start, stride)) {
+        const unsigned char *client_pointer;
+        if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) {
+          return false;
+        }
+
+        CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno];
+
+        if (numeric_type == GeomEnums::NT_packed_dabc) {
+          cgGLSetParameterPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
+                                  stride, client_pointer + start);
+        } else {
+          if (name == InternalName::get_normal() && num_values == 4) {
+            // In some cases, the normals are aligned to 4 values.
+            // This would cause an error on some rivers, so we tell it
+            // to use the first three values only.
+            num_values = 3;
+          }
+          cgGLSetParameterPointer(p,
+                                  num_values, _glgsg->get_numeric_type(numeric_type),
+                                  stride, client_pointer + start);
+        }
+        cgGLEnableClientState(p);
+      } else {
+        CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno];
+        cgGLDisableClientState(p);
+      }
+    }
+  }
+
+  cg_report_errors();
+  _glgsg->report_my_gl_errors();
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::disable_shader_texture_bindings
+//       Access: Public
+//  Description: Disable all the texture bindings used by this shader.
+////////////////////////////////////////////////////////////////////
+void CLP(CgShaderContext)::
+disable_shader_texture_bindings() {
+  if (!valid()) {
+    return;
+  }
+
+#ifndef OPENGLES_2
+  for (int i=0; i<(int)_shader->_tex_spec.size(); i++) {
+    CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno];
+    if (p == 0) continue;
+    int texunit = cgGetParameterResourceIndex(p);
+    _glgsg->_glActiveTexture(GL_TEXTURE0 + texunit);
+
+#ifndef OPENGLES
+    glBindTexture(GL_TEXTURE_1D, 0);
+#endif  // OPENGLES
+    glBindTexture(GL_TEXTURE_2D, 0);
+#ifndef OPENGLES_1
+    if (_glgsg->_supports_3d_texture) {
+      glBindTexture(GL_TEXTURE_3D, 0);
+    }
+#endif  // OPENGLES_1
+#ifndef OPENGLES
+    if (_glgsg->_supports_2d_texture_array) {
+      glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 0);
+    }
+#endif
+    if (_glgsg->_supports_cube_map) {
+      glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+    }
+    // This is probably faster - but maybe not as safe?
+    // cgGLDisableTextureParameter(p);
+  }
+#endif  // OPENGLES_2
+
+  cg_report_errors();
+  _glgsg->report_my_gl_errors();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLCgShaderContext::update_shader_texture_bindings
+//       Access: Public
+//  Description: Disables all texture bindings used by the previous
+//               shader, then enables all the texture bindings needed
+//               by this shader.  Extracts the relevant vertex array
+//               data from the gsg.
+//               The current implementation is inefficient, because
+//               it may unnecessarily disable textures then immediately
+//               reenable them.  We may optimize this someday.
+////////////////////////////////////////////////////////////////////
+void CLP(CgShaderContext)::
+update_shader_texture_bindings(ShaderContext *prev) {
+  if (prev) {
+    prev->disable_shader_texture_bindings();
+  }
+
+  if (!valid()) {
+    return;
+  }
+
+  // We get the TextureAttrib directly from the _target_rs, not the
+  // filtered TextureAttrib in _target_texture.
+  const TextureAttrib *texattrib = DCAST(TextureAttrib, _glgsg->_target_rs->get_attrib_def(TextureAttrib::get_class_slot()));
+  nassertv(texattrib != (TextureAttrib *)NULL);
+
+  for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) {
+    InternalName *id = _shader->_tex_spec[i]._name;
+
+    CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno];
+    if (p == 0) {
+      continue;
+    }
+    int texunit = cgGetParameterResourceIndex(p);
+
+    Texture *tex = 0;
+    int view = _glgsg->get_current_tex_view_offset();
+    if (id != 0) {
+      const ShaderInput *input = _glgsg->_target_shader->get_shader_input(id);
+      tex = input->get_texture();
+    } else {
+      if (_shader->_tex_spec[i]._stage >= texattrib->get_num_on_stages()) {
+        continue;
+      }
+      TextureStage *stage = texattrib->get_on_stage(_shader->_tex_spec[i]._stage);
+      tex = texattrib->get_on_texture(stage);
+      view += stage->get_tex_view_offset();
+    }
+    if (_shader->_tex_spec[i]._suffix != 0) {
+      // The suffix feature is inefficient. It is a temporary hack.
+      if (tex == 0) {
+        continue;
+      }
+      tex = tex->load_related(_shader->_tex_spec[i]._suffix);
+    }
+    if ((tex == 0) || (tex->get_texture_type() != _shader->_tex_spec[i]._desired_type)) {
+      continue;
+    }
+
+    _glgsg->_glActiveTexture(GL_TEXTURE0 + texunit);
+
+    TextureContext *tc = tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg);
+    if (tc == (TextureContext*)NULL) {
+      continue;
+    }
+
+    GLenum target = _glgsg->get_texture_target(tex->get_texture_type());
+    if (target == GL_NONE) {
+      // Unsupported texture mode.
+      continue;
+    }
+
+    if (!_glgsg->update_texture(tc, false)) {
+      continue;
+    }
+
+    _glgsg->apply_texture(tc);
+  }
+
+  cg_report_errors();
+  _glgsg->report_my_gl_errors();
+}
+
+#endif  // OPENGLES_1

+ 89 - 0
panda/src/glstuff/glCgShaderContext_src.h

@@ -0,0 +1,89 @@
+// Filename: glShaderContext_src.h
+// Created by: jyelon (01Sep05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+#if defined(HAVE_CG) && !defined(OPENGLES)
+
+#include "pandabase.h"
+#include "string_utils.h"
+#include "internalName.h"
+#include "shader.h"
+#include "shaderContext.h"
+#include "deletedChain.h"
+
+#include <Cg/cg.h>
+
+class CLP(GraphicsStateGuardian);
+
+////////////////////////////////////////////////////////////////////
+//       Class : GLShaderContext
+// Description : xyz
+////////////////////////////////////////////////////////////////////
+class EXPCL_GL CLP(CgShaderContext) : public ShaderContext {
+public:
+  friend class CLP(GraphicsStateGuardian);
+
+  CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s);
+  ~CLP(CgShaderContext)();
+  ALLOC_DELETED_CHAIN(CLP(CgShaderContext));
+
+  INLINE bool valid(void);
+  void bind(bool reissue_parameters = true);
+  void unbind();
+  void issue_parameters(int altered);
+  void disable_shader_vertex_arrays();
+  bool update_shader_vertex_arrays(ShaderContext *prev, bool force);
+  void disable_shader_texture_bindings();
+  void update_shader_texture_bindings(ShaderContext *prev);
+
+  INLINE bool uses_standard_vertex_arrays(void);
+  INLINE bool uses_custom_vertex_arrays(void);
+  INLINE bool uses_custom_texture_bindings(void);
+
+private:
+  CGcontext _cg_context;
+  CGprogram _cg_vprogram;
+  CGprogram _cg_fprogram;
+  CGprogram _cg_gprogram;
+  CGprofile _cg_vprofile;
+  CGprofile _cg_fprofile;
+  CGprofile _cg_gprofile;
+
+  pvector <CGparameter> _cg_parameter_map;
+
+  CLP(GraphicsStateGuardian) *_glgsg;
+
+  void release_resources();
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TypedObject::init_type();
+    register_type(_type_handle, CLASSPREFIX_QUOTED "CgShaderContext",
+                  TypedObject::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "glCgShaderContext_src.I"
+
+#endif  // OPENGLES_1
+

+ 2 - 2
panda/src/glstuff/glGeomContext_src.cxx

@@ -46,7 +46,7 @@ get_display_list(GLuint &index, const CLP(GeomMunger) *munger,
   DisplayList &dl = _display_lists[(CLP(GeomMunger) *)munger];
   bool list_current = (dl._modified == modified);
   if (dl._index == 0) {
-    dl._index = GLP(GenLists)(1);    
+    dl._index = glGenLists(1);
     list_current = false;
     if (munger != (CLP(GeomMunger) *)NULL) {
       ((CLP(GeomMunger) *)munger)->_geom_contexts.insert(this);
@@ -87,7 +87,7 @@ release_display_lists() {
       GLCAT.debug()
         << "releasing index " << (int)dl._index << "\n";
     }
-    GLP(DeleteLists)(dl._index, 1);
+    glDeleteLists(dl._index, 1);
   }
 
   _display_lists.clear();

+ 31 - 23
panda/src/glstuff/glGeomMunger_src.cxx

@@ -36,9 +36,9 @@ CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) :
 
   _flags = 0;
 
-  if (CLP(interleaved_arrays)) {
+  if (gl_interleaved_arrays) {
     _flags |= F_interleaved_arrays;
-  } else if (CLP(parallel_arrays)) {
+  } else if (gl_parallel_arrays) {
     _flags |= F_parallel_arrays;
   }
 }
@@ -46,7 +46,7 @@ CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) :
 ////////////////////////////////////////////////////////////////////
 //     Function: CLP(GeomMunger)::Destructor
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 CLP(GeomMunger)::
 ~CLP(GeomMunger)() {
@@ -84,9 +84,13 @@ munge_format_impl(const GeomVertexFormat *orig,
   PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig);
   new_format->set_animation(animation);
 
+  CLP(GraphicsStateGuardian) *glgsg;
+  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) {
+      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());
@@ -102,7 +106,7 @@ munge_format_impl(const GeomVertexFormat *orig,
   if (animation.get_animation_type() == AT_hardware) {
     // If we want hardware animation, we need to reserve space for the
     // blend weights.
-      
+
     // Make sure the old weights and indices are removed, just in
     // case.
     new_format->remove_column(InternalName::get_transform_weight());
@@ -116,11 +120,11 @@ munge_format_impl(const GeomVertexFormat *orig,
       new_array_format->add_column
         (InternalName::get_transform_weight(), animation.get_num_transforms() - 1,
          NT_stdfloat, C_other);
-      
+
       if (animation.get_indexed_transforms()) {
         // Also, if we'll be indexing into the transform table, reserve
         // space for the index.
-        
+
         // TODO: We should examine the maximum palette index so we can
         // decide whether we need 16-bit indices.  That implies saving
         // the maximum palette index, presumably in the AnimationSpec.
@@ -129,7 +133,7 @@ munge_format_impl(const GeomVertexFormat *orig,
         new_array_format->add_column
           (InternalName::get_transform_index(), animation.get_num_transforms(),
            NT_uint8, C_index);
-      }                                    
+      }
 
       new_format->add_array(new_array_format);
     }
@@ -149,16 +153,16 @@ munge_format_impl(const GeomVertexFormat *orig,
       new_format->add_array(new_array_format);
     }
     format = GeomVertexFormat::register_format(new_format);
-  
+
   } else if ((_flags & F_interleaved_arrays) != 0) {
     // Combine the primary data columns into a single array.
     new_format = new GeomVertexFormat(*format);
     PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
-  
+
     const GeomVertexColumn *column = format->get_vertex_column();
     if (column != (const GeomVertexColumn *)NULL) {
       new_array_format->add_column
-        (column->get_name(), column->get_num_components(), 
+        (column->get_name(), column->get_num_components(),
          column->get_numeric_type(), column->get_contents(),
          -1, column->get_column_alignment());
       new_format->remove_column(column->get_name());
@@ -167,7 +171,7 @@ munge_format_impl(const GeomVertexFormat *orig,
     column = format->get_normal_column();
     if (column != (const GeomVertexColumn *)NULL) {
       new_array_format->add_column
-        (column->get_name(), column->get_num_components(), 
+        (column->get_name(), column->get_num_components(),
          column->get_numeric_type(), column->get_contents(),
          -1, column->get_column_alignment());
       new_format->remove_column(column->get_name());
@@ -176,7 +180,7 @@ munge_format_impl(const GeomVertexFormat *orig,
     column = format->get_color_column();
     if (column != (const GeomVertexColumn *)NULL) {
       new_array_format->add_column
-        (column->get_name(), column->get_num_components(), 
+        (column->get_name(), column->get_num_components(),
          column->get_numeric_type(), column->get_contents(),
          -1, column->get_column_alignment());
       new_format->remove_column(column->get_name());
@@ -187,7 +191,7 @@ munge_format_impl(const GeomVertexFormat *orig,
     if (_texture != (TextureAttrib *)NULL) {
       typedef pset<const InternalName *> UsedStages;
       UsedStages used_stages;
-      
+
       int num_stages = _texture->get_num_on_stages();
       for (int i = 0; i < num_stages; ++i) {
         TextureStage *stage = _texture->get_on_stage(i);
@@ -197,7 +201,7 @@ munge_format_impl(const GeomVertexFormat *orig,
           if (used_stages.insert(name).second) {
             // This is the first time we've encountered this texcoord name.
             const GeomVertexColumn *texcoord_type = format->get_column(name);
-            
+
             if (texcoord_type != (const GeomVertexColumn *)NULL) {
               new_array_format->add_column
                 (name, texcoord_type->get_num_values(), NT_stdfloat, C_texcoord,
@@ -230,9 +234,13 @@ CPT(GeomVertexFormat) CLP(GeomMunger)::
 premunge_format_impl(const GeomVertexFormat *orig) {
   PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig);
 
+  CLP(GraphicsStateGuardian) *glgsg;
+  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) {
+      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());
@@ -259,7 +267,7 @@ premunge_format_impl(const GeomVertexFormat *orig) {
       new_format->add_array(new_array_format);
     }
     format = GeomVertexFormat::register_format(new_format);
-  
+
   } else {
     // Combine the primary data columns into a single array.  Unlike
     // the munge case, above, in the premunge case, we do this even if
@@ -269,11 +277,11 @@ premunge_format_impl(const GeomVertexFormat *orig) {
     // at run time.
     new_format = new GeomVertexFormat(*format);
     PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
-  
+
     const GeomVertexColumn *column = format->get_vertex_column();
     if (column != (const GeomVertexColumn *)NULL) {
       new_array_format->add_column
-        (column->get_name(), column->get_num_components(), 
+        (column->get_name(), column->get_num_components(),
          column->get_numeric_type(), column->get_contents(),
          -1, column->get_column_alignment());
       new_format->remove_column(column->get_name());
@@ -282,7 +290,7 @@ premunge_format_impl(const GeomVertexFormat *orig) {
     column = format->get_normal_column();
     if (column != (const GeomVertexColumn *)NULL) {
       new_array_format->add_column
-        (column->get_name(), column->get_num_components(), 
+        (column->get_name(), column->get_num_components(),
          column->get_numeric_type(), column->get_contents(),
          -1, column->get_column_alignment());
       new_format->remove_column(column->get_name());
@@ -291,7 +299,7 @@ premunge_format_impl(const GeomVertexFormat *orig) {
     column = format->get_color_column();
     if (column != (const GeomVertexColumn *)NULL) {
       new_array_format->add_column
-        (column->get_name(), column->get_num_components(), 
+        (column->get_name(), column->get_num_components(),
          column->get_numeric_type(), column->get_contents(),
          -1, column->get_column_alignment());
       new_format->remove_column(column->get_name());
@@ -303,7 +311,7 @@ premunge_format_impl(const GeomVertexFormat *orig) {
     if (_texture != (TextureAttrib *)NULL) {
       typedef pset<const InternalName *> UsedStages;
       UsedStages used_stages;
-      
+
       int num_stages = _texture->get_num_on_stages();
       for (int i = 0; i < num_stages; ++i) {
         TextureStage *stage = _texture->get_on_stage(i);
@@ -313,7 +321,7 @@ premunge_format_impl(const GeomVertexFormat *orig) {
           if (used_stages.insert(name).second) {
             // This is the first time we've encountered this texcoord name.
             const GeomVertexColumn *texcoord_type = format->get_column(name);
-            
+
             if (texcoord_type != (const GeomVertexColumn *)NULL) {
               new_array_format->add_column
                 (name, texcoord_type->get_num_values(), NT_stdfloat, C_texcoord,

+ 198 - 66
panda/src/glstuff/glGraphicsBuffer_src.cxx

@@ -73,9 +73,8 @@ CLP(GraphicsBuffer)(GraphicsEngine *engine, GraphicsPipe *pipe,
   _rb_size_x = 0;
   _rb_size_y = 0;
   _rb_size_z = 0;
-  for (int i=0; i<RTP_COUNT; i++) {
+  for (int i = 0; i < RTP_COUNT; ++i) {
     _rb[i] = 0;
-    _tex[i] = 0;
     _rbm[i] = 0;
   }
 
@@ -170,6 +169,24 @@ begin_frame(FrameMode mode, Thread *current_thread) {
       // rebuild_bitplanes().
       return false;
     }
+
+    // In case of multisample rendering, we don't need to issue
+    // the barrier until we call glBlitFramebuffer.
+    if (gl_enable_memory_barriers && _fbo_multisample == 0) {
+      CLP(GraphicsStateGuardian) *glgsg;
+      DCAST_INTO_R(glgsg, _gsg, false);
+
+      pvector<CLP(TextureContext)*>::iterator it;
+      for (it = _texture_contexts.begin(); it != _texture_contexts.end(); ++it) {
+        CLP(TextureContext) *gtc = *it;
+
+        if (gtc->needs_barrier(GL_FRAMEBUFFER_BARRIER_BIT)) {
+          glgsg->issue_memory_barrier(GL_FRAMEBUFFER_BARRIER_BIT);
+          // If we've done it for one, we've done it for all.
+          break;
+        }
+      }
+    }
   }
 
   _gsg->set_current_properties(&get_fb_properties());
@@ -248,7 +265,9 @@ rebuild_bitplanes() {
   DCAST_INTO_V(glgsg, _gsg);
 
   if (!_needs_rebuild) {
-    if (_fbo.size() > 0) {
+    if (_fbo_multisample != 0) {
+      glgsg->bind_fbo(_fbo_multisample);
+    } else if (_fbo.size() > 0) {
       glgsg->bind_fbo(_fbo[0]);
     } else {
       glgsg->bind_fbo(0);
@@ -284,6 +303,7 @@ rebuild_bitplanes() {
   // These variables indicate what should be bound to each bitplane.
   Texture *attach[RTP_COUNT];
   memset(attach, 0, sizeof(Texture *) * RTP_COUNT);
+  _texture_contexts.clear();
 
   // Sort the textures list into appropriate slots.
   {
@@ -370,6 +390,11 @@ rebuild_bitplanes() {
       // explicitly bound something to RTP_depth.
       _use_depth_stencil = false;
 
+    } else if (_fb_properties.get_float_depth()) {
+      // Let's not bother with a depth-stencil buffer
+      // if a float buffer was requested.
+      _use_depth_stencil = false;
+
     } else if (_fb_properties.get_depth_bits() > 24) {
       // We can't give more than 24 depth bits with a depth-stencil buffer.
       _use_depth_stencil = false;
@@ -432,12 +457,13 @@ rebuild_bitplanes() {
       bind_slot(layer, rb_resize, attach, RTP_color, next++);
 
       if (_fb_properties.is_stereo()) {
-        // The texture has already been initialized, so bind it straight away.
+        // The second tex view has already been initialized, so bind it straight away.
         if (attach[RTP_color] != NULL) {
           attach_tex(layer, 1, attach[RTP_color], next++);
         } else {
           //XXX hack: I needed a slot to use, and we don't currently use RTP_stencil
-          // which is treated as a color attachment below, so this fits the bill.
+          // and it's treated as a color attachment below, so this fits the bill.
+          // Eventually, we might want to add RTP_color_left and RTP_color_right.
           bind_slot(layer, rb_resize, attach, RTP_stencil, next++);
         }
       }
@@ -548,7 +574,6 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
   DCAST_INTO_V(glgsg, _gsg);
 
   Texture *tex = attach[slot];
-  _tex[slot] = tex;
 
   if (tex && layer >= tex->get_z_size()) {
     // If the requested layer index exceeds the number of layers
@@ -582,7 +607,10 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
     // Adjust the texture format based on the requested framebuffer settings.
     switch (slot) {
     case RTP_depth:
-      if (_fb_properties.get_depth_bits() > 24) {
+      if (_fb_properties.get_float_depth()) {
+        tex->set_format(Texture::F_depth_component32);
+        tex->set_component_type(Texture::T_float);
+      } else if (_fb_properties.get_depth_bits() > 24) {
         tex->set_format(Texture::F_depth_component32);
       } else if (_fb_properties.get_depth_bits() > 16) {
         tex->set_format(Texture::F_depth_component24);
@@ -594,7 +622,12 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
       break;
     case RTP_depth_stencil:
       tex->set_format(Texture::F_depth_stencil);
-      tex->set_component_type(Texture::T_unsigned_int_24_8);
+
+      if (_fb_properties.get_float_depth()) {
+        tex->set_component_type(Texture::T_float);
+      } else {
+        tex->set_component_type(Texture::T_unsigned_int_24_8);
+      }
       break;
     case RTP_aux_hrgba_0:
     case RTP_aux_hrgba_1:
@@ -611,16 +644,24 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
       tex->set_component_type(Texture::T_float);
       break;
     default:
-      if (_fb_properties.get_color_bits() > 48) {
-        tex->set_format(Texture::F_rgba32);
-        // Currently a float format.  Should change.
-        tex->set_component_type(Texture::T_float);
-      } else if (_fb_properties.get_color_bits() > 24) {
-        tex->set_format(Texture::F_rgba16);
-        // Currently a float format.  Should change.
-        tex->set_component_type(Texture::T_float);
+      if (_fb_properties.get_srgb_color()) {
+        if (_fb_properties.get_alpha_bits() == 0) {
+          tex->set_format(Texture::F_srgb);
+        } else {
+          tex->set_format(Texture::F_srgb_alpha);
+        }
       } else {
-        tex->set_format(Texture::F_rgba);
+        if (_fb_properties.get_float_color()) {
+          tex->set_component_type(Texture::T_float);
+        }
+        if (_fb_properties.get_color_bits() > 16 * 3) {
+          tex->set_format(Texture::F_rgba32);
+          tex->set_component_type(Texture::T_float);
+        } else if (_fb_properties.get_color_bits() > 8 * 3) {
+          tex->set_format(Texture::F_rgba16);
+        } else {
+          tex->set_format(Texture::F_rgba);
+        }
       }
     }
 
@@ -638,7 +679,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
 
 #ifndef OPENGLES
       GLint depth_size = 0;
-      GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_DEPTH_SIZE, &depth_size);
+      glGetTexLevelParameteriv(target, 0, GL_TEXTURE_DEPTH_SIZE, &depth_size);
       _fb_properties.set_depth_bits(depth_size);
 #endif
 
@@ -649,7 +690,7 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
 
 #ifndef OPENGLES
         GLint stencil_size = 0;
-        GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_STENCIL_SIZE, &stencil_size);
+        glGetTexLevelParameteriv(target, 0, GL_TEXTURE_STENCIL_SIZE, &stencil_size);
         _fb_properties.set_stencil_bits(stencil_size);
 #endif
       }
@@ -662,10 +703,10 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
 #ifndef OPENGLES
       if (attachpoint == GL_COLOR_ATTACHMENT0_EXT) {
         GLint red_size = 0, green_size = 0, blue_size = 0, alpha_size = 0;
-        GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_RED_SIZE, &red_size);
-        GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_GREEN_SIZE, &green_size);
-        GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_BLUE_SIZE, &blue_size);
-        GLP(GetTexLevelParameteriv)(target, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size);
+        glGetTexLevelParameteriv(target, 0, GL_TEXTURE_RED_SIZE, &red_size);
+        glGetTexLevelParameteriv(target, 0, GL_TEXTURE_GREEN_SIZE, &green_size);
+        glGetTexLevelParameteriv(target, 0, GL_TEXTURE_BLUE_SIZE, &blue_size);
+        glGetTexLevelParameteriv(target, 0, GL_TEXTURE_ALPHA_SIZE, &alpha_size);
 
         _fb_properties.set_color_bits(red_size + green_size + blue_size);
         _fb_properties.set_alpha_bits(alpha_size);
@@ -730,10 +771,16 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
     GLuint gl_format = GL_RGBA;
     switch (slot) {
       case RTP_depth_stencil:
-        gl_format = GL_DEPTH_STENCIL_EXT;
+        if (_fb_properties.get_float_depth()) {
+          gl_format = GL_DEPTH32F_STENCIL8;
+        } else {
+          gl_format = GL_DEPTH24_STENCIL8;
+        }
         break;
       case RTP_depth:
-        if (_fb_properties.get_depth_bits() > 24) {
+        if (_fb_properties.get_float_depth()) {
+          gl_format = GL_DEPTH_COMPONENT32F;
+        } else if (_fb_properties.get_depth_bits() > 24) {
           gl_format = GL_DEPTH_COMPONENT32;
         } else if (_fb_properties.get_depth_bits() > 16) {
           gl_format = GL_DEPTH_COMPONENT24;
@@ -763,7 +810,41 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
         break;
       default:
         if (_fb_properties.get_alpha_bits() == 0) {
-          gl_format = GL_RGB;
+          if (_fb_properties.get_srgb_color()) {
+            gl_format = GL_SRGB8;
+          } else if (_fb_properties.get_float_color()) {
+            if (_fb_properties.get_color_bits() > 16 * 3) {
+              gl_format = GL_RGB32F_ARB;
+            } else {
+              gl_format = GL_RGB16F_ARB;
+            }
+          } else {
+            if (_fb_properties.get_color_bits() > 16 * 3) {
+              gl_format = GL_RGBA32F_ARB;
+            } else if (_fb_properties.get_color_bits() > 8 * 3) {
+              gl_format = GL_RGB16_EXT;
+            } else {
+              gl_format = GL_RGB;
+            }
+          }
+        } else {
+          if (_fb_properties.get_srgb_color()) {
+            gl_format = GL_SRGB8_ALPHA8;
+          } else if (_fb_properties.get_float_color()) {
+            if (_fb_properties.get_color_bits() > 16 * 3) {
+              gl_format = GL_RGBA32F_ARB;
+            } else {
+              gl_format = GL_RGBA16F_ARB;
+            }
+          } else {
+            if (_fb_properties.get_color_bits() > 16 * 3) {
+              gl_format = GL_RGB32F_ARB;
+            } else if (_fb_properties.get_color_bits() > 8 * 3) {
+              gl_format = GL_RGB16_EXT;
+            } else {
+              gl_format = GL_RGB;
+            }
+          }
         }
     };
 #endif
@@ -986,7 +1067,10 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) {
   TextureContext *tc = attach->prepare_now(view, glgsg->get_prepared_objects(), glgsg);
   nassertv(tc != (TextureContext *)NULL);
   CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
-  glgsg->update_texture(tc, true);
+
+  glgsg->update_texture(gtc, true);
+  gtc->set_active(true);
+  _texture_contexts.push_back(gtc);
 
 #ifndef OPENGLES
   GLclampf priority = 1.0f;
@@ -1037,23 +1121,26 @@ attach_tex(int layer, int view, Texture *attach, GLenum attachpoint) {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsBuffer)::
 generate_mipmaps() {
+  if (gl_ignore_mipmaps && !gl_force_mipmaps) {
+    return;
+  }
+
   CLP(GraphicsStateGuardian) *glgsg;
   DCAST_INTO_V(glgsg, _gsg);
 
-  for (int slot=0; slot<RTP_COUNT; slot++) {
-    Texture *tex = _tex[slot];
-    if ((tex != 0) && (tex->uses_mipmaps())) {
+  pvector<CLP(TextureContext)*>::iterator it;
+  for (it = _texture_contexts.begin(); it != _texture_contexts.end(); ++it) {
+    CLP(TextureContext) *gtc = *it;
+
+    if (gtc->_generate_mipmaps) {
       glgsg->_state_texture = 0;
-      TextureContext *tc = tex->prepare_now(0, glgsg->get_prepared_objects(), glgsg);
-      nassertv(tc != (TextureContext *)NULL);
-      CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
-      glgsg->update_texture(tc, true);
-      GLenum target = glgsg->get_texture_target(tex->get_texture_type());
-      GLP(BindTexture)(target, gtc->_index);
-      glgsg->_glGenerateMipmap(target);
-      GLP(BindTexture)(target, 0);
+      glgsg->update_texture(gtc, true);
+      glgsg->apply_texture(gtc);
+      glgsg->_glGenerateMipmap(gtc->_target);
+      glBindTexture(gtc->_target, 0);
     }
   }
+
   report_my_gl_errors();
 }
 
@@ -1136,8 +1223,12 @@ select_target_tex_page(int page) {
         resolve_multisamples();
       }
     }
-    
-    glgsg->bind_fbo(_fbo[page]);
+
+    if (_fbo_multisample != 0) {
+      // TODO: re-issue clears?
+    } else {
+      glgsg->bind_fbo(_fbo[page]);
+    }
     _bound_tex_page = page;
   }
 
@@ -1160,7 +1251,7 @@ open_buffer() {
 
   // Count total color buffers.
   int totalcolor =
-   (_fb_properties.is_stereo() ? 2 : 1) +
+   (_fb_properties.get_stereo() ? 2 : 1) +
     _fb_properties.get_aux_rgba() +
     _fb_properties.get_aux_hrgba() +
     _fb_properties.get_aux_float();
@@ -1215,12 +1306,37 @@ open_buffer() {
     _fb_properties.set_alpha_bits(32);
   }
 
+  if (_fb_properties.get_float_depth()) {
+    // GL_DEPTH_COMPONENT32F seems the only depth float format.
+    _fb_properties.set_depth_bits(32);
+  }
+
+  // We currently only support color formats this big as float.
+  if (_fb_properties.get_color_bits() > 16 * 3) {
+    _fb_properties.set_color_bits(32 * 3);
+    _fb_properties.set_float_color(true);
+
+    if (_fb_properties.get_alpha_bits() > 0) {
+      _fb_properties.set_alpha_bits(32);
+    }
+  }
+
+  if (_fb_properties.get_srgb_color()) {
+    _fb_properties.set_color_bits(24);
+    _fb_properties.set_float_color(false);
+
+    if (_fb_properties.get_alpha_bits() > 0) {
+      _fb_properties.set_alpha_bits(32);
+    }
+  }
+
   if (!_gsg->get_supports_depth_stencil()) {
     // At least we know we won't be getting stencil bits.
     _fb_properties.set_stencil_bits(0);
   }
   _fb_properties.set_accum_bits(0);
-  _fb_properties.set_multisamples(_host->get_fb_properties().get_multisamples());
+
+  _fb_properties.set_multisamples(_requested_multisamples);
 
   // Update aux settings to reflect the GL_MAX_DRAW_BUFFERS limit,
   // if we exceed it, that is.
@@ -1293,7 +1409,6 @@ close_buffer() {
       glgsg->_glDeleteRenderbuffers(1, &(_rb[i]));
       _rb[i] = 0;
     }
-    _tex[i] = 0;
   }
   // Delete the renderbuffers.
   for (int i=0; i<RTP_COUNT; i++) {
@@ -1301,7 +1416,6 @@ close_buffer() {
       glgsg->_glDeleteRenderbuffers(1, &(_rbm[i]));
       _rb[i] = 0;
     }
-    _tex[i] = 0;
   }
   _rb_size_x = 0;
   _rb_size_y = 0;
@@ -1492,6 +1606,21 @@ resolve_multisamples() {
 
   nassertv(_fbo.size() > 0);
 
+  if (gl_enable_memory_barriers) {
+    // Issue memory barriers as necessary to make sure that the
+    // texture memory is synchronized before we blit to it.
+    pvector<CLP(TextureContext)*>::iterator it;
+    for (it = _texture_contexts.begin(); it != _texture_contexts.end(); ++it) {
+      CLP(TextureContext) *gtc = *it;
+
+      if (gtc->needs_barrier(GL_FRAMEBUFFER_BARRIER_BIT)) {
+        glgsg->issue_memory_barrier(GL_FRAMEBUFFER_BARRIER_BIT);
+        // If we've done it for one, we've done it for all.
+        break;
+      }
+    }
+  }
+
   glgsg->report_my_gl_errors();
   GLuint fbo = _fbo[0];
   if (_bound_tex_page != -1) {
@@ -1501,31 +1630,34 @@ resolve_multisamples() {
   glgsg->_glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, _fbo_multisample);
   
   // If the depth buffer is shared, resolve it only on the last to render FBO.
-  int do_depth_blit = 0;
-  if (_shared_depth_buffer) {
-    CLP(GraphicsBuffer) *graphics_buffer = NULL;
-    CLP(GraphicsBuffer) *highest_sort_graphics_buffer = NULL;
-    list <CLP(GraphicsBuffer) *>::iterator graphics_buffer_iterator;
-    
-    int max_sort_order = 0;
-    for (graphics_buffer_iterator = _shared_depth_buffer_list.begin();
-         graphics_buffer_iterator != _shared_depth_buffer_list.end();
-         graphics_buffer_iterator++) {
-      graphics_buffer = (*graphics_buffer_iterator);
-      if (graphics_buffer) {
-        // this call removes the entry from the list
-        if ( graphics_buffer->get_sort() >= max_sort_order ) {
-          max_sort_order = graphics_buffer->get_sort();
-          highest_sort_graphics_buffer = graphics_buffer;
+  bool do_depth_blit = false;
+  if (_rbm[RTP_depth_stencil] != 0 || _rbm[RTP_depth] != 0) {
+    if (_shared_depth_buffer) {
+      CLP(GraphicsBuffer) *graphics_buffer = NULL;
+      CLP(GraphicsBuffer) *highest_sort_graphics_buffer = NULL;
+      list <CLP(GraphicsBuffer) *>::iterator graphics_buffer_iterator;
+
+      int max_sort_order = 0;
+      for (graphics_buffer_iterator = _shared_depth_buffer_list.begin();
+           graphics_buffer_iterator != _shared_depth_buffer_list.end();
+           graphics_buffer_iterator++) {
+        graphics_buffer = (*graphics_buffer_iterator);
+        if (graphics_buffer) {
+          // this call removes the entry from the list
+          if (graphics_buffer->get_sort() >= max_sort_order) {
+            max_sort_order = graphics_buffer->get_sort();
+            highest_sort_graphics_buffer = graphics_buffer;
+          }
         }
       }
+      if (max_sort_order == this->get_sort()) {
+        do_depth_blit = true;
+      }
+    } else {
+      do_depth_blit = true;
     }
-    if (max_sort_order == this->get_sort()) {
-      do_depth_blit = 1;
-    }
-  } else {
-    do_depth_blit = 1;
   }
+
   if (do_depth_blit) {
     glgsg->_glBlitFramebuffer(0, 0, _rb_size_x, _rb_size_y, 0, 0, _rb_size_x, _rb_size_y,
                               GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
@@ -1535,7 +1667,6 @@ resolve_multisamples() {
                               GL_COLOR_BUFFER_BIT,
                               GL_NEAREST);
   }
-#ifndef OPENGLES
   // Now handle the other color buffers.
   int next = GL_COLOR_ATTACHMENT1_EXT;
   if (_fb_properties.is_stereo()) {
@@ -1545,6 +1676,7 @@ resolve_multisamples() {
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
     next += 1;
   }
+#ifndef OPENGLES
   for (int i = 0; i < _fb_properties.get_aux_rgba(); ++i) {
     glReadBuffer(next);
     glDrawBuffer(next);

+ 6 - 4
panda/src/glstuff/glGraphicsBuffer_src.h

@@ -120,13 +120,15 @@ private:
   int         _rb_size_y;
   int         _rb_size_z;
 
-  // The texture or render buffer bound to each plane.
-  PT(Texture) _tex[RTP_COUNT];
+  // Stores the render buffers for each plane.
+  // _rbm stores the multisample renderbuffers.
   GLuint      _rb[RTP_COUNT];
-
-  // The render buffer for _fbo_multisample.
   GLuint      _rbm[RTP_COUNT];
 
+  // List of textures for which we might have to generate mipmaps
+  // after rendering one frame.
+  pvector<CLP(TextureContext)*> _texture_contexts;
+
   // The cube map face we are currently drawing to or have just
   // finished drawing to, or -1 if we are not drawing to a cube map.
   int _bound_tex_page;

+ 55 - 55
panda/src/glstuff/glGraphicsStateGuardian_src.I

@@ -27,7 +27,7 @@
 INLINE bool CLP(GraphicsStateGuardian)::
 report_errors(int line, const char *source_file) {
 #ifndef NDEBUG
-  GLenum error_code = GLP(GetError)();
+  GLenum error_code = glGetError();
   if (error_code != GL_NO_ERROR) {
     int error_count = 0;
     return report_errors_loop(line, source_file, error_code, error_count);
@@ -45,8 +45,8 @@ report_errors(int line, const char *source_file) {
 INLINE void CLP(GraphicsStateGuardian)::
 report_my_errors(int line, const char *source_file) {
 #ifndef NDEBUG
-  if (_track_errors) {
-    GLenum error_code = GLP(GetError)();
+  if (_check_errors) {
+    GLenum error_code = glGetError();
     if (error_code != GL_NO_ERROR) {
       if (!report_errors_loop(line, source_file, error_code, _error_count)) {
         panic_deactivate();
@@ -69,7 +69,7 @@ report_my_errors(int line, const char *source_file) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool CLP(GraphicsStateGuardian)::
 clear_errors(int line, const char *source_file) {
-  GLenum error_code = GLP(GetError)();
+  GLenum error_code = glGetError();
   if (error_code != GL_NO_ERROR) {
     int error_count = 0;
     return report_errors_loop(line, source_file, error_code, error_count);
@@ -83,7 +83,7 @@ clear_errors(int line, const char *source_file) {
 //       Access: Public
 //  Description: This works like report_my_errors(), except that it
 //               always runs, even in the NDEBUG case (but not when
-//               _track_errors is false), and it never calls
+//               _check_errors is false), and it never calls
 //               panic_deactivate().  It is designed to be called when
 //               it is important to clear the error stack (for
 //               instance, because we want to be able to reliably
@@ -91,8 +91,8 @@ clear_errors(int line, const char *source_file) {
 ////////////////////////////////////////////////////////////////////
 INLINE void CLP(GraphicsStateGuardian)::
 clear_my_errors(int line, const char *source_file) {
-  if (_track_errors) {
-    GLenum error_code = GLP(GetError)();
+  if (_check_errors) {
+    GLenum error_code = glGetError();
     if (error_code != GL_NO_ERROR) {
       int error_count = 0;
       report_errors_loop(line, source_file, error_code, error_count);
@@ -161,8 +161,8 @@ get_gl_version_minor() const {
 INLINE void CLP(GraphicsStateGuardian)::
 maybe_gl_finish() const {
 #ifdef DO_PSTATS
-  if (CLP(finish)) {
-    GLP(Finish)();
+  if (gl_finish) {
+    glFinish();
   }
 #endif
 }
@@ -231,12 +231,12 @@ enable_multisample_antialias(bool val) {
       // Turn off antialias multisample.
       _multisample_mode &= ~MM_antialias;
       if (_multisample_mode == 0) {
-        GLP(Disable)(GL_MULTISAMPLE);
+        glDisable(GL_MULTISAMPLE);
       }
     } else if ((_multisample_mode & MM_antialias) == 0 && val) {
       // Turn on antialias multisample.
       if (_multisample_mode == 0) {
-        GLP(Enable)(GL_MULTISAMPLE);
+        glEnable(GL_MULTISAMPLE);
       }
       _multisample_mode |= MM_antialias;
     }
@@ -258,16 +258,16 @@ enable_multisample_alpha_one(bool val) {
     if ((_multisample_mode & MM_alpha_one) != 0 && !val) {
       // Turn off sample_alpha_to_one multisample.
       _multisample_mode &= ~MM_alpha_one;
-      GLP(Disable)(GL_SAMPLE_ALPHA_TO_ONE);
+      glDisable(GL_SAMPLE_ALPHA_TO_ONE);
       if (_multisample_mode == 0) {
-        GLP(Disable)(GL_MULTISAMPLE);
+        glDisable(GL_MULTISAMPLE);
       }
     } else if ((_multisample_mode & MM_alpha_one) == 0 && val) {
       // Turn on sample_alpha_to_one multisample.
       if (_multisample_mode == 0) {
-        GLP(Enable)(GL_MULTISAMPLE);
+        glEnable(GL_MULTISAMPLE);
       }
-      GLP(Enable)(GL_SAMPLE_ALPHA_TO_ONE);
+      glEnable(GL_SAMPLE_ALPHA_TO_ONE);
       _multisample_mode |= MM_alpha_one;
     }
   }
@@ -288,16 +288,16 @@ enable_multisample_alpha_mask(bool val) {
     if ((_multisample_mode & MM_alpha_mask) != 0 && !val) {
       // Turn off sample_alpha_to_mask multisample.
       _multisample_mode &= ~MM_alpha_mask;
-      GLP(Disable)(GL_SAMPLE_ALPHA_TO_COVERAGE);
+      glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
       if (_multisample_mode == 0) {
-        GLP(Disable)(GL_MULTISAMPLE);
+        glDisable(GL_MULTISAMPLE);
       }
     } else if ((_multisample_mode & MM_alpha_mask) == 0 && val) {
       // Turn on sample_alpha_to_mask multisample.
       if (_multisample_mode == 0) {
-        GLP(Enable)(GL_MULTISAMPLE);
+        glEnable(GL_MULTISAMPLE);
       }
-      GLP(Enable)(GL_SAMPLE_ALPHA_TO_COVERAGE);
+      glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
       _multisample_mode |= MM_alpha_mask;
     }
   }
@@ -316,9 +316,9 @@ enable_line_smooth(bool val) {
     _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
     _line_smooth_enabled = val;
     if (val) {
-      GLP(Enable)(GL_LINE_SMOOTH);
+      glEnable(GL_LINE_SMOOTH);
     } else {
-      GLP(Disable)(GL_LINE_SMOOTH);
+      glDisable(GL_LINE_SMOOTH);
     }
   }
 #endif
@@ -336,9 +336,9 @@ enable_point_smooth(bool val) {
     _state_mask.clear_bit(TransparencyAttrib::get_class_slot());
     _point_smooth_enabled = val;
     if (val) {
-      GLP(Enable)(GL_POINT_SMOOTH);
+      glEnable(GL_POINT_SMOOTH);
     } else {
-      GLP(Disable)(GL_POINT_SMOOTH);
+      glDisable(GL_POINT_SMOOTH);
     }
   }
 #endif
@@ -355,9 +355,9 @@ enable_polygon_smooth(bool val) {
   if (_polygon_smooth_enabled != val) {
     _polygon_smooth_enabled = val;
     if (val) {
-      GLP(Enable)(GL_POLYGON_SMOOTH);
+      glEnable(GL_POLYGON_SMOOTH);
     } else {
-      GLP(Disable)(GL_POLYGON_SMOOTH);
+      glDisable(GL_POLYGON_SMOOTH);
     }
   }
 #endif  // OPENGLES
@@ -448,13 +448,13 @@ enable_stencil_test(bool val) {
       GLCAT.spam()
         << "glEnable(GL_STENCIL_TEST)" << endl;
 #endif
-      GLP(Enable)(GL_STENCIL_TEST);
+      glEnable(GL_STENCIL_TEST);
     } else {
 #ifdef GSG_VERBOSE
       GLCAT.spam()
         << "glDisable(GL_STENCIL_TEST)" << endl;
 #endif
-      GLP(Disable)(GL_STENCIL_TEST);
+      glDisable(GL_STENCIL_TEST);
     }
   }
 }
@@ -473,13 +473,13 @@ enable_blend(bool val) {
       GLCAT.spam()
         << "glEnable(GL_BLEND)" << endl;
 #endif
-      GLP(Enable)(GL_BLEND);
+      glEnable(GL_BLEND);
     } else {
 #ifdef GSG_VERBOSE
       GLCAT.spam()
         << "glDisable(GL_BLEND)" << endl;
 #endif
-      GLP(Disable)(GL_BLEND);
+      glDisable(GL_BLEND);
     }
   }
 }
@@ -498,13 +498,13 @@ enable_depth_test(bool val) {
       GLCAT.spam()
         << "glEnable(GL_DEPTH_TEST)" << endl;
 #endif
-      GLP(Enable)(GL_DEPTH_TEST);
+      glEnable(GL_DEPTH_TEST);
     } else {
 #ifdef GSG_VERBOSE
       GLCAT.spam()
         << "glDisable(GL_DEPTH_TEST)" << endl;
 #endif
-      GLP(Disable)(GL_DEPTH_TEST);
+      glDisable(GL_DEPTH_TEST);
     }
   }
 }
@@ -524,13 +524,13 @@ enable_fog(bool val) {
       GLCAT.spam()
         << "glEnable(GL_FOG)" << endl;
 #endif
-      GLP(Enable)(GL_FOG);
+      glEnable(GL_FOG);
     } else {
 #ifdef GSG_VERBOSE
       GLCAT.spam()
         << "glDisable(GL_FOG)" << endl;
 #endif
-      GLP(Disable)(GL_FOG);
+      glDisable(GL_FOG);
     }
   }
 #endif
@@ -551,13 +551,13 @@ enable_alpha_test(bool val) {
       GLCAT.spam()
         << "glEnable(GL_ALPHA_TEST)" << endl;
 #endif
-      GLP(Enable)(GL_ALPHA_TEST);
+      glEnable(GL_ALPHA_TEST);
     } else {
 #ifdef GSG_VERBOSE
       GLCAT.spam()
         << "glDisable(GL_ALPHA_TEST)" << endl;
 #endif
-      GLP(Disable)(GL_ALPHA_TEST);
+      glDisable(GL_ALPHA_TEST);
     }
   }
 #endif // OPENGLES_2
@@ -578,17 +578,17 @@ enable_polygon_offset(bool val) {
       GLCAT.spam()
         << "glEnable(GL_POLYGON_OFFSET_*)" << endl;
 #endif
-      GLP(Enable)(GL_POLYGON_OFFSET_FILL);
-      //GLP(Enable)(GL_POLYGON_OFFSET_LINE);  // not widely supported anyway
-      //GLP(Enable)(GL_POLYGON_OFFSET_POINT);
+      glEnable(GL_POLYGON_OFFSET_FILL);
+      //glEnable(GL_POLYGON_OFFSET_LINE);  // not widely supported anyway
+      //glEnable(GL_POLYGON_OFFSET_POINT);
     } else {
 #ifdef GSG_VERBOSE
       GLCAT.spam()
         << "glDisable(GL_POLYGON_OFFSET_*)" << endl;
 #endif
-      GLP(Disable)(GL_POLYGON_OFFSET_FILL);
-      //GLP(Disable)(GL_POLYGON_OFFSET_LINE);  // not widely supported anyway
-      //GLP(Disable)(GL_POLYGON_OFFSET_POINT);
+      glDisable(GL_POLYGON_OFFSET_FILL);
+      //glDisable(GL_POLYGON_OFFSET_LINE);  // not widely supported anyway
+      //glDisable(GL_POLYGON_OFFSET_POINT);
     }
   }
 }
@@ -603,10 +603,10 @@ INLINE void CLP(GraphicsStateGuardian)::
 call_glFogfv(GLenum pname, const LColor &color) {
 #ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
-  GLP(Fogfv)(pname, color.get_data());
+  glFogfv(pname, color.get_data());
 #else  // STDFLOAT_DOUBLE
   LColorf fcolor = LCAST(float, color);
-  GLP(Fogfv)(pname, fcolor.get_data());
+  glFogfv(pname, fcolor.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif
 }
@@ -621,10 +621,10 @@ INLINE void CLP(GraphicsStateGuardian)::
 call_glMaterialfv(GLenum face, GLenum pname, const LColor &color) {
 #ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
-  GLP(Materialfv)(face, pname, color.get_data());
+  glMaterialfv(face, pname, color.get_data());
 #else  // STDFLOAT_DOUBLE
   LColorf fcolor = LCAST(float, color);
-  GLP(Materialfv)(face, pname, fcolor.get_data());
+  glMaterialfv(face, pname, fcolor.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif
 }
@@ -639,10 +639,10 @@ INLINE void CLP(GraphicsStateGuardian)::
 call_glLightfv(GLenum light, GLenum pname, const LVecBase4 &value) {
 #ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
-  GLP(Lightfv)(light, pname, value.get_data());
+  glLightfv(light, pname, value.get_data());
 #else  // STDFLOAT_DOUBLE
   LVecBase4f fvalue = LCAST(float, value);
-  GLP(Lightfv)(light, pname, fvalue.get_data());
+  glLightfv(light, pname, fvalue.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif
 }
@@ -657,10 +657,10 @@ INLINE void CLP(GraphicsStateGuardian)::
 call_glLightfv(GLenum light, GLenum pname, const LVecBase3 &value) {
 #ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
-  GLP(Lightfv)(light, pname, value.get_data());
+  glLightfv(light, pname, value.get_data());
 #else  // STDFLOAT_DOUBLE
   LVecBase3f fvalue = LCAST(float, value);
-  GLP(Lightfv)(light, pname, fvalue.get_data());
+  glLightfv(light, pname, fvalue.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif
 }
@@ -675,10 +675,10 @@ INLINE void CLP(GraphicsStateGuardian)::
 call_glLightModelfv(GLenum pname, const LVecBase4 &value) {
 #ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
-  GLP(LightModelfv)(pname, value.get_data());
+  glLightModelfv(pname, value.get_data());
 #else  // STDFLOAT_DOUBLE
   LVecBase4f fvalue = LCAST(float, value);
-  GLP(LightModelfv)(pname, fvalue.get_data());
+  glLightModelfv(pname, fvalue.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif  // OPENGLES_2
 }
@@ -693,10 +693,10 @@ INLINE void CLP(GraphicsStateGuardian)::
 call_glTexEnvfv(GLenum target, GLenum pname, const LVecBase4 &value) {
 #ifndef OPENGLES_2
 #ifndef STDFLOAT_DOUBLE
-  GLP(TexEnvfv)(target, pname, value.get_data());
+  glTexEnvfv(target, pname, value.get_data());
 #else  // STDFLOAT_DOUBLE
   LVecBase4f fvalue = LCAST(float, value);
-  GLP(TexEnvfv)(target, pname, fvalue.get_data());
+  glTexEnvfv(target, pname, fvalue.get_data());
 #endif  //  STDFLOAT_DOUBLE
 #endif
 }
@@ -710,10 +710,10 @@ call_glTexEnvfv(GLenum target, GLenum pname, const LVecBase4 &value) {
 INLINE void CLP(GraphicsStateGuardian)::
 call_glTexParameterfv(GLenum target, GLenum pname, const LVecBase4 &value) {
 #ifndef STDFLOAT_DOUBLE
-  GLP(TexParameterfv)(target, pname, value.get_data());
+  glTexParameterfv(target, pname, value.get_data());
 #else  // STDFLOAT_DOUBLE
   LVecBase4f fvalue = LCAST(float, value);
-  GLP(TexParameterfv)(target, pname, fvalue.get_data());
+  glTexParameterfv(target, pname, fvalue.get_data());
 #endif  //  STDFLOAT_DOUBLE
 }
 

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


+ 100 - 15
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -55,6 +55,9 @@ typedef double GLdouble;
 // functions are defined, and the system gl.h sometimes doesn't
 // declare these typedefs.
 #if !defined( __EDG__ ) || defined( __INTEL_COMPILER )  // Protect the following from the Tau instrumentor and expose it for the intel compiler.
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
 typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);
 typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
 typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
@@ -131,6 +134,9 @@ typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXOESPROC) (GLuint matrixpalettei
 typedef void (APIENTRYP PFNGLLOADPALETTEFROMMODELVIEWMATRIXOESPROC) (void);
 typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
 typedef void (APIENTRYP PFNGLWEIGHTPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 
 #ifndef OPENGLES_1
 // GLSL shader functions
@@ -161,15 +167,44 @@ typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, con
 typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
 typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
 typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *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 PFNGLVALIDATEPROGRAMPROC) (GLuint program);
 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 PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
 #endif  // OPENGLES_1
 #ifndef OPENGLES
 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 PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); 
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEPROC) (GLuint texture);
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEPROC) (GLuint texture, GLuint sampler);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTPROC) (GLuint64 handle);
+typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLEPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTPROC) (GLuint64 handle, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64PROC) (GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64PROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTPROC) (GLuint64 handle);
+typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64PROC) (GLuint index, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VPROC) (GLuint index, GLenum pname, GLuint64EXT *params);
 #endif  // OPENGLES
 #endif  // __EDG__
 
@@ -193,6 +228,10 @@ public:
   virtual int get_driver_shader_version_major();
   virtual int get_driver_shader_version_minor();
   
+#ifndef OPENGLES_1
+  static void debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, GLvoid *userParam);
+#endif
+
   virtual void reset();
 
   virtual void prepare_display_region(DisplayRegionPipelineReader *dr);
@@ -225,6 +264,8 @@ public:
                            bool force);
   virtual void end_draw_primitives();
 
+  void issue_memory_barrier(GLbitfield barrier);
+
   virtual TextureContext *prepare_texture(Texture *tex, int view);
   virtual bool update_texture(TextureContext *tc, bool force);
   virtual void release_texture(TextureContext *tc);
@@ -260,6 +301,8 @@ public:
   virtual void begin_occlusion_query();
   virtual PT(OcclusionQueryContext) end_occlusion_query();
 
+  virtual void dispatch_compute(int size_x, int size_y, int size_z);
+
   virtual PT(GeomMunger) make_geom_munger(const RenderState *state,
                                           Thread *current_thread);
 
@@ -343,8 +386,8 @@ protected:
   bool has_extension(const string &extension) const;
   INLINE bool is_at_least_gl_version(int major_version, int minor_version) const;
   INLINE bool is_at_least_gles_version(int major_version, int minor_version) const;
-  void *get_extension_func(const char *prefix, const char *name);
-  virtual void *do_get_extension_func(const char *prefix, const char *name);
+  void *get_extension_func(const char *name);
+  virtual void *do_get_extension_func(const char *name);
 
   virtual void reissue_transforms();
   virtual void enable_lighting(bool enable);
@@ -429,7 +472,7 @@ protected:
   bool specify_texture(CLP(TextureContext) *gtc);
   bool apply_texture(TextureContext *tc);
   bool upload_texture(CLP(TextureContext) *gtc, bool force);
-  bool upload_texture_image(CLP(TextureContext) *gtc,
+  bool upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
                             bool uses_mipmaps, int mipmap_bias,
                             GLenum texture_target, GLenum page_target, 
                             GLint internal_format, GLint external_format, 
@@ -487,12 +530,12 @@ protected:
   bool _vertex_blending_enabled;
 
 #ifndef OPENGLES_1
-  PT(Shader)  _current_shader;
-  CLP(ShaderContext)  *_current_shader_context;
-  PT(Shader)  _vertex_array_shader;
-  CLP(ShaderContext)  *_vertex_array_shader_context;
-  PT(Shader)  _texture_binding_shader;
-  CLP(ShaderContext)  *_texture_binding_shader_context;
+  PT(Shader) _current_shader;
+  ShaderContext *_current_shader_context;
+  PT(Shader) _vertex_array_shader;
+  ShaderContext *_vertex_array_shader_context;
+  PT(Shader) _texture_binding_shader;
+  ShaderContext *_texture_binding_shader_context;
 #endif
 #ifdef OPENGLES_2
   static PT(Shader)  _default_shader;
@@ -522,6 +565,9 @@ protected:
   int _num_active_texture_stages;
   PN_stdfloat _max_anisotropy;
   bool _supports_anisotropy;
+  GLint _max_image_units;
+  bool _supports_multi_bind;
+  bool _supports_get_program_binary;
 
 #ifdef OPENGLES
   bool _supports_depth24;
@@ -536,6 +582,7 @@ protected:
   int _gl_version_major, _gl_version_minor;
   //#--- Zhao Nov/2011
   int _gl_shadlang_ver_major, _gl_shadlang_ver_minor;
+
   pset<string> _extensions;
 
 public:
@@ -567,6 +614,11 @@ public:
   PFNGLTEXSUBIMAGE3DPROC _glTexSubImage3D;
   PFNGLCOPYTEXSUBIMAGE3DPROC _glCopyTexSubImage3D;
 
+  bool _supports_tex_storage;
+  PFNGLTEXSTORAGE1DPROC _glTexStorage1D;
+  PFNGLTEXSTORAGE2DPROC _glTexStorage2D;
+  PFNGLTEXSTORAGE3DPROC _glTexStorage3D;
+
   PFNGLCOMPRESSEDTEXIMAGE1DPROC _glCompressedTexImage1D;
   PFNGLCOMPRESSEDTEXIMAGE2DPROC _glCompressedTexImage2D;
   PFNGLCOMPRESSEDTEXIMAGE3DPROC _glCompressedTexImage3D;
@@ -577,8 +629,8 @@ public:
 
   bool _supports_bgr;
   bool _supports_rescale_normal;
-  bool _supports_mesa_6;
-  
+  bool _supports_packed_dabc;
+
   bool _supports_multitexture;
   PFNGLACTIVETEXTUREPROC _glActiveTexture;
   PFNGLCLIENTACTIVETEXTUREPROC _glClientActiveTexture;
@@ -638,6 +690,8 @@ public:
   PFNGLBLITFRAMEBUFFEREXTPROC _glBlitFramebuffer;
   PFNGLDRAWBUFFERSPROC _glDrawBuffers;
   int _max_fb_samples;
+  bool _supports_viewport_arrays;
+  bool _supports_bindless_texture;
 
   PFNGLGENQUERIESPROC _glGenQueries;
   PFNGLBEGINQUERYPROC _glBeginQuery;
@@ -677,16 +731,37 @@ public:
   PFNGLUNIFORM2FVPROC _glUniform2fv;
   PFNGLUNIFORM3FVPROC _glUniform3fv;
   PFNGLUNIFORM4FVPROC _glUniform4fv;
+  PFNGLUNIFORM1IVPROC _glUniform1iv;
+  PFNGLUNIFORM2IVPROC _glUniform2iv;
+  PFNGLUNIFORM3IVPROC _glUniform3iv;
+  PFNGLUNIFORM4IVPROC _glUniform4iv;
   PFNGLUNIFORMMATRIX3FVPROC _glUniformMatrix3fv;
   PFNGLUNIFORMMATRIX4FVPROC _glUniformMatrix4fv;
   PFNGLVALIDATEPROGRAMPROC _glValidateProgram;
   PFNGLVERTEXATTRIBPOINTERPROC _glVertexAttribPointer;
+  PFNGLVERTEXATTRIBIPOINTERPROC _glVertexAttribIPointer;
+  PFNGLVERTEXATTRIBLPOINTERPROC _glVertexAttribLPointer;
 #endif  // OPENGLES_1
 #ifndef OPENGLES
   PFNGLPROGRAMPARAMETERIPROC _glProgramParameteri;
   PFNGLPATCHPARAMETERIPROC _glPatchParameteri;
   PFNGLDRAWARRAYSINSTANCEDPROC _glDrawArraysInstanced;
   PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced;
+  PFNGLBINDTEXTURESPROC _glBindTextures;
+  PFNGLBINDIMAGETEXTUREPROC _glBindImageTexture;
+  PFNGLBINDIMAGETEXTURESPROC _glBindImageTextures;
+  PFNGLDISPATCHCOMPUTEPROC _glDispatchCompute;
+  PFNGLMEMORYBARRIERPROC _glMemoryBarrier;
+  PFNGLGETPROGRAMBINARYPROC _glGetProgramBinary;
+  PFNGLGETINTERNALFORMATIVPROC _glGetInternalformativ;
+  PFNGLVIEWPORTARRAYVPROC _glViewportArrayv;
+  PFNGLSCISSORARRAYVPROC _glScissorArrayv;
+  PFNGLDEPTHRANGEARRAYVPROC _glDepthRangeArrayv;
+  PFNGLGETTEXTUREHANDLEPROC _glGetTextureHandle;
+  PFNGLMAKETEXTUREHANDLERESIDENTPROC _glMakeTextureHandleResident;
+  PFNGLMAKETEXTUREHANDLENONRESIDENTPROC _glMakeTextureHandleNonResident;
+  PFNGLUNIFORMHANDLEUI64PROC _glUniformHandleui64;
+  PFNGLUNIFORMHANDLEUI64VPROC _glUniformHandleui64v;
 #endif  // OPENGLES
 
   GLenum _edge_clamp;
@@ -704,10 +779,20 @@ public:
   DeletedDisplayLists _deleted_display_lists;
   DeletedDisplayLists _deleted_queries;
 
+#ifndef OPENGLES
+  // Stores textures for which memory bariers should be issued.
+  typedef pset<TextureContext*> TextureSet;
+  TextureSet _textures_needing_fetch_barrier;
+  TextureSet _textures_needing_image_access_barrier;
+  TextureSet _textures_needing_update_barrier;
+  TextureSet _textures_needing_framebuffer_barrier;
+#endif
+
   //RenderState::SlotMask _inv_state_mask;
 
-  bool _track_errors;
-  bool _allow_flush;
+  bool _check_errors;
+  bool _force_flush;
+  bool _supports_debug;
 
 #ifndef NDEBUG
   bool _show_texture_usage;
@@ -730,6 +815,7 @@ public:
   static PStatCollector _primitive_batches_display_list_pcollector;
   static PStatCollector _vertices_display_list_pcollector;
   static PStatCollector _vertices_immediate_pcollector;
+  static PStatCollector _compute_dispatch_pcollector;
 
 public:
   virtual TypeHandle get_type() const {
@@ -754,10 +840,9 @@ private:
   friend class CLP(VertexBufferContext);
   friend class CLP(IndexBufferContext);
   friend class CLP(ShaderContext);
+  friend class CLP(CgShaderContext);
   friend class CLP(GraphicsBuffer);
   friend class CLP(OcclusionQueryContext);
 };
 
 #include "glGraphicsStateGuardian_src.I"
-
-

+ 6 - 6
panda/src/glstuff/glImmediateModeSender_src.cxx

@@ -564,7 +564,7 @@ issue_vertex() {
 ////////////////////////////////////////////////////////////////////
 void CLP(ImmediateModeSender)::VectorSender2fui::
 issue_vertex() {
-  const int *d = _reader->get_data2i();
+  const LVecBase2i &d = _reader->get_data2i();
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
     GLCAT.spam()
@@ -573,7 +573,7 @@ issue_vertex() {
   }
 #endif  // NDEBUG
 
-  (*_func)(2, (const GLuint *)d);
+  (*_func)(2, (const GLuint *)d.get_data());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -583,7 +583,7 @@ issue_vertex() {
 ////////////////////////////////////////////////////////////////////
 void CLP(ImmediateModeSender)::VectorSender3fui::
 issue_vertex() {
-  const int *d = _reader->get_data3i();
+  const LVecBase3i &d = _reader->get_data3i();
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
     GLCAT.spam()
@@ -592,7 +592,7 @@ issue_vertex() {
   }
 #endif  // NDEBUG
 
-  (*_func)(3, (const GLuint *)d);
+  (*_func)(3, (const GLuint *)d.get_data());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -602,7 +602,7 @@ issue_vertex() {
 ////////////////////////////////////////////////////////////////////
 void CLP(ImmediateModeSender)::VectorSender4fui::
 issue_vertex() {
-  const int *d = _reader->get_data4i();
+  const LVecBase4i &d = _reader->get_data4i();
 #ifndef NDEBUG
   if (GLCAT.is_spam()) {
     GLCAT.spam()
@@ -611,7 +611,7 @@ issue_vertex() {
   }
 #endif  // NDEBUG
 
-  (*_func)(4, (const GLuint *)d);
+  (*_func)(4, (const GLuint *)d.get_data());
 }
 
 #endif  // SUPPORT_IMMEDIATE_MODE

+ 1 - 1
panda/src/glstuff/glIndexBufferContext_src.cxx

@@ -35,7 +35,7 @@ evict_lru() {
 
   // Make sure the buffer is unbound before we delete it.
   if (_glgsg->_current_ibuffer_index == _index) {
-    if (GLCAT.is_debug() && CLP(debug_buffers)) {
+    if (GLCAT.is_debug() && gl_debug_buffers) {
       GLCAT.debug()
         << "unbinding index buffer\n";
     }

+ 1 - 1
panda/src/glstuff/glOcclusionQueryContext_src.cxx

@@ -75,7 +75,7 @@ is_answer_ready() const {
 void CLP(OcclusionQueryContext)::
 waiting_for_answer() {
   PStatTimer timer(GraphicsStateGuardian::_wait_occlusion_pcollector);
-  GLP(Flush)();
+  glFlush();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 4 - 9
panda/src/glstuff/glShaderContext_src.I

@@ -12,7 +12,6 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#ifndef OPENGLES_1
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GLShaderContext::valid
@@ -26,11 +25,10 @@
 INLINE bool CLP(ShaderContext)::
 valid() {
   if (_shader->get_error_flag()) return false;
-  if (_shader->get_language() == Shader::SL_none) return false;
-#if defined(HAVE_CG) && !defined(OPENGLES)
-  if (_cg_context) return true;
-#endif
-  if (_shader->get_language() == Shader::SL_GLSL && _glsl_program != 0) {
+  if (_shader->get_language() != Shader::SL_GLSL) {
+    return false;
+  }
+  if (_glsl_program != 0) {
     return true;
   }
   return false;
@@ -67,6 +65,3 @@ INLINE bool CLP(ShaderContext)::
 uses_custom_texture_bindings() {
   return true;
 }
-
-#endif  // OPENGLES_1
-

File diff suppressed because it is too large
+ 444 - 485
panda/src/glstuff/glShaderContext_src.cxx


+ 31 - 43
panda/src/glstuff/glShaderContext_src.h

@@ -21,75 +21,64 @@
 #include "shaderContext.h"
 #include "deletedChain.h"
 
-#if defined(HAVE_CG) && !defined(OPENGLES)
-#include <Cg/cg.h>
-#endif
-
 class CLP(GraphicsStateGuardian);
 
 ////////////////////////////////////////////////////////////////////
 //       Class : GLShaderContext
 // Description : xyz
 ////////////////////////////////////////////////////////////////////
-class EXPCL_GL CLP(ShaderContext): public ShaderContext {
+class EXPCL_GL CLP(ShaderContext) : public ShaderContext {
 public:
   friend class CLP(GraphicsStateGuardian);
-  typedef CLP(GraphicsStateGuardian) GSG;
 
-  CLP(ShaderContext)(Shader *s, GSG *gsg);
+  CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s);
   ~CLP(ShaderContext)();
   ALLOC_DELETED_CHAIN(CLP(ShaderContext));
 
   INLINE bool valid(void);
-  void bind(GSG *gsg, bool reissue_parameters = true);
-  void unbind(GSG *gsg);
-  void issue_parameters(GSG *gsg, int altered);
-  void disable_shader_vertex_arrays(GSG *gsg);
-  bool update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg,
-                                   bool force);
-  void disable_shader_texture_bindings(GSG *gsg);
-  void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
+  void bind(bool reissue_parameters = true);
+  void unbind();
+  void issue_parameters(int altered);
+  void disable_shader_vertex_arrays();
+  bool update_shader_vertex_arrays(ShaderContext *prev, bool force);
+  void disable_shader_texture_bindings();
+  void update_shader_texture_bindings(ShaderContext *prev);
 
   INLINE bool uses_standard_vertex_arrays(void);
   INLINE bool uses_custom_vertex_arrays(void);
   INLINE bool uses_custom_texture_bindings(void);
 
 private:
+  GLuint _glsl_program;
+  typedef pvector<GLuint> GLSLShaders;
+  GLSLShaders _glsl_shaders;
 
-#if defined(HAVE_CG) && !defined(OPENGLES)
-  CGcontext _cg_context;
-  CGprogram _cg_vprogram;
-  CGprogram _cg_fprogram;
-  CGprogram _cg_gprogram;
-  CGprofile _cg_vprofile;
-  CGprofile _cg_fprofile;
-  CGprofile _cg_gprofile;
+  //struct ParamContext {
+  //  CPT(InternalName) _name;
+  //  GLint _location;
+  //  GLsizei _count;
+  //  WPT(ParamValue) _value;
+  //  UpdateSeq _updated;
+  //};
+  //typedef pvector<ParamContext> ParamContexts;
+  //ParamContexts _params;
 
-  pvector <CGparameter> _cg_parameter_map;
-#endif
+  pvector<GLint> _glsl_parameter_map;
+  pmap<GLint, GLuint64> _glsl_uniform_handles;
 
-  GLuint _glsl_program;
-  GLuint _glsl_vshader;
-  GLuint _glsl_fshader;
-  GLuint _glsl_gshader;
-  GLuint _glsl_tcshader;
-  GLuint _glsl_teshader;
+  pvector<CPT(InternalName)> _glsl_img_inputs;
+  pvector<CLP(TextureContext)*> _glsl_img_textures;
 
-  pvector <GLint> _glsl_parameter_map;
-
-  int _stage_offset;
-  // Avoid using this! It merely exists so the
-  // destructor has access to the extension functions.
-  WPT(GSG) _last_gsg;
+  CLP(GraphicsStateGuardian) *_glgsg;
 
   bool _uses_standard_vertex_arrays;
 
-  void glsl_report_shader_errors(GSG *gsg, unsigned int shader);
-  void glsl_report_program_errors(GSG *gsg, unsigned int program);
-  unsigned int glsl_compile_entry_point(GSG *gsg, Shader::ShaderType type);
-  bool glsl_compile_shader(GSG *gsg);
+  void glsl_report_shader_errors(GLuint shader);
+  void glsl_report_program_errors(GLuint program);
+  bool glsl_compile_shader(Shader::ShaderType type);
+  bool glsl_compile_and_link();
   bool parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *s);
-  void release_resources(GSG *gsg);
+  void release_resources();
 
 public:
   static TypeHandle get_class_type() {
@@ -112,4 +101,3 @@ private:
 #include "glShaderContext_src.I"
 
 #endif  // OPENGLES_1
-

+ 11 - 3
panda/src/glstuff/glTextureContext_src.I

@@ -19,12 +19,20 @@
 //  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE CLP(TextureContext)::
-CLP(TextureContext)(PreparedGraphicsObjects *pgo, Texture *tex, int view) :
+CLP(TextureContext)(CLP(GraphicsStateGuardian) *glgsg,
+  PreparedGraphicsObjects *pgo, Texture *tex, int view) :
   TextureContext(pgo, tex, view)
 {
-  _index = 0;
-  _already_applied = false;
+  _glgsg = glgsg;
+
+  glGenTextures(1, &_index);
+
+  _handle = 0;
+  _needs_barrier = false;
+  _has_storage = false;
+  _immutable = false;
   _uses_mipmaps = false;
+  _generate_mipmaps = false;
   _internal_format = 0;
   _width = 0;
   _height = 0;

+ 131 - 4
panda/src/glstuff/glTextureContext_src.cxx

@@ -16,6 +16,23 @@
 
 TypeHandle CLP(TextureContext)::_type_handle;
 
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(TextureContext)::Denstructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+CLP(TextureContext)::
+~CLP(TextureContext)() {
+  if (gl_enable_memory_barriers) {
+    _glgsg->_textures_needing_fetch_barrier.erase(this);
+    _glgsg->_textures_needing_image_access_barrier.erase(this);
+    _glgsg->_textures_needing_update_barrier.erase(this);
+    _glgsg->_textures_needing_framebuffer_barrier.erase(this);
+  }
+
+  glDeleteTextures(1, &_index);
+  _index = 0;
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GLTextureContext::evict_lru
@@ -35,7 +52,16 @@ TypeHandle CLP(TextureContext)::_type_handle;
 void CLP(TextureContext)::
 evict_lru() {
   dequeue_lru();
-  reset_data();
+
+  if (_handle != 0) {
+    if (_handle_resident) {
+      _glgsg->_glMakeTextureHandleNonResident(_handle);
+    }
+    _handle_resident = false;
+  } else {
+    reset_data();
+  }
+
   update_data_size_bytes(0);
   mark_unloaded();
 }
@@ -48,12 +74,113 @@ evict_lru() {
 ////////////////////////////////////////////////////////////////////
 void CLP(TextureContext)::
 reset_data() {
+  if (_handle != 0 && _handle_resident) {
+    _glgsg->_glMakeTextureHandleNonResident(_handle);
+  }
+
   // Free the texture resources.
-  GLP(DeleteTextures)(1, &_index);
+  glDeleteTextures(1, &_index);
 
   // We still need a valid index number, though, in case we want to
   // re-load the texture later.
-  GLP(GenTextures)(1, &_index);
+  glGenTextures(1, &_index);
+
+  _handle = 0;
+  _handle_resident = false;
+  _needs_barrier = false;
+  _has_storage = false;
+  _immutable = false;
+
+#ifndef OPENGLES
+  // Mark the texture as coherent.
+  if (gl_enable_memory_barriers) {
+    _glgsg->_textures_needing_fetch_barrier.erase(this);
+    _glgsg->_textures_needing_image_access_barrier.erase(this);
+    _glgsg->_textures_needing_update_barrier.erase(this);
+    _glgsg->_textures_needing_framebuffer_barrier.erase(this);
+  }
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLTextureContext::make_handle_resident
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void CLP(TextureContext)::
+make_handle_resident() {
+  if (_handle != 0) {
+    if (!_handle_resident) {
+      _glgsg->_glMakeTextureHandleResident(_handle);
+      _handle_resident = true;
+    }
+    set_resident(true);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CLP(TextureContext)::get_handle
+//       Access: Public
+//  Description: Returns a handle for this texture.  Once this has
+//               been created, the texture data may still be updated,
+//               but its properties may not.
+////////////////////////////////////////////////////////////////////
+INLINE GLuint64 CLP(TextureContext)::
+get_handle() {
+#ifdef OPENGLES
+  return 0;
+#else
+  if (!_glgsg->_supports_bindless_texture) {
+    return false;
+  }
+
+  if (_handle == 0) {
+    _handle = _glgsg->_glGetTextureHandle(_index);
+  }
+
+  _immutable = true;
+  return _handle;
+#endif
+}
+
+#ifndef OPENGLES
+////////////////////////////////////////////////////////////////////
+//     Function: GLTextureContext::needs_barrier
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool CLP(TextureContext)::
+needs_barrier(GLbitfield barrier) {
+  if (!gl_enable_memory_barriers) {
+    return false;
+  }
 
-  _already_applied = false;
+  return (((barrier & GL_TEXTURE_FETCH_BARRIER_BIT) &&
+           _glgsg->_textures_needing_fetch_barrier.count(this)))
+      || (((barrier & GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) &&
+           _glgsg->_textures_needing_image_access_barrier.count(this)))
+      || (((barrier & GL_TEXTURE_UPDATE_BARRIER_BIT) &&
+           _glgsg->_textures_needing_update_barrier.count(this)))
+      || (((barrier & GL_FRAMEBUFFER_BARRIER_BIT) &&
+           _glgsg->_textures_needing_framebuffer_barrier.count(this)));
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: GLTextureContext::mark_incoherent
+//       Access: Public
+//  Description: Mark a texture as needing a memory barrier, since
+//               a non-coherent write just happened to it.
+////////////////////////////////////////////////////////////////////
+void CLP(TextureContext)::
+mark_incoherent() {
+  if (!gl_enable_memory_barriers) {
+    return;
+  }
+
+  _glgsg->_textures_needing_fetch_barrier.insert(this);
+  _glgsg->_textures_needing_image_access_barrier.insert(this);
+  _glgsg->_textures_needing_update_barrier.insert(this);
+  _glgsg->_textures_needing_framebuffer_barrier.insert(this);
+}
+
+#endif // OPENGLES

+ 32 - 4
panda/src/glstuff/glTextureContext_src.h

@@ -16,32 +16,60 @@
 #include "textureContext.h"
 #include "deletedChain.h"
 
+class CLP(GraphicsStateGuardian);
+
 ////////////////////////////////////////////////////////////////////
 //       Class : GLTextureContext
 // Description :
 ////////////////////////////////////////////////////////////////////
 class EXPCL_GL CLP(TextureContext) : public TextureContext {
 public:
-  INLINE CLP(TextureContext)(PreparedGraphicsObjects *pgo, Texture *tex, int view);
+  INLINE CLP(TextureContext)(CLP(GraphicsStateGuardian) *glgsg,
+                             PreparedGraphicsObjects *pgo,
+                             Texture *tex, int view);
   ALLOC_DELETED_CHAIN(CLP(TextureContext));
 
+  virtual ~CLP(TextureContext)();
   virtual void evict_lru();
   void reset_data();
 
+  void make_handle_resident();
+  GLuint64 get_handle();
+
+#ifdef OPENGLES
+  CONSTEXPR bool needs_barrier(GLbitfield barrier) { return false; };
+#else
+  bool needs_barrier(GLbitfield barrier);
+  void mark_incoherent();
+#endif
+
   // This is the GL "name" of the texture object.
   GLuint _index;
 
+  // This is the bindless "handle" to the texture object.
+  GLuint64 _handle;
+  bool _handle_resident;
+
+  // This is true if the texture was recently written to in a
+  // non-coherent way, and Panda may have to call glMemoryBarrier
+  // for the results of this write to become visible.
+  bool _needs_barrier;
+
   // These are the parameters that we specified with the last
-  // glTexImage2D() call.  If none of these have changed, we can
-  // reload the texture image with a glTexSubImage2D().
-  bool _already_applied;
+  // glTexImage2D() or glTexStorage2D() call.  If none of these have
+  // changed, we can reload the texture image with a glTexSubImage2D().
+  bool _has_storage;
+  bool _immutable;
   bool _uses_mipmaps;
+  bool _generate_mipmaps;
   GLint _internal_format;
   GLsizei _width;
   GLsizei _height;
   GLsizei _depth;
   GLenum _target;
 
+  CLP(GraphicsStateGuardian) *_glgsg;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 1 - 1
panda/src/glstuff/glVertexBufferContext_src.cxx

@@ -35,7 +35,7 @@ evict_lru() {
 
   // Make sure the buffer is unbound before we delete it.
   if (_glgsg->_current_vbuffer_index == _index) {
-    if (GLCAT.is_debug() && CLP(debug_buffers)) {
+    if (GLCAT.is_debug() && gl_debug_buffers) {
       GLCAT.debug()
         << "unbinding vertex buffer\n";
     }

+ 104 - 33
panda/src/glstuff/glmisc_src.cxx

@@ -14,45 +14,45 @@
 
 #include "pandaSystem.h"
 
-ConfigVariableBool CLP(cheap_textures)
+ConfigVariableBool gl_cheap_textures
   ("gl-cheap-textures", false,
-   PRC_DESC("Configure this true to GLP(Hint) the textures into the cheapest "
+   PRC_DESC("Configure this true to glHint the textures into the cheapest "
             "possible mode."));
 
-ConfigVariableBool CLP(ignore_clamp)
+ConfigVariableBool gl_ignore_clamp
   ("gl-ignore-clamp", false,
    PRC_DESC("Configure this true to disable texture clamp mode (all textures "
             "repeat, a little cheaper for software renderers)."));
 
-ConfigVariableBool CLP(support_clamp_to_border)
+ConfigVariableBool gl_support_clamp_to_border
   ("gl-support-clamp-to-border", true,
    PRC_DESC("Configure this true to enable the use of the clamp_to_border "
             "extension if the GL claims to support it, or false not to "
             "use it even if it appears to be available.  (On some OpenGL "
             "drivers, enabling this mode can force software rendering.)"));
 
-ConfigVariableBool CLP(support_rescale_normal)
+ConfigVariableBool gl_support_rescale_normal
   ("gl-support-rescale-normal", true,
    PRC_DESC("Configure this true to enable the use of the rescale_normal "
             "extension if the GL claims to support it, or false not to use "
             "it even if it appears to be available.  (This appears to be "
             "buggy on some drivers.)"));
 
-ConfigVariableBool CLP(ignore_filters)
+ConfigVariableBool gl_ignore_filters
   ("gl-ignore-filters", false,
    PRC_DESC("Configure this true to disable any texture filters at all (forcing "
             "point sampling)."));
 
-ConfigVariableBool CLP(ignore_mipmaps)
+ConfigVariableBool gl_ignore_mipmaps
   ("gl-ignore-mipmaps", false,
    PRC_DESC("Configure this true to disable mipmapping only."));
 
-ConfigVariableBool CLP(force_mipmaps)
+ConfigVariableBool gl_force_mipmaps
   ("gl-force-mipmaps", false,
    PRC_DESC("Configure this true to enable full trilinear mipmapping on every "
             "texture, whether it asks for it or not."));
 
-ConfigVariableBool CLP(show_texture_usage)
+ConfigVariableBool gl_show_texture_usage
   ("gl-show-texture-usage", false,
    PRC_DESC("If you set this true, the screen will flash with textures drawn "
             "in a special mode that shows the mipmap detail level and texture "
@@ -60,27 +60,27 @@ ConfigVariableBool CLP(show_texture_usage)
             "mipmap level 0, yellow for mipmap level 1, and red for all higher "
             "mipmap levels.  Brighter colors represent larger textures."));
 
-ConfigVariableInt CLP(show_texture_usage_max_size)
+ConfigVariableInt gl_show_texture_usage_max_size
   ("gl-show-texture-usage-max-size", 1024,
    PRC_DESC("Specifies the texture size (along one side) of the largest "
             "texture expected to be loaded.  This controls the assignment "
             "of the texture color in gl-show-texture-usage mode; colors "
             "will be fully bright for textures of this size or larger."));
 
-ConfigVariableBool CLP(color_mask)
+ConfigVariableBool gl_color_mask
   ("gl-color-mask", true,
    PRC_DESC("Configure this false if your GL's implementation of glColorMask() "
             "is broken (some are).  This will force the use of a (presumably) "
             "more expensive blending operation instead."));
 
-ConfigVariableBool CLP(support_occlusion_query)
+ConfigVariableBool gl_support_occlusion_query
   ("gl-support-occlusion-query", true,
    PRC_DESC("Configure this true to enable the use of the occlusion_query "
             "extension if the GL claims to support it, or false not to "
             "use it even if it appears to be available.  (On some OpenGL "
             "drivers, enabling this mode can force software rendering.)"));
 
-ConfigVariableBool CLP(compile_and_execute)
+ConfigVariableBool gl_compile_and_execute
   ("gl-compile-and-execute", false,
    PRC_DESC("Configure this true if you know your GL's implementation of "
             "glNewList(n, GL_COMPILE_AND_EXECUTE) works.  It is "
@@ -90,7 +90,7 @@ ConfigVariableBool CLP(compile_and_execute)
             "for the first time, by allowing the display list to be "
             "rendered at the same time it is being compiled."));
 
-ConfigVariableBool CLP(interleaved_arrays)
+ConfigVariableBool gl_interleaved_arrays
   ("gl-interleaved-arrays", false,
    PRC_DESC("Set this true to convert OpenGL geometry such that the "
             "primary data columns vertex, normal, color, and texcoord "
@@ -98,20 +98,20 @@ ConfigVariableBool CLP(interleaved_arrays)
             "render geometry as it appears in the GeomVertexData.  See "
             "also gl-parallel-arrays."));
 
-ConfigVariableBool CLP(parallel_arrays)
+ConfigVariableBool gl_parallel_arrays
   ("gl-parallel-arrays", false,
    PRC_DESC("Set this true to convert OpenGL geometry such that each "
             "data column is a separate array, or false to "
             "render geometry as it appears in the GeomVertexData.  See "
             "also gl-interleaved-arrays."));
 
-ConfigVariableInt CLP(max_errors)
+ConfigVariableInt gl_max_errors
   ("gl-max-errors", 20,
    PRC_DESC("This is the limit on the number of OpenGL errors Panda will "
             "detect and report before it shuts down rendering.  Set it to "
             "-1 for no limit."));
 
-ConfigVariableEnum<GeomEnums::UsageHint> CLP(min_buffer_usage_hint)
+ConfigVariableEnum<GeomEnums::UsageHint> gl_min_buffer_usage_hint
   ("gl-min-buffer-usage-hint", GeomEnums::UH_stream,
    PRC_DESC("This specifies the first usage hint value that will be "
             "loaded as a vertex buffer, instead of directly from the "
@@ -126,13 +126,38 @@ ConfigVariableEnum<GeomEnums::UsageHint> CLP(min_buffer_usage_hint)
             "of reusing the same buffers.  Consider increasing "
             "released-vbuffer-cache-size instead."));
 
-ConfigVariableBool CLP(debug_buffers)
+ConfigVariableBool gl_debug
+  ("gl-debug", false,
+   PRC_DESC("Setting this to true will cause OpenGL to emit more useful "
+            "error and debug messages, at a slight runtime performance cost.  "
+            "notify-level-glgsg controls which severity levels are shown."));
+
+ConfigVariableBool gl_debug_synchronous
+  ("gl-debug-synchronous", false,
+   PRC_DESC("Set this true to make sure that the errors generated by "
+            "gl-debug are reported as soon as they happen.  This is "
+            "highly recommended if you want to attach a debugger since "
+            "the call stack may otherwise not point to the GL call "
+            "where the error originated."));
+
+ConfigVariableEnum<NotifySeverity> gl_debug_abort_level
+  ("gl-debug-abort-level", NS_fatal,
+   PRC_DESC("Set this to a setting other than 'fatal' to cause an "
+            "abort to be triggered when an error of the indicated "
+            "severity level (or a more severe one) occurs.  This is "
+            "useful if you want to attach a debugger.  If you set this, "
+            "it is highly recommended to also set gl-debug-synchronous, "
+            "since the call stack will otherwise not point to the GL call "
+            "that triggered the error message.  "
+            "This feature is not available when NDEBUG has been defined."));
+
+ConfigVariableBool gl_debug_buffers
   ("gl-debug-buffers", false,
    PRC_DESC("Set this true, in addition to enabling debug notify for "
             "glgsg, to enable debug messages about the creation and "
             "destruction of OpenGL vertex buffers."));
 
-ConfigVariableBool CLP(finish)
+ConfigVariableBool gl_finish
   ("gl-finish", false,
    PRC_DESC("Set this true to force a call to glFinish() after every major "
             "graphics operation.  This is likely to slow down rendering "
@@ -140,31 +165,78 @@ ConfigVariableBool CLP(finish)
             "more accurately reflect where the graphics bottlenecks are.  "
             "This variable is enabled only if PStats is compiled in."));
 
-ConfigVariableBool CLP(force_depth_stencil)
-  ("gl-force-depth-stencil", false, 
+ConfigVariableBool gl_force_depth_stencil
+  ("gl-force-depth-stencil", false,
    PRC_DESC("Temporary hack variable 7x00 vs 8x00 nVidia bug.  See glGraphicsStateGuardian_src.cxx."));
 
-ConfigVariableBool CLP(matrix_palette)
-  ("gl-matrix-palette", false, 
+ConfigVariableBool gl_matrix_palette
+  ("gl-matrix-palette", false,
    PRC_DESC("Temporary hack variable protecting untested code.  See glGraphicsStateGuardian_src.cxx."));
 
-ConfigVariableBool CLP(force_no_error)
-  ("gl-force-no-error", false,
-   PRC_DESC("Avoid reporting OpenGL errors, for a small performance benefit."));
+ConfigVariableBool gl_check_errors
+  ("gl-check-errors", false,
+   PRC_DESC("Regularly call glGetError() to check for OpenGL errors.  "
+            "This will slow down rendering significantly.  If your "
+            "video driver supports it, you should use gl-debug instead."));
 
-ConfigVariableBool CLP(force_no_flush)
-  ("gl-force-no-flush", false, 
-   PRC_DESC("Avoid calling glFlush(), for a potential performance benefit.  This may be a little dangerous."));
+ConfigVariableBool gl_force_flush
+  ("gl-force-flush", false,
+   PRC_DESC("Call this to force a call to glFlush() after rendering a "
+            "frame, even when using a double-buffered framebuffer.  "
+            "This can incur a significant performance penalty."));
 
-ConfigVariableBool CLP(separate_specular_color)
-  ("gl-separate-specular-color", true, 
+ConfigVariableBool gl_separate_specular_color
+  ("gl-separate-specular-color", true,
    PRC_DESC("When separate specular mode is on, the specular component "
             "will be written to the secondary instead of the primary "
             "color, which is added after the texturing stage.  In other "
             "words, the specular highlight will be unmodulated by the "
             "color of the texture."));
 
-extern ConfigVariableBool CLP(parallel_arrays);
+ConfigVariableBool gl_cube_map_seamless
+  ("gl-cube-map-seamless", true,
+   PRC_DESC("This configures Panda to try and enable seamless cube map "
+            "sampling when supported.  This will help to remove seams "
+            "that show up at cube map edges, especially at lower "
+            "resolutions.  On by default; disable if you suspect that "
+            "this is causing problems or if you simply don't need the "
+            "functionality."));
+
+ConfigVariableBool gl_dump_compiled_shaders
+  ("gl-dump-compiled-shaders", false,
+   PRC_DESC("This configures Panda to dump the binary content of GLSL "
+            "programs to disk with a filename like glsl_program0.dump "
+            "into the current directory."));
+
+ConfigVariableBool gl_immutable_texture_storage
+  ("gl-immutable-texture-storage", false,
+   PRC_DESC("This configures Panda to pre-allocate immutable storage "
+            "for each texture.  This improves runtime performance, but "
+            "changing the size or type of a texture will be slower."));
+
+ConfigVariableBool gl_use_bindless_texture
+  ("gl-use-bindless-texture", false,
+   PRC_DESC("Set this to let Panda use OpenGL's bindless texture "
+            "extension for all textures passed to shaders, for improved "
+            "performance.  This is an experimental feature and comes "
+            "with a few caveats; for one, it requires that all sampler "
+            "uniforms have a layout(bindless_sampler) qualifier, and "
+            "it also requires that the texture properties are not "
+            "modified after the texture handle has been initialized."));
+
+ConfigVariableBool gl_enable_memory_barriers
+  ("gl-enable-memory-barriers", true,
+   PRC_DESC("If this is set, Panda will make sure that every write "
+            "to an image using an image2D (et al) binding will cause "
+            "Panda to issue a memory barrier before the next use of "
+            "said texture, to ensure that all reads and writes are "
+            "properly synchronized.  This may not be strictly necessary "
+            "when using the 'coherent' qualifier, but Panda has no "
+            "way to detect whether you are using those.  Turning "
+            "this off may give a slight performance increase, but you "
+            "have to know what you're doing."));
+
+extern ConfigVariableBool gl_parallel_arrays;
 
 void CLP(init_classes)() {
   CLP(GeomContext)::init_type();
@@ -189,4 +261,3 @@ void CLP(init_classes)() {
   // since we won't know those until we create a graphics context (and
   // the answer may be different for different contexts).
 }
-

+ 30 - 22
panda/src/glstuff/glmisc_src.h

@@ -40,28 +40,36 @@
 
 //#define GSG_VERBOSE 1
 
-extern ConfigVariableBool CLP(cheap_textures);
-extern ConfigVariableBool CLP(ignore_clamp);
-extern ConfigVariableBool CLP(support_clamp_to_border);
-extern ConfigVariableBool CLP(ignore_filters);
-extern ConfigVariableBool CLP(ignore_mipmaps);
-extern ConfigVariableBool CLP(force_mipmaps);
-extern ConfigVariableBool CLP(show_texture_usage);
-extern ConfigVariableInt CLP(show_texture_usage_max_size);
-extern ConfigVariableBool CLP(color_mask);
-extern ConfigVariableBool CLP(support_occlusion_query);
-extern ConfigVariableBool CLP(compile_and_execute);
-extern ConfigVariableBool CLP(interleaved_arrays);
-extern ConfigVariableBool CLP(parallel_arrays);
-extern ConfigVariableInt CLP(max_errors);
-extern ConfigVariableEnum<GeomEnums::UsageHint> CLP(min_buffer_usage_hint);
-extern ConfigVariableBool CLP(debug_buffers);
-extern ConfigVariableBool CLP(finish);
-extern ConfigVariableBool CLP(force_depth_stencil);
-extern ConfigVariableBool CLP(matrix_palette);
-extern ConfigVariableBool CLP(force_no_error);
-extern ConfigVariableBool CLP(force_no_flush);
-extern ConfigVariableBool CLP(separate_specular_color);
+extern ConfigVariableBool gl_cheap_textures;
+extern ConfigVariableBool gl_ignore_clamp;
+extern ConfigVariableBool gl_support_clamp_to_border;
+extern ConfigVariableBool gl_ignore_filters;
+extern ConfigVariableBool gl_ignore_mipmaps;
+extern ConfigVariableBool gl_force_mipmaps;
+extern ConfigVariableBool gl_show_texture_usage;
+extern ConfigVariableInt gl_show_texture_usage_max_size;
+extern ConfigVariableBool gl_color_mask;
+extern ConfigVariableBool gl_support_occlusion_query;
+extern ConfigVariableBool gl_compile_and_execute;
+extern ConfigVariableBool gl_interleaved_arrays;
+extern ConfigVariableBool gl_parallel_arrays;
+extern ConfigVariableInt gl_max_errors;
+extern ConfigVariableEnum<GeomEnums::UsageHint> gl_min_buffer_usage_hint;
+extern ConfigVariableBool gl_debug;
+extern ConfigVariableBool gl_debug_synchronous;
+extern ConfigVariableEnum<NotifySeverity> gl_debug_abort_level;
+extern ConfigVariableBool gl_debug_buffers;
+extern ConfigVariableBool gl_finish;
+extern ConfigVariableBool gl_force_depth_stencil;
+extern ConfigVariableBool gl_matrix_palette;
+extern ConfigVariableBool gl_check_errors;
+extern ConfigVariableBool gl_force_flush;
+extern ConfigVariableBool gl_separate_specular_color;
+extern ConfigVariableBool gl_cube_map_seamless;
+extern ConfigVariableBool gl_dump_compiled_shaders;
+extern ConfigVariableBool gl_immutable_texture_storage;
+extern ConfigVariableBool gl_use_bindless_texture;
+extern ConfigVariableBool gl_enable_memory_barriers;
 
 extern EXPCL_GL void CLP(init_classes)();
 

+ 1 - 2
panda/src/glstuff/glstuff_src.cxx

@@ -25,8 +25,7 @@
 #include "glGeomContext_src.cxx"
 #include "glGeomMunger_src.cxx"
 #include "glShaderContext_src.cxx"
+#include "glCgShaderContext_src.cxx"
 #include "glImmediateModeSender_src.cxx"
 #include "glGraphicsBuffer_src.cxx"
 #include "glGraphicsStateGuardian_src.cxx"
-
-

+ 1 - 2
panda/src/glstuff/glstuff_src.h

@@ -18,7 +18,6 @@
 // some such), define the following symbols and #include this header
 // file.
 
-// #define GLP(name): returns name prefixed by the gl prefix, e.g. gl##name
 // #define CLP(name): returns name prefixed by the class prefix, e.g. GL##name
 // #define CLASSPREFIX_QUOTED: the quoted prefix of CLP, e.g. "GL"
 // #define CONFIGOBJ: a Configrc object, e.g. config_glgsg
@@ -40,7 +39,7 @@
 #include "glGeomContext_src.h"
 #include "glGeomMunger_src.h"
 #include "glShaderContext_src.h"
+#include "glCgShaderContext_src.h"
 #include "glImmediateModeSender_src.h"
 #include "glGraphicsBuffer_src.h"
 #include "glGraphicsStateGuardian_src.h"
-

+ 109 - 0
panda/src/glstuff/panda_glext.h

@@ -2398,6 +2398,71 @@ extern "C" {
 #define GL_TEXTURE_IMMUTABLE_FORMAT       0x912F
 #endif
 
+#ifndef GL_KHR_debug
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS       0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION        0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM      0x8245
+#define GL_DEBUG_SOURCE_API               0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM     0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER   0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY       0x8249
+#define GL_DEBUG_SOURCE_APPLICATION       0x824A
+#define GL_DEBUG_SOURCE_OTHER             0x824B
+#define GL_DEBUG_TYPE_ERROR               0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR  0x824E
+#define GL_DEBUG_TYPE_PORTABILITY         0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE         0x8250
+#define GL_DEBUG_TYPE_OTHER               0x8251
+#define GL_DEBUG_TYPE_MARKER              0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP          0x8269
+#define GL_DEBUG_TYPE_POP_GROUP           0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION    0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH    0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH        0x826D
+#define GL_BUFFER                         0x82E0
+#define GL_SHADER                         0x82E1
+#define GL_PROGRAM                        0x82E2
+#define GL_QUERY                          0x82E3
+#define GL_PROGRAM_PIPELINE               0x82E4
+#define GL_SAMPLER                        0x82E6
+#define GL_DISPLAY_LIST                   0x82E7
+/* DISPLAY_LIST used in compatibility profile only */
+#define GL_MAX_LABEL_LENGTH               0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH       0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES      0x9144
+#define GL_DEBUG_LOGGED_MESSAGES          0x9145
+#define GL_DEBUG_SEVERITY_HIGH            0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM          0x9147
+#define GL_DEBUG_SEVERITY_LOW             0x9148
+#define GL_DEBUG_OUTPUT                   0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT         0x00000002
+/* reuse GL_STACK_UNDERFLOW */
+/* reuse GL_STACK_OVERFLOW */
+#endif
+
+#ifndef GL_ARB_compute_shader
+#define GL_COMPUTE_SHADER                 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS     0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS     0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS    0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_LOCAL_INVOCATIONS  0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT   0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE    0x91BF
+#define GL_COMPUTE_LOCAL_WORK_SIZE        0x8267
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define GL_DISPATCH_INDIRECT_BUFFER       0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER_BIT             0x00000020
+#endif
+
 #ifndef GL_EXT_abgr
 #define GL_ABGR_EXT                       0x8000
 #endif
@@ -5501,8 +5566,12 @@ typedef ptrdiff_t GLsizeiptrARB;
 #ifndef GL_ARB_shader_objects
 /* GL types for program/shader text and shader object handles */
 typedef char GLcharARB;
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
 typedef unsigned int GLhandleARB;
 #endif
+#endif
 
 /* GL type for "half" precision (s10e5) float data in host memory */
 #ifndef GL_ARB_half_float_pixel
@@ -5576,6 +5645,10 @@ typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLen
 typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
 #endif
 
+#ifndef GL_KHR_debug
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+#endif
+
 #ifndef GL_NV_vdpau_interop
 typedef GLintptr GLvdpauSurfaceNV;
 #endif
@@ -7882,6 +7955,42 @@ typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum ta
 typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 #endif
 
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GLAPI void APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GLAPI void APIENTRY glPopDebugGroup (void);
+GLAPI void APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GLAPI void APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+
+#ifndef GL_ARB_compute_shader
+#define GL_ARB_compute_shader 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+#endif
+
 #ifndef GL_EXT_abgr
 #define GL_EXT_abgr 1
 #endif

+ 21 - 14
panda/src/glxdisplay/glxGraphicsPipe.cxx

@@ -88,14 +88,17 @@ make_output(const string &name,
             GraphicsOutput *host,
             int retry,
             bool &precertify) {
-  
+
   if (!_is_valid) {
     return NULL;
   }
 
-  glxGraphicsStateGuardian *glxgsg = 0;
-  if (gsg != 0) {
-    DCAST_INTO_R(glxgsg, gsg, NULL);
+  // This may not be a GLX GSG; it might be a callback GSG.
+  PosixGraphicsStateGuardian *posixgsg = NULL;
+  glxGraphicsStateGuardian *glxgsg = NULL;
+  if (gsg != NULL) {
+    DCAST_INTO_R(posixgsg, gsg, NULL);
+    glxgsg = DCAST(glxGraphicsStateGuardian, posixgsg);
   }
 
   bool support_rtt;
@@ -103,15 +106,19 @@ make_output(const string &name,
   /*
     Currently, no support for glxGraphicsBuffer render-to-texture.
   if (glxgsg) {
-     support_rtt = 
-      glxgsg -> get_supports_render_texture() && 
+     support_rtt =
+      glxgsg -> get_supports_render_texture() &&
       support_render_texture;
-  }  
+  }
   */
 
   // First thing to try: a glxGraphicsWindow
 
   if (retry == 0) {
+    if (gsg != NULL && glxgsg == NULL) {
+      // We can't use a non-GLX GSG.
+      return NULL;
+    }
     if (((flags&BF_require_parasite)!=0)||
         ((flags&BF_refuse_window)!=0)||
         ((flags&BF_resizeable)!=0)||
@@ -125,7 +132,7 @@ make_output(const string &name,
     return new glxGraphicsWindow(engine, this, name, fb_prop, win_prop,
                                  flags, gsg, host);
   }
-  
+
   // Second thing to try: a GLGraphicsBuffer
 
   if (retry == 1) {
@@ -139,7 +146,7 @@ make_output(const string &name,
     // meet specs, we can bail out early.
     int _fbo_multisample = 0;
     if (!ConfigVariableBool("framebuffer-object-multisample", false, PRC_DESC("Enabled Multisample."))) {
-        _fbo_multisample = 16;
+      _fbo_multisample = 16;
     }
     if ((flags & BF_fb_props_optional)==0) {
       if ((fb_prop.get_indexed_color() > 0)||
@@ -151,11 +158,11 @@ make_output(const string &name,
     }
     // Early success - if we are sure that this buffer WILL
     // meet specs, we can precertify it.
-    if ((glxgsg != 0) &&
-        (glxgsg->is_valid()) &&
-        (!glxgsg->needs_reset()) &&
-        (glxgsg->_supports_framebuffer_object) &&
-        (glxgsg->_glDrawBuffers != 0)&&
+    if ((posixgsg != 0) &&
+        (posixgsg->is_valid()) &&
+        (!posixgsg->needs_reset()) &&
+        (posixgsg->_supports_framebuffer_object) &&
+        (posixgsg->_glDrawBuffers != 0)&&
         (fb_prop.is_basic())) {
       precertify = true;
     }

+ 224 - 184
panda/src/glxdisplay/glxGraphicsStateGuardian.cxx

@@ -90,7 +90,7 @@ get_properties(FrameBufferProperties &properties, XVisualInfo *visual) {
     red_size, green_size, blue_size,
     alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
     depth_size, stencil_size;
-  
+
   glXGetConfig(_display, visual, GLX_USE_GL, &use_gl);
   glXGetConfig(_display, visual, GLX_RGBA, &render_mode);
   glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer);
@@ -131,7 +131,7 @@ get_properties(FrameBufferProperties &properties, XVisualInfo *visual) {
   properties.set_depth_bits(depth_size);
   properties.set_alpha_bits(alpha_size);
   properties.set_accum_bits(ared_size+agreen_size+ablue_size+aalpha_size);
-  
+
   // Set both hardware and software bits, indicating not-yet-known.
   properties.set_force_software(1);
   properties.set_force_hardware(1);
@@ -153,8 +153,8 @@ get_properties_advanced(FrameBufferProperties &properties,
     // Now update our framebuffer_mode and bit depth appropriately.
     int render_type, double_buffer, stereo, red_size, green_size, blue_size,
       alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
-      depth_size, stencil_size, samples, drawable_type, caveat;
-    
+      depth_size, stencil_size, samples, drawable_type, caveat, srgb_capable;
+
     _glXGetFBConfigAttrib(_display, config, GLX_RENDER_TYPE, &render_type);
     _glXGetFBConfigAttrib(_display, config, GLX_DOUBLEBUFFER, &double_buffer);
     _glXGetFBConfigAttrib(_display, config, GLX_STEREO, &stereo);
@@ -171,47 +171,54 @@ get_properties_advanced(FrameBufferProperties &properties,
     _glXGetFBConfigAttrib(_display, config, GLX_SAMPLES, &samples);
     _glXGetFBConfigAttrib(_display, config, GLX_DRAWABLE_TYPE, &drawable_type);
     _glXGetFBConfigAttrib(_display, config, GLX_CONFIG_CAVEAT, &caveat);
-    
+    _glXGetFBConfigAttrib(_display, config, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable);
+
     context_has_pbuffer = false;
     if ((drawable_type & GLX_PBUFFER_BIT)!=0) {
       context_has_pbuffer = true;
     }
-    
+
     context_has_pixmap = false;
     if ((drawable_type & GLX_PIXMAP_BIT)!=0) {
       context_has_pixmap = true;
     }
-    
+
     slow = false;
     if (caveat == GLX_SLOW_CONFIG) {
       slow = true;
     }
-    
+
     if ((drawable_type & GLX_WINDOW_BIT)==0) {
       // We insist on having a context that will support an onscreen window.
       return;
     }
-    
+
     if (double_buffer) {
       properties.set_back_buffers(1);
     }
+
     if (stereo) {
-      properties.set_stereo(1);
+      properties.set_stereo(true);
+    }
+
+    if (srgb_capable) {
+      properties.set_srgb_color(true);
     }
-    
+
     if ((render_type & GLX_RGBA_BIT)!=0) {
-      properties.set_rgb_color(1);
+      properties.set_rgb_color(true);
     }
     if ((render_type & GLX_COLOR_INDEX_BIT)!=0) {
-      properties.set_indexed_color(1);
+      properties.set_indexed_color(true);
     }
+
     properties.set_color_bits(red_size+green_size+blue_size);
     properties.set_stencil_bits(stencil_size);
     properties.set_depth_bits(depth_size);
     properties.set_alpha_bits(alpha_size);
     properties.set_accum_bits(ared_size+agreen_size+ablue_size+aalpha_size);
     properties.set_multisamples(samples);
-    
+
     // Set both hardware and software bits, indicating not-yet-known.
     properties.set_force_software(1);
     properties.set_force_hardware(1);
@@ -288,6 +295,11 @@ choose_pixel_format(const FrameBufferProperties &properties,
   int best_result = 0;
   FrameBufferProperties best_props;
 
+  int render_type = GLX_RGBA_TYPE;
+  if (properties.get_indexed_color()) {
+    render_type = GLX_COLOR_INDEX_TYPE;
+  }
+
   static const int max_attrib_list = 32;
   int attrib_list[max_attrib_list];
   int n = 0;
@@ -298,11 +310,11 @@ choose_pixel_format(const FrameBufferProperties &properties,
   attrib_list[n++] = GLX_DRAWABLE_TYPE;
   attrib_list[n++] = GLX_DONT_CARE;
   attrib_list[n] = (int)None;
-  
+
   int num_configs = 0;
   GLXFBConfig *configs =
     _glXChooseFBConfig(_display, _screen, attrib_list, &num_configs);
-  
+
   if (configs != 0) {
     bool context_has_pbuffer, context_has_pixmap, slow;
     int quality, i;
@@ -317,7 +329,8 @@ choose_pixel_format(const FrameBufferProperties &properties,
         const char *pixmaptext = context_has_pixmap ? " (pixmap)" : "";
         const char *slowtext = slow ? " (slow)" : "";
         glxdisplay_cat.debug()
-          << i << ": " << fbprops << " quality=" << quality << pbuffertext << pixmaptext << slowtext << "\n";
+          << i << ": " << fbprops << " quality=" << quality << pbuffertext
+          << pixmaptext << slowtext << "\n";
       }
       if (need_pbuffer && !context_has_pbuffer) {
         continue;
@@ -325,7 +338,7 @@ choose_pixel_format(const FrameBufferProperties &properties,
       if (need_pixmap && !context_has_pixmap) {
         continue;
       }
-      
+
       if (quality > best_quality) {
         best_quality = quality;
         best_result = i;
@@ -336,10 +349,29 @@ choose_pixel_format(const FrameBufferProperties &properties,
 
   if (best_quality > 0) {
     _fbconfig = configs[best_result];
-    _context = 
-      _glXCreateNewContext(_display, _fbconfig, GLX_RGBA_TYPE, _share_context,
-                           GL_TRUE);
+
+    if (_glXCreateContextAttribs != NULL) {
+      // NB.  This is a wholly different type of attrib list
+      // than below, the same values are not used!
+      n = 0;
+      attrib_list[n++] = GLX_RENDER_TYPE;
+      attrib_list[n++] = render_type;
+      if (gl_debug) {
+        attrib_list[n++] = GLX_CONTEXT_FLAGS_ARB;
+        attrib_list[n++] = GLX_CONTEXT_DEBUG_BIT_ARB;
+      }
+      attrib_list[n] = None;
+      _context = _glXCreateContextAttribs(_display, _fbconfig, _share_context,
+                                          GL_TRUE, attrib_list);
+    } else {
+      _context =
+        _glXCreateNewContext(_display, _fbconfig, render_type, _share_context,
+                             GL_TRUE);
+    }
+
     if (_context) {
+      mark_new();
+
       if (_visuals != (XVisualInfo *)NULL) {
         XFree(_visuals);
         _visuals = NULL;
@@ -351,6 +383,10 @@ choose_pixel_format(const FrameBufferProperties &properties,
         get_properties_advanced(_fbprops, _context_has_pbuffer, _context_has_pixmap,
                                 _slow, _fbconfig);
 
+        if (!properties.get_srgb_color()) {
+          _fbprops.set_srgb_color(false);
+        }
+
         if (glxdisplay_cat.is_debug()) {
           glxdisplay_cat.debug()
             << "Selected context " << best_result << ": " << _fbprops << "\n";
@@ -387,150 +423,6 @@ choose_pixel_format(const FrameBufferProperties &properties,
   _context_has_pbuffer = false;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: glxGraphicsStateGuardian::reset
-//       Access: Public, Virtual
-//  Description: Resets all internal state as if the gsg were newly
-//               created.
-////////////////////////////////////////////////////////////////////
-void glxGraphicsStateGuardian::
-reset() {
-  PosixGraphicsStateGuardian::reset();
-
-  _supports_swap_control = has_extension("GLX_SGI_swap_control");
-
-  if (_supports_swap_control) {
-    _glXSwapIntervalSGI = 
-      (PFNGLXSWAPINTERVALSGIPROC)get_extension_func("glX", "SwapIntervalSGI");
-    if (_glXSwapIntervalSGI == NULL) {
-      glxdisplay_cat.error()
-        << "Driver claims to support GLX_SGI_swap_control extension, but does not define all functions.\n";
-      _supports_swap_control = false;
-    }
-  }
-
-  if (_supports_swap_control) {
-    // Set the video-sync setting up front, if we have the extension
-    // that supports it.
-    _glXSwapIntervalSGI(sync_video ? 1 : 0);
-  }
-
-  if (glx_support_fbconfig) {
-    if (glx_is_at_least_version(1, 3)) {
-      // If we have glx 1.3 or better, we have the FBConfig interface.
-      _supports_fbconfig = true;
-      
-      _glXChooseFBConfig = 
-        (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glX", "ChooseFBConfig");
-      _glXCreateNewContext = 
-        (PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glX", "CreateNewContext");
-      _glXGetVisualFromFBConfig = 
-        (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glX", "GetVisualFromFBConfig");
-      _glXGetFBConfigAttrib = 
-        (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glX", "GetFBConfigAttrib");
-      _glXCreatePixmap = 
-        (PFNGLXCREATEPIXMAPPROC)get_extension_func("glX", "CreatePixmap");
-      
-      if (_glXChooseFBConfig == NULL ||
-          _glXCreateNewContext == NULL ||
-          _glXGetVisualFromFBConfig == NULL ||
-          _glXGetFBConfigAttrib == NULL ||
-          _glXCreatePixmap == NULL) {
-        glxdisplay_cat.error()
-          << "Driver claims to support GLX_fbconfig extension, but does not define all functions.\n";
-        _supports_fbconfig = false;
-      }
-    } else if (has_extension("GLX_SGIX_fbconfig")) {
-      // Or maybe we have the old SGIX extension for FBConfig.  This is
-      // the same, but the function names are different--we just remap
-      // them to the same function pointers.
-      _supports_fbconfig = true;
-      
-      _glXChooseFBConfig = 
-        (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glX", "ChooseFBConfigSGIX");
-      _glXCreateNewContext = 
-        (PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glX", "CreateContextWithConfigSGIX");
-      _glXGetVisualFromFBConfig = 
-        (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glX", "GetVisualFromFBConfigSGIX");
-      _glXGetFBConfigAttrib = 
-        (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glX", "GetFBConfigAttribSGIX");
-      _glXCreatePixmap = 
-        (PFNGLXCREATEPIXMAPPROC)get_extension_func("glX", "CreateGLXPixmapWithConfigSGIX");
-      
-      if (_glXChooseFBConfig == NULL ||
-          _glXCreateNewContext == NULL ||
-          _glXGetVisualFromFBConfig == NULL ||
-          _glXGetFBConfigAttrib == NULL ||
-          _glXCreatePixmap == NULL) {
-        glxdisplay_cat.error()
-          << "Driver claims to support GLX_SGIX_fbconfig extension, but does not define all functions.\n";
-        _supports_fbconfig = false;
-      }
-    }
-    
-    if (glx_is_at_least_version(1, 3)) {
-      // If we have glx 1.3 or better, we have the PBuffer interface.
-      _supports_pbuffer = true;
-      _uses_sgix_pbuffer = false;
-      
-      _glXCreatePbuffer = 
-        (PFNGLXCREATEPBUFFERPROC)get_extension_func("glX", "CreatePbuffer");
-      _glXCreateGLXPbufferSGIX = NULL;
-      _glXDestroyPbuffer = 
-        (PFNGLXDESTROYPBUFFERPROC)get_extension_func("glX", "DestroyPbuffer");
-      if (_glXCreatePbuffer == NULL ||
-          _glXDestroyPbuffer == NULL) {
-        glxdisplay_cat.error()
-          << "Driver claims to support GLX_pbuffer extension, but does not define all functions.\n";
-        _supports_pbuffer = false;
-      }
-      
-    } else if (has_extension("GLX_SGIX_pbuffer")) {
-      // Or maybe we have the old SGIX extension for PBuffers.
-      _uses_sgix_pbuffer = true;
-      
-      // CreatePbuffer has a different form between SGIX and 1.3,
-      // however, so we must treat it specially.  But we can use the
-      // same function pointer for DestroyPbuffer.
-      _glXCreatePbuffer = NULL;
-      _glXCreateGLXPbufferSGIX = 
-        (PFNGLXCREATEGLXPBUFFERSGIXPROC)get_extension_func("glX", "CreateGLXPbufferSGIX");
-      _glXDestroyPbuffer = 
-        (PFNGLXDESTROYPBUFFERPROC)get_extension_func("glX", "DestroyGLXPbufferSGIX");
-      if (_glXCreateGLXPbufferSGIX == NULL ||
-          _glXDestroyPbuffer == NULL) {
-        glxdisplay_cat.error()
-          << "Driver claims to support GLX_SGIX_pbuffer extension, but does not define all functions.\n";
-        _supports_pbuffer = false;
-      }
-    }
-  }
-
-
-  if (glxdisplay_cat.is_debug()) {
-    glxdisplay_cat.debug()
-      << "supports_swap_control = " << _supports_swap_control << "\n";
-    glxdisplay_cat.debug()
-      << "supports_fbconfig = " << _supports_fbconfig << "\n";
-    glxdisplay_cat.debug()
-      << "supports_pbuffer = " << _supports_pbuffer
-      << " sgix = " << _uses_sgix_pbuffer << "\n";
-  }
-
-  // If "Mesa" is present, assume software.  However, if "Mesa DRI" is
-  // found, it's actually a Mesa-based OpenGL layer running over a
-  // hardware driver.
-  if (_gl_renderer.find("Mesa") != string::npos &&
-      _gl_renderer.find("Mesa DRI") == string::npos) {
-    // It's Mesa, therefore probably a software context.
-    _fbprops.set_force_software(1);
-    _fbprops.set_force_hardware(0);
-  } else {
-    _fbprops.set_force_hardware(1);
-    _fbprops.set_force_software(0);
-  }
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: glxGraphicsStateGuardian::glx_is_at_least_version
 //       Access: Public
@@ -625,41 +517,39 @@ get_extra_extensions() {
 //               not defined.
 ////////////////////////////////////////////////////////////////////
 void *glxGraphicsStateGuardian::
-do_get_extension_func(const char *prefix, const char *name) {
-  nassertr(prefix != NULL, NULL);
+do_get_extension_func(const char *name) {
   nassertr(name != NULL, NULL);
-  string fullname = string(prefix) + string(name);
 
   if (glx_get_proc_address) {
     // First, check if we have glXGetProcAddress available.  This will
     // be superior if we can get it.
-    
+
 #if defined(LINK_IN_GLXGETPROCADDRESS) && defined(HAVE_GLXGETPROCADDRESS)
       // If we are confident the system headers defined it, we can
       // call it directly.  This is more reliable than trying to
       // determine its address dynamically, but it may make
       // libpandagl.so fail to load if the symbol isn't in the runtime
       // library.
-    return (void *)glXGetProcAddress((const GLubyte *)fullname.c_str());
-      
+    return (void *)glXGetProcAddress((const GLubyte *)name);
+
 #elif defined(LINK_IN_GLXGETPROCADDRESS) && defined(HAVE_GLXGETPROCADDRESSARB)
     // The ARB extension version is OK too.  Sometimes the prototype
     // isn't supplied for some reason.
-    return (void *)glXGetProcAddressARB((const GLubyte *)fullname.c_str());
-    
+    return (void *)glXGetProcAddressARB((const GLubyte *)name);
+
 #else
     // Otherwise, we have to fiddle around with the dynamic runtime.
-    
+
     if (!_checked_get_proc_address) {
       const char *funcName = NULL;
-      
+
       if (glx_is_at_least_version(1, 4)) {
         funcName = "glXGetProcAddress";
 
       } else if (has_extension("GLX_ARB_get_proc_address")) {
         funcName = "glXGetProcAddressARB";
       }
-      
+
       if (funcName != NULL) {
         _glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC)get_system_func(funcName);
         if (_glXGetProcAddress == NULL) {
@@ -671,16 +561,163 @@ do_get_extension_func(const char *prefix, const char *name) {
 
       _checked_get_proc_address = true;
     }
-    
+
     // Use glxGetProcAddress() if we've got it; it should be more robust.
     if (_glXGetProcAddress != NULL) {
-      return (void *)_glXGetProcAddress((const GLubyte *)fullname.c_str());
+      return (void *)_glXGetProcAddress((const GLubyte *)name);
     }
 #endif // HAVE_GLXGETPROCADDRESS
   }
 
   // Otherwise, fall back to the OS-provided calls.
-  return PosixGraphicsStateGuardian::do_get_extension_func(prefix, name);
+  return PosixGraphicsStateGuardian::do_get_extension_func(name);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: glxGraphicsStateGuardian::query_glx_extensions
+//       Access: Private
+//  Description: Queries the GLX extension pointers.
+////////////////////////////////////////////////////////////////////
+void glxGraphicsStateGuardian::
+query_glx_extensions() {
+  _supports_swap_control = has_extension("GLX_SGI_swap_control");
+
+  if (_supports_swap_control) {
+    _glXSwapIntervalSGI = 
+      (PFNGLXSWAPINTERVALSGIPROC)get_extension_func("glXSwapIntervalSGI");
+    if (_glXSwapIntervalSGI == NULL) {
+      glxdisplay_cat.error()
+        << "Driver claims to support GLX_SGI_swap_control extension, but does not define all functions.\n";
+      _supports_swap_control = false;
+    }
+  }
+
+  if (_supports_swap_control) {
+    // Set the video-sync setting up front, if we have the extension
+    // that supports it.
+    _glXSwapIntervalSGI(sync_video ? 1 : 0);
+  }
+
+  if (glx_support_fbconfig) {
+    if (glx_is_at_least_version(1, 3)) {
+      // If we have glx 1.3 or better, we have the FBConfig interface.
+      _supports_fbconfig = true;
+
+      _glXChooseFBConfig =
+        (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glXChooseFBConfig");
+      _glXCreateNewContext =
+        (PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glXCreateNewContext");
+      _glXGetVisualFromFBConfig =
+        (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glXGetVisualFromFBConfig");
+      _glXGetFBConfigAttrib =
+        (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glXGetFBConfigAttrib");
+      _glXCreatePixmap =
+        (PFNGLXCREATEPIXMAPPROC)get_extension_func("glXCreatePixmap");
+
+      if (_glXChooseFBConfig == NULL ||
+          _glXCreateNewContext == NULL ||
+          _glXGetVisualFromFBConfig == NULL ||
+          _glXGetFBConfigAttrib == NULL ||
+          _glXCreatePixmap == NULL) {
+        glxdisplay_cat.error()
+          << "Driver claims to support GLX_fbconfig extension, but does not define all functions.\n";
+        _supports_fbconfig = false;
+      }
+    } else if (has_extension("GLX_SGIX_fbconfig")) {
+      // Or maybe we have the old SGIX extension for FBConfig.  This is
+      // the same, but the function names are different--we just remap
+      // them to the same function pointers.
+      _supports_fbconfig = true;
+
+      _glXChooseFBConfig =
+        (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func("glXChooseFBConfigSGIX");
+      _glXCreateNewContext =
+        (PFNGLXCREATENEWCONTEXTPROC)get_extension_func("glXCreateContextWithConfigSGIX");
+      _glXGetVisualFromFBConfig =
+        (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func("glXGetVisualFromFBConfigSGIX");
+      _glXGetFBConfigAttrib =
+        (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func("glXGetFBConfigAttribSGIX");
+      _glXCreatePixmap =
+        (PFNGLXCREATEPIXMAPPROC)get_extension_func("glXCreateGLXPixmapWithConfigSGIX");
+
+      if (_glXChooseFBConfig == NULL ||
+          _glXCreateNewContext == NULL ||
+          _glXGetVisualFromFBConfig == NULL ||
+          _glXGetFBConfigAttrib == NULL ||
+          _glXCreatePixmap == NULL) {
+        glxdisplay_cat.error()
+          << "Driver claims to support GLX_SGIX_fbconfig extension, but does not define all functions.\n";
+        _supports_fbconfig = false;
+      }
+    }
+
+    if (glx_is_at_least_version(1, 3)) {
+      // If we have glx 1.3 or better, we have the PBuffer interface.
+      _supports_pbuffer = true;
+      _uses_sgix_pbuffer = false;
+
+      _glXCreatePbuffer =
+        (PFNGLXCREATEPBUFFERPROC)get_extension_func("glXCreatePbuffer");
+      _glXCreateGLXPbufferSGIX = NULL;
+      _glXDestroyPbuffer =
+        (PFNGLXDESTROYPBUFFERPROC)get_extension_func("glXDestroyPbuffer");
+      if (_glXCreatePbuffer == NULL ||
+          _glXDestroyPbuffer == NULL) {
+        glxdisplay_cat.error()
+          << "Driver claims to support GLX_pbuffer extension, but does not define all functions.\n";
+        _supports_pbuffer = false;
+      }
+
+    } else if (has_extension("GLX_SGIX_pbuffer")) {
+      // Or maybe we have the old SGIX extension for PBuffers.
+      _uses_sgix_pbuffer = true;
+
+      // CreatePbuffer has a different form between SGIX and 1.3,
+      // however, so we must treat it specially.  But we can use the
+      // same function pointer for DestroyPbuffer.
+      _glXCreatePbuffer = NULL;
+      _glXCreateGLXPbufferSGIX =
+        (PFNGLXCREATEGLXPBUFFERSGIXPROC)get_extension_func("glXCreateGLXPbufferSGIX");
+      _glXDestroyPbuffer =
+        (PFNGLXDESTROYPBUFFERPROC)get_extension_func("glXDestroyGLXPbufferSGIX");
+      if (_glXCreateGLXPbufferSGIX == NULL ||
+          _glXDestroyPbuffer == NULL) {
+        glxdisplay_cat.error()
+          << "Driver claims to support GLX_SGIX_pbuffer extension, but does not define all functions.\n";
+        _supports_pbuffer = false;
+      }
+    }
+
+    if (has_extension("GLX_ARB_create_context")) {
+      _glXCreateContextAttribs = 
+        (PFNGLXCREATECONTEXTATTRIBSARBPROC)get_extension_func("glXCreateContextAttribsARB");
+    } else {
+      _glXCreateContextAttribs = NULL;
+    }
+  }
+
+  if (glxdisplay_cat.is_debug()) {
+    glxdisplay_cat.debug()
+      << "supports_swap_control = " << _supports_swap_control << "\n";
+    glxdisplay_cat.debug()
+      << "supports_fbconfig = " << _supports_fbconfig << "\n";
+    glxdisplay_cat.debug()
+      << "supports_pbuffer = " << _supports_pbuffer
+      << " sgix = " << _uses_sgix_pbuffer << "\n";
+  }
+
+  // If "Mesa" is present, assume software.  However, if "Mesa DRI" is
+  // found, it's actually a Mesa-based OpenGL layer running over a
+  // hardware driver.
+  if (_gl_renderer.find("Mesa") != string::npos &&
+      _gl_renderer.find("Mesa DRI") == string::npos) {
+    // It's Mesa, therefore probably a software context.
+    _fbprops.set_force_software(1);
+    _fbprops.set_force_hardware(0);
+  } else {
+    _fbprops.set_force_hardware(1);
+    _fbprops.set_force_software(0);
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -759,17 +796,17 @@ choose_temp_visual(const FrameBufferProperties &properties) {
       }
     }
   }
-  
+
   if (best_quality > 0) {
     _visual = _visuals + best_result;
-    _temp_context = glXCreateContext(_display, _visual, None, GL_TRUE);    
+    _temp_context = glXCreateContext(_display, _visual, None, GL_TRUE);
     if (_temp_context) {
       _fbprops = best_props;
       return;
     }
   }
 
-  glxdisplay_cat.error() 
+  glxdisplay_cat.error()
     << "Could not find a usable pixel format.\n";
 }
 
@@ -805,8 +842,11 @@ init_temp_context() {
     return;
   }
 
+  // Now use it to query the available GLX features.
   glXMakeCurrent(_display, _temp_xwindow, _temp_context);
-  reset();
+  query_gl_version();
+  get_extra_extensions();
+  query_glx_extensions();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -828,7 +868,7 @@ destroy_temp_xwindow() {
     _temp_xwindow = (X11_Window)NULL;
   }
 
-  if (_temp_context != (GLXContext)NULL){ 
+  if (_temp_context != (GLXContext)NULL) {
     glXDestroyContext(_display, _temp_context);
     _temp_context = (GLXContext)NULL;
   }

+ 4 - 4
panda/src/glxdisplay/glxGraphicsStateGuardian.h

@@ -67,7 +67,7 @@ typedef int (* PFNGLXGETFBCONFIGATTRIBPROC) (X11_Display *dpy, GLXFBConfig confi
 typedef GLXPixmap (* PFNGLXCREATEPIXMAPPROC) (X11_Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
 typedef GLXPbuffer (* PFNGLXCREATEPBUFFERPROC) (X11_Display *dpy, GLXFBConfig config, const int *attrib_list);
 typedef void (* PFNGLXDESTROYPBUFFERPROC) (X11_Display *dpy, GLXPbuffer pbuf);
-
+typedef GLXContext ( *PFNGLXCREATECONTEXTATTRIBSARBPROC) (X11_Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
 #endif  // __EDG__
 
 ////////////////////////////////////////////////////////////////////
@@ -92,8 +92,6 @@ public:
 
   virtual ~glxGraphicsStateGuardian();
 
-  virtual void reset();
-
   bool glx_is_at_least_version(int major_version, int minor_version) const;
 
   GLXContext _share_context;
@@ -119,6 +117,7 @@ public:
   PFNGLXGETVISUALFROMFBCONFIGPROC _glXGetVisualFromFBConfig;
   PFNGLXGETFBCONFIGATTRIBPROC _glXGetFBConfigAttrib;
   PFNGLXCREATEPIXMAPPROC _glXCreatePixmap;
+  PFNGLXCREATECONTEXTATTRIBSARBPROC _glXCreateContextAttribs;
 
   bool _supports_pbuffer;  // true if the interface is available.
   bool _uses_sgix_pbuffer;
@@ -132,9 +131,10 @@ protected:
 
   virtual void query_gl_version();
   virtual void get_extra_extensions();
-  virtual void *do_get_extension_func(const char *prefix, const char *name);
+  virtual void *do_get_extension_func(const char *name);
 
 private:
+  void query_glx_extensions();
   void show_glx_client_string(const string &name, int id);
   void show_glx_server_string(const string &name, int id);
   void choose_temp_visual(const FrameBufferProperties &properties);

+ 765 - 512
panda/src/glxdisplay/panda_glxext.h

@@ -1,614 +1,867 @@
 #ifndef panda__glxext_h_
-#define panda__glxext_h_
+#define panda__glxext_h_ 1
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
-** License Applicability. Except to the extent portions of this file are
-** made subject to an alternative license as permitted in the SGI Free
-** Software License B, Version 1.1 (the "License"), the contents of this
-** file are subject only to the provisions of the License. You may not use
-** this file except in compliance with the License. You may obtain a copy
-** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
-** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
-** 
-** http://oss.sgi.com/projects/FreeB
-** 
-** Note that, as provided in the License, the Software is distributed on an
-** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
-** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
-** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
-** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
-** 
-** Original Code. The Original Code is: OpenGL Sample Implementation,
-** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
-** Inc. The Original Code is Copyright (c) 1991-2002 Silicon Graphics, Inc.
-** Copyright in any portions created by third parties is as indicated
-** elsewhere herein. All Rights Reserved.
-** 
-** Additional Notice Provisions: This software was created using the
-** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has
-** not been independently verified as being compliant with the OpenGL(R)
-** version 1.2.1 Specification.
+** Copyright (c) 2013-2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/
+**
+** Khronos $Revision$ on $Date$
 */
 
-#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
-#define WIN32_LEAN_AND_MEAN 1
-#include <windows.h>
-#endif
-
-#ifndef APIENTRY
-#define APIENTRY
-#endif
-#ifndef APIENTRYP
-#define APIENTRYP APIENTRY *
-#endif
-#ifndef GLAPI
-#define GLAPI extern
-#endif
-
-/*************************************************************/
+#define GLX_GLXEXT_VERSION 20140416
 
-/* Header file version number, required by OpenGL ABI for Linux */
-/* glxext.h last updated 2002/03/22 */
-/* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */
-#define GLX_GLXEXT_VERSION 5
+/* Generated C header for:
+ * API: glx
+ * Versions considered: .*
+ * Versions emitted: 1\.[3-9]
+ * Default extensions included: glx
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
 
 #ifndef GLX_VERSION_1_3
-#define GLX_WINDOW_BIT                     0x00000001
-#define GLX_PIXMAP_BIT                     0x00000002
-#define GLX_PBUFFER_BIT                    0x00000004
-#define GLX_RGBA_BIT                       0x00000001
-#define GLX_COLOR_INDEX_BIT                0x00000002
-#define GLX_PBUFFER_CLOBBER_MASK           0x08000000
-#define GLX_FRONT_LEFT_BUFFER_BIT          0x00000001
-#define GLX_FRONT_RIGHT_BUFFER_BIT         0x00000002
-#define GLX_BACK_LEFT_BUFFER_BIT           0x00000004
-#define GLX_BACK_RIGHT_BUFFER_BIT          0x00000008
-#define GLX_AUX_BUFFERS_BIT                0x00000010
-#define GLX_DEPTH_BUFFER_BIT               0x00000020
-#define GLX_STENCIL_BUFFER_BIT             0x00000040
-#define GLX_ACCUM_BUFFER_BIT               0x00000080
-#define GLX_CONFIG_CAVEAT                  0x20
-#define GLX_X_VISUAL_TYPE                  0x22
-#define GLX_TRANSPARENT_TYPE               0x23
-#define GLX_TRANSPARENT_INDEX_VALUE        0x24
-#define GLX_TRANSPARENT_RED_VALUE          0x25
-#define GLX_TRANSPARENT_GREEN_VALUE        0x26
-#define GLX_TRANSPARENT_BLUE_VALUE         0x27
-#define GLX_TRANSPARENT_ALPHA_VALUE        0x28
-#define GLX_DONT_CARE                      0xFFFFFFFF
-#define GLX_NONE                           0x8000
-#define GLX_SLOW_CONFIG                    0x8001
-#define GLX_TRUE_COLOR                     0x8002
-#define GLX_DIRECT_COLOR                   0x8003
-#define GLX_PSEUDO_COLOR                   0x8004
-#define GLX_STATIC_COLOR                   0x8005
-#define GLX_GRAY_SCALE                     0x8006
-#define GLX_STATIC_GRAY                    0x8007
-#define GLX_TRANSPARENT_RGB                0x8008
-#define GLX_TRANSPARENT_INDEX              0x8009
-#define GLX_VISUAL_ID                      0x800B
-#define GLX_SCREEN                         0x800C
-#define GLX_NON_CONFORMANT_CONFIG          0x800D
-#define GLX_DRAWABLE_TYPE                  0x8010
-#define GLX_RENDER_TYPE                    0x8011
-#define GLX_X_RENDERABLE                   0x8012
-#define GLX_FBCONFIG_ID                    0x8013
-#define GLX_RGBA_TYPE                      0x8014
-#define GLX_COLOR_INDEX_TYPE               0x8015
-#define GLX_MAX_PBUFFER_WIDTH              0x8016
-#define GLX_MAX_PBUFFER_HEIGHT             0x8017
-#define GLX_MAX_PBUFFER_PIXELS             0x8018
-#define GLX_PRESERVED_CONTENTS             0x801B
-#define GLX_LARGEST_PBUFFER                0x801C
-#define GLX_WIDTH                          0x801D
-#define GLX_HEIGHT                         0x801E
-#define GLX_EVENT_MASK                     0x801F
-#define GLX_DAMAGED                        0x8020
-#define GLX_SAVED                          0x8021
-#define GLX_WINDOW                         0x8022
-#define GLX_PBUFFER                        0x8023
-#define GLX_PBUFFER_HEIGHT                 0x8040
-#define GLX_PBUFFER_WIDTH                  0x8041
-#endif
+#define GLX_VERSION_1_3 1
+typedef XID GLXContextID;
+typedef struct __GLXFBConfigRec *GLXFBConfig;
+typedef XID GLXWindow;
+typedef XID GLXPbuffer;
+#define GLX_WINDOW_BIT                    0x00000001
+#define GLX_PIXMAP_BIT                    0x00000002
+#define GLX_PBUFFER_BIT                   0x00000004
+#define GLX_RGBA_BIT                      0x00000001
+#define GLX_COLOR_INDEX_BIT               0x00000002
+#define GLX_PBUFFER_CLOBBER_MASK          0x08000000
+#define GLX_FRONT_LEFT_BUFFER_BIT         0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT        0x00000002
+#define GLX_BACK_LEFT_BUFFER_BIT          0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT         0x00000008
+#define GLX_AUX_BUFFERS_BIT               0x00000010
+#define GLX_DEPTH_BUFFER_BIT              0x00000020
+#define GLX_STENCIL_BUFFER_BIT            0x00000040
+#define GLX_ACCUM_BUFFER_BIT              0x00000080
+#define GLX_CONFIG_CAVEAT                 0x20
+#define GLX_X_VISUAL_TYPE                 0x22
+#define GLX_TRANSPARENT_TYPE              0x23
+#define GLX_TRANSPARENT_INDEX_VALUE       0x24
+#define GLX_TRANSPARENT_RED_VALUE         0x25
+#define GLX_TRANSPARENT_GREEN_VALUE       0x26
+#define GLX_TRANSPARENT_BLUE_VALUE        0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE       0x28
+#define GLX_DONT_CARE                     0xFFFFFFFF
+#define GLX_NONE                          0x8000
+#define GLX_SLOW_CONFIG                   0x8001
+#define GLX_TRUE_COLOR                    0x8002
+#define GLX_DIRECT_COLOR                  0x8003
+#define GLX_PSEUDO_COLOR                  0x8004
+#define GLX_STATIC_COLOR                  0x8005
+#define GLX_GRAY_SCALE                    0x8006
+#define GLX_STATIC_GRAY                   0x8007
+#define GLX_TRANSPARENT_RGB               0x8008
+#define GLX_TRANSPARENT_INDEX             0x8009
+#define GLX_VISUAL_ID                     0x800B
+#define GLX_SCREEN                        0x800C
+#define GLX_NON_CONFORMANT_CONFIG         0x800D
+#define GLX_DRAWABLE_TYPE                 0x8010
+#define GLX_RENDER_TYPE                   0x8011
+#define GLX_X_RENDERABLE                  0x8012
+#define GLX_FBCONFIG_ID                   0x8013
+#define GLX_RGBA_TYPE                     0x8014
+#define GLX_COLOR_INDEX_TYPE              0x8015
+#define GLX_MAX_PBUFFER_WIDTH             0x8016
+#define GLX_MAX_PBUFFER_HEIGHT            0x8017
+#define GLX_MAX_PBUFFER_PIXELS            0x8018
+#define GLX_PRESERVED_CONTENTS            0x801B
+#define GLX_LARGEST_PBUFFER               0x801C
+#define GLX_WIDTH                         0x801D
+#define GLX_HEIGHT                        0x801E
+#define GLX_EVENT_MASK                    0x801F
+#define GLX_DAMAGED                       0x8020
+#define GLX_SAVED                         0x8021
+#define GLX_WINDOW                        0x8022
+#define GLX_PBUFFER                       0x8023
+#define GLX_PBUFFER_HEIGHT                0x8040
+#define GLX_PBUFFER_WIDTH                 0x8041
+typedef GLXFBConfig *( *PFNGLXGETFBCONFIGSPROC) (X11_Display *dpy, int screen, int *nelements);
+typedef GLXFBConfig *( *PFNGLXCHOOSEFBCONFIGPROC) (X11_Display *dpy, int screen, const int *attrib_list, int *nelements);
+typedef int ( *PFNGLXGETFBCONFIGATTRIBPROC) (X11_Display *dpy, GLXFBConfig config, int attribute, int *value);
+typedef XVisualInfo *( *PFNGLXGETVISUALFROMFBCONFIGPROC) (X11_Display *dpy, GLXFBConfig config);
+typedef GLXWindow ( *PFNGLXCREATEWINDOWPROC) (X11_Display *dpy, GLXFBConfig config, X11_Window win, const int *attrib_list);
+typedef void ( *PFNGLXDESTROYWINDOWPROC) (X11_Display *dpy, GLXWindow win);
+typedef GLXPixmap ( *PFNGLXCREATEPIXMAPPROC) (X11_Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
+typedef void ( *PFNGLXDESTROYPIXMAPPROC) (X11_Display *dpy, GLXPixmap pixmap);
+typedef GLXPbuffer ( *PFNGLXCREATEPBUFFERPROC) (X11_Display *dpy, GLXFBConfig config, const int *attrib_list);
+typedef void ( *PFNGLXDESTROYPBUFFERPROC) (X11_Display *dpy, GLXPbuffer pbuf);
+typedef void ( *PFNGLXQUERYDRAWABLEPROC) (X11_Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
+typedef GLXContext ( *PFNGLXCREATENEWCONTEXTPROC) (X11_Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef Bool ( *PFNGLXMAKECONTEXTCURRENTPROC) (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+typedef GLXDrawable ( *PFNGLXGETCURRENTREADDRAWABLEPROC) (void);
+typedef int ( *PFNGLXQUERYCONTEXTPROC) (X11_Display *dpy, GLXContext ctx, int attribute, int *value);
+typedef void ( *PFNGLXSELECTEVENTPROC) (X11_Display *dpy, GLXDrawable draw, unsigned long event_mask);
+typedef void ( *PFNGLXGETSELECTEDEVENTPROC) (X11_Display *dpy, GLXDrawable draw, unsigned long *event_mask);
+#ifdef GLX_GLXEXT_PROTOTYPES
+GLXFBConfig *glXGetFBConfigs (X11_Display *dpy, int screen, int *nelements);
+GLXFBConfig *glXChooseFBConfig (X11_Display *dpy, int screen, const int *attrib_list, int *nelements);
+int glXGetFBConfigAttrib (X11_Display *dpy, GLXFBConfig config, int attribute, int *value);
+XVisualInfo *glXGetVisualFromFBConfig (X11_Display *dpy, GLXFBConfig config);
+GLXWindow glXCreateWindow (X11_Display *dpy, GLXFBConfig config, X11_Window win, const int *attrib_list);
+void glXDestroyWindow (X11_Display *dpy, GLXWindow win);
+GLXPixmap glXCreatePixmap (X11_Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
+void glXDestroyPixmap (X11_Display *dpy, GLXPixmap pixmap);
+GLXPbuffer glXCreatePbuffer (X11_Display *dpy, GLXFBConfig config, const int *attrib_list);
+void glXDestroyPbuffer (X11_Display *dpy, GLXPbuffer pbuf);
+void glXQueryDrawable (X11_Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
+GLXContext glXCreateNewContext (X11_Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+Bool glXMakeContextCurrent (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+GLXDrawable glXGetCurrentReadDrawable (void);
+int glXQueryContext (X11_Display *dpy, GLXContext ctx, int attribute, int *value);
+void glXSelectEvent (X11_Display *dpy, GLXDrawable draw, unsigned long event_mask);
+void glXGetSelectedEvent (X11_Display *dpy, GLXDrawable draw, unsigned long *event_mask);
+#endif
+#endif /* GLX_VERSION_1_3 */
 
 #ifndef GLX_VERSION_1_4
-#define GLX_SAMPLE_BUFFERS                 100000
-#define GLX_SAMPLES                        100001
-#endif
-
-/* drose: the version of GL/glx.h that ships with Fedora Core 2 seems
-   to define GLX_VERSION_1_4, but for some reason does not define
-   GLX_SAMPLE_BUFFERS or GLX_SAMPLES.  We work around that here. */
-#ifndef GLX_SAMPLE_BUFFERS
-#define GLX_SAMPLE_BUFFERS                 100000
-#endif
-#ifndef GLX_SAMPLES
-#define GLX_SAMPLES                        100001
-#endif
+#define GLX_VERSION_1_4 1
+typedef void ( *__GLXextFuncPtr)(void);
+#define GLX_SAMPLE_BUFFERS                100000
+#define GLX_SAMPLES                       100001
+typedef __GLXextFuncPtr ( *PFNGLXGETPROCADDRESSPROC) (const GLubyte *procName);
+#ifdef GLX_GLXEXT_PROTOTYPES
+__GLXextFuncPtr glXGetProcAddress (const GLubyte *procName);
+#endif
+#endif /* GLX_VERSION_1_4 */
+
+#ifndef GLX_ARB_create_context
+#define GLX_ARB_create_context 1
+#define GLX_CONTEXT_DEBUG_BIT_ARB         0x00000001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB     0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB     0x2092
+#define GLX_CONTEXT_FLAGS_ARB             0x2094
+typedef GLXContext ( *PFNGLXCREATECONTEXTATTRIBSARBPROC) (X11_Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
+#ifdef GLX_GLXEXT_PROTOTYPES
+GLXContext glXCreateContextAttribsARB (X11_Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
+#endif
+#endif /* GLX_ARB_create_context */
+
+#ifndef GLX_ARB_create_context_profile
+#define GLX_ARB_create_context_profile 1
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB  0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_PROFILE_MASK_ARB      0x9126
+#endif /* GLX_ARB_create_context_profile */
+
+#ifndef GLX_ARB_create_context_robustness
+#define GLX_ARB_create_context_robustness 1
+#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GLX_LOSE_CONTEXT_ON_RESET_ARB     0x8252
+#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GLX_NO_RESET_NOTIFICATION_ARB     0x8261
+#endif /* GLX_ARB_create_context_robustness */
+
+#ifndef GLX_ARB_fbconfig_float
+#define GLX_ARB_fbconfig_float 1
+#define GLX_RGBA_FLOAT_TYPE_ARB           0x20B9
+#define GLX_RGBA_FLOAT_BIT_ARB            0x00000004
+#endif /* GLX_ARB_fbconfig_float */
+
+#ifndef GLX_ARB_framebuffer_sRGB
+#define GLX_ARB_framebuffer_sRGB 1
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB  0x20B2
+#endif /* GLX_ARB_framebuffer_sRGB */
 
 #ifndef GLX_ARB_get_proc_address
+#define GLX_ARB_get_proc_address 1
+typedef __GLXextFuncPtr ( *PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName);
+#ifdef GLX_GLXEXT_PROTOTYPES
+__GLXextFuncPtr glXGetProcAddressARB (const GLubyte *procName);
 #endif
+#endif /* GLX_ARB_get_proc_address */
 
 #ifndef GLX_ARB_multisample
-#define GLX_SAMPLE_BUFFERS_ARB             100000
-#define GLX_SAMPLES_ARB                    100001
-#endif
+#define GLX_ARB_multisample 1
+#define GLX_SAMPLE_BUFFERS_ARB            100000
+#define GLX_SAMPLES_ARB                   100001
+#endif /* GLX_ARB_multisample */
 
-#ifndef GLX_SGIS_multisample
-#define GLX_SAMPLE_BUFFERS_SGIS            100000
-#define GLX_SAMPLES_SGIS                   100001
-#endif
+#ifndef GLX_ARB_robustness_application_isolation
+#define GLX_ARB_robustness_application_isolation 1
+#define GLX_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+#endif /* GLX_ARB_robustness_application_isolation */
 
-#ifndef GLX_EXT_visual_info
-#define GLX_X_VISUAL_TYPE_EXT              0x22
-#define GLX_TRANSPARENT_TYPE_EXT           0x23
-#define GLX_TRANSPARENT_INDEX_VALUE_EXT    0x24
-#define GLX_TRANSPARENT_RED_VALUE_EXT      0x25
-#define GLX_TRANSPARENT_GREEN_VALUE_EXT    0x26
-#define GLX_TRANSPARENT_BLUE_VALUE_EXT     0x27
-#define GLX_TRANSPARENT_ALPHA_VALUE_EXT    0x28
-#define GLX_NONE_EXT                       0x8000
-#define GLX_TRUE_COLOR_EXT                 0x8002
-#define GLX_DIRECT_COLOR_EXT               0x8003
-#define GLX_PSEUDO_COLOR_EXT               0x8004
-#define GLX_STATIC_COLOR_EXT               0x8005
-#define GLX_GRAY_SCALE_EXT                 0x8006
-#define GLX_STATIC_GRAY_EXT                0x8007
-#define GLX_TRANSPARENT_RGB_EXT            0x8008
-#define GLX_TRANSPARENT_INDEX_EXT          0x8009
-#endif
+#ifndef GLX_ARB_robustness_share_group_isolation
+#define GLX_ARB_robustness_share_group_isolation 1
+#endif /* GLX_ARB_robustness_share_group_isolation */
 
-#ifndef GLX_SGI_swap_control
-#endif
+#ifndef GLX_ARB_vertex_buffer_object
+#define GLX_ARB_vertex_buffer_object 1
+#define GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095
+#endif /* GLX_ARB_vertex_buffer_object */
 
-#ifndef GLX_SGI_video_sync
-#endif
-
-#ifndef GLX_SGI_make_current_read
+#ifndef GLX_3DFX_multisample
+#define GLX_3DFX_multisample 1
+#define GLX_SAMPLE_BUFFERS_3DFX           0x8050
+#define GLX_SAMPLES_3DFX                  0x8051
+#endif /* GLX_3DFX_multisample */
+
+#ifndef GLX_AMD_gpu_association
+#define GLX_AMD_gpu_association 1
+#define GLX_GPU_VENDOR_AMD                0x1F00
+#define GLX_GPU_RENDERER_STRING_AMD       0x1F01
+#define GLX_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
+#define GLX_GPU_FASTEST_TARGET_GPUS_AMD   0x21A2
+#define GLX_GPU_RAM_AMD                   0x21A3
+#define GLX_GPU_CLOCK_AMD                 0x21A4
+#define GLX_GPU_NUM_PIPES_AMD             0x21A5
+#define GLX_GPU_NUM_SIMD_AMD              0x21A6
+#define GLX_GPU_NUM_RB_AMD                0x21A7
+#define GLX_GPU_NUM_SPI_AMD               0x21A8
+#endif /* GLX_AMD_gpu_association */
+
+#ifndef GLX_EXT_buffer_age
+#define GLX_EXT_buffer_age 1
+#define GLX_BACK_BUFFER_AGE_EXT           0x20F4
+#endif /* GLX_EXT_buffer_age */
+
+#ifndef GLX_EXT_create_context_es2_profile
+#define GLX_EXT_create_context_es2_profile 1
+#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT   0x00000004
+#endif /* GLX_EXT_create_context_es2_profile */
+
+#ifndef GLX_EXT_create_context_es_profile
+#define GLX_EXT_create_context_es_profile 1
+#define GLX_CONTEXT_ES_PROFILE_BIT_EXT    0x00000004
+#endif /* GLX_EXT_create_context_es_profile */
+
+#ifndef GLX_EXT_fbconfig_packed_float
+#define GLX_EXT_fbconfig_packed_float 1
+#define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT  0x20B1
+#define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT   0x00000008
+#endif /* GLX_EXT_fbconfig_packed_float */
+
+#ifndef GLX_EXT_framebuffer_sRGB
+#define GLX_EXT_framebuffer_sRGB 1
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT  0x20B2
+#endif /* GLX_EXT_framebuffer_sRGB */
+
+#ifndef GLX_EXT_stereo_tree
+#define GLX_EXT_stereo_tree 1
+typedef struct {
+    int type;
+    unsigned long serial;
+    Bool send_event;
+    X11_Display *display;
+    int extension;
+    int evtype;
+    GLXDrawable window;
+    Bool stereo_tree;
+} GLXStereoNotifyEventEXT;
+#define GLX_STEREO_TREE_EXT               0x20F5
+#define GLX_STEREO_NOTIFY_MASK_EXT        0x00000001
+#define GLX_STEREO_NOTIFY_EXT             0x00000000
+#endif /* GLX_EXT_stereo_tree */
+
+#ifndef GLX_EXT_swap_control
+#define GLX_EXT_swap_control 1
+#define GLX_SWAP_INTERVAL_EXT             0x20F1
+#define GLX_MAX_SWAP_INTERVAL_EXT         0x20F2
+typedef void ( *PFNGLXSWAPINTERVALEXTPROC) (X11_Display *dpy, GLXDrawable drawable, int interval);
+#ifdef GLX_GLXEXT_PROTOTYPES
+void glXSwapIntervalEXT (X11_Display *dpy, GLXDrawable drawable, int interval);
+#endif
+#endif /* GLX_EXT_swap_control */
+
+#ifndef GLX_EXT_swap_control_tear
+#define GLX_EXT_swap_control_tear 1
+#define GLX_LATE_SWAPS_TEAR_EXT           0x20F3
+#endif /* GLX_EXT_swap_control_tear */
+
+#ifndef GLX_EXT_texture_from_pixmap
+#define GLX_EXT_texture_from_pixmap 1
+#define GLX_TEXTURE_1D_BIT_EXT            0x00000001
+#define GLX_TEXTURE_2D_BIT_EXT            0x00000002
+#define GLX_TEXTURE_RECTANGLE_BIT_EXT     0x00000004
+#define GLX_BIND_TO_TEXTURE_RGB_EXT       0x20D0
+#define GLX_BIND_TO_TEXTURE_RGBA_EXT      0x20D1
+#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT    0x20D2
+#define GLX_BIND_TO_TEXTURE_TARGETS_EXT   0x20D3
+#define GLX_Y_INVERTED_EXT                0x20D4
+#define GLX_TEXTURE_FORMAT_EXT            0x20D5
+#define GLX_TEXTURE_TARGET_EXT            0x20D6
+#define GLX_MIPMAP_TEXTURE_EXT            0x20D7
+#define GLX_TEXTURE_FORMAT_NONE_EXT       0x20D8
+#define GLX_TEXTURE_FORMAT_RGB_EXT        0x20D9
+#define GLX_TEXTURE_FORMAT_RGBA_EXT       0x20DA
+#define GLX_TEXTURE_1D_EXT                0x20DB
+#define GLX_TEXTURE_2D_EXT                0x20DC
+#define GLX_TEXTURE_RECTANGLE_EXT         0x20DD
+#define GLX_FRONT_LEFT_EXT                0x20DE
+#define GLX_FRONT_RIGHT_EXT               0x20DF
+#define GLX_BACK_LEFT_EXT                 0x20E0
+#define GLX_BACK_RIGHT_EXT                0x20E1
+#define GLX_FRONT_EXT                     0x20DE
+#define GLX_BACK_EXT                      0x20E0
+#define GLX_AUX0_EXT                      0x20E2
+#define GLX_AUX1_EXT                      0x20E3
+#define GLX_AUX2_EXT                      0x20E4
+#define GLX_AUX3_EXT                      0x20E5
+#define GLX_AUX4_EXT                      0x20E6
+#define GLX_AUX5_EXT                      0x20E7
+#define GLX_AUX6_EXT                      0x20E8
+#define GLX_AUX7_EXT                      0x20E9
+#define GLX_AUX8_EXT                      0x20EA
+#define GLX_AUX9_EXT                      0x20EB
+typedef void ( *PFNGLXBINDTEXIMAGEEXTPROC) (X11_Display *dpy, GLXDrawable drawable, int buffer, const int *attrib_list);
+typedef void ( *PFNGLXRELEASETEXIMAGEEXTPROC) (X11_Display *dpy, GLXDrawable drawable, int buffer);
+#ifdef GLX_GLXEXT_PROTOTYPES
+void glXBindTexImageEXT (X11_Display *dpy, GLXDrawable drawable, int buffer, const int *attrib_list);
+void glXReleaseTexImageEXT (X11_Display *dpy, GLXDrawable drawable, int buffer);
 #endif
+#endif /* GLX_EXT_texture_from_pixmap */
 
-#ifndef GLX_SGIX_video_source
-#endif
+#ifndef GLX_EXT_visual_info
+#define GLX_EXT_visual_info 1
+#define GLX_X_VISUAL_TYPE_EXT             0x22
+#define GLX_TRANSPARENT_TYPE_EXT          0x23
+#define GLX_TRANSPARENT_INDEX_VALUE_EXT   0x24
+#define GLX_TRANSPARENT_RED_VALUE_EXT     0x25
+#define GLX_TRANSPARENT_GREEN_VALUE_EXT   0x26
+#define GLX_TRANSPARENT_BLUE_VALUE_EXT    0x27
+#define GLX_TRANSPARENT_ALPHA_VALUE_EXT   0x28
+#define GLX_NONE_EXT                      0x8000
+#define GLX_TRUE_COLOR_EXT                0x8002
+#define GLX_DIRECT_COLOR_EXT              0x8003
+#define GLX_PSEUDO_COLOR_EXT              0x8004
+#define GLX_STATIC_COLOR_EXT              0x8005
+#define GLX_GRAY_SCALE_EXT                0x8006
+#define GLX_STATIC_GRAY_EXT               0x8007
+#define GLX_TRANSPARENT_RGB_EXT           0x8008
+#define GLX_TRANSPARENT_INDEX_EXT         0x8009
+#endif /* GLX_EXT_visual_info */
 
 #ifndef GLX_EXT_visual_rating
-#define GLX_VISUAL_CAVEAT_EXT              0x20
-#define GLX_SLOW_VISUAL_EXT                0x8001
-#define GLX_NON_CONFORMANT_VISUAL_EXT      0x800D
-/* reuse GLX_NONE_EXT */
-#endif
-
-#ifndef GLX_SGIX_fbconfig
-#define GLX_WINDOW_BIT_SGIX                0x00000001
-#define GLX_PIXMAP_BIT_SGIX                0x00000002
-#define GLX_RGBA_BIT_SGIX                  0x00000001
-#define GLX_COLOR_INDEX_BIT_SGIX           0x00000002
-#define GLX_DRAWABLE_TYPE_SGIX             0x8010
-#define GLX_RENDER_TYPE_SGIX               0x8011
-#define GLX_X_RENDERABLE_SGIX              0x8012
-#define GLX_FBCONFIG_ID_SGIX               0x8013
-#define GLX_RGBA_TYPE_SGIX                 0x8014
-#define GLX_COLOR_INDEX_TYPE_SGIX          0x8015
-/* reuse GLX_SCREEN_EXT */
-#endif
-
-#ifndef GLX_SGIX_pbuffer
-#define GLX_PBUFFER_BIT_SGIX               0x00000004
-#define GLX_BUFFER_CLOBBER_MASK_SGIX       0x08000000
-#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX     0x00000001
-#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX    0x00000002
-#define GLX_BACK_LEFT_BUFFER_BIT_SGIX      0x00000004
-#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX     0x00000008
-#define GLX_AUX_BUFFERS_BIT_SGIX           0x00000010
-#define GLX_DEPTH_BUFFER_BIT_SGIX          0x00000020
-#define GLX_STENCIL_BUFFER_BIT_SGIX        0x00000040
-#define GLX_ACCUM_BUFFER_BIT_SGIX          0x00000080
-#define GLX_SAMPLE_BUFFERS_BIT_SGIX        0x00000100
-#define GLX_MAX_PBUFFER_WIDTH_SGIX         0x8016
-#define GLX_MAX_PBUFFER_HEIGHT_SGIX        0x8017
-#define GLX_MAX_PBUFFER_PIXELS_SGIX        0x8018
-#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX     0x8019
-#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX    0x801A
-#define GLX_PRESERVED_CONTENTS_SGIX        0x801B
-#define GLX_LARGEST_PBUFFER_SGIX           0x801C
-#define GLX_WIDTH_SGIX                     0x801D
-#define GLX_HEIGHT_SGIX                    0x801E
-#define GLX_EVENT_MASK_SGIX                0x801F
-#define GLX_DAMAGED_SGIX                   0x8020
-#define GLX_SAVED_SGIX                     0x8021
-#define GLX_WINDOW_SGIX                    0x8022
-#define GLX_PBUFFER_SGIX                   0x8023
-#endif
-
-#ifndef GLX_SGI_cushion
-#endif
-
-#ifndef GLX_SGIX_video_resize
-#define GLX_SYNC_FRAME_SGIX                0x00000000
-#define GLX_SYNC_SWAP_SGIX                 0x00000001
-#endif
-
-#ifndef GLX_SGIX_dmbuffer
-#define GLX_DIGITAL_MEDIA_PBUFFER_SGIX     0x8024
-#endif
-
-#ifndef GLX_SGIX_swap_group
-#endif
-
-#ifndef GLX_SGIX_swap_barrier
-#endif
-
-#ifndef GLX_SGIS_blended_overlay
-#define GLX_BLENDED_RGBA_SGIS              0x8025
-#endif
-
-#ifndef GLX_SGIS_shared_multisample
-#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026
-#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027
-#endif
-
-#ifndef GLX_SUN_get_transparent_index
-#endif
-
-#ifndef GLX_3DFX_multisample
-#define GLX_SAMPLE_BUFFERS_3DFX            0x8050
-#define GLX_SAMPLES_3DFX                   0x8051
+#define GLX_EXT_visual_rating 1
+#define GLX_VISUAL_CAVEAT_EXT             0x20
+#define GLX_SLOW_VISUAL_EXT               0x8001
+#define GLX_NON_CONFORMANT_VISUAL_EXT     0x800D
+#endif /* GLX_EXT_visual_rating */
+
+#ifndef GLX_INTEL_swap_event
+#define GLX_INTEL_swap_event 1
+#define GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000
+#define GLX_EXCHANGE_COMPLETE_INTEL       0x8180
+#define GLX_COPY_COMPLETE_INTEL           0x8181
+#define GLX_FLIP_COMPLETE_INTEL           0x8182
+#endif /* GLX_INTEL_swap_event */
+
+#ifndef GLX_MESA_agp_offset
+#define GLX_MESA_agp_offset 1
+typedef unsigned int ( *PFNGLXGETAGPOFFSETMESAPROC) (const void *pointer);
+#ifdef GLX_GLXEXT_PROTOTYPES
+unsigned int glXGetAGPOffsetMESA (const void *pointer);
 #endif
+#endif /* GLX_MESA_agp_offset */
 
 #ifndef GLX_MESA_copy_sub_buffer
+#define GLX_MESA_copy_sub_buffer 1
+typedef void ( *PFNGLXCOPYSUBBUFFERMESAPROC) (X11_Display *dpy, GLXDrawable drawable, int x, int y, int width, int height);
+#ifdef GLX_GLXEXT_PROTOTYPES
+void glXCopySubBufferMESA (X11_Display *dpy, GLXDrawable drawable, int x, int y, int width, int height);
 #endif
+#endif /* GLX_MESA_copy_sub_buffer */
 
 #ifndef GLX_MESA_pixmap_colormap
+#define GLX_MESA_pixmap_colormap 1
+typedef GLXPixmap ( *PFNGLXCREATEGLXPIXMAPMESAPROC) (X11_Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap);
+#ifdef GLX_GLXEXT_PROTOTYPES
+GLXPixmap glXCreateGLXPixmapMESA (X11_Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap);
+#endif
+#endif /* GLX_MESA_pixmap_colormap */
+
+#ifndef GLX_MESA_query_renderer
+#define GLX_MESA_query_renderer 1
+#define GLX_RENDERER_VENDOR_ID_MESA       0x8183
+#define GLX_RENDERER_DEVICE_ID_MESA       0x8184
+#define GLX_RENDERER_VERSION_MESA         0x8185
+#define GLX_RENDERER_ACCELERATED_MESA     0x8186
+#define GLX_RENDERER_VIDEO_MEMORY_MESA    0x8187
+#define GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA 0x8188
+#define GLX_RENDERER_PREFERRED_PROFILE_MESA 0x8189
+#define GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA 0x818A
+#define GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA 0x818B
+#define GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA 0x818C
+#define GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA 0x818D
+#define GLX_RENDERER_ID_MESA              0x818E
+typedef Bool ( *PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) (int attribute, unsigned int *value);
+typedef const char *( *PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC) (int attribute);
+typedef Bool ( *PFNGLXQUERYRENDERERINTEGERMESAPROC) (X11_Display *dpy, int screen, int renderer, int attribute, unsigned int *value);
+typedef const char *( *PFNGLXQUERYRENDERERSTRINGMESAPROC) (X11_Display *dpy, int screen, int renderer, int attribute);
+#ifdef GLX_GLXEXT_PROTOTYPES
+Bool glXQueryCurrentRendererIntegerMESA (int attribute, unsigned int *value);
+const char *glXQueryCurrentRendererStringMESA (int attribute);
+Bool glXQueryRendererIntegerMESA (X11_Display *dpy, int screen, int renderer, int attribute, unsigned int *value);
+const char *glXQueryRendererStringMESA (X11_Display *dpy, int screen, int renderer, int attribute);
 #endif
+#endif /* GLX_MESA_query_renderer */
 
 #ifndef GLX_MESA_release_buffers
+#define GLX_MESA_release_buffers 1
+typedef Bool ( *PFNGLXRELEASEBUFFERSMESAPROC) (X11_Display *dpy, GLXDrawable drawable);
+#ifdef GLX_GLXEXT_PROTOTYPES
+Bool glXReleaseBuffersMESA (X11_Display *dpy, GLXDrawable drawable);
 #endif
+#endif /* GLX_MESA_release_buffers */
 
 #ifndef GLX_MESA_set_3dfx_mode
-#define GLX_3DFX_WINDOW_MODE_MESA          0x1
-#define GLX_3DFX_FULLSCREEN_MODE_MESA      0x2
+#define GLX_MESA_set_3dfx_mode 1
+#define GLX_3DFX_WINDOW_MODE_MESA         0x1
+#define GLX_3DFX_FULLSCREEN_MODE_MESA     0x2
+typedef Bool ( *PFNGLXSET3DFXMODEMESAPROC) (int mode);
+#ifdef GLX_GLXEXT_PROTOTYPES
+Bool glXSet3DfxModeMESA (int mode);
 #endif
+#endif /* GLX_MESA_set_3dfx_mode */
 
-#ifndef GLX_SGIX_visual_select_group
-#define GLX_VISUAL_SELECT_GROUP_SGIX       0x8028
+#ifndef GLX_NV_copy_image
+#define GLX_NV_copy_image 1
+typedef void ( *PFNGLXCOPYIMAGESUBDATANVPROC) (X11_Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#ifdef GLX_GLXEXT_PROTOTYPES
+void glXCopyImageSubDataNV (X11_Display *dpy, GLXContext srcCtx, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLXContext dstCtx, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
 #endif
+#endif /* GLX_NV_copy_image */
 
-#ifndef GLX_OML_swap_method
-#define GLX_SWAP_METHOD_OML                0x8060
-#define GLX_SWAP_EXCHANGE_OML              0x8061
-#define GLX_SWAP_COPY_OML                  0x8062
-#define GLX_SWAP_UNDEFINED_OML             0x8063
+#ifndef GLX_NV_delay_before_swap
+#define GLX_NV_delay_before_swap 1
+typedef Bool ( *PFNGLXDELAYBEFORESWAPNVPROC) (X11_Display *dpy, GLXDrawable drawable, GLfloat seconds);
+#ifdef GLX_GLXEXT_PROTOTYPES
+Bool glXDelayBeforeSwapNV (X11_Display *dpy, GLXDrawable drawable, GLfloat seconds);
+#endif
+#endif /* GLX_NV_delay_before_swap */
+
+#ifndef GLX_NV_float_buffer
+#define GLX_NV_float_buffer 1
+#define GLX_FLOAT_COMPONENTS_NV           0x20B0
+#endif /* GLX_NV_float_buffer */
+
+#ifndef GLX_NV_multisample_coverage
+#define GLX_NV_multisample_coverage 1
+#define GLX_COVERAGE_SAMPLES_NV           100001
+#define GLX_COLOR_SAMPLES_NV              0x20B3
+#endif /* GLX_NV_multisample_coverage */
+
+#ifndef GLX_NV_present_video
+#define GLX_NV_present_video 1
+#define GLX_NUM_VIDEO_SLOTS_NV            0x20F0
+typedef unsigned int *( *PFNGLXENUMERATEVIDEODEVICESNVPROC) (X11_Display *dpy, int screen, int *nelements);
+typedef int ( *PFNGLXBINDVIDEODEVICENVPROC) (X11_Display *dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list);
+#ifdef GLX_GLXEXT_PROTOTYPES
+unsigned int *glXEnumerateVideoDevicesNV (X11_Display *dpy, int screen, int *nelements);
+int glXBindVideoDeviceNV (X11_Display *dpy, unsigned int video_slot, unsigned int video_device, const int *attrib_list);
+#endif
+#endif /* GLX_NV_present_video */
+
+#ifndef GLX_NV_swap_group
+#define GLX_NV_swap_group 1
+typedef Bool ( *PFNGLXJOINSWAPGROUPNVPROC) (X11_Display *dpy, GLXDrawable drawable, GLuint group);
+typedef Bool ( *PFNGLXBINDSWAPBARRIERNVPROC) (X11_Display *dpy, GLuint group, GLuint barrier);
+typedef Bool ( *PFNGLXQUERYSWAPGROUPNVPROC) (X11_Display *dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier);
+typedef Bool ( *PFNGLXQUERYMAXSWAPGROUPSNVPROC) (X11_Display *dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers);
+typedef Bool ( *PFNGLXQUERYFRAMECOUNTNVPROC) (X11_Display *dpy, int screen, GLuint *count);
+typedef Bool ( *PFNGLXRESETFRAMECOUNTNVPROC) (X11_Display *dpy, int screen);
+#ifdef GLX_GLXEXT_PROTOTYPES
+Bool glXJoinSwapGroupNV (X11_Display *dpy, GLXDrawable drawable, GLuint group);
+Bool glXBindSwapBarrierNV (X11_Display *dpy, GLuint group, GLuint barrier);
+Bool glXQuerySwapGroupNV (X11_Display *dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier);
+Bool glXQueryMaxSwapGroupsNV (X11_Display *dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers);
+Bool glXQueryFrameCountNV (X11_Display *dpy, int screen, GLuint *count);
+Bool glXResetFrameCountNV (X11_Display *dpy, int screen);
+#endif
+#endif /* GLX_NV_swap_group */
+
+#ifndef GLX_NV_video_capture
+#define GLX_NV_video_capture 1
+typedef XID GLXVideoCaptureDeviceNV;
+#define GLX_DEVICE_ID_NV                  0x20CD
+#define GLX_UNIQUE_ID_NV                  0x20CE
+#define GLX_NUM_VIDEO_CAPTURE_SLOTS_NV    0x20CF
+typedef int ( *PFNGLXBINDVIDEOCAPTUREDEVICENVPROC) (X11_Display *dpy, unsigned int video_capture_slot, GLXVideoCaptureDeviceNV device);
+typedef GLXVideoCaptureDeviceNV *( *PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC) (X11_Display *dpy, int screen, int *nelements);
+typedef void ( *PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC) (X11_Display *dpy, GLXVideoCaptureDeviceNV device);
+typedef int ( *PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC) (X11_Display *dpy, GLXVideoCaptureDeviceNV device, int attribute, int *value);
+typedef void ( *PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC) (X11_Display *dpy, GLXVideoCaptureDeviceNV device);
+#ifdef GLX_GLXEXT_PROTOTYPES
+int glXBindVideoCaptureDeviceNV (X11_Display *dpy, unsigned int video_capture_slot, GLXVideoCaptureDeviceNV device);
+GLXVideoCaptureDeviceNV *glXEnumerateVideoCaptureDevicesNV (X11_Display *dpy, int screen, int *nelements);
+void glXLockVideoCaptureDeviceNV (X11_Display *dpy, GLXVideoCaptureDeviceNV device);
+int glXQueryVideoCaptureDeviceNV (X11_Display *dpy, GLXVideoCaptureDeviceNV device, int attribute, int *value);
+void glXReleaseVideoCaptureDeviceNV (X11_Display *dpy, GLXVideoCaptureDeviceNV device);
+#endif
+#endif /* GLX_NV_video_capture */
+
+#ifndef GLX_NV_video_output
+#define GLX_NV_video_output 1
+typedef unsigned int GLXVideoDeviceNV;
+#define GLX_VIDEO_OUT_COLOR_NV            0x20C3
+#define GLX_VIDEO_OUT_ALPHA_NV            0x20C4
+#define GLX_VIDEO_OUT_DEPTH_NV            0x20C5
+#define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV  0x20C6
+#define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV  0x20C7
+#define GLX_VIDEO_OUT_FRAME_NV            0x20C8
+#define GLX_VIDEO_OUT_FIELD_1_NV          0x20C9
+#define GLX_VIDEO_OUT_FIELD_2_NV          0x20CA
+#define GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB
+#define GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC
+typedef int ( *PFNGLXGETVIDEODEVICENVPROC) (X11_Display *dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice);
+typedef int ( *PFNGLXRELEASEVIDEODEVICENVPROC) (X11_Display *dpy, int screen, GLXVideoDeviceNV VideoDevice);
+typedef int ( *PFNGLXBINDVIDEOIMAGENVPROC) (X11_Display *dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer);
+typedef int ( *PFNGLXRELEASEVIDEOIMAGENVPROC) (X11_Display *dpy, GLXPbuffer pbuf);
+typedef int ( *PFNGLXSENDPBUFFERTOVIDEONVPROC) (X11_Display *dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock);
+typedef int ( *PFNGLXGETVIDEOINFONVPROC) (X11_Display *dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
+#ifdef GLX_GLXEXT_PROTOTYPES
+int glXGetVideoDeviceNV (X11_Display *dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice);
+int glXReleaseVideoDeviceNV (X11_Display *dpy, int screen, GLXVideoDeviceNV VideoDevice);
+int glXBindVideoImageNV (X11_Display *dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer);
+int glXReleaseVideoImageNV (X11_Display *dpy, GLXPbuffer pbuf);
+int glXSendPbufferToVideoNV (X11_Display *dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock);
+int glXGetVideoInfoNV (X11_Display *dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
 #endif
+#endif /* GLX_NV_video_output */
+
+#ifndef GLX_OML_swap_method
+#define GLX_OML_swap_method 1
+#define GLX_SWAP_METHOD_OML               0x8060
+#define GLX_SWAP_EXCHANGE_OML             0x8061
+#define GLX_SWAP_COPY_OML                 0x8062
+#define GLX_SWAP_UNDEFINED_OML            0x8063
+#endif /* GLX_OML_swap_method */
 
 #ifndef GLX_OML_sync_control
+#define GLX_OML_sync_control 1
+#ifndef GLEXT_64_TYPES_DEFINED
+/* This code block is duplicated in glext.h, so must be protected */
+#define GLEXT_64_TYPES_DEFINED
+/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
+/* (as used in the GLX_OML_sync_control extension). */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+#elif defined(__sun__) || defined(__digital__)
+#include <inttypes.h>
+#if defined(__STDC__)
+#if defined(__arch64__) || defined(_LP64)
+typedef long int int64_t;
+typedef unsigned long int uint64_t;
+#else
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#endif /* __arch64__ */
+#endif /* __STDC__ */
+#elif defined( __VMS ) || defined(__sgi)
+#include <inttypes.h>
+#elif defined(__SCO__) || defined(__USLC__)
+#include <stdint.h>
+#elif defined(__UNIXOS2__) || defined(__SOL64__)
+typedef long int int32_t;
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#elif defined(_WIN32) && defined(__GNUC__)
+#include <stdint.h>
+#elif defined(_WIN32)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+/* Fallback if nothing above works */
+#include <inttypes.h>
 #endif
-
-
-/*************************************************************/
-
-/* drose: glxext.h seems to have an error in that it assumes
-   __GLXextFuncPtr will be typedeffed if GLX_ARB_get_proc_address is
-   defined, which does not seem to be the case (at least it is not so
-   on my redhat 8.0 box).  So we work around this by typedeffing it
-   explicitly; and we use #define in case it is already typedeffed. */
-#define __GLXextFuncPtr panda__GLXextFuncPtr
-typedef void (*__GLXextFuncPtr)();
-
-  /*
-#ifndef GLX_ARB_get_proc_address
-typedef void (*__GLXextFuncPtr)();
 #endif
-  */
-
-#ifndef GLX_SGIX_video_source
-typedef XID GLXVideoSourceSGIX;
+typedef Bool ( *PFNGLXGETSYNCVALUESOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc);
+typedef Bool ( *PFNGLXGETMSCRATEOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator);
+typedef int64_t ( *PFNGLXSWAPBUFFERSMSCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder);
+typedef Bool ( *PFNGLXWAITFORMSCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc);
+typedef Bool ( *PFNGLXWAITFORSBCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_sbc, int64_t *ust, int64_t *msc, int64_t *sbc);
+#ifdef GLX_GLXEXT_PROTOTYPES
+Bool glXGetSyncValuesOML (X11_Display *dpy, GLXDrawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc);
+Bool glXGetMscRateOML (X11_Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator);
+int64_t glXSwapBuffersMscOML (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder);
+Bool glXWaitForMscOML (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc);
+Bool glXWaitForSbcOML (X11_Display *dpy, GLXDrawable drawable, int64_t target_sbc, int64_t *ust, int64_t *msc, int64_t *sbc);
 #endif
+#endif /* GLX_OML_sync_control */
 
-#ifndef GLX_SGIX_fbconfig
-typedef XID GLXFBConfigIDSGIX;
-typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
-#endif
+#ifndef GLX_SGIS_blended_overlay
+#define GLX_SGIS_blended_overlay 1
+#define GLX_BLENDED_RGBA_SGIS             0x8025
+#endif /* GLX_SGIS_blended_overlay */
 
-#ifndef GLX_SGIX_pbuffer
-typedef XID GLXPbufferSGIX;
-typedef struct {
-    int type;
-    unsigned long serial;         /* # of last request processed by server */
-    Bool send_event;              /* true if this came for SendEvent request */
-    X11_Display *display;             /* display the event was read from */
-    GLXDrawable drawable;         /* i.d. of Drawable */
-    int event_type;               /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */
-    int draw_type;                /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */
-    unsigned int mask;    /* mask indicating which buffers are affected*/
-    int x, y;
-    int width, height;
-    int count;            /* if nonzero, at least this many more */
-} GLXBufferClobberEventSGIX;
-#endif
+#ifndef GLX_SGIS_multisample
+#define GLX_SGIS_multisample 1
+#define GLX_SAMPLE_BUFFERS_SGIS           100000
+#define GLX_SAMPLES_SGIS                  100001
+#endif /* GLX_SGIS_multisample */
 
-#ifndef GLX_VERSION_1_3
-#define GLX_VERSION_1_3 1
-  /* drose: If the system glx.h isn't at least version 1.3, it won't
-     have defined these types, so we need to do so here in order for
-     the following to compile. */
-typedef struct __GLXFBConfigRec *GLXFBConfig;    
-typedef XID GLXPbuffer;
-typedef XID GLXWindow;
+#ifndef GLX_SGIS_shared_multisample
+#define GLX_SGIS_shared_multisample 1
+#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026
+#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027
+#endif /* GLX_SGIS_shared_multisample */
 
+#ifndef GLX_SGIX_dmbuffer
+#define GLX_SGIX_dmbuffer 1
+typedef XID GLXPbufferSGIX;
+#ifdef _DM_BUFFER_H_
+#define GLX_DIGITAL_MEDIA_PBUFFER_SGIX    0x8024
+typedef Bool ( *PFNGLXASSOCIATEDMPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern GLXFBConfig * glXGetFBConfigs (X11_Display *, int, int *);
-extern GLXFBConfig * glXChooseFBConfig (X11_Display *, int, const int *, int *);
-extern int glXGetFBConfigAttrib (X11_Display *, GLXFBConfig, int, int *);
-extern XVisualInfo * glXGetVisualFromFBConfig (X11_Display *, GLXFBConfig);
-extern GLXWindow glXCreateWindow (X11_Display *, GLXFBConfig, X11_Window, const int *);
-extern void glXDestroyWindow (X11_Display *, GLXWindow);
-extern GLXPixmap glXCreatePixmap (X11_Display *, GLXFBConfig, Pixmap, const int *);
-extern void glXDestroyPixmap (X11_Display *, GLXPixmap);
-extern GLXPbuffer glXCreatePbuffer (X11_Display *, GLXFBConfig, const int *);
-extern void glXDestroyPbuffer (X11_Display *, GLXPbuffer);
-extern void glXQueryDrawable (X11_Display *, GLXDrawable, int, unsigned int *);
-extern GLXContext glXCreateNewContext (X11_Display *, GLXFBConfig, int, GLXContext, Bool);
-extern Bool glXMakeContextCurrent (X11_Display *, GLXDrawable, GLXDrawable, GLXContext);
-extern GLXDrawable glXGetCurrentReadDrawable ();
-extern X11_Display * glXGetCurrentDisplay ();
-extern int glXQueryContext (X11_Display *, GLXContext, int, int *);
-extern void glXSelectEvent (X11_Display *, GLXDrawable, unsigned long);
-extern void glXGetSelectedEvent (X11_Display *, GLXDrawable, unsigned long *);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-  /* drose: all of the following PFN... typedefs seemed to be
-     incorrect.  I put a * just inside the leading parenthesis. */
-typedef GLXFBConfig * (* PFNGLXGETFBCONFIGSPROC) (X11_Display *dpy, int screen, int *nelements);
-typedef GLXFBConfig * (* PFNGLXCHOOSEFBCONFIGPROC) (X11_Display *dpy, int screen, const int *attrib_list, int *nelements);
-typedef int (* PFNGLXGETFBCONFIGATTRIBPROC) (X11_Display *dpy, GLXFBConfig config, int attribute, int *value);
-typedef XVisualInfo * (* PFNGLXGETVISUALFROMFBCONFIGPROC) (X11_Display *dpy, GLXFBConfig config);
-typedef GLXWindow (* PFNGLXCREATEWINDOWPROC) (X11_Display *dpy, GLXFBConfig config, X11_Window win, const int *attrib_list);
-typedef void (* PFNGLXDESTROYWINDOWPROC) (X11_Display *dpy, GLXWindow win);
-typedef GLXPixmap (* PFNGLXCREATEPIXMAPPROC) (X11_Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
-typedef void (* PFNGLXDESTROYPIXMAPPROC) (X11_Display *dpy, GLXPixmap pixmap);
-typedef GLXPbuffer (* PFNGLXCREATEPBUFFERPROC) (X11_Display *dpy, GLXFBConfig config, const int *attrib_list);
-typedef void (* PFNGLXDESTROYPBUFFERPROC) (X11_Display *dpy, GLXPbuffer pbuf);
-typedef void (* PFNGLXQUERYDRAWABLEPROC) (X11_Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
-typedef GLXContext (* PFNGLXCREATENEWCONTEXTPROC) (X11_Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
-typedef Bool (* PFNGLXMAKECONTEXTCURRENTPROC) (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
-typedef GLXDrawable (* PFNGLXGETCURRENTREADDRAWABLEPROC) ();
-typedef X11_Display * (* PFNGLXGETCURRENTDISPLAYPROC) ();
-typedef int (* PFNGLXQUERYCONTEXTPROC) (X11_Display *dpy, GLXContext ctx, int attribute, int *value);
-typedef void (* PFNGLXSELECTEVENTPROC) (X11_Display *dpy, GLXDrawable draw, unsigned long event_mask);
-typedef void (* PFNGLXGETSELECTEDEVENTPROC) (X11_Display *dpy, GLXDrawable draw, unsigned long *event_mask);
+Bool glXAssociateDMPbufferSGIX (X11_Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer);
 #endif
+#endif /* _DM_BUFFER_H_ */
+#endif /* GLX_SGIX_dmbuffer */
 
-#ifndef GLX_VERSION_1_4
-#define GLX_VERSION_1_4 1
+#ifndef GLX_SGIX_fbconfig
+#define GLX_SGIX_fbconfig 1
+typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
+#define GLX_WINDOW_BIT_SGIX               0x00000001
+#define GLX_PIXMAP_BIT_SGIX               0x00000002
+#define GLX_RGBA_BIT_SGIX                 0x00000001
+#define GLX_COLOR_INDEX_BIT_SGIX          0x00000002
+#define GLX_DRAWABLE_TYPE_SGIX            0x8010
+#define GLX_RENDER_TYPE_SGIX              0x8011
+#define GLX_X_RENDERABLE_SGIX             0x8012
+#define GLX_FBCONFIG_ID_SGIX              0x8013
+#define GLX_RGBA_TYPE_SGIX                0x8014
+#define GLX_COLOR_INDEX_TYPE_SGIX         0x8015
+typedef int ( *PFNGLXGETFBCONFIGATTRIBSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, int attribute, int *value);
+typedef GLXFBConfigSGIX *( *PFNGLXCHOOSEFBCONFIGSGIXPROC) (X11_Display *dpy, int screen, int *attrib_list, int *nelements);
+typedef GLXPixmap ( *PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap);
+typedef GLXContext ( *PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct);
+typedef XVisualInfo *( *PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config);
+typedef GLXFBConfigSGIX ( *PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (X11_Display *dpy, XVisualInfo *vis);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern __GLXextFuncPtr glXGetProcAddress (const GLubyte *);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef __GLXextFuncPtr (* PFNGLXGETPROCADDRESSPROC) (const GLubyte *procName);
+int glXGetFBConfigAttribSGIX (X11_Display *dpy, GLXFBConfigSGIX config, int attribute, int *value);
+GLXFBConfigSGIX *glXChooseFBConfigSGIX (X11_Display *dpy, int screen, int *attrib_list, int *nelements);
+GLXPixmap glXCreateGLXPixmapWithConfigSGIX (X11_Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap);
+GLXContext glXCreateContextWithConfigSGIX (X11_Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct);
+XVisualInfo *glXGetVisualFromFBConfigSGIX (X11_Display *dpy, GLXFBConfigSGIX config);
+GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX (X11_Display *dpy, XVisualInfo *vis);
 #endif
+#endif /* GLX_SGIX_fbconfig */
 
-#ifndef GLX_ARB_get_proc_address
-#define GLX_ARB_get_proc_address 1
+#ifndef GLX_SGIX_hyperpipe
+#define GLX_SGIX_hyperpipe 1
+typedef struct {
+    char    pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+    int     networkId;
+} GLXHyperpipeNetworkSGIX;
+typedef struct {
+    char    pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+    int     channel;
+    unsigned int participationType;
+    int     timeSlice;
+} GLXHyperpipeConfigSGIX;
+typedef struct {
+    char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+    int srcXOrigin, srcYOrigin, srcWidth, srcHeight;
+    int destXOrigin, destYOrigin, destWidth, destHeight;
+} GLXPipeRect;
+typedef struct {
+    char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
+    int XOrigin, YOrigin, maxHeight, maxWidth;
+} GLXPipeRectLimits;
+#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80
+#define GLX_BAD_HYPERPIPE_CONFIG_SGIX     91
+#define GLX_BAD_HYPERPIPE_SGIX            92
+#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX   0x00000001
+#define GLX_HYPERPIPE_RENDER_PIPE_SGIX    0x00000002
+#define GLX_PIPE_RECT_SGIX                0x00000001
+#define GLX_PIPE_RECT_LIMITS_SGIX         0x00000002
+#define GLX_HYPERPIPE_STEREO_SGIX         0x00000003
+#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX  0x00000004
+#define GLX_HYPERPIPE_ID_SGIX             0x8030
+typedef GLXHyperpipeNetworkSGIX *( *PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (X11_Display *dpy, int *npipes);
+typedef int ( *PFNGLXHYPERPIPECONFIGSGIXPROC) (X11_Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId);
+typedef GLXHyperpipeConfigSGIX *( *PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (X11_Display *dpy, int hpId, int *npipes);
+typedef int ( *PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (X11_Display *dpy, int hpId);
+typedef int ( *PFNGLXBINDHYPERPIPESGIXPROC) (X11_Display *dpy, int hpId);
+typedef int ( *PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (X11_Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList);
+typedef int ( *PFNGLXHYPERPIPEATTRIBSGIXPROC) (X11_Display *dpy, int timeSlice, int attrib, int size, void *attribList);
+typedef int ( *PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (X11_Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef __GLXextFuncPtr (* PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName);
+GLXHyperpipeNetworkSGIX *glXQueryHyperpipeNetworkSGIX (X11_Display *dpy, int *npipes);
+int glXHyperpipeConfigSGIX (X11_Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId);
+GLXHyperpipeConfigSGIX *glXQueryHyperpipeConfigSGIX (X11_Display *dpy, int hpId, int *npipes);
+int glXDestroyHyperpipeConfigSGIX (X11_Display *dpy, int hpId);
+int glXBindHyperpipeSGIX (X11_Display *dpy, int hpId);
+int glXQueryHyperpipeBestAttribSGIX (X11_Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList);
+int glXHyperpipeAttribSGIX (X11_Display *dpy, int timeSlice, int attrib, int size, void *attribList);
+int glXQueryHyperpipeAttribSGIX (X11_Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList);
 #endif
+#endif /* GLX_SGIX_hyperpipe */
 
-#ifndef GLX_ARB_multisample
-#define GLX_ARB_multisample 1
-#endif
-
-#ifndef GLX_SGIS_multisample
-#define GLX_SGIS_multisample 1
-#endif
-
-#ifndef GLX_EXT_visual_info
-#define GLX_EXT_visual_info 1
+#ifndef GLX_SGIX_pbuffer
+#define GLX_SGIX_pbuffer 1
+#define GLX_PBUFFER_BIT_SGIX              0x00000004
+#define GLX_BUFFER_CLOBBER_MASK_SGIX      0x08000000
+#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX    0x00000001
+#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX   0x00000002
+#define GLX_BACK_LEFT_BUFFER_BIT_SGIX     0x00000004
+#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX    0x00000008
+#define GLX_AUX_BUFFERS_BIT_SGIX          0x00000010
+#define GLX_DEPTH_BUFFER_BIT_SGIX         0x00000020
+#define GLX_STENCIL_BUFFER_BIT_SGIX       0x00000040
+#define GLX_ACCUM_BUFFER_BIT_SGIX         0x00000080
+#define GLX_SAMPLE_BUFFERS_BIT_SGIX       0x00000100
+#define GLX_MAX_PBUFFER_WIDTH_SGIX        0x8016
+#define GLX_MAX_PBUFFER_HEIGHT_SGIX       0x8017
+#define GLX_MAX_PBUFFER_PIXELS_SGIX       0x8018
+#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX    0x8019
+#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX   0x801A
+#define GLX_PRESERVED_CONTENTS_SGIX       0x801B
+#define GLX_LARGEST_PBUFFER_SGIX          0x801C
+#define GLX_WIDTH_SGIX                    0x801D
+#define GLX_HEIGHT_SGIX                   0x801E
+#define GLX_EVENT_MASK_SGIX               0x801F
+#define GLX_DAMAGED_SGIX                  0x8020
+#define GLX_SAVED_SGIX                    0x8021
+#define GLX_WINDOW_SGIX                   0x8022
+#define GLX_PBUFFER_SGIX                  0x8023
+typedef GLXPbufferSGIX ( *PFNGLXCREATEGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list);
+typedef void ( *PFNGLXDESTROYGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuf);
+typedef int ( *PFNGLXQUERYGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value);
+typedef void ( *PFNGLXSELECTEVENTSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, unsigned long mask);
+typedef void ( *PFNGLXGETSELECTEDEVENTSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, unsigned long *mask);
+#ifdef GLX_GLXEXT_PROTOTYPES
+GLXPbufferSGIX glXCreateGLXPbufferSGIX (X11_Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list);
+void glXDestroyGLXPbufferSGIX (X11_Display *dpy, GLXPbufferSGIX pbuf);
+int glXQueryGLXPbufferSGIX (X11_Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value);
+void glXSelectEventSGIX (X11_Display *dpy, GLXDrawable drawable, unsigned long mask);
+void glXGetSelectedEventSGIX (X11_Display *dpy, GLXDrawable drawable, unsigned long *mask);
 #endif
+#endif /* GLX_SGIX_pbuffer */
 
-#ifndef GLX_SGI_swap_control
-#define GLX_SGI_swap_control 1
+#ifndef GLX_SGIX_swap_barrier
+#define GLX_SGIX_swap_barrier 1
+typedef void ( *PFNGLXBINDSWAPBARRIERSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, int barrier);
+typedef Bool ( *PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (X11_Display *dpy, int screen, int *max);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern int glXSwapIntervalSGI (int);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef int (* PFNGLXSWAPINTERVALSGIPROC) (int interval);
+void glXBindSwapBarrierSGIX (X11_Display *dpy, GLXDrawable drawable, int barrier);
+Bool glXQueryMaxSwapBarriersSGIX (X11_Display *dpy, int screen, int *max);
 #endif
+#endif /* GLX_SGIX_swap_barrier */
 
-#ifndef GLX_SGI_video_sync
-#define GLX_SGI_video_sync 1
+#ifndef GLX_SGIX_swap_group
+#define GLX_SGIX_swap_group 1
+typedef void ( *PFNGLXJOINSWAPGROUPSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, GLXDrawable member);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern int glXGetVideoSyncSGI (unsigned int *);
-extern int glXWaitVideoSyncSGI (int, int, unsigned int *);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef int (* PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int *count);
-typedef int (* PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count);
+void glXJoinSwapGroupSGIX (X11_Display *dpy, GLXDrawable drawable, GLXDrawable member);
 #endif
+#endif /* GLX_SGIX_swap_group */
 
-#ifndef GLX_SGI_make_current_read
-#define GLX_SGI_make_current_read 1
+#ifndef GLX_SGIX_video_resize
+#define GLX_SGIX_video_resize 1
+#define GLX_SYNC_FRAME_SGIX               0x00000000
+#define GLX_SYNC_SWAP_SGIX                0x00000001
+typedef int ( *PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (X11_Display *display, int screen, int channel, X11_Window window);
+typedef int ( *PFNGLXCHANNELRECTSGIXPROC) (X11_Display *display, int screen, int channel, int x, int y, int w, int h);
+typedef int ( *PFNGLXQUERYCHANNELRECTSGIXPROC) (X11_Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh);
+typedef int ( *PFNGLXQUERYCHANNELDELTASSGIXPROC) (X11_Display *display, int screen, int channel, int *x, int *y, int *w, int *h);
+typedef int ( *PFNGLXCHANNELRECTSYNCSGIXPROC) (X11_Display *display, int screen, int channel, GLenum synctype);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern Bool glXMakeCurrentReadSGI (X11_Display *, GLXDrawable, GLXDrawable, GLXContext);
-extern GLXDrawable glXGetCurrentReadDrawableSGI ();
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef Bool (* PFNGLXMAKECURRENTREADSGIPROC) (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
-typedef GLXDrawable (* PFNGLXGETCURRENTREADDRAWABLESGIPROC) ();
+int glXBindChannelToWindowSGIX (X11_Display *display, int screen, int channel, X11_Window window);
+int glXChannelRectSGIX (X11_Display *display, int screen, int channel, int x, int y, int w, int h);
+int glXQueryChannelRectSGIX (X11_Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh);
+int glXQueryChannelDeltasSGIX (X11_Display *display, int screen, int channel, int *x, int *y, int *w, int *h);
+int glXChannelRectSyncSGIX (X11_Display *display, int screen, int channel, GLenum synctype);
 #endif
+#endif /* GLX_SGIX_video_resize */
 
 #ifndef GLX_SGIX_video_source
 #define GLX_SGIX_video_source 1
+typedef XID GLXVideoSourceSGIX;
 #ifdef _VL_H
+typedef GLXVideoSourceSGIX ( *PFNGLXCREATEGLXVIDEOSOURCESGIXPROC) (X11_Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode);
+typedef void ( *PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC) (X11_Display *dpy, GLXVideoSourceSGIX glxvideosource);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX (X11_Display *, int, VLServer, VLPath, int, VLNode);
-extern void glXDestroyGLXVideoSourceSGIX (X11_Display *, GLXVideoSourceSGIX);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef GLXVideoSourceSGIX (* PFNGLXCREATEGLXVIDEOSOURCESGIXPROC) (X11_Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode);
-typedef void (* PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC) (X11_Display *dpy, GLXVideoSourceSGIX glxvideosource);
+GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX (X11_Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode);
+void glXDestroyGLXVideoSourceSGIX (X11_Display *dpy, GLXVideoSourceSGIX glxvideosource);
 #endif
-
 #endif /* _VL_H */
-#ifndef GLX_EXT_visual_rating
-#define GLX_EXT_visual_rating 1
-#endif
-
-#ifndef GLX_SGIX_fbconfig
-#define GLX_SGIX_fbconfig 1
-#ifdef GLX_GLXEXT_PROTOTYPES
-extern int glXGetFBConfigAttribSGIX (X11_Display *, GLXFBConfigSGIX, int, int *);
-extern GLXFBConfigSGIX * glXChooseFBConfigSGIX (X11_Display *, int, int *, int *);
-extern GLXPixmap glXCreateGLXPixmapWithConfigSGIX (X11_Display *, GLXFBConfigSGIX, Pixmap);
-extern GLXContext glXCreateContextWithConfigSGIX (X11_Display *, GLXFBConfigSGIX, int, GLXContext, Bool);
-extern XVisualInfo * glXGetVisualFromFBConfigSGIX (X11_Display *, GLXFBConfigSGIX);
-extern GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX (X11_Display *, XVisualInfo *);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef int (* PFNGLXGETFBCONFIGATTRIBSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, int attribute, int *value);
-typedef GLXFBConfigSGIX * (* PFNGLXCHOOSEFBCONFIGSGIXPROC) (X11_Display *dpy, int screen, int *attrib_list, int *nelements);
-typedef GLXPixmap (* PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap);
-typedef GLXContext (* PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct);
-typedef XVisualInfo * (* PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config);
-typedef GLXFBConfigSGIX (* PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (X11_Display *dpy, XVisualInfo *vis);
-#endif
+#endif /* GLX_SGIX_video_source */
 
-#ifndef GLX_SGIX_pbuffer
-#define GLX_SGIX_pbuffer 1
-#ifdef GLX_GLXEXT_PROTOTYPES
-extern GLXPbufferSGIX glXCreateGLXPbufferSGIX (X11_Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *);
-extern void glXDestroyGLXPbufferSGIX (X11_Display *, GLXPbufferSGIX);
-extern int glXQueryGLXPbufferSGIX (X11_Display *, GLXPbufferSGIX, int, unsigned int *);
-extern void glXSelectEventSGIX (X11_Display *, GLXDrawable, unsigned long);
-extern void glXGetSelectedEventSGIX (X11_Display *, GLXDrawable, unsigned long *);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef GLXPbufferSGIX (* PFNGLXCREATEGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list);
-typedef void (* PFNGLXDESTROYGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuf);
-typedef int (* PFNGLXQUERYGLXPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value);
-typedef void (* PFNGLXSELECTEVENTSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, unsigned long mask);
-typedef void (* PFNGLXGETSELECTEDEVENTSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, unsigned long *mask);
-#endif
+#ifndef GLX_SGIX_visual_select_group
+#define GLX_SGIX_visual_select_group 1
+#define GLX_VISUAL_SELECT_GROUP_SGIX      0x8028
+#endif /* GLX_SGIX_visual_select_group */
 
 #ifndef GLX_SGI_cushion
 #define GLX_SGI_cushion 1
+typedef void ( *PFNGLXCUSHIONSGIPROC) (X11_Display *dpy, X11_Window window, float cushion);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern void glXCushionSGI (X11_Display *, X11_Window, float);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef void (* PFNGLXCUSHIONSGIPROC) (X11_Display *dpy, X11_Window window, float cushion);
-#endif
-
-#ifndef GLX_SGIX_video_resize
-#define GLX_SGIX_video_resize 1
-#ifdef GLX_GLXEXT_PROTOTYPES
-extern int glXBindChannelToWindowSGIX (X11_Display *, int, int, X11_Window);
-extern int glXChannelRectSGIX (X11_Display *, int, int, int, int, int, int);
-extern int glXQueryChannelRectSGIX (X11_Display *, int, int, int *, int *, int *, int *);
-extern int glXQueryChannelDeltasSGIX (X11_Display *, int, int, int *, int *, int *, int *);
-extern int glXChannelRectSyncSGIX (X11_Display *, int, int, GLenum);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef int (* PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (X11_Display *display, int screen, int channel, X11_Window window);
-typedef int (* PFNGLXCHANNELRECTSGIXPROC) (X11_Display *display, int screen, int channel, int x, int y, int w, int h);
-typedef int (* PFNGLXQUERYCHANNELRECTSGIXPROC) (X11_Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh);
-typedef int (* PFNGLXQUERYCHANNELDELTASSGIXPROC) (X11_Display *display, int screen, int channel, int *x, int *y, int *w, int *h);
-typedef int (* PFNGLXCHANNELRECTSYNCSGIXPROC) (X11_Display *display, int screen, int channel, GLenum synctype);
+void glXCushionSGI (X11_Display *dpy, X11_Window window, float cushion);
 #endif
+#endif /* GLX_SGI_cushion */
 
-#ifndef GLX_SGIX_dmbuffer
-#define GLX_SGIX_dmbuffer 1
-#ifdef _DM_BUFFER_H_
+#ifndef GLX_SGI_make_current_read
+#define GLX_SGI_make_current_read 1
+typedef Bool ( *PFNGLXMAKECURRENTREADSGIPROC) (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+typedef GLXDrawable ( *PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern Bool glXAssociateDMPbufferSGIX (X11_Display *, GLXPbufferSGIX, DMparams *, DMbuffer);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef Bool (* PFNGLXASSOCIATEDMPBUFFERSGIXPROC) (X11_Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer);
+Bool glXMakeCurrentReadSGI (X11_Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+GLXDrawable glXGetCurrentReadDrawableSGI (void);
 #endif
+#endif /* GLX_SGI_make_current_read */
 
-#endif /* _DM_BUFFER_H_ */
-#ifndef GLX_SGIX_swap_group
-#define GLX_SGIX_swap_group 1
+#ifndef GLX_SGI_swap_control
+#define GLX_SGI_swap_control 1
+typedef int ( *PFNGLXSWAPINTERVALSGIPROC) (int interval);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern void glXJoinSwapGroupSGIX (X11_Display *, GLXDrawable, GLXDrawable);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef void (* PFNGLXJOINSWAPGROUPSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, GLXDrawable member);
+int glXSwapIntervalSGI (int interval);
 #endif
+#endif /* GLX_SGI_swap_control */
 
-#ifndef GLX_SGIX_swap_barrier
-#define GLX_SGIX_swap_barrier 1
+#ifndef GLX_SGI_video_sync
+#define GLX_SGI_video_sync 1
+typedef int ( *PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int *count);
+typedef int ( *PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern void glXBindSwapBarrierSGIX (X11_Display *, GLXDrawable, int);
-extern Bool glXQueryMaxSwapBarriersSGIX (X11_Display *, int, int *);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef void (* PFNGLXBINDSWAPBARRIERSGIXPROC) (X11_Display *dpy, GLXDrawable drawable, int barrier);
-typedef Bool (* PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (X11_Display *dpy, int screen, int *max);
+int glXGetVideoSyncSGI (unsigned int *count);
+int glXWaitVideoSyncSGI (int divisor, int remainder, unsigned int *count);
 #endif
+#endif /* GLX_SGI_video_sync */
 
 #ifndef GLX_SUN_get_transparent_index
 #define GLX_SUN_get_transparent_index 1
+typedef Status ( *PFNGLXGETTRANSPARENTINDEXSUNPROC) (X11_Display *dpy, X11_Window overlay, X11_Window underlay, long *pTransparentIndex);
 #ifdef GLX_GLXEXT_PROTOTYPES
-extern Status glXGetTransparentIndexSUN (X11_Display *, X11_Window, X11_Window, long *);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef Status (* PFNGLXGETTRANSPARENTINDEXSUNPROC) (X11_Display *dpy, X11_Window overlay, X11_Window underlay, long *pTransparentIndex);
+Status glXGetTransparentIndexSUN (X11_Display *dpy, X11_Window overlay, X11_Window underlay, long *pTransparentIndex);
 #endif
-
-#ifndef GLX_MESA_copy_sub_buffer
-#define GLX_MESA_copy_sub_buffer 1
-#ifdef GLX_GLXEXT_PROTOTYPES
-extern void glXCopySubBufferMESA (X11_Display *, GLXDrawable, int, int, int, int);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef void (* PFNGLXCOPYSUBBUFFERMESAPROC) (X11_Display *dpy, GLXDrawable drawable, int x, int y, int width, int height);
-#endif
-
-#ifndef GLX_MESA_pixmap_colormap
-#define GLX_MESA_pixmap_colormap 1
-#ifdef GLX_GLXEXT_PROTOTYPES
-extern GLXPixmap glXCreateGLXPixmapMESA (X11_Display *, XVisualInfo *, Pixmap, Colormap);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef GLXPixmap (* PFNGLXCREATEGLXPIXMAPMESAPROC) (X11_Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap);
-#endif
-
-#ifndef GLX_MESA_release_buffers
-#define GLX_MESA_release_buffers 1
-#ifdef GLX_GLXEXT_PROTOTYPES
-extern Bool glXReleaseBuffersMESA (X11_Display *, GLXDrawable);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef Bool (* PFNGLXRELEASEBUFFERSMESAPROC) (X11_Display *dpy, GLXDrawable drawable);
-#endif
-
-#ifndef GLX_MESA_set_3dfx_mode
-#define GLX_MESA_set_3dfx_mode 1
-#ifdef GLX_GLXEXT_PROTOTYPES
-extern Bool glXSet3DfxModeMESA (int);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef Bool (* PFNGLXSET3DFXMODEMESAPROC) (int mode);
-#endif
-
-#ifndef GLX_SGIX_visual_select_group
-#define GLX_SGIX_visual_select_group 1
-#endif
-
-#ifndef GLX_OML_swap_method
-#define GLX_OML_swap_method 1
-#endif
-
-#ifndef GLX_OML_sync_control
-#define GLX_OML_sync_control 1
-#if defined(__STDC_VERSION__)
-#if __STDC_VERSION__ >= 199901L
-/* Include ISO C99 integer types for OML_sync_control; need a better test */
-#include <inttypes.h>
-
-#ifdef GLX_GLXEXT_PROTOTYPES
-extern Bool glXGetSyncValuesOML (X11_Display *, GLXDrawable, int64_t *, int64_t *, int64_t *);
-extern Bool glXGetMscRateOML (X11_Display *, GLXDrawable, int32_t *, int32_t *);
-extern int64_t glXSwapBuffersMscOML (X11_Display *, GLXDrawable, int64_t, int64_t, int64_t);
-extern Bool glXWaitForMscOML (X11_Display *, GLXDrawable, int64_t, int64_t, int64_t, int64_t *, int64_t *, int64_t *);
-extern Bool glXWaitForSbcOML (X11_Display *, GLXDrawable, int64_t, int64_t *, int64_t *, int64_t *);
-#endif /* GLX_GLXEXT_PROTOTYPES */
-typedef Bool (* PFNGLXGETSYNCVALUESOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc);
-typedef Bool (* PFNGLXGETMSCRATEOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator);
-typedef int64_t (* PFNGLXSWAPBUFFERSMSCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder);
-typedef Bool (* PFNGLXWAITFORMSCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc);
-typedef Bool (* PFNGLXWAITFORSBCOMLPROC) (X11_Display *dpy, GLXDrawable drawable, int64_t target_sbc, int64_t *ust, int64_t *msc, int64_t *sbc);
-#endif
-
-#endif /* C99 version test */
-#endif /* STDC test */
+#endif /* GLX_SUN_get_transparent_index */
 
 #ifdef __cplusplus
 }

+ 2 - 4
panda/src/glxdisplay/posixGraphicsStateGuardian.cxx

@@ -53,13 +53,11 @@ PosixGraphicsStateGuardian::
 //               not defined.
 ////////////////////////////////////////////////////////////////////
 void *PosixGraphicsStateGuardian::
-do_get_extension_func(const char *prefix, const char *name) {
-  nassertr(prefix != NULL, NULL);
+do_get_extension_func(const char *name) {
   nassertr(name != NULL, NULL);
-  string fullname = string(prefix) + string(name);
 
   if (glx_get_os_address) {
-    return get_system_func(fullname.c_str());
+    return get_system_func(name);
   }
 
   return NULL;

+ 1 - 1
panda/src/glxdisplay/posixGraphicsStateGuardian.h

@@ -32,7 +32,7 @@ public:
   ~PosixGraphicsStateGuardian();
 
 protected:
-  virtual void *do_get_extension_func(const char *prefix, const char *name);
+  virtual void *do_get_extension_func(const char *name);
   void *get_system_func(const char *name);
 
 private:

+ 7 - 0
panda/src/gobj/config_gobj.cxx

@@ -510,6 +510,13 @@ ConfigVariableInt lens_geom_segments
           "lens; for a normal perspective or orthographic lens, the "
           "wireframe is not subdivided."));
 
+ConfigVariableString cg_glsl_version
+("cg-glsl-version", "",
+ PRC_DESC("If this is set, it forces the Cg compiler to generate GLSL "
+          "code conforming to the given GLSL version when using the "
+          "glslv, glslf or glslg profiles.  Use this when you are having "
+          "problems with these profiles.  Example values are 120 or 150."));
+
 ConfigureFn(config_gobj) {
   AnimateVerticesRequest::init_type();
   BufferContext::init_type();

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

@@ -101,6 +101,6 @@ extern EXPCL_PANDA_GOBJ ConfigVariableInt adaptive_lru_max_updates_per_frame;
 extern EXPCL_PANDA_GOBJ ConfigVariableDouble async_load_delay;
 extern EXPCL_PANDA_GOBJ ConfigVariableInt lens_geom_segments;
 
-#endif
-
+extern EXPCL_PANDA_GOBJ ConfigVariableString cg_glsl_version;
 
+#endif

+ 13 - 0
panda/src/gobj/geom.I

@@ -242,6 +242,19 @@ make_points() const {
   return new_geom;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Geom::make_patches
+//       Access: Published
+//  Description: Returns a new Geom with each primitive converted
+//               into a patch.  Calls decompose() first.
+////////////////////////////////////////////////////////////////////
+INLINE PT(Geom) Geom::
+make_patches() const {
+  PT(Geom) new_geom = make_copy();
+  new_geom->make_patches_in_place();
+  return new_geom;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Geom::get_modified
 //       Access: Published

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